Fixed VIMS to postpone ASSISTANT rule change on pre-created users.

RoleService should not be calling onRoleHoldersChanged() on
pre-created users, but that behavior cannot be changed because its
implemented by a system app, and pre-created users APIs are hidden.

To test it:

$ adb shell pm create-user --pre-create-only  --guest
Success: created user id 12

$ adb shell pm create-user --guest ElGuesto
Success: created user id 12

$ adb shell cmd user list --all -v
4 users:

0: id=0, name=Driver, type=system.HEADLESS, flags=ADMIN|INITIALIZED|PRIMARY|SYSTEM (running)
1: id=10, name=Driver, type=full.SECONDARY, flags=ADMIN|FULL|INITIALIZED (running) (current)
2: id=11, name=null, type=full.SECONDARY, flags=FULL|INITIALIZED (pre-created)
3: id=12, name=ElGuesto, type=full.GUEST, flags=EPHEMERAL|FULL|GUEST|INITIALIZED (converted)

$ adb shell am switch-user 12

$ adb shell dumpsys voiceinteraction |egrep '(mBound|implementation)'
  mBound=true mService=android.service.voice.IVoiceInteractionService$Stub$Proxy@77da1bc

$ adb shell cmd voiceinteraction show

Test: see bove
Bug: 216141085
Bug: 226201975

Merged-In: I12d9bb32e144ecf91ee4b452affea0dcea546127
Change-Id: I12d9bb32e144ecf91ee4b452affea0dcea546127
(cherry picked from commit 39acca1d72df6b07bc57806e74f5f0ecfb65ccb1)
diff --git a/core/java/android/service/voice/VoiceInteractionManagerInternal.java b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
index b20dccc..a09b74d 100644
--- a/core/java/android/service/voice/VoiceInteractionManagerInternal.java
+++ b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
@@ -17,6 +17,7 @@
 package android.service.voice;
 
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.os.Bundle;
 import android.os.IBinder;
 
@@ -65,6 +66,13 @@
     public abstract HotwordDetectionServiceIdentity getHotwordDetectionServiceIdentity();
 
     /**
+     * Called by {@code UMS.convertPreCreatedUserIfPossible()} when a new user is not created from
+     * scratched, but converted from the pool of existing pre-created users.
+     */
+    // TODO(b/226201975): remove method once RoleService supports pre-created users
+    public abstract void onPreCreatedUserConversion(@UserIdInt int userId);
+
+    /**
      * Provides the uids of the currently active
      * {@link android.service.voice.HotwordDetectionService} and its owning package. The
      * HotwordDetectionService is an isolated service, so it has a separate uid.
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 409ca03..701ac73c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -88,6 +88,7 @@
 import android.provider.Settings;
 import android.security.GateKeeper;
 import android.service.gatekeeper.IGateKeeperService;
+import android.service.voice.VoiceInteractionManagerInternal;
 import android.stats.devicepolicy.DevicePolicyEnums;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -4252,6 +4253,11 @@
         Binder.withCleanCallingIdentity(() -> {
             mPm.onNewUserCreated(preCreatedUser.id, /* convertedFromPreCreated= */ true);
             dispatchUserAdded(preCreatedUser, token);
+            VoiceInteractionManagerInternal vimi = LocalServices
+                    .getService(VoiceInteractionManagerInternal.class);
+            if (vimi != null) {
+                vimi.onPreCreatedUserConversion(preCreatedUser.id);
+            }
         });
         return preCreatedUser;
     }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index bcfee82..0ce0265 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -102,6 +102,7 @@
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.pm.permission.LegacyPermissionManagerInternal;
 import com.android.server.soundtrigger.SoundTriggerInternal;
+import com.android.server.utils.Slogf;
 import com.android.server.utils.TimingsTraceAndSlog;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
@@ -134,18 +135,21 @@
     private final RemoteCallbackList<IVoiceInteractionSessionListener>
             mVoiceInteractionSessionListeners = new RemoteCallbackList<>();
 
+    // TODO(b/226201975): remove once RoleService supports pre-created users
+    private final ArrayList<UserHandle> mIgnoredPreCreatedUsers = new ArrayList<>();
+
     public VoiceInteractionManagerService(Context context) {
         super(context);
         mContext = context;
         mResolver = context.getContentResolver();
+        mUserManagerInternal = Objects.requireNonNull(
+                LocalServices.getService(UserManagerInternal.class));
         mDbHelper = new DatabaseHelper(context);
         mServiceStub = new VoiceInteractionManagerServiceStub();
         mAmInternal = Objects.requireNonNull(
                 LocalServices.getService(ActivityManagerInternal.class));
         mAtmInternal = Objects.requireNonNull(
                 LocalServices.getService(ActivityTaskManagerInternal.class));
-        mUserManagerInternal = Objects.requireNonNull(
-                LocalServices.getService(UserManagerInternal.class));
 
         LegacyPermissionManagerInternal permissionManagerInternal = LocalServices.getService(
                 LegacyPermissionManagerInternal.class);
@@ -300,6 +304,25 @@
             }
             return hotwordDetectionConnection.mIdentity;
         }
+
+        @Override
+        public void onPreCreatedUserConversion(int userId) {
+            Slogf.d(TAG, "onPreCreatedUserConversion(%d)", userId);
+
+            for (int i = 0; i < mIgnoredPreCreatedUsers.size(); i++) {
+                UserHandle preCreatedUser = mIgnoredPreCreatedUsers.get(i);
+                if (preCreatedUser.getIdentifier() == userId) {
+                    Slogf.d(TAG, "Updating role on pre-created user %d", userId);
+                    mServiceStub.mRoleObserver.onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT,
+                            preCreatedUser);
+                    mIgnoredPreCreatedUsers.remove(i);
+                    return;
+                }
+            }
+            Slogf.w(TAG, "onPreCreatedUserConversion(%d): not available on "
+                    + "mIgnoredPreCreatedUserIds (%s)", userId, mIgnoredPreCreatedUsers);
+        }
+
     }
 
     // implementation entry point and binder service
@@ -317,10 +340,12 @@
         private boolean mTemporarilyDisabled;
 
         private final boolean mEnableService;
+        // TODO(b/226201975): remove reference once RoleService supports pre-created users
+        private final RoleObserver mRoleObserver;
 
         VoiceInteractionManagerServiceStub() {
             mEnableService = shouldEnableService(mContext);
-            new RoleObserver(mContext.getMainExecutor());
+            mRoleObserver = new RoleObserver(mContext.getMainExecutor());
         }
 
         void handleUserStop(String packageName, int userHandle) {
@@ -1884,6 +1909,7 @@
                 pw.println("  mTemporarilyDisabled: " + mTemporarilyDisabled);
                 pw.println("  mCurUser: " + mCurUser);
                 pw.println("  mCurUserSupported: " + mCurUserSupported);
+                pw.println("  mIgnoredPreCreatedUsers: " + mIgnoredPreCreatedUsers);
                 dumpSupportedUsers(pw, "  ");
                 mDbHelper.dump(pw);
                 if (mImpl == null) {
@@ -1997,6 +2023,23 @@
 
                 List<String> roleHolders = mRm.getRoleHoldersAsUser(roleName, user);
 
+                // TODO(b/226201975): this method is beling called when a pre-created user is added,
+                // at which point it doesn't have any role holders. But it's not called again when
+                // the actual user is added (i.e., when the  pre-created user is converted), so we
+                // need to save the user id and call this method again when it's converted
+                // (at onPreCreatedUserConversion()).
+                // Once RoleService properly handles pre-created users, this workaround should be
+                // removed.
+                if (roleHolders.isEmpty()) {
+                    UserInfo userInfo = mUserManagerInternal.getUserInfo(user.getIdentifier());
+                    if (userInfo != null && userInfo.preCreated) {
+                        Slogf.d(TAG, "onRoleHoldersChanged(): ignoring pre-created user %s for now",
+                                userInfo.toFullString());
+                        mIgnoredPreCreatedUsers.add(user);
+                        return;
+                    }
+                }
+
                 int userId = user.getIdentifier();
                 if (roleHolders.isEmpty()) {
                     Settings.Secure.putStringForUser(getContext().getContentResolver(),