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(),