diff options
| author | 2023-12-13 00:16:24 +0000 | |
|---|---|---|
| committer | 2023-12-13 00:16:24 +0000 | |
| commit | 75d57fa8f7b6610c4d15ff0fdc401ce51b718cdf (patch) | |
| tree | 6eaf34e59f031c0d0294257eb914effadcab817f | |
| parent | fbc5e550c4fdee76a8d1105b965f3adfe0c3bc21 (diff) | |
| parent | d2818e217bf840ccde761f4acb7b1cdf5c50f8da (diff) | |
Merge "phonewm: refactor Talkback shortcut logic into a controller" into main
3 files changed, 154 insertions, 81 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 4e5dc1dd76fa..fed32e59c846 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -76,7 +76,6 @@ import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED; import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY; -import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; @@ -97,7 +96,6 @@ import static com.android.server.wm.WindowManagerPolicyProto.SCREEN_ON_FULLY; import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE; import android.accessibilityservice.AccessibilityService; -import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -124,7 +122,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -204,8 +201,6 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.accessibility.AccessibilityShortcutController; -import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; -import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.AssistUtils; import com.android.internal.display.BrightnessUtils; @@ -385,8 +380,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { public static final String TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD = "waitForAllWindowsDrawn"; - private static final String TALKBACK_LABEL = "TalkBack"; - private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800; /** @@ -477,6 +470,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** Controller that supports enabling an AccessibilityService by holding down the volume keys */ private AccessibilityShortcutController mAccessibilityShortcutController; + private TalkbackShortcutController mTalkbackShortcutController; + boolean mSafeMode; // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. @@ -1602,19 +1597,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_INPUT) { Slog.d(TAG, "Executing stem primary triple press action behavior."); } - - if (Settings.System.getIntForUser(mContext.getContentResolver(), - Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, - /* def= */ 0, UserHandle.USER_CURRENT) == 1) { - /** Toggle talkback begin */ - ComponentName componentName = getTalkbackComponent(); - if (componentName != null && toggleTalkBack(componentName)) { - /** log stem triple press telemetry if it's a talkback enabled event */ - logStemTriplePressAccessibilityTelemetry(componentName); - } - performHapticFeedback(HapticFeedbackConstants.CONFIRM, /* always = */ false, - /* reason = */ "Stem primary - Triple Press - Toggle Accessibility"); - /** Toggle talkback end */ + mTalkbackShortcutController.toggleTalkback(mCurrentUserId); + if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) { + performHapticFeedback(HapticFeedbackConstants.CONFIRM, /* always = */ + false, /* reason = */ + "Stem primary - Triple Press - Toggle Accessibility"); } break; } @@ -1640,61 +1627,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } /** - * A function that toggles talkback service - * - * @return {@code true} if talkback is enabled, {@code false} if talkback is disabled - */ - private boolean toggleTalkBack(ComponentName componentName) { - final Set<ComponentName> enabledServices = - AccessibilityUtils.getEnabledServicesFromSettings(mContext, mCurrentUserId); - - boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName); - AccessibilityUtils.setAccessibilityServiceState(mContext, componentName, - !isTalkbackAlreadyEnabled); - /** if isTalkbackAlreadyEnabled is true, then it's a disabled event so return false - * and if isTalkbackAlreadyEnabled is false, return true as it's an enabled event */ - return !isTalkbackAlreadyEnabled; - } - - /** - * A function that logs stem triple press accessibility telemetry - * If the user setup (Oobe) is not completed, set the - * WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE - * setting which will be later logged via Settings Snapshot - * else, log ACCESSIBILITY_SHORTCUT_REPORTED atom - */ - private void logStemTriplePressAccessibilityTelemetry(ComponentName componentName) { - if (!AccessibilityUtils.isUserSetupCompleted(mContext)) { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, 1); - } else { - AccessibilityStatsLogUtils.logAccessibilityShortcutActivated(mContext, componentName, - ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE, - /* serviceEnabled= */ true); - } - } - - private ComponentName getTalkbackComponent() { - AccessibilityManager accessibilityManager = mContext.getSystemService( - AccessibilityManager.class); - List<AccessibilityServiceInfo> serviceInfos = - accessibilityManager.getInstalledAccessibilityServiceList(); - - for (AccessibilityServiceInfo service : serviceInfos) { - final ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo; - if (isTalkback(serviceInfo)) { - return new ComponentName(serviceInfo.packageName, serviceInfo.name); - } - } - return null; - } - - private boolean isTalkback(ServiceInfo info) { - String label = info.loadLabel(mPackageManager).toString(); - return label.equals(TALKBACK_LABEL); - } - - /** * Load most recent task (expect current task) and bring it to the front. */ void performStemPrimaryDoublePressSwitchToRecentTask() { @@ -1731,12 +1663,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TRIPLE_PRESS_PRIMARY_NOTHING: break; case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY: - if (Settings.System.getIntForUser( - mContext.getContentResolver(), - Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, - /* def= */ 0, - UserHandle.USER_CURRENT) - == 1) { + if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) { return 3; } break; @@ -2252,6 +2179,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { ButtonOverridePermissionChecker getButtonOverridePermissionChecker() { return new ButtonOverridePermissionChecker(); } + + TalkbackShortcutController getTalkbackShortcutController() { + return new TalkbackShortcutController(mContext); + } } /** {@inheritDoc} */ @@ -2515,6 +2446,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardDrawnTimeout = mContext.getResources().getInteger( com.android.internal.R.integer.config_keyguardDrawnTimeout); mKeyguardDelegate = injector.getKeyguardServiceDelegate(); + mTalkbackShortcutController = injector.getTalkbackShortcutController(); initKeyCombinationRules(); initSingleKeyGestureRules(injector.getLooper()); mButtonOverridePermissionChecker = injector.getButtonOverridePermissionChecker(); diff --git a/services/core/java/com/android/server/policy/TalkbackShortcutController.java b/services/core/java/com/android/server/policy/TalkbackShortcutController.java new file mode 100644 index 000000000000..906da2f4cdf5 --- /dev/null +++ b/services/core/java/com/android/server/policy/TalkbackShortcutController.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.policy; + +import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; +import android.os.UserHandle; +import android.provider.Settings; +import android.view.accessibility.AccessibilityManager; + +import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; +import com.android.internal.accessibility.util.AccessibilityUtils; +import com.android.internal.annotations.VisibleForTesting; + +import java.util.List; +import java.util.Set; + +/** + * This class controls talkback shortcut related operations such as toggling, quering and + * logging. + */ +@VisibleForTesting +class TalkbackShortcutController { + private static final String TALKBACK_LABEL = "TalkBack"; + private final Context mContext; + private final PackageManager mPackageManager; + + TalkbackShortcutController(Context context) { + mContext = context; + mPackageManager = mContext.getPackageManager(); + } + + /** + * A function that toggles talkback service. + * + * @return talkback state after toggle. {@code true} if talkback is enabled, {@code false} if + * talkback is disabled + */ + boolean toggleTalkback(int userId) { + final Set<ComponentName> enabledServices = + AccessibilityUtils.getEnabledServicesFromSettings(mContext, userId); + ComponentName componentName = getTalkbackComponent(); + boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName); + + if (isTalkBackShortcutGestureEnabled()) { + isTalkbackAlreadyEnabled = !isTalkbackAlreadyEnabled; + AccessibilityUtils.setAccessibilityServiceState(mContext, componentName, + isTalkbackAlreadyEnabled); + + // log stem triple press telemetry if it's a talkback enabled event. + if (componentName != null && isTalkbackAlreadyEnabled) { + logStemTriplePressAccessibilityTelemetry(componentName); + } + } + return isTalkbackAlreadyEnabled; + } + + private ComponentName getTalkbackComponent() { + AccessibilityManager accessibilityManager = mContext.getSystemService( + AccessibilityManager.class); + List<AccessibilityServiceInfo> serviceInfos = + accessibilityManager.getInstalledAccessibilityServiceList(); + + for (AccessibilityServiceInfo service : serviceInfos) { + final ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo; + if (isTalkback(serviceInfo)) { + return new ComponentName(serviceInfo.packageName, serviceInfo.name); + } + } + return null; + } + + boolean isTalkBackShortcutGestureEnabled() { + return Settings.System.getIntForUser(mContext.getContentResolver(), + Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED, + /* def= */ 0, UserHandle.USER_CURRENT) == 1; + } + + /** + * A function that logs stem triple press accessibility telemetry. If the user setup (Oobe) + * is not completed, set the WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE setting which + * will be later logged via Settings Snapshot else, log ACCESSIBILITY_SHORTCUT_REPORTED atom + */ + private void logStemTriplePressAccessibilityTelemetry(ComponentName componentName) { + if (!AccessibilityUtils.isUserSetupCompleted(mContext)) { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED_DURING_OOBE, 1); + return; + } + AccessibilityStatsLogUtils.logAccessibilityShortcutActivated(mContext, + componentName, + ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__A11Y_WEAR_TRIPLE_PRESS_GESTURE, + /* serviceEnabled= */ true); + } + + private boolean isTalkback(ServiceInfo info) { + return TALKBACK_LABEL.equals(info.loadLabel(mPackageManager).toString()); + } +} diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java index d057226836a3..48d3503fe43b 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -172,6 +172,25 @@ class TestPhoneWindowManager { private HandlerThread mHandlerThread; private Handler mHandler; + private boolean mIsTalkBackEnabled; + + class TestTalkbackShortcutController extends TalkbackShortcutController { + TestTalkbackShortcutController(Context context) { + super(context); + } + + @Override + boolean toggleTalkback(int currentUserId) { + mIsTalkBackEnabled = !mIsTalkBackEnabled; + return mIsTalkBackEnabled; + } + + @Override + boolean isTalkBackShortcutGestureEnabled() { + return true; + } + } + private class TestInjector extends PhoneWindowManager.Injector { TestInjector(Context context, WindowManagerPolicy.WindowManagerFuncs funcs) { super(context, funcs, mTestLooper.getLooper()); @@ -197,6 +216,10 @@ class TestPhoneWindowManager { PhoneWindowManager.ButtonOverridePermissionChecker getButtonOverridePermissionChecker() { return mButtonOverridePermissionChecker; } + + TalkbackShortcutController getTalkbackShortcutController() { + return new TestTalkbackShortcutController(mContext); + } } TestPhoneWindowManager(Context context, boolean supportSettingsUpdate) { |