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