1 /* 2 * Copyright (C) 2022 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.wm.shell.compatui; 18 19 import android.annotation.NonNull; 20 import android.app.TaskInfo; 21 import android.content.Context; 22 import android.content.SharedPreferences; 23 import android.provider.DeviceConfig; 24 25 import com.android.wm.shell.R; 26 import com.android.wm.shell.common.ShellExecutor; 27 import com.android.wm.shell.common.annotations.ShellMainThread; 28 import com.android.wm.shell.dagger.WMSingleton; 29 30 import javax.inject.Inject; 31 32 /** 33 * Configuration flags for the CompatUX implementation 34 */ 35 @WMSingleton 36 public class CompatUIConfiguration implements DeviceConfig.OnPropertiesChangedListener { 37 38 private static final String KEY_ENABLE_LETTERBOX_RESTART_DIALOG = 39 "enable_letterbox_restart_confirmation_dialog"; 40 41 private static final String KEY_ENABLE_LETTERBOX_REACHABILITY_EDUCATION = 42 "enable_letterbox_education_for_reachability"; 43 44 private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_RESTART_DIALOG = true; 45 46 private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_REACHABILITY_EDUCATION = true; 47 48 /** 49 * The name of the {@link SharedPreferences} that holds information about compat ui. 50 */ 51 private static final String COMPAT_UI_SHARED_PREFERENCES = "dont_show_restart_dialog"; 52 53 /** 54 * The name of the {@link SharedPreferences} that holds which user has seen the Letterbox 55 * Education dialog. 56 */ 57 private static final String HAS_SEEN_LETTERBOX_EDUCATION_SHARED_PREFERENCES = 58 "has_seen_letterbox_education"; 59 60 /** 61 * Key prefix for the {@link SharedPreferences} entries related to the horizontal 62 * reachability education. 63 */ 64 private static final String HAS_SEEN_HORIZONTAL_REACHABILITY_EDUCATION_KEY_PREFIX = 65 "has_seen_horizontal_reachability_education"; 66 67 /** 68 * Key prefix for the {@link SharedPreferences} entries related to the vertical reachability 69 * education. 70 */ 71 private static final String HAS_SEEN_VERTICAL_REACHABILITY_EDUCATION_KEY_PREFIX = 72 "has_seen_vertical_reachability_education"; 73 74 /** 75 * The {@link SharedPreferences} instance for the restart dialog and the reachability 76 * education. 77 */ 78 private final SharedPreferences mCompatUISharedPreferences; 79 80 /** 81 * The {@link SharedPreferences} instance for the letterbox education dialog. 82 */ 83 private final SharedPreferences mLetterboxEduSharedPreferences; 84 85 // Whether the extended restart dialog is enabled 86 private boolean mIsRestartDialogEnabled; 87 88 // Whether the additional education about reachability is enabled 89 private boolean mIsReachabilityEducationEnabled; 90 91 // Whether the extended restart dialog is enabled 92 private boolean mIsRestartDialogOverrideEnabled; 93 94 // Whether the additional education about reachability is enabled 95 private boolean mIsReachabilityEducationOverrideEnabled; 96 97 // Whether the extended restart dialog is allowed from backend 98 private boolean mIsLetterboxRestartDialogAllowed; 99 100 // Whether the additional education about reachability is allowed from backend 101 private boolean mIsLetterboxReachabilityEducationAllowed; 102 103 @Inject CompatUIConfiguration(Context context, @ShellMainThread ShellExecutor mainExecutor)104 public CompatUIConfiguration(Context context, @ShellMainThread ShellExecutor mainExecutor) { 105 mIsRestartDialogEnabled = context.getResources().getBoolean( 106 R.bool.config_letterboxIsRestartDialogEnabled); 107 mIsReachabilityEducationEnabled = context.getResources().getBoolean( 108 R.bool.config_letterboxIsReachabilityEducationEnabled); 109 mIsLetterboxRestartDialogAllowed = DeviceConfig.getBoolean( 110 DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_LETTERBOX_RESTART_DIALOG, 111 DEFAULT_VALUE_ENABLE_LETTERBOX_RESTART_DIALOG); 112 mIsLetterboxReachabilityEducationAllowed = DeviceConfig.getBoolean( 113 DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_LETTERBOX_REACHABILITY_EDUCATION, 114 DEFAULT_VALUE_ENABLE_LETTERBOX_REACHABILITY_EDUCATION); 115 DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_APP_COMPAT, mainExecutor, 116 this); 117 mCompatUISharedPreferences = context.getSharedPreferences(getCompatUISharedPreferenceName(), 118 Context.MODE_PRIVATE); 119 mLetterboxEduSharedPreferences = context.getSharedPreferences( 120 getHasSeenLetterboxEducationSharedPreferencedName(), Context.MODE_PRIVATE); 121 } 122 123 /** 124 * @return {@value true} if the restart dialog is enabled. 125 */ isRestartDialogEnabled()126 boolean isRestartDialogEnabled() { 127 return mIsRestartDialogOverrideEnabled || (mIsRestartDialogEnabled 128 && mIsLetterboxRestartDialogAllowed); 129 } 130 131 /** 132 * Enables/Disables the restart education dialog 133 */ setIsRestartDialogOverrideEnabled(boolean enabled)134 void setIsRestartDialogOverrideEnabled(boolean enabled) { 135 mIsRestartDialogOverrideEnabled = enabled; 136 } 137 138 /** 139 * Enables/Disables the reachability education 140 */ setIsReachabilityEducationOverrideEnabled(boolean enabled)141 void setIsReachabilityEducationOverrideEnabled(boolean enabled) { 142 mIsReachabilityEducationOverrideEnabled = enabled; 143 } 144 setDontShowRestartDialogAgain(TaskInfo taskInfo)145 void setDontShowRestartDialogAgain(TaskInfo taskInfo) { 146 mCompatUISharedPreferences.edit().putBoolean( 147 dontShowAgainRestartKey(taskInfo.userId, taskInfo.topActivity.getPackageName()), 148 true).apply(); 149 } 150 shouldShowRestartDialogAgain(TaskInfo taskInfo)151 boolean shouldShowRestartDialogAgain(TaskInfo taskInfo) { 152 return !mCompatUISharedPreferences.getBoolean(dontShowAgainRestartKey(taskInfo.userId, 153 taskInfo.topActivity.getPackageName()), /* default= */ false); 154 } 155 setUserHasSeenHorizontalReachabilityEducation(TaskInfo taskInfo)156 void setUserHasSeenHorizontalReachabilityEducation(TaskInfo taskInfo) { 157 mCompatUISharedPreferences.edit().putBoolean( 158 hasSeenHorizontalReachabilityEduKey(taskInfo.userId), true).apply(); 159 } 160 setUserHasSeenVerticalReachabilityEducation(TaskInfo taskInfo)161 void setUserHasSeenVerticalReachabilityEducation(TaskInfo taskInfo) { 162 mCompatUISharedPreferences.edit().putBoolean( 163 hasSeenVerticalReachabilityEduKey(taskInfo.userId), true).apply(); 164 } 165 hasSeenHorizontalReachabilityEducation(@onNull TaskInfo taskInfo)166 boolean hasSeenHorizontalReachabilityEducation(@NonNull TaskInfo taskInfo) { 167 return mCompatUISharedPreferences.getBoolean( 168 hasSeenHorizontalReachabilityEduKey(taskInfo.userId), /* default= */false); 169 } 170 hasSeenVerticalReachabilityEducation(@onNull TaskInfo taskInfo)171 boolean hasSeenVerticalReachabilityEducation(@NonNull TaskInfo taskInfo) { 172 return mCompatUISharedPreferences.getBoolean( 173 hasSeenVerticalReachabilityEduKey(taskInfo.userId), /* default= */false); 174 } 175 shouldShowReachabilityEducation(@onNull TaskInfo taskInfo)176 boolean shouldShowReachabilityEducation(@NonNull TaskInfo taskInfo) { 177 return isReachabilityEducationEnabled() 178 && (!hasSeenHorizontalReachabilityEducation(taskInfo) 179 || !hasSeenVerticalReachabilityEducation(taskInfo)); 180 } 181 getHasSeenLetterboxEducation(int userId)182 boolean getHasSeenLetterboxEducation(int userId) { 183 return mLetterboxEduSharedPreferences 184 .getBoolean(dontShowLetterboxEduKey(userId), /* default= */ false); 185 } 186 setSeenLetterboxEducation(int userId)187 void setSeenLetterboxEducation(int userId) { 188 mLetterboxEduSharedPreferences.edit().putBoolean(dontShowLetterboxEduKey(userId), 189 true).apply(); 190 } 191 getCompatUISharedPreferenceName()192 protected String getCompatUISharedPreferenceName() { 193 return COMPAT_UI_SHARED_PREFERENCES; 194 } 195 getHasSeenLetterboxEducationSharedPreferencedName()196 protected String getHasSeenLetterboxEducationSharedPreferencedName() { 197 return HAS_SEEN_LETTERBOX_EDUCATION_SHARED_PREFERENCES; 198 } 199 200 /** 201 * Updates the {@link DeviceConfig} state for the CompatUI 202 * @param properties Contains the complete collection of properties which have changed for a 203 * single namespace. This includes only those which were added, updated, 204 */ 205 @Override onPropertiesChanged(@onNull DeviceConfig.Properties properties)206 public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) { 207 if (properties.getKeyset().contains(KEY_ENABLE_LETTERBOX_RESTART_DIALOG)) { 208 mIsLetterboxRestartDialogAllowed = DeviceConfig.getBoolean( 209 DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_LETTERBOX_RESTART_DIALOG, 210 DEFAULT_VALUE_ENABLE_LETTERBOX_RESTART_DIALOG); 211 } 212 // TODO(b/263349751): Update flag and default value to true 213 if (properties.getKeyset().contains(KEY_ENABLE_LETTERBOX_REACHABILITY_EDUCATION)) { 214 mIsLetterboxReachabilityEducationAllowed = DeviceConfig.getBoolean( 215 DeviceConfig.NAMESPACE_WINDOW_MANAGER, 216 KEY_ENABLE_LETTERBOX_REACHABILITY_EDUCATION, 217 DEFAULT_VALUE_ENABLE_LETTERBOX_REACHABILITY_EDUCATION); 218 } 219 } 220 isReachabilityEducationEnabled()221 private boolean isReachabilityEducationEnabled() { 222 return mIsReachabilityEducationOverrideEnabled || (mIsReachabilityEducationEnabled 223 && mIsLetterboxReachabilityEducationAllowed); 224 } 225 hasSeenHorizontalReachabilityEduKey(int userId)226 private static String hasSeenHorizontalReachabilityEduKey(int userId) { 227 return HAS_SEEN_HORIZONTAL_REACHABILITY_EDUCATION_KEY_PREFIX + "@" + userId; 228 } 229 hasSeenVerticalReachabilityEduKey(int userId)230 private static String hasSeenVerticalReachabilityEduKey(int userId) { 231 return HAS_SEEN_VERTICAL_REACHABILITY_EDUCATION_KEY_PREFIX + "@" + userId; 232 } 233 dontShowLetterboxEduKey(int userId)234 private static String dontShowLetterboxEduKey(int userId) { 235 return String.valueOf(userId); 236 } 237 dontShowAgainRestartKey(int userId, String packageName)238 private String dontShowAgainRestartKey(int userId, String packageName) { 239 return packageName + "@" + userId; 240 } 241 }