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 
43 import android.content.ComponentName;
44 import android.content.Context;
45 import android.provider.Settings;
46 import android.view.accessibility.AccessibilityManager;
47 import android.view.accessibility.AccessibilityManager.ShortcutType;
48 
49 import com.android.internal.util.FrameworkStatsLog;
50 
51 /** Methods for logging accessibility states. */
52 public final class AccessibilityStatsLogUtils {
53     private static final int UNKNOWN_STATUS =
54             ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__UNKNOWN;
55 
AccessibilityStatsLogUtils()56     private AccessibilityStatsLogUtils() {}
57 
58     /**
59      * Logs accessibility feature name that is assigned to the given {@code shortcutType}.
60      * Calls this when clicking the shortcut {@link AccessibilityManager#ACCESSIBILITY_BUTTON} or
61      * {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY}.
62      *
63      * @param context context used to retrieve the {@link Settings} provider
64      * @param componentName component name of the accessibility feature
65      * @param shortcutType  accessibility shortcut type
66      */
logAccessibilityShortcutActivated(Context context, ComponentName componentName, @ShortcutType int shortcutType)67     public static void logAccessibilityShortcutActivated(Context context,
68             ComponentName componentName, @ShortcutType int shortcutType) {
69         logAccessibilityShortcutActivatedInternal(componentName,
70                 convertToLoggingShortcutType(context, shortcutType), UNKNOWN_STATUS);
71     }
72 
73     /**
74      * Logs accessibility feature name that is assigned to the given {@code shortcutType} and the
75      * {@code serviceEnabled} status.
76      * Calls this when clicking the shortcut {@link AccessibilityManager#ACCESSIBILITY_BUTTON}
77      * or {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY}.
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      * @param serviceEnabled {@code true} if the service is enabled
83      */
logAccessibilityShortcutActivated(Context context, ComponentName componentName, @ShortcutType int shortcutType, boolean serviceEnabled)84     public static void logAccessibilityShortcutActivated(Context context,
85             ComponentName componentName, @ShortcutType int shortcutType, boolean serviceEnabled) {
86         logAccessibilityShortcutActivatedInternal(componentName,
87                 convertToLoggingShortcutType(context, shortcutType),
88                 convertToLoggingServiceStatus(serviceEnabled));
89     }
90 
91     /**
92      * Logs accessibility feature name that is assigned to the given {@code loggingShortcutType} and
93      * {@code loggingServiceStatus} code.
94      *
95      * @param componentName        component name of the accessibility feature
96      * @param loggingShortcutType  accessibility shortcut type for logging. 0 denotes
97      *                             unknown_type, 1 denotes accessibility button, 2 denotes volume
98      *                             key, 3 denotes triple tap on the screen, 4 denotes long press on
99      *                             accessibility button, 5 denotes accessibility floating menu.
100      * @param loggingServiceStatus The service status code for logging. 0 denotes unknown_status, 1
101      *                             denotes enabled, 2 denotes disabled.
102      */
logAccessibilityShortcutActivatedInternal(ComponentName componentName, int loggingShortcutType, int loggingServiceStatus)103     private static void logAccessibilityShortcutActivatedInternal(ComponentName componentName,
104             int loggingShortcutType, int loggingServiceStatus) {
105         FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED,
106                 componentName.flattenToString(), loggingShortcutType, loggingServiceStatus);
107     }
108 
109     /**
110      * Logs magnification that is assigned to the triple tap shortcut. Calls this when triggering
111      * the magnification triple tap shortcut.
112      */
logMagnificationTripleTap(boolean enabled)113     public static void logMagnificationTripleTap(boolean enabled) {
114         FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED,
115                 MAGNIFICATION_COMPONENT_NAME.flattenToString(),
116                 ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TRIPLE_TAP,
117                 convertToLoggingServiceStatus(enabled));
118     }
119 
120     /**
121      * Logs accessibility feature name that is assigned to the long pressed accessibility button
122      * shortcut. Calls this when clicking the long pressed accessibility button shortcut.
123      *
124      * @param componentName The component name of the accessibility feature.
125      */
logAccessibilityButtonLongPressStatus(ComponentName componentName)126     public static void logAccessibilityButtonLongPressStatus(ComponentName componentName) {
127         FrameworkStatsLog.write(FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED,
128                 componentName.flattenToString(),
129                 ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON_LONG_PRESS,
130                 UNKNOWN_STATUS);
131     }
132 
133     /**
134      * Logs the magnification activated mode and its duration of the usage.
135      * Calls this when the magnification is disabled.
136      *
137      * @param mode The activated magnification mode.
138      * @param duration The duration in milliseconds during the magnification is activated.
139      */
logMagnificationUsageState(int mode, long duration)140     public static void logMagnificationUsageState(int mode, long duration) {
141         FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_USAGE_REPORTED,
142                 convertToLoggingMagnificationMode(mode),
143                 duration);
144     }
145 
146     /**
147      * Logs the activated mode of the magnification when the IME window is shown on the screen.
148      * Calls this when the magnification is enabled and the IME window is shown on the screen.
149      *
150      * @param mode The activated magnification mode.
151      */
logMagnificationModeWithImeOn(int mode)152     public static void logMagnificationModeWithImeOn(int mode) {
153         FrameworkStatsLog.write(FrameworkStatsLog.MAGNIFICATION_MODE_WITH_IME_ON_REPORTED,
154                 convertToLoggingMagnificationMode(mode));
155     }
156 
isAccessibilityFloatingMenuEnabled(Context context)157     private static boolean isAccessibilityFloatingMenuEnabled(Context context) {
158         return Settings.Secure.getInt(context.getContentResolver(),
159                 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, /* def= */ -1)
160                 == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
161     }
162 
isAccessibilityGestureEnabled(Context context)163     private static boolean isAccessibilityGestureEnabled(Context context) {
164         return Settings.Secure.getInt(context.getContentResolver(),
165                 Settings.Secure.ACCESSIBILITY_BUTTON_MODE, /* def= */ -1)
166                 == ACCESSIBILITY_BUTTON_MODE_GESTURE;
167     }
168 
convertToLoggingShortcutType(Context context, @ShortcutType int shortcutType)169     private static int convertToLoggingShortcutType(Context context,
170             @ShortcutType int shortcutType) {
171         switch (shortcutType) {
172             case ACCESSIBILITY_BUTTON:
173                 if (isAccessibilityFloatingMenuEnabled(context)) {
174                     return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_FLOATING_MENU;
175                 } else if (isAccessibilityGestureEnabled(context)) {
176                     return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_GESTURE;
177                 } else {
178                     return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_BUTTON;
179                 }
180             case ACCESSIBILITY_SHORTCUT_KEY:
181                 return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY;
182         }
183         return ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__UNKNOWN_TYPE;
184     }
185 
convertToLoggingServiceStatus(boolean enabled)186     private static int convertToLoggingServiceStatus(boolean enabled) {
187         return enabled ? ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__ENABLED
188                 : ACCESSIBILITY_SHORTCUT_REPORTED__SERVICE_STATUS__DISABLED;
189     }
190 
convertToLoggingMagnificationMode(int mode)191     private static int convertToLoggingMagnificationMode(int mode) {
192         switch (mode) {
193             case ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN:
194                 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_FULL_SCREEN;
195             case ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW:
196                 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_WINDOW;
197             case ACCESSIBILITY_MAGNIFICATION_MODE_ALL:
198                 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_ALL;
199 
200             default:
201                 return MAGNIFICATION_USAGE_REPORTED__ACTIVATED_MODE__MAGNIFICATION_UNKNOWN_MODE;
202         }
203     }
204 }
205