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.internal.accessibility.util; 18 19 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; 20 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE; 21 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL; 22 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN; 23 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; 24 25 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME; 26 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE; 27 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE; 28 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS; 29 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; 30 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__DISABLED; 31 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__ENABLED; 32 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__UNKNOWN; 33 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON; 34 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON_LONG_PRESS; 35 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_FLOATING_MENU; 36 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_GESTURE; 37 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__QUICK_SETTINGS; 38 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TRIPLE_TAP; 39 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TWO_FINGER_TRIPLE_TAP; 40 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__UNKNOWN_TYPE; 41 import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY; 42 import static com.android.internal.util.FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_ALL; 43 import static com.android.internal.util.FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_FULL_SCREEN; 44 import static com.android.internal.util.FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_UNKNOWN_MODE; 45 import static com.android.internal.util.FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_WINDOW; 46 import static com.android.internal.util.FrameworkStatsLog.NON_A11Y_TOOL_SERVICE_WARNING_REPORTED__STATUS__WARNING_CLICKED; 47 import static com.android.internal.util.FrameworkStatsLog.NON_A11Y_TOOL_SERVICE_WARNING_REPORTED__STATUS__WARNING_SERVICE_DISABLED; 48 import static com.android.internal.util.FrameworkStatsLog.NON_A11Y_TOOL_SERVICE_WARNING_REPORTED__STATUS__WARNING_SHOWN; 49 50 import android.content.ComponentName; 51 import android.content.Context; 52 import android.provider.Settings; 53 54 import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType; 55 import com.android.internal.util.FrameworkStatsLog; 56 57 /** Methods for logging accessibility states. */ 58 public final class AccessibilityStatsLogUtils { 59 /** The status represents an accessibility privacy warning has been shown. */ 60 public static int ACCESSIBILITY_PRIVACY_WARNING_STATUS_SHOWN = 61 NON_A11Y_TOOL_SERVICE_WARNING_REPORTED__STATUS__WARNING_SHOWN; 62 /** The status represents an accessibility privacy warning has been clicked to review. */ 63 public static int ACCESSIBILITY_PRIVACY_WARNING_STATUS_CLICKED = 64 NON_A11Y_TOOL_SERVICE_WARNING_REPORTED__STATUS__WARNING_CLICKED; 65 /** The status represents an accessibility privacy warning service has been disabled. */ 66 public static int ACCESSIBILITY_PRIVACY_WARNING_STATUS_SERVICE_DISABLED = 67 NON_A11Y_TOOL_SERVICE_WARNING_REPORTED__STATUS__WARNING_SERVICE_DISABLED; 68 69 private static final int UNKNOWN_STATUS = 70 ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__UNKNOWN; 71 AccessibilityStatsLogUtils()72 private AccessibilityStatsLogUtils() {} 73 74 /** 75 * Logs accessibility feature name that is assigned to the given {@code shortcutType}. 76 * Calls this when clicking the shortcut {@link ShortcutConstants.UserShortcutType#SOFTWARE} or 77 * {@link ShortcutConstants.UserShortcutType#HARDWARE}. 78 * 79 * @param context context used to retrieve the {@link Settings} provider 80 * @param componentName component name of the accessibility feature 81 * @param shortcutType accessibility shortcut type 82 */ logAccessibilityShortcutActivated(Context context, ComponentName componentName, @UserShortcutType int shortcutType)83 public static void logAccessibilityShortcutActivated(Context context, 84 ComponentName componentName, @UserShortcutType int shortcutType) { 85 logAccessibilityShortcutActivatedInternal(componentName, 86 convertToLoggingShortcutType(context, shortcutType), UNKNOWN_STATUS); 87 } 88 89 /** 90 * Logs accessibility feature name that is assigned to the given {@code shortcutType} and the 91 * {@code serviceEnabled} status. 92 * Calls this when clicking the shortcut {@link ShortcutConstants.UserShortcutType#SOFTWARE} 93 * or {@link ShortcutConstants.UserShortcutType#HARDWARE}. 94 * 95 * @param context context used to retrieve the {@link Settings} provider 96 * @param componentName component name of the accessibility feature 97 * @param shortcutType accessibility shortcut type 98 * @param serviceEnabled {@code true} if the service is enabled 99 */ logAccessibilityShortcutActivated( Context context, ComponentName componentName, @UserShortcutType int shortcutType, boolean serviceEnabled)100 public static void logAccessibilityShortcutActivated( 101 Context context, ComponentName componentName, 102 @UserShortcutType int shortcutType, boolean serviceEnabled) { 103 logAccessibilityShortcutActivatedInternal(componentName, 104 convertToLoggingShortcutType(context, shortcutType), 105 convertToLoggingServiceStatus(serviceEnabled)); 106 } 107 108 /** 109 * Logs accessibility feature name that is assigned to the given {@code loggingShortcutType} and 110 * {@code loggingServiceStatus} code. 111 * 112 * @param componentName component name of the accessibility feature 113 * @param loggingShortcutType accessibility shortcut type for logging. 0 denotes 114 * unknown_type, 1 denotes accessibility button, 2 denotes volume 115 * key, 3 denotes triple tap on the screen, 4 denotes long press on 116 * accessibility button, 5 denotes accessibility floating menu. 117 * @param loggingServiceStatus The service status code for logging. 0 denotes unknown_status, 1 118 * denotes enabled, 2 denotes disabled. 119 */ logAccessibilityShortcutActivatedInternal(ComponentName componentName, int loggingShortcutType, int loggingServiceStatus)120 private static void logAccessibilityShortcutActivatedInternal(ComponentName componentName, 121 int loggingShortcutType, int loggingServiceStatus) { 122 FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED, 123 componentName.flattenToString(), loggingShortcutType, loggingServiceStatus); 124 } 125 126 /** 127 * Logs magnification that is assigned to the triple tap shortcut. Calls this when triggering 128 * the magnification triple tap shortcut. 129 */ logMagnificationTripleTap(boolean enabled)130 public static void logMagnificationTripleTap(boolean enabled) { 131 FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED, 132 MAGNIFICATION_COMPONENT_NAME.flattenToString(), 133 ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TRIPLE_TAP, 134 convertToLoggingServiceStatus(enabled)); 135 } 136 137 /** 138 * Logs magnification that is assigned to the two finger triple tap shortcut. Calls this when 139 * triggering the magnification two finger triple tap shortcut. 140 */ logMagnificationTwoFingerTripleTap(boolean enabled)141 public static void logMagnificationTwoFingerTripleTap(boolean enabled) { 142 FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED, 143 MAGNIFICATION_COMPONENT_NAME.flattenToString(), 144 // jean update 145 ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TWO_FINGER_TRIPLE_TAP, 146 convertToLoggingServiceStatus(enabled)); 147 } 148 149 /** 150 * Logs accessibility feature name that is assigned to the long pressed accessibility button 151 * shortcut. Calls this when clicking the long pressed accessibility button shortcut. 152 * 153 * @param componentName The component name of the accessibility feature. 154 */ logAccessibilityButtonLongPressStatus(ComponentName componentName)155 public static void logAccessibilityButtonLongPressStatus(ComponentName componentName) { 156 FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED, 157 componentName.flattenToString(), 158 ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON_LONG_PRESS, 159 UNKNOWN_STATUS); 160 } 161 162 /** 163 * Logs the magnification activated mode and its duration of the usage. 164 * Calls this when the magnification is disabled. 165 * 166 * @param mode The activated magnification mode. 167 * @param duration The duration in milliseconds during the magnification is activated. 168 * @param scale The last magnification scale for the activation 169 */ logMagnificationUsageState(int mode, long duration, float scale)170 public static void logMagnificationUsageState(int mode, long duration, float scale) { 171 FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED, 172 convertToLoggingMagnificationMode(mode), 173 duration, 174 convertToLoggingMagnificationScale(scale)); 175 } 176 177 /** 178 * Logs the activated mode of the magnification when the IME window is shown on the screen. 179 * Calls this when the magnification is enabled and the IME window is shown on the screen. 180 * 181 * @param mode The activated magnification mode. 182 */ logMagnificationModeWithImeOn(int mode)183 public static void logMagnificationModeWithImeOn(int mode) { 184 FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_MODE_WITH_IME_ON_REPORTED, 185 convertToLoggingMagnificationMode(mode)); 186 } 187 188 /** 189 * Logs the duration for the window magnifier's following typing focus session. 190 * 191 * @param duration The duration of a triple-tap-and-hold activation session. 192 */ logMagnificationFollowTypingFocusSession(long duration)193 public static void logMagnificationFollowTypingFocusSession(long duration) { 194 FrameworkStatsLog.write( 195 FrameworkStatsLog.MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED, 196 duration); 197 } 198 199 /** 200 * Logs the duration for the magnification session which is activated by the triple tap and 201 * hold gesture. 202 * 203 * @param duration The duration of a triple-tap-and-hold activation session. 204 */ logMagnificationTripleTapAndHoldSession(long duration)205 public static void logMagnificationTripleTapAndHoldSession(long duration) { 206 FrameworkStatsLog.write( 207 FrameworkStatsLog.MAGNIFICATION_TRIPLE_TAP_AND_HOLD_ACTIVATED_SESSION_REPORTED, 208 duration); 209 } 210 211 /** 212 * Logs the warning status of the non-a11yTool service. Calls this when the warning status is 213 * changed. 214 * 215 * @param packageName The package name of the non-a11yTool service 216 * @param status The warning status of the non-a11yTool service, it should be one of 217 * {@code ACCESSIBILITY_PRIVACY_WARNING_STATUS_SHOWN},{@code 218 * ACCESSIBILITY_PRIVACY_WARNING_STATUS_CLICKED} and {@code 219 * ACCESSIBILITY_PRIVACY_WARNING_STATUS_SERVICE_DISABLED} 220 * @param durationMillis The duration in milliseconds between current and previous status 221 */ logNonA11yToolServiceWarningReported(String packageName, int status, long durationMillis)222 public static void logNonA11yToolServiceWarningReported(String packageName, int status, 223 long durationMillis) { 224 FrameworkStatsLog.write(FrameworkStatsLog.NON_A11Y_TOOL_SERVICE_WARNING_REPORT, 225 packageName, status, durationMillis); 226 } 227 isAccessibilityFloatingMenuEnabled(Context context)228 private static boolean isAccessibilityFloatingMenuEnabled(Context context) { 229 return Settings.Secure.getInt(context.getContentResolver(), 230 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, /* def= */ -1) 231 == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; 232 } 233 isAccessibilityGestureEnabled(Context context)234 private static boolean isAccessibilityGestureEnabled(Context context) { 235 return Settings.Secure.getInt(context.getContentResolver(), 236 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, /* def= */ -1) 237 == ACCESSIBILITY_BUTTON_MODE_GESTURE; 238 } 239 convertToLoggingShortcutType(Context context, @UserShortcutType int shortcutType)240 private static int convertToLoggingShortcutType(Context context, 241 @UserShortcutType int shortcutType) { 242 switch (shortcutType) { 243 case SOFTWARE: 244 if (isAccessibilityFloatingMenuEnabled(context)) { 245 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_FLOATING_MENU; 246 } else if (isAccessibilityGestureEnabled(context)) { 247 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_GESTURE; 248 } else { 249 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON; 250 } 251 case GESTURE: 252 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_GESTURE; 253 case HARDWARE: 254 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY; 255 case QUICK_SETTINGS: 256 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__QUICK_SETTINGS; 257 } 258 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__UNKNOWN_TYPE; 259 } 260 convertToLoggingServiceStatus(boolean enabled)261 private static int convertToLoggingServiceStatus(boolean enabled) { 262 return enabled ? ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__ENABLED 263 : ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__DISABLED; 264 } 265 convertToLoggingMagnificationMode(int mode)266 private static int convertToLoggingMagnificationMode(int mode) { 267 switch (mode) { 268 case ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN: 269 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_FULL_SCREEN; 270 case ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW: 271 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_WINDOW; 272 case ACCESSIBILITY_MAGNIFICATION_MODE_ALL: 273 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_ALL; 274 275 default: 276 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_UNKNOWN_MODE; 277 } 278 } 279 convertToLoggingMagnificationScale(float scale)280 private static int convertToLoggingMagnificationScale(float scale) { 281 // per b/269366674, we make every 10% a bucket for both privacy and readability concern. 282 // For example 283 // 1. both 2.30f(230%) and 2.36f(236%) would return 230 as bucket id. 284 // 2. bucket id 370 means scale range in [370%, 379%] 285 return ((int) (scale * 10)) * 10; 286 } 287 } 288