diff options
4 files changed, 76 insertions, 46 deletions
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index f2df7da0bcc8..7bd3bf693442 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -19,6 +19,7 @@ package android.os; import android.Manifest; import android.accounts.AccountManager; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -2129,7 +2130,7 @@ public class UserManager { * @return the list of users that were created. * @hide */ - public List<UserInfo> getUsers(boolean excludeDying) { + public @NonNull List<UserInfo> getUsers(boolean excludeDying) { try { return mService.getUsers(excludeDying); } catch (RemoteException re) { diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 0e1f48507423..ef3e7bcefc17 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -20,6 +20,7 @@ import static android.app.AppGlobals.getPackageManager; import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_PACKAGE_CHANGED; import static android.content.Intent.ACTION_PACKAGE_REMOVED; +import static android.content.Intent.ACTION_USER_ADDED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.pm.PackageManager.SIGNATURE_MATCH; @@ -46,6 +47,7 @@ import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.UserManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -243,11 +245,14 @@ public final class OverlayManagerService extends SystemService { packageFilter, null, null); final IntentFilter userFilter = new IntentFilter(); + userFilter.addAction(ACTION_USER_ADDED); userFilter.addAction(ACTION_USER_REMOVED); getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL, userFilter, null, null); restoreSettings(); + + initIfNeeded(); onSwitchUser(UserHandle.USER_SYSTEM); publishBinderService(Context.OVERLAY_SERVICE, mService); @@ -269,14 +274,31 @@ public final class OverlayManagerService extends SystemService { } } + private void initIfNeeded() { + final UserManager um = getContext().getSystemService(UserManager.class); + final List<UserInfo> users = um.getUsers(true /*excludeDying*/); + synchronized (mLock) { + final int userCount = users.size(); + for (int i = 0; i < userCount; i++) { + final UserInfo userInfo = users.get(i); + if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) { + // Initialize any users that can't be switched to, as there state would + // never be setup in onSwitchUser(). We will switch to the system user right + // after this, and its state will be setup there. + final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id); + updateOverlayPaths(users.get(i).id, targets); + } + } + } + } + @Override public void onSwitchUser(final int newUserId) { // ensure overlays in the settings are up-to-date, and propagate // any asset changes to the rest of the system - final List<String> targets; synchronized (mLock) { - targets = mImpl.onSwitchUser(newUserId); - updateAssetsLocked(newUserId, targets); + final List<String> targets = mImpl.updateOverlaysForUser(newUserId); + updateAssets(newUserId, targets); } schedulePersistSettings(); } @@ -428,10 +450,19 @@ public final class OverlayManagerService extends SystemService { private final class UserReceiver extends BroadcastReceiver { @Override public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); switch (intent.getAction()) { + case ACTION_USER_ADDED: + if (userId != UserHandle.USER_NULL) { + final ArrayList<String> targets; + synchronized (mLock) { + targets = mImpl.updateOverlaysForUser(userId); + } + updateOverlayPaths(userId, targets); + } + break; + case ACTION_USER_REMOVED: - final int userId = - intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); if (userId != UserHandle.USER_NULL) { synchronized (mLock) { mImpl.onUserRemoved(userId); @@ -647,9 +678,7 @@ public final class OverlayManagerService extends SystemService { public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) { schedulePersistSettings(); FgThread.getHandler().post(() -> { - synchronized (mLock) { - updateAssetsLocked(userId, targetPackageName); - } + updateAssets(userId, targetPackageName); final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED, Uri.fromParts("package", targetPackageName, null)); @@ -670,13 +699,10 @@ public final class OverlayManagerService extends SystemService { } } - private void updateAssetsLocked(final int userId, final String targetPackageName) { - final List<String> list = new ArrayList<>(); - list.add(targetPackageName); - updateAssetsLocked(userId, list); - } - - private void updateAssetsLocked(final int userId, List<String> targetPackageNames) { + /** + * Updates the target packages' set of enabled overlays in PackageManager. + */ + private void updateOverlayPaths(int userId, List<String> targetPackageNames) { if (DEBUG) { Slog.d(TAG, "Updating overlay assets"); } @@ -706,12 +732,19 @@ public final class OverlayManagerService extends SystemService { } if (!pm.setEnabledOverlayPackages( - userId, targetPackageName, pendingChanges.get(targetPackageName))) { + userId, targetPackageName, pendingChanges.get(targetPackageName))) { Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d", - targetPackageName, userId)); + targetPackageName, userId)); } } + } + + private void updateAssets(final int userId, final String targetPackageName) { + updateAssets(userId, Collections.singletonList(targetPackageName)); + } + private void updateAssets(final int userId, List<String> targetPackageNames) { + updateOverlayPaths(userId, targetPackageNames); final IActivityManager am = ActivityManager.getService(); try { am.scheduleApplicationInfoChanged(targetPackageNames, userId); diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 5196c66f8ab4..261bcc5838f8 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -68,15 +68,15 @@ final class OverlayManagerServiceImpl { mListener = listener; } - /* - * Call this when switching to a new Android user. Will return a list of - * target packages that must refresh their overlays. This list is the union + /** + * Call this to synchronize the Settings for a user with what PackageManager knows about a user. + * Returns a list of target packages that must refresh their overlays. This list is the union * of two sets: the set of targets with currently active overlays, and the * set of targets that had, but no longer have, active overlays. */ - List<String> onSwitchUser(final int newUserId) { + ArrayList<String> updateOverlaysForUser(final int newUserId) { if (DEBUG) { - Slog.d(TAG, "onSwitchUser newUserId=" + newUserId); + Slog.d(TAG, "updateOverlaysForUser newUserId=" + newUserId); } final Set<String> packagesToUpdateAssets = new ArraySet<>(); diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index 2f837932d76f..353b710138ae 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -22,12 +22,14 @@ import static com.android.server.om.OverlayManagerService.TAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.om.OverlayInfo; +import android.os.UserHandle; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.Slog; import android.util.Xml; import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; @@ -266,32 +268,32 @@ final class OverlayManagerSettings { return true; } - private static final String TAB1 = " "; - private static final String TAB2 = TAB1 + TAB1; - private static final String TAB3 = TAB2 + TAB1; - - void dump(@NonNull final PrintWriter pw) { + void dump(@NonNull final PrintWriter p) { + final IndentingPrintWriter pw = new IndentingPrintWriter(p, " "); pw.println("Settings"); - pw.println(TAB1 + "Items"); + pw.increaseIndent(); if (mItems.isEmpty()) { - pw.println(TAB2 + "<none>"); + pw.println("<none>"); return; } final int N = mItems.size(); for (int i = 0; i < N; i++) { final SettingsItem item = mItems.get(i); - final StringBuilder sb = new StringBuilder(); - sb.append(TAB2 + item.mPackageName + ":" + item.getUserId() + " {\n"); - sb.append(TAB3 + "mPackageName.......: " + item.mPackageName + "\n"); - sb.append(TAB3 + "mUserId............: " + item.getUserId() + "\n"); - sb.append(TAB3 + "mTargetPackageName.: " + item.getTargetPackageName() + "\n"); - sb.append(TAB3 + "mBaseCodePath......: " + item.getBaseCodePath() + "\n"); - sb.append(TAB3 + "mState.............: " + OverlayInfo.stateToString(item.getState()) + "\n"); - sb.append(TAB3 + "mIsEnabled.........: " + item.isEnabled() + "\n"); - sb.append(TAB2 + "}"); - pw.println(sb.toString()); + pw.println(item.mPackageName + ":" + item.getUserId() + " {"); + pw.increaseIndent(); + + pw.print("mPackageName.......: "); pw.println(item.mPackageName); + pw.print("mUserId............: "); pw.println(item.getUserId()); + pw.print("mTargetPackageName.: "); pw.println(item.getTargetPackageName()); + pw.print("mBaseCodePath......: "); pw.println(item.getBaseCodePath()); + pw.print("mState.............: "); pw.println(OverlayInfo.stateToString(item.getState())); + pw.print("mIsEnabled.........: "); pw.println(item.isEnabled()); + pw.print("mIsStatic..........: "); pw.println(item.isStatic()); + + pw.decreaseIndent(); + pw.println("}"); } } @@ -527,12 +529,6 @@ final class OverlayManagerSettings { .filter(item -> item.getTargetPackageName().equals(targetPackageName)); } - private void assertNotNull(@Nullable final Object o) { - if (o == null) { - throw new AndroidRuntimeException("object must not be null"); - } - } - static final class BadKeyException extends RuntimeException { BadKeyException(@NonNull final String packageName, final int userId) { super("Bad key mPackageName=" + packageName + " mUserId=" + userId); |