1 /* 2 * Copyright (C) 2020 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.onehanded; 18 19 import static com.android.internal.accessibility.AccessibilityShortcutController.ONE_HANDED_COMPONENT_NAME; 20 21 import android.annotation.IntDef; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.database.ContentObserver; 25 import android.net.Uri; 26 import android.provider.Settings; 27 import android.text.TextUtils; 28 29 import androidx.annotation.Nullable; 30 31 import com.android.wm.shell.R; 32 33 import java.io.PrintWriter; 34 import java.lang.annotation.Retention; 35 import java.lang.annotation.RetentionPolicy; 36 37 /** 38 * APIs for querying or updating one handed settings. 39 */ 40 public final class OneHandedSettingsUtil { 41 private static final String TAG = "OneHandedSettingsUtil"; 42 private static final String ONE_HANDED_MODE_TARGET_NAME = 43 ONE_HANDED_COMPONENT_NAME.getShortClassName(); 44 45 @IntDef(prefix = {"ONE_HANDED_TIMEOUT_"}, value = { 46 ONE_HANDED_TIMEOUT_NEVER, 47 ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS, 48 ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS, 49 ONE_HANDED_TIMEOUT_LONG_IN_SECONDS, 50 }) 51 @Retention(RetentionPolicy.SOURCE) 52 public @interface OneHandedTimeout { 53 } 54 55 /** 56 * Never stop one handed automatically 57 */ 58 public static final int ONE_HANDED_TIMEOUT_NEVER = 0; 59 /** 60 * Auto stop one handed in {@link OneHandedSettingsUtil#ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS} 61 */ 62 public static final int ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS = 4; 63 /** 64 * Auto stop one handed in {@link OneHandedSettingsUtil#ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS} 65 */ 66 public static final int ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS = 8; 67 /** 68 * Auto stop one handed in {@link OneHandedSettingsUtil#ONE_HANDED_TIMEOUT_LONG_IN_SECONDS} 69 */ 70 public static final int ONE_HANDED_TIMEOUT_LONG_IN_SECONDS = 12; 71 72 /** 73 * Registers one handed preference settings observer 74 * 75 * @param key Setting key to monitor in observer 76 * @param resolver ContentResolver of context 77 * @param observer Observer from caller 78 * @param newUserId New user id to be registered 79 * @return uri key for observing 80 */ 81 @Nullable registerSettingsKeyObserver(String key, ContentResolver resolver, ContentObserver observer, int newUserId)82 public Uri registerSettingsKeyObserver(String key, ContentResolver resolver, 83 ContentObserver observer, int newUserId) { 84 Uri uriKey = null; 85 uriKey = Settings.Secure.getUriFor(key); 86 if (resolver != null && uriKey != null) { 87 resolver.registerContentObserver(uriKey, false, observer, newUserId); 88 } 89 return uriKey; 90 } 91 92 /** 93 * Unregisters one handed preference settings observer. 94 * 95 * @param resolver ContentResolver of context 96 * @param observer preference key change observer 97 */ unregisterSettingsKeyObserver(ContentResolver resolver, ContentObserver observer)98 public void unregisterSettingsKeyObserver(ContentResolver resolver, 99 ContentObserver observer) { 100 if (resolver != null) { 101 resolver.unregisterContentObserver(observer); 102 } 103 } 104 105 /** 106 * Queries one handed enable or disable flag from Settings provider. 107 * 108 * @return enable or disable one handed mode flag. 109 */ getSettingsOneHandedModeEnabled(ContentResolver resolver, int userId)110 public boolean getSettingsOneHandedModeEnabled(ContentResolver resolver, int userId) { 111 return Settings.Secure.getIntForUser(resolver, 112 Settings.Secure.ONE_HANDED_MODE_ENABLED, 0 /* Disabled */, userId) == 1; 113 } 114 115 /** 116 * Sets one handed enable or disable flag from Settings provider. 117 * 118 * @return true if the value was set, false on database errors 119 */ setOneHandedModeEnabled(ContentResolver resolver, int enabled, int userId)120 public boolean setOneHandedModeEnabled(ContentResolver resolver, int enabled, int userId) { 121 return Settings.Secure.putIntForUser(resolver, 122 Settings.Secure.ONE_HANDED_MODE_ENABLED, enabled, userId); 123 } 124 125 126 /** 127 * Queries taps app to exit config from Settings provider. 128 * 129 * @return enable or disable taps app exit. 130 */ getSettingsTapsAppToExit(ContentResolver resolver, int userId)131 public boolean getSettingsTapsAppToExit(ContentResolver resolver, int userId) { 132 return Settings.Secure.getIntForUser(resolver, 133 Settings.Secure.TAPS_APP_TO_EXIT, 1, userId) == 1; 134 } 135 136 /** 137 * Queries timeout value from Settings provider. Default is. 138 * {@link OneHandedSettingsUtil#ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS} 139 * 140 * @return timeout value in seconds. 141 */ getSettingsOneHandedModeTimeout(ContentResolver resolver, int userId)142 public @OneHandedTimeout int getSettingsOneHandedModeTimeout(ContentResolver resolver, 143 int userId) { 144 return Settings.Secure.getIntForUser(resolver, 145 Settings.Secure.ONE_HANDED_MODE_TIMEOUT, ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS, 146 userId); 147 } 148 149 /** 150 * Returns whether swipe bottom to notification gesture enabled or not. 151 */ getSettingsSwipeToNotificationEnabled(ContentResolver resolver, int userId)152 public boolean getSettingsSwipeToNotificationEnabled(ContentResolver resolver, int userId) { 153 return Settings.Secure.getIntForUser(resolver, 154 Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0, userId) == 1; 155 } 156 157 158 /** 159 * Queries tutorial shown counts from Settings provider. Default is 0. 160 * 161 * @return counts tutorial shown counts. 162 */ getTutorialShownCounts(ContentResolver resolver, int userId)163 public int getTutorialShownCounts(ContentResolver resolver, int userId) { 164 return Settings.Secure.getIntForUser(resolver, 165 Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0, userId); 166 } 167 168 /** 169 * Queries one-handed mode shortcut enabled in settings or not. 170 * 171 * @return true if user enabled one-handed shortcut in settings, false otherwise. 172 */ getShortcutEnabled(ContentResolver resolver, int userId)173 public boolean getShortcutEnabled(ContentResolver resolver, int userId) { 174 final String targets = Settings.Secure.getStringForUser(resolver, 175 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId); 176 return TextUtils.isEmpty(targets) ? false : targets.contains(ONE_HANDED_MODE_TARGET_NAME); 177 } 178 179 /** 180 * Sets tutorial shown counts. 181 * 182 * @return true if the value was set, false on database errors. 183 */ setTutorialShownCounts(ContentResolver resolver, int shownCounts, int userId)184 public boolean setTutorialShownCounts(ContentResolver resolver, int shownCounts, int userId) { 185 return Settings.Secure.putIntForUser(resolver, 186 Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, shownCounts, userId); 187 } 188 189 /** 190 * Sets one handed activated or not to notify state for shortcut. 191 * 192 * @return true if one handed mode is activated. 193 */ getOneHandedModeActivated(ContentResolver resolver, int userId)194 public boolean getOneHandedModeActivated(ContentResolver resolver, int userId) { 195 return Settings.Secure.getIntForUser(resolver, 196 Settings.Secure.ONE_HANDED_MODE_ACTIVATED, 0, userId) == 1; 197 } 198 199 /** 200 * Sets one handed activated or not to notify state for shortcut. 201 * 202 * @return true if the value was set, false on database errors. 203 */ setOneHandedModeActivated(ContentResolver resolver, int state, int userId)204 public boolean setOneHandedModeActivated(ContentResolver resolver, int state, int userId) { 205 return Settings.Secure.putIntForUser(resolver, 206 Settings.Secure.ONE_HANDED_MODE_ACTIVATED, state, userId); 207 } 208 209 /** 210 * Obtains one-handed mode transition duration from resource config. 211 * 212 * @return durationMs The duration in milli-seconds 213 */ getTransitionDuration(Context context)214 public int getTransitionDuration(Context context) { 215 return context.getResources().getInteger( 216 R.integer.config_one_handed_translate_animation_duration); 217 } 218 219 /** 220 * Obtains one-handed mode offset fraction from resource config. 221 * 222 * @return fraction The fraction of offset of the whole screen. 223 */ getTranslationFraction(Context context)224 public float getTranslationFraction(Context context) { 225 return context.getResources().getFraction(R.fraction.config_one_handed_offset, 1, 1); 226 } 227 dump(PrintWriter pw, String prefix, ContentResolver resolver, int userId)228 void dump(PrintWriter pw, String prefix, ContentResolver resolver, 229 int userId) { 230 final String innerPrefix = " "; 231 pw.println(TAG); 232 pw.print(innerPrefix + "isOneHandedModeEnable="); 233 pw.println(getSettingsOneHandedModeEnabled(resolver, userId)); 234 pw.print(innerPrefix + "oneHandedTimeOut="); 235 pw.println(getSettingsOneHandedModeTimeout(resolver, userId)); 236 pw.print(innerPrefix + "tapsAppToExit="); 237 pw.println(getSettingsTapsAppToExit(resolver, userId)); 238 pw.print(innerPrefix + "shortcutActivated="); 239 pw.println(getOneHandedModeActivated(resolver, userId)); 240 pw.print(innerPrefix + "tutorialShownCounts="); 241 pw.println(getTutorialShownCounts(resolver, userId)); 242 } 243 OneHandedSettingsUtil()244 public OneHandedSettingsUtil() { 245 } 246 } 247