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 */ logMagnificationUsageState(int mode, long duration)153 public static void logMagnificationUsageState(int mode, long duration) { 154 FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED, 155 convertToLoggingMagnificationMode(mode), 156 duration); 157 } 158 159 /** 160 * Logs the activated mode of the magnification when the IME window is shown on the screen. 161 * Calls this when the magnification is enabled and the IME window is shown on the screen. 162 * 163 * @param mode The activated magnification mode. 164 */ logMagnificationModeWithImeOn(int mode)165 public static void logMagnificationModeWithImeOn(int mode) { 166 FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_MODE_WITH_IME_ON_REPORTED, 167 convertToLoggingMagnificationMode(mode)); 168 } 169 170 /** 171 * Logs the duration for the window magnifier's following typing focus session. 172 * 173 * @param duration The duration of a triple-tap-and-hold activation session. 174 */ logMagnificationFollowTypingFocusSession(long duration)175 public static void logMagnificationFollowTypingFocusSession(long duration) { 176 FrameworkStatsLog.write( 177 FrameworkStatsLog.MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED, 178 duration); 179 } 180 181 /** 182 * Logs the duration for the magnification session which is activated by the triple tap and 183 * hold gesture. 184 * 185 * @param duration The duration of a triple-tap-and-hold activation session. 186 */ logMagnificationTripleTapAndHoldSession(long duration)187 public static void logMagnificationTripleTapAndHoldSession(long duration) { 188 FrameworkStatsLog.write( 189 FrameworkStatsLog.MAGNIFICATION_TRIPLE_TAP_AND_HOLD_ACTIVATED_SESSION_REPORTED, 190 duration); 191 } 192 193 /** 194 * Logs the warning status of the non-a11yTool service. Calls this when the warning status is 195 * changed. 196 * 197 * @param packageName The package name of the non-a11yTool service 198 * @param status The warning status of the non-a11yTool service, it should be one of 199 * {@code ACCESSIBILITY_PRIVACY_WARNING_STATUS_SHOWN},{@code 200 * ACCESSIBILITY_PRIVACY_WARNING_STATUS_CLICKED} and {@code 201 * ACCESSIBILITY_PRIVACY_WARNING_STATUS_SERVICE_DISABLED} 202 * @param durationMillis The duration in milliseconds between current and previous status 203 */ logNonA11yToolServiceWarningReported(String packageName, int status, long durationMillis)204 public static void logNonA11yToolServiceWarningReported(String packageName, int status, 205 long durationMillis) { 206 FrameworkStatsLog.write(FrameworkStatsLog.NON_A11Y_TOOL_SERVICE_WARNING_REPORT, 207 packageName, status, durationMillis); 208 } 209 isAccessibilityFloatingMenuEnabled(Context context)210 private static boolean isAccessibilityFloatingMenuEnabled(Context context) { 211 return Settings.Secure.getInt(context.getContentResolver(), 212 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, /* def= */ -1) 213 == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; 214 } 215 isAccessibilityGestureEnabled(Context context)216 private static boolean isAccessibilityGestureEnabled(Context context) { 217 return Settings.Secure.getInt(context.getContentResolver(), 218 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, /* def= */ -1) 219 == ACCESSIBILITY_BUTTON_MODE_GESTURE; 220 } 221 convertToLoggingShortcutType(Context context, @ShortcutType int shortcutType)222 private static int convertToLoggingShortcutType(Context context, 223 @ShortcutType int shortcutType) { 224 switch (shortcutType) { 225 case ACCESSIBILITY_BUTTON: 226 if (isAccessibilityFloatingMenuEnabled(context)) { 227 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_FLOATING_MENU; 228 } else if (isAccessibilityGestureEnabled(context)) { 229 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_GESTURE; 230 } else { 231 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON; 232 } 233 case ACCESSIBILITY_SHORTCUT_KEY: 234 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY; 235 } 236 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__UNKNOWN_TYPE; 237 } 238 convertToLoggingServiceStatus(boolean enabled)239 private static int convertToLoggingServiceStatus(boolean enabled) { 240 return enabled ? ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__ENABLED 241 : ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__DISABLED; 242 } 243 convertToLoggingMagnificationMode(int mode)244 private static int convertToLoggingMagnificationMode(int mode) { 245 switch (mode) { 246 case ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN: 247 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_FULL_SCREEN; 248 case ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW: 249 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_WINDOW; 250 case ACCESSIBILITY_MAGNIFICATION_MODE_ALL: 251 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_ALL; 252 253 default: 254 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_UNKNOWN_MODE; 255 } 256 } 257 } 258