Fix the initialization issue in AccessibilityManager

There is an issue when the AccessibilityManagerService receives the onSomePackageChange callback before the UserSwitch signal. The service would be marked as initialized, but it would not load the services when the switch user signal would be later received.

This patch ensures the onSomePackageChanged is handled only after the service is initialized.


Bug: 340927041
Test: atest AccessibilityEndToEndTest
Test: AccessibilityManagerServiceTest in presubmit

Change-Id: I99fba0d08cb0ca5f2e24c104d1a7735109955683
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index 1c57dd3..9353150 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -220,3 +220,13 @@
     description: "Feature allows users to change color correction saturation for daltonizer."
     bug: "322829049"
 }
+
+flag {
+    name: "skip_package_change_before_user_switch"
+    namespace: "accessibility"
+    description: "Skip onSomePackageChanged callback if the SwitchUser signal is not received yet."
+    bug: "340927041"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 053a1a7..20b727c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -588,6 +588,15 @@
         return Thread.holdsLock(mLock);
     }
 
+    /**
+     * Returns if the service is initialized.
+     *
+     * The service is considered initialized when the user switch happened.
+     */
+    private boolean isServiceInitializedLocked() {
+        return mInitialized;
+    }
+
     @Override
     public int getCurrentUserIdLocked() {
         return mCurrentUserId;
@@ -6234,6 +6243,15 @@
                 if (userId != mManagerService.getCurrentUserIdLocked()) {
                     return;
                 }
+
+                // Only continue setting up the packages if the service has been initialized.
+                // See: b/340927041
+                if (Flags.skipPackageChangeBeforeUserSwitch()
+                        && !mManagerService.isServiceInitializedLocked()) {
+                    Slog.w(LOG_TAG,
+                            "onSomePackagesChanged: service not initialized, skip the callback.");
+                    return;
+                }
                 mManagerService.onSomePackagesChangedLocked(parsedAccessibilityServiceInfos,
                         parsedAccessibilityShortcutInfos);
             }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index f971f0e..4e8c755 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -923,6 +923,8 @@
         ResolveInfo resolveInfo1 = installedService1.getResolveInfo();
         AccessibilityServiceInfo installedService2 =
                 mA11yms.getCurrentUserState().mInstalledServices.getLast();
+        // Invokes client change to trigger onUserStateChanged.
+        mA11yms.onClientChangeLocked(false);
 
         // Disables `installedService2`
         when(mMockPackageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt()))