1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.incallui.answer.impl.hint; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 import android.graphics.drawable.Drawable; 22 import android.os.Build; 23 import android.support.annotation.NonNull; 24 import android.support.annotation.VisibleForTesting; 25 import com.android.dialer.common.Assert; 26 import com.android.dialer.common.LogUtil; 27 import com.android.dialer.configprovider.ConfigProviderComponent; 28 import com.android.dialer.storage.StorageComponent; 29 import com.android.incallui.util.AccessibilityUtil; 30 31 /** 32 * Selects a AnswerHint to show. If there's no suitable hints {@link EmptyAnswerHint} will be used, 33 * which does nothing. 34 */ 35 public class AnswerHintFactory { 36 37 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) 38 static final String CONFIG_ANSWER_HINT_ANSWERED_THRESHOLD_KEY = "answer_hint_answered_threshold"; 39 40 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) 41 static final String CONFIG_ANSWER_HINT_WHITELISTED_DEVICES_KEY = 42 "answer_hint_whitelisted_devices"; 43 // Most popular devices released before NDR1 is whitelisted. Their user are likely to have seen 44 // the legacy UI. 45 private static final String DEFAULT_WHITELISTED_DEVICES_CSV = 46 "/hammerhead//bullhead//angler//shamu//gm4g//gm4g_s//AQ4501//gce_x86_phone//gm4gtkc_s/" 47 + "/Sparkle_V//Mi-498//AQ4502//imobileiq2//A65//H940//m8_google//m0xx//A10//ctih220/" 48 + "/Mi438S//bacon/"; 49 50 @VisibleForTesting 51 static final String ANSWERED_COUNT_PREFERENCE_KEY = "answer_hint_answered_count"; 52 53 private final PawImageLoader pawImageLoader; 54 AnswerHintFactory(@onNull PawImageLoader pawImageLoader)55 public AnswerHintFactory(@NonNull PawImageLoader pawImageLoader) { 56 this.pawImageLoader = Assert.isNotNull(pawImageLoader); 57 } 58 59 @NonNull create(Context context, long puckUpDuration, long puckUpDelay)60 public AnswerHint create(Context context, long puckUpDuration, long puckUpDelay) { 61 if (shouldShowAnswerHint(context, Build.PRODUCT)) { 62 return new DotAnswerHint(context, puckUpDuration, puckUpDelay); 63 } 64 65 // Display the event answer hint if the payload is available. 66 Drawable eventPayload = pawImageLoader.loadPayload(context); 67 if (eventPayload != null) { 68 return new PawAnswerHint(context, eventPayload, puckUpDuration, puckUpDelay); 69 } 70 71 return new EmptyAnswerHint(); 72 } 73 increaseAnsweredCount(Context context)74 public static void increaseAnsweredCount(Context context) { 75 SharedPreferences sharedPreferences = StorageComponent.get(context).unencryptedSharedPrefs(); 76 int answeredCount = sharedPreferences.getInt(ANSWERED_COUNT_PREFERENCE_KEY, 0); 77 sharedPreferences.edit().putInt(ANSWERED_COUNT_PREFERENCE_KEY, answeredCount + 1).apply(); 78 } 79 80 @VisibleForTesting shouldShowAnswerHint(Context context, String device)81 static boolean shouldShowAnswerHint(Context context, String device) { 82 if (AccessibilityUtil.isTouchExplorationEnabled(context)) { 83 return false; 84 } 85 // Devices that has the legacy dialer installed are whitelisted as they are likely to go through 86 // a UX change during updates. 87 if (!isDeviceWhitelisted(context, device)) { 88 return false; 89 } 90 91 // If the user has gone through the process a few times we can assume they have learnt the 92 // method. 93 int answeredCount = 94 StorageComponent.get(context) 95 .unencryptedSharedPrefs() 96 .getInt(ANSWERED_COUNT_PREFERENCE_KEY, 0); 97 long threshold = 98 ConfigProviderComponent.get(context) 99 .getConfigProvider() 100 .getLong(CONFIG_ANSWER_HINT_ANSWERED_THRESHOLD_KEY, 3); 101 LogUtil.i( 102 "AnswerHintFactory.shouldShowAnswerHint", 103 "answerCount: %d, threshold: %d", 104 answeredCount, 105 threshold); 106 return answeredCount < threshold; 107 } 108 109 /** 110 * @param device should be the value of{@link Build#PRODUCT}. 111 * @param configProvider should provide a list of devices quoted with '/' concatenated to a 112 * string. 113 */ isDeviceWhitelisted(Context context, String device)114 private static boolean isDeviceWhitelisted(Context context, String device) { 115 return ConfigProviderComponent.get(context) 116 .getConfigProvider() 117 .getString(CONFIG_ANSWER_HINT_WHITELISTED_DEVICES_KEY, DEFAULT_WHITELISTED_DEVICES_CSV) 118 .contains("/" + device + "/"); 119 } 120 } 121