Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b070e9ed authored by Riley Jones's avatar Riley Jones
Browse files

Fix for a11yManagerService broadcastReceiver ANR

Offloads hard computations to background thread so broadcastReceiver can conclude before timeout

Bug: 333890389
Flag: aconfig android.view.accessibility.Flags.manager_avoid_receiver_timeout ENABLED
Test: add a long Thread.sleep() to the runnable and verify no ANR occurs
Change-Id: I64fe4e54c836a82ad028b908fae691b469a485d7
parent 0136d6e4
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -117,6 +117,16 @@ flag {
    }
}

flag {
    name: "manager_avoid_receiver_timeout"
    namespace: "accessibility"
    description: "Avoid broadcast receiver timeout by offloading potentially slow operations to the background thread."
    bug: "333890389"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "pinch_zoom_zero_min_span"
    namespace: "accessibility"
+49 −37
Original line number Diff line number Diff line
@@ -994,43 +994,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                            "context=" + context + ";intent=" + intent);
                }

                String action = intent.getAction();
                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
                    unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
                    final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
                    if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
                        synchronized (mLock) {
                            restoreEnabledAccessibilityServicesLocked(
                                    intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
                                    intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
                                            0));
                        }
                    } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
                        synchronized (mLock) {
                            restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
                                    intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
                                            0));
                        }
                    } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
                        synchronized (mLock) {
                            restoreAccessibilityButtonTargetsLocked(
                                    intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
                        }
                    } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
                        if (!android.view.accessibility.Flags.a11yQsShortcut()) {
                            return;
                        }
                        restoreAccessibilityQsTargets(
                                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
                    }
                if (com.android.server.accessibility.Flags.managerAvoidReceiverTimeout()) {
                    BackgroundThread.getHandler().post(() -> processBroadcast(intent));
                } else {
                    processBroadcast(intent);
                }
            }
        }, UserHandle.ALL, intentFilter, null, null);
@@ -2033,6 +2000,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        mA11yWindowManager.onTouchInteractionEnd();
    }

    private void processBroadcast(Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_USER_SWITCHED.equals(action)) {
            switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
        } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
            unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
        } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
            removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
        } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
            restoreSetting(intent);
        }
    }

    @VisibleForTesting
    void switchUser(int userId) {
        mMagnificationController.updateUserIdIfNeeded(userId);
@@ -2125,6 +2105,38 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        getMagnificationController().onUserRemoved(userId);
    }

    private void restoreSetting(Intent intent) {
        final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
        if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
            synchronized (mLock) {
                restoreEnabledAccessibilityServicesLocked(
                        intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
                        intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
                        intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
                                0));
            }
        } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
            synchronized (mLock) {
                restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
                        intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
                        intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
                                0));
            }
        } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
            synchronized (mLock) {
                restoreAccessibilityButtonTargetsLocked(
                        intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
                        intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
            }
        } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
            if (!android.view.accessibility.Flags.a11yQsShortcut()) {
                return;
            }
            restoreAccessibilityQsTargets(
                    intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
        }
    }

    // Called only during settings restore; currently supports only the owner user
    // TODO: http://b/22388012
    void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting,