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