diff options
| author | 2024-02-01 12:57:34 +0900 | |
|---|---|---|
| committer | 2024-04-17 01:06:34 +0000 | |
| commit | 02be488a21221f20203cb482223591e8eb2d1925 (patch) | |
| tree | 7d76f74eb9dff3f1e5aabb0e9c8683a7802741c2 | |
| parent | 1699048dfd26367a52ea79d7196fb6b004652cd3 (diff) | |
Handle AppWarnings per-user per-display
Previously, AppWarning dialogs were not handled per-user per-display
and that caused the following issues:
- AppWarning dialogs were managed based on the default display and the
system user. Therefore, all the warning dialogs were only shown on
the default display even if it's for the app running on the secondary
display.
In addition, it could only receive Intent.ACTION_CLOSE_SYSTEM_DIALOGS
delivered to the system user regardless of who the actual user is.
- The warning dialog could be shown to the only one user at a time.
In 'MUMD'(multi-user on multiple displays), each warning dialog should
be shown to each user independently, but it wasn't.
- The flags that determine whether to hide the warning dialog were
handled per package, but not per user. As a result, flags set by
one user for specific package were also applied to other users.
To fix these, ensure that the warning dialogs are handled per-user and
per-display for MUMD devices. Please note that handling the warning
dialogs per-user per-display is only applicable to the devices that
enable the visible background users.
Bug: 296334639
Test: Manual test
(cherry picked from https://partner-android-review.googlesource.com/q/commit:1e099c7254ab802b747595b1180ee39b9a1674ba)
Change-Id: I3cdad53172748c452a941b8a798c3a799d9028c0
6 files changed, 351 insertions, 106 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index d984fb14f523..ff950d3e2c21 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -886,6 +886,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { mRecentTasks.onSystemReadyLocked(); mTaskSupervisor.onSystemReady(); mActivityClientController.onSystemReady(); + mAppWarnings.onSystemReady(); // TODO(b/258792202) Cleanup once ASM is ready to launch ActivitySecurityModelFeatureFlags.initialize(mContext.getMainExecutor()); mGrammaticalManagerInternal = LocalServices.getService( @@ -6360,7 +6361,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public void onPackageDataCleared(String name, int userId) { synchronized (mGlobalLock) { mCompatModePackages.handlePackageDataClearedLocked(name); - mAppWarnings.onPackageDataCleared(name); + mAppWarnings.onPackageDataCleared(name, userId); mPackageConfigPersister.onPackageDataCleared(name, userId); } } @@ -6368,7 +6369,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void onPackageUninstalled(String name, int userId) { synchronized (mGlobalLock) { - mAppWarnings.onPackageUninstalled(name); + mAppWarnings.onPackageUninstalled(name, userId); mCompatModePackages.handlePackageUninstalledLocked(name); mPackageConfigPersister.onPackageUninstall(name, userId); } diff --git a/services/core/java/com/android/server/wm/AppWarnings.java b/services/core/java/com/android/server/wm/AppWarnings.java index ad5f4427fbc4..9fd543fca30e 100644 --- a/services/core/java/com/android/server/wm/AppWarnings.java +++ b/services/core/java/com/android/server/wm/AppWarnings.java @@ -16,8 +16,14 @@ package com.android.server.wm; +import static android.os.UserHandle.USER_NULL; +import static android.os.UserHandle.USER_SYSTEM; +import static android.os.UserManager.isHeadlessSystemUserMode; +import static android.os.UserManager.isVisibleBackgroundUsersEnabled; + import android.annotation.NonNull; import android.annotation.UiThread; +import android.annotation.UserIdInt; import android.annotation.WorkerThread; import android.app.AlertDialog; import android.content.BroadcastReceiver; @@ -26,17 +32,21 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; +import android.content.pm.UserInfo; import android.content.res.Configuration; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemProperties; +import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.DisplayMetrics; +import android.util.Pair; import android.util.Slog; +import android.util.SparseArray; import android.util.Xml; import com.android.internal.annotations.GuardedBy; @@ -44,6 +54,8 @@ import com.android.internal.util.ArrayUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.IoThread; +import com.android.server.LocalServices; +import com.android.server.pm.UserManagerInternal; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -65,19 +77,30 @@ class AppWarnings { public static final int FLAG_HIDE_DEPRECATED_SDK = 0x04; public static final int FLAG_HIDE_DEPRECATED_ABI = 0x08; + /** + * Map of package flags for each user. + * Key: {@literal Pair<userId, packageName>} + * Value: Flags + */ @GuardedBy("mPackageFlags") - private final ArrayMap<String, Integer> mPackageFlags = new ArrayMap<>(); + private final ArrayMap<Pair<Integer, String>, Integer> mPackageFlags = new ArrayMap<>(); private final ActivityTaskManagerService mAtm; - private final Context mUiContext; private final WriteConfigTask mWriteConfigTask; private final UiHandler mUiHandler; private final AtomicFile mConfigFile; - private UnsupportedDisplaySizeDialog mUnsupportedDisplaySizeDialog; - private UnsupportedCompileSdkDialog mUnsupportedCompileSdkDialog; - private DeprecatedTargetSdkVersionDialog mDeprecatedTargetSdkVersionDialog; - private DeprecatedAbiDialog mDeprecatedAbiDialog; + private UserManagerInternal mUserManagerInternal; + + /** + * Maps of app warning dialogs for each user. + * Key: userId + * Value: The warning dialog for specific user + */ + private SparseArray<UnsupportedDisplaySizeDialog> mUnsupportedDisplaySizeDialogs; + private SparseArray<UnsupportedCompileSdkDialog> mUnsupportedCompileSdkDialogs; + private SparseArray<DeprecatedTargetSdkVersionDialog> mDeprecatedTargetSdkVersionDialogs; + private SparseArray<DeprecatedAbiDialog> mDeprecatedAbiDialogs; /** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */ private final ArraySet<ComponentName> mAlwaysShowUnsupportedCompileSdkWarningActivities = @@ -92,12 +115,35 @@ class AppWarnings { public AppWarnings(ActivityTaskManagerService atm, Context uiContext, Handler handler, Handler uiHandler, File systemDir) { mAtm = atm; - mUiContext = uiContext; mWriteConfigTask = new WriteConfigTask(); mUiHandler = new UiHandler(uiHandler.getLooper()); mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME), "warnings-config"); + } + /** + * Called when ActivityManagerService receives its systemReady call during boot. + */ + void onSystemReady() { + mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); readConfigFromFileAmsThread(); + + if (!isVisibleBackgroundUsersEnabled()) { + return; + } + + mUserManagerInternal.addUserLifecycleListener( + new UserManagerInternal.UserLifecycleListener() { + @Override + public void onUserRemoved(UserInfo user) { + // Ignore profile user. + if (!user.isFull()) { + return; + } + // Dismiss all warnings and clear all package flags for the user. + mUiHandler.hideDialogsForPackage(/* name= */ null, user.id); + clearAllPackageFlagsForUser(user.id); + } + }); } /** @@ -227,18 +273,20 @@ class AppWarnings { * Called by ActivityManagerService when package data has been cleared. * * @param name the package whose data has been cleared + * @param userId the user where the package resides. */ - public void onPackageDataCleared(String name) { - removePackageAndHideDialogs(name); + public void onPackageDataCleared(String name, int userId) { + removePackageAndHideDialogs(name, userId); } /** * Called by ActivityManagerService when a package has been uninstalled. * * @param name the package that has been uninstalled + * @param userId the user where the package resides. */ - public void onPackageUninstalled(String name) { - removePackageAndHideDialogs(name); + public void onPackageUninstalled(String name, int userId) { + removePackageAndHideDialogs(name, userId); } /** @@ -251,11 +299,24 @@ class AppWarnings { /** * Does what it says on the tin. */ - private void removePackageAndHideDialogs(String name) { - mUiHandler.hideDialogsForPackage(name); + private void removePackageAndHideDialogs(String name, int userId) { + // Per-user AppWarnings only affects the behavior of the devices that enable the visible + // background users. + // To preserve existing behavior of the other devices, handle AppWarnings as a system user + // regardless of the actual user. + if (!isVisibleBackgroundUsersEnabled()) { + userId = USER_SYSTEM; + } else { + // If the userId is of a profile, use the parent user ID, + // since the warning dialogs and the flags for a package are handled per profile group. + userId = mUserManagerInternal.getProfileParentId(userId); + } + + mUiHandler.hideDialogsForPackage(name, userId); synchronized (mPackageFlags) { - if (mPackageFlags.remove(name) != null) { + final Pair<Integer, String> packageKey = Pair.create(userId, name); + if (mPackageFlags.remove(packageKey) != null) { mWriteConfigTask.schedule(); } } @@ -268,10 +329,14 @@ class AppWarnings { */ @UiThread private void hideUnsupportedDisplaySizeDialogUiThread() { - if (mUnsupportedDisplaySizeDialog != null) { - mUnsupportedDisplaySizeDialog.dismiss(); - mUnsupportedDisplaySizeDialog = null; + if (mUnsupportedDisplaySizeDialogs == null) { + return; } + + for (int i = 0; i < mUnsupportedDisplaySizeDialogs.size(); i++) { + mUnsupportedDisplaySizeDialogs.valueAt(i).dismiss(); + } + mUnsupportedDisplaySizeDialogs.clear(); } /** @@ -282,16 +347,24 @@ class AppWarnings { * @param ar record for the activity that triggered the warning */ @UiThread - private void showUnsupportedDisplaySizeDialogUiThread(ActivityRecord ar) { - if (mUnsupportedDisplaySizeDialog != null) { - mUnsupportedDisplaySizeDialog.dismiss(); - mUnsupportedDisplaySizeDialog = null; + private void showUnsupportedDisplaySizeDialogUiThread(@NonNull ActivityRecord ar) { + final int userId = getUserIdForActivity(ar); + UnsupportedDisplaySizeDialog unsupportedDisplaySizeDialog; + if (mUnsupportedDisplaySizeDialogs != null) { + unsupportedDisplaySizeDialog = mUnsupportedDisplaySizeDialogs.get(userId); + if (unsupportedDisplaySizeDialog != null) { + unsupportedDisplaySizeDialog.dismiss(); + mUnsupportedDisplaySizeDialogs.remove(userId); + } } - if (ar != null && !hasPackageFlag( - ar.packageName, FLAG_HIDE_DISPLAY_SIZE)) { - mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog( - AppWarnings.this, mUiContext, ar.info.applicationInfo); - mUnsupportedDisplaySizeDialog.show(); + if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_DISPLAY_SIZE)) { + unsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog( + AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId); + unsupportedDisplaySizeDialog.show(); + if (mUnsupportedDisplaySizeDialogs == null) { + mUnsupportedDisplaySizeDialogs = new SparseArray<>(); + } + mUnsupportedDisplaySizeDialogs.put(userId, unsupportedDisplaySizeDialog); } } @@ -303,16 +376,24 @@ class AppWarnings { * @param ar record for the activity that triggered the warning */ @UiThread - private void showUnsupportedCompileSdkDialogUiThread(ActivityRecord ar) { - if (mUnsupportedCompileSdkDialog != null) { - mUnsupportedCompileSdkDialog.dismiss(); - mUnsupportedCompileSdkDialog = null; + private void showUnsupportedCompileSdkDialogUiThread(@NonNull ActivityRecord ar) { + final int userId = getUserIdForActivity(ar); + UnsupportedCompileSdkDialog unsupportedCompileSdkDialog; + if (mUnsupportedCompileSdkDialogs != null) { + unsupportedCompileSdkDialog = mUnsupportedCompileSdkDialogs.get(userId); + if (unsupportedCompileSdkDialog != null) { + unsupportedCompileSdkDialog.dismiss(); + mUnsupportedCompileSdkDialogs.remove(userId); + } } - if (ar != null && !hasPackageFlag( - ar.packageName, FLAG_HIDE_COMPILE_SDK)) { - mUnsupportedCompileSdkDialog = new UnsupportedCompileSdkDialog( - AppWarnings.this, mUiContext, ar.info.applicationInfo); - mUnsupportedCompileSdkDialog.show(); + if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_COMPILE_SDK)) { + unsupportedCompileSdkDialog = new UnsupportedCompileSdkDialog( + AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId); + unsupportedCompileSdkDialog.show(); + if (mUnsupportedCompileSdkDialogs == null) { + mUnsupportedCompileSdkDialogs = new SparseArray<>(); + } + mUnsupportedCompileSdkDialogs.put(userId, unsupportedCompileSdkDialog); } } @@ -324,16 +405,24 @@ class AppWarnings { * @param ar record for the activity that triggered the warning */ @UiThread - private void showDeprecatedTargetSdkDialogUiThread(ActivityRecord ar) { - if (mDeprecatedTargetSdkVersionDialog != null) { - mDeprecatedTargetSdkVersionDialog.dismiss(); - mDeprecatedTargetSdkVersionDialog = null; + private void showDeprecatedTargetSdkDialogUiThread(@NonNull ActivityRecord ar) { + final int userId = getUserIdForActivity(ar); + DeprecatedTargetSdkVersionDialog deprecatedTargetSdkVersionDialog; + if (mDeprecatedTargetSdkVersionDialogs != null) { + deprecatedTargetSdkVersionDialog = mDeprecatedTargetSdkVersionDialogs.get(userId); + if (deprecatedTargetSdkVersionDialog != null) { + deprecatedTargetSdkVersionDialog.dismiss(); + mDeprecatedTargetSdkVersionDialogs.remove(userId); + } } - if (ar != null && !hasPackageFlag( - ar.packageName, FLAG_HIDE_DEPRECATED_SDK)) { - mDeprecatedTargetSdkVersionDialog = new DeprecatedTargetSdkVersionDialog( - AppWarnings.this, mUiContext, ar.info.applicationInfo); - mDeprecatedTargetSdkVersionDialog.show(); + if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_DEPRECATED_SDK)) { + deprecatedTargetSdkVersionDialog = new DeprecatedTargetSdkVersionDialog( + AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId); + deprecatedTargetSdkVersionDialog.show(); + if (mDeprecatedTargetSdkVersionDialogs == null) { + mDeprecatedTargetSdkVersionDialogs = new SparseArray<>(); + } + mDeprecatedTargetSdkVersionDialogs.put(userId, deprecatedTargetSdkVersionDialog); } } @@ -345,16 +434,24 @@ class AppWarnings { * @param ar record for the activity that triggered the warning */ @UiThread - private void showDeprecatedAbiDialogUiThread(ActivityRecord ar) { - if (mDeprecatedAbiDialog != null) { - mDeprecatedAbiDialog.dismiss(); - mDeprecatedAbiDialog = null; + private void showDeprecatedAbiDialogUiThread(@NonNull ActivityRecord ar) { + final int userId = getUserIdForActivity(ar); + DeprecatedAbiDialog deprecatedAbiDialog; + if (mDeprecatedAbiDialogs != null) { + deprecatedAbiDialog = mDeprecatedAbiDialogs.get(userId); + if (deprecatedAbiDialog != null) { + deprecatedAbiDialog.dismiss(); + mDeprecatedAbiDialogs.remove(userId); + } } - if (ar != null && !hasPackageFlag( - ar.packageName, FLAG_HIDE_DEPRECATED_ABI)) { - mDeprecatedAbiDialog = new DeprecatedAbiDialog( - AppWarnings.this, mUiContext, ar.info.applicationInfo); - mDeprecatedAbiDialog.show(); + if (!hasPackageFlag(userId, ar.packageName, FLAG_HIDE_DEPRECATED_ABI)) { + deprecatedAbiDialog = new DeprecatedAbiDialog( + AppWarnings.this, getUiContextForActivity(ar), ar.info.applicationInfo, userId); + deprecatedAbiDialog.show(); + if (mDeprecatedAbiDialogs == null) { + mDeprecatedAbiDialogs = new SparseArray<>(); + } + mDeprecatedAbiDialogs.put(userId, deprecatedAbiDialog); } } @@ -365,65 +462,84 @@ class AppWarnings { * * @param name the package for which warnings should be dismissed, or {@code null} to dismiss * all warnings + * @param userId the user where the package resides. */ @UiThread - private void hideDialogsForPackageUiThread(String name) { + private void hideDialogsForPackageUiThread(String name, int userId) { // Hides the "unsupported display" dialog if necessary. - if (mUnsupportedDisplaySizeDialog != null && (name == null || name.equals( - mUnsupportedDisplaySizeDialog.mPackageName))) { - mUnsupportedDisplaySizeDialog.dismiss(); - mUnsupportedDisplaySizeDialog = null; + if (mUnsupportedDisplaySizeDialogs != null) { + UnsupportedDisplaySizeDialog unsupportedDisplaySizeDialog = + mUnsupportedDisplaySizeDialogs.get(userId); + if (unsupportedDisplaySizeDialog != null && (name == null || name.equals( + unsupportedDisplaySizeDialog.mPackageName))) { + unsupportedDisplaySizeDialog.dismiss(); + mUnsupportedDisplaySizeDialogs.remove(userId); + } } // Hides the "unsupported compile SDK" dialog if necessary. - if (mUnsupportedCompileSdkDialog != null && (name == null || name.equals( - mUnsupportedCompileSdkDialog.mPackageName))) { - mUnsupportedCompileSdkDialog.dismiss(); - mUnsupportedCompileSdkDialog = null; + if (mUnsupportedCompileSdkDialogs != null) { + UnsupportedCompileSdkDialog unsupportedCompileSdkDialog = + mUnsupportedCompileSdkDialogs.get(userId); + if (unsupportedCompileSdkDialog != null && (name == null || name.equals( + unsupportedCompileSdkDialog.mPackageName))) { + unsupportedCompileSdkDialog.dismiss(); + mUnsupportedCompileSdkDialogs.remove(userId); + } } // Hides the "deprecated target sdk version" dialog if necessary. - if (mDeprecatedTargetSdkVersionDialog != null && (name == null || name.equals( - mDeprecatedTargetSdkVersionDialog.mPackageName))) { - mDeprecatedTargetSdkVersionDialog.dismiss(); - mDeprecatedTargetSdkVersionDialog = null; + if (mDeprecatedTargetSdkVersionDialogs != null) { + DeprecatedTargetSdkVersionDialog deprecatedTargetSdkVersionDialog = + mDeprecatedTargetSdkVersionDialogs.get(userId); + if (deprecatedTargetSdkVersionDialog != null && (name == null || name.equals( + deprecatedTargetSdkVersionDialog.mPackageName))) { + deprecatedTargetSdkVersionDialog.dismiss(); + mDeprecatedTargetSdkVersionDialogs.remove(userId); + } } // Hides the "deprecated abi" dialog if necessary. - if (mDeprecatedAbiDialog != null && (name == null || name.equals( - mDeprecatedAbiDialog.mPackageName))) { - mDeprecatedAbiDialog.dismiss(); - mDeprecatedAbiDialog = null; + if (mDeprecatedAbiDialogs != null) { + DeprecatedAbiDialog deprecatedAbiDialog = mDeprecatedAbiDialogs.get(userId); + if (deprecatedAbiDialog != null && (name == null || name.equals( + deprecatedAbiDialog.mPackageName))) { + deprecatedAbiDialog.dismiss(); + mDeprecatedAbiDialogs.remove(userId); + } } } /** * Returns the value of the flag for the given package. * + * @param userId the user where the package resides. * @param name the package from which to retrieve the flag * @param flag the bitmask for the flag to retrieve * @return {@code true} if the flag is enabled, {@code false} otherwise */ - boolean hasPackageFlag(String name, int flag) { - return (getPackageFlags(name) & flag) == flag; + boolean hasPackageFlag(int userId, String name, int flag) { + return (getPackageFlags(userId, name) & flag) == flag; } /** * Sets the flag for the given package to the specified value. * + * @param userId the user where the package resides. * @param name the package on which to set the flag * @param flag the bitmask for flag to set * @param enabled the value to set for the flag */ - void setPackageFlag(String name, int flag, boolean enabled) { + void setPackageFlag(int userId, String name, int flag, boolean enabled) { synchronized (mPackageFlags) { - final int curFlags = getPackageFlags(name); + final int curFlags = getPackageFlags(userId, name); final int newFlags = enabled ? (curFlags | flag) : (curFlags & ~flag); if (curFlags != newFlags) { + final Pair<Integer, String> packageKey = Pair.create(userId, name); if (newFlags != 0) { - mPackageFlags.put(name, newFlags); + mPackageFlags.put(packageKey, newFlags); } else { - mPackageFlags.remove(name); + mPackageFlags.remove(packageKey); } mWriteConfigTask.schedule(); } @@ -433,13 +549,95 @@ class AppWarnings { /** * Returns the bitmask of flags set for the specified package. */ - private int getPackageFlags(String name) { + private int getPackageFlags(int userId, String packageName) { synchronized (mPackageFlags) { - return mPackageFlags.getOrDefault(name, 0); + final Pair<Integer, String> packageKey = Pair.create(userId, packageName); + return mPackageFlags.getOrDefault(packageKey, 0); } } /** + * Clear all the package flags for given user. + */ + private void clearAllPackageFlagsForUser(int userId) { + synchronized (mPackageFlags) { + boolean hasPackageFlagsForUser = false; + for (int i = mPackageFlags.size() - 1; i >= 0; i--) { + Pair<Integer, String> key = mPackageFlags.keyAt(i); + if (key.first == userId) { + hasPackageFlagsForUser = true; + mPackageFlags.remove(key); + } + } + + if (hasPackageFlagsForUser) { + mWriteConfigTask.schedule(); + } + } + } + + /** + * Returns the user ID for handling AppWarnings per user. + * Per-user AppWarnings only affects the behavior of the devices that enable + * the visible background users. + * If the device doesn't enable visible background users, it will return the system user ID + * for handling AppWarnings as a system user regardless of the actual user + * to preserve existing behavior of the device. + * Otherwise, it will return the main user (i.e., not a profile) that is assigned to the display + * where the activity is launched. + */ + private @UserIdInt int getUserIdForActivity(@NonNull ActivityRecord ar) { + if (!isVisibleBackgroundUsersEnabled()) { + return USER_SYSTEM; + } + + if (ar.mUserId == USER_SYSTEM) { + return getUserAssignedToDisplay(ar.mDisplayContent.getDisplayId()); + } + + return mUserManagerInternal.getProfileParentId(ar.mUserId); + } + + /** + * Returns the UI context for handling AppWarnings per user. + * Per-user AppWarnings only affects the behavior of the devices that enable + * the visible background users. + * If the device enables the visible background users, it will return the UI context associated + * with the assigned user and the display where the activity is launched. + * If the HSUM device doesn't enable the visible background users, it will return the UI context + * associated with the current user and the default display. + * Otherwise, it will return the UI context associated with the system user and the default + * display. + */ + private Context getUiContextForActivity(@NonNull ActivityRecord ar) { + if (!isVisibleBackgroundUsersEnabled()) { + if (!isHeadlessSystemUserMode()) { + return mAtm.getUiContext(); + } + + Context uiContextForCurrentUser = mAtm.getUiContext().createContextAsUser( + new UserHandle(mAtm.getCurrentUserId()), /* flags= */ 0); + return uiContextForCurrentUser; + } + + DisplayContent dc = ar.mDisplayContent; + Context systemUiContext = dc.getDisplayPolicy().getSystemUiContext(); + int assignedUser = getUserAssignedToDisplay(dc.getDisplayId()); + Context uiContextForUser = systemUiContext.createContextAsUser( + new UserHandle(assignedUser), /* flags= */ 0); + return uiContextForUser; + } + + /** + * Returns the main user that is assigned to the display. + * + * See {@link UserManagerInternal#getUserAssignedToDisplay(int)}. + */ + private @UserIdInt int getUserAssignedToDisplay(int displayId) { + return mUserManagerInternal.getUserAssignedToDisplay(displayId); + } + + /** * Handles messages on the system process UI thread. */ private final class UiHandler extends Handler { @@ -470,7 +668,8 @@ class AppWarnings { } break; case MSG_HIDE_DIALOGS_FOR_PACKAGE: { final String name = (String) msg.obj; - hideDialogsForPackageUiThread(name); + final int userId = (int) msg.arg1; + hideDialogsForPackageUiThread(name, userId); } break; case MSG_SHOW_DEPRECATED_TARGET_SDK_DIALOG: { final ActivityRecord ar = (ActivityRecord) msg.obj; @@ -508,20 +707,24 @@ class AppWarnings { obtainMessage(MSG_SHOW_DEPRECATED_ABI_DIALOG, r).sendToTarget(); } - public void hideDialogsForPackage(String name) { - obtainMessage(MSG_HIDE_DIALOGS_FOR_PACKAGE, name).sendToTarget(); + public void hideDialogsForPackage(String name, int userId) { + obtainMessage(MSG_HIDE_DIALOGS_FOR_PACKAGE, userId, 0, name).sendToTarget(); } } static class BaseDialog { final AppWarnings mManager; + final Context mUiContext; final String mPackageName; + final int mUserId; AlertDialog mDialog; private BroadcastReceiver mCloseReceiver; - BaseDialog(AppWarnings manager, String packageName) { + BaseDialog(AppWarnings manager, Context uiContext, String packageName, int userId) { mManager = manager; + mUiContext = uiContext; mPackageName = packageName; + mUserId = userId; } @UiThread @@ -532,11 +735,11 @@ class AppWarnings { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { - mManager.mUiHandler.hideDialogsForPackage(mPackageName); + mManager.mUiHandler.hideDialogsForPackage(mPackageName, mUserId); } } }; - mManager.mUiContext.registerReceiver(mCloseReceiver, + mUiContext.registerReceiver(mCloseReceiver, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), Context.RECEIVER_EXPORTED); } @@ -548,7 +751,7 @@ class AppWarnings { void dismiss() { if (mDialog == null) return; if (mCloseReceiver != null) { - mManager.mUiContext.unregisterReceiver(mCloseReceiver); + mUiContext.unregisterReceiver(mCloseReceiver); mCloseReceiver = null; } mDialog.dismiss(); @@ -558,12 +761,13 @@ class AppWarnings { private final class WriteConfigTask implements Runnable { private static final long WRITE_CONFIG_DELAY_MS = 10000; - final AtomicReference<ArrayMap<String, Integer>> mPendingPackageFlags = + final AtomicReference<ArrayMap<Pair<Integer, String>, Integer>> mPendingPackageFlags = new AtomicReference<>(); @Override public void run() { - final ArrayMap<String, Integer> packageFlags = mPendingPackageFlags.getAndSet(null); + final ArrayMap<Pair<Integer, String>, Integer> packageFlags = + mPendingPackageFlags.getAndSet(null); if (packageFlags != null) { writeConfigToFile(packageFlags); } @@ -579,7 +783,7 @@ class AppWarnings { /** Writes the configuration file. */ @WorkerThread - private void writeConfigToFile(@NonNull ArrayMap<String, Integer> packageFlags) { + private void writeConfigToFile(@NonNull ArrayMap<Pair<Integer, String>, Integer> packageFlags) { FileOutputStream fos = null; try { fos = mConfigFile.startWrite(); @@ -590,13 +794,16 @@ class AppWarnings { out.startTag(null, "packages"); for (int i = 0; i < packageFlags.size(); i++) { - final String pkg = packageFlags.keyAt(i); + final Pair<Integer, String> key = packageFlags.keyAt(i); + final int userId = key.first; + final String packageName = key.second; final int mode = packageFlags.valueAt(i); if (mode == 0) { continue; } out.startTag(null, "package"); - out.attribute(null, "name", pkg); + out.attributeInt(null, "user", userId); + out.attribute(null, "name", packageName); out.attributeInt(null, "flags", mode); out.endTag(null, "package"); } @@ -616,7 +823,7 @@ class AppWarnings { /** * Reads the configuration file and populates the package flags. * <p> - * <strong>Note:</strong> Must be called from the constructor (and thus on the + * <strong>Note:</strong> Must be called from #onSystemReady() (and thus on the * ActivityManagerService thread) since we don't synchronize on config. */ private void readConfigFromFileAmsThread() { @@ -639,21 +846,58 @@ class AppWarnings { String tagName = parser.getName(); if ("packages".equals(tagName)) { eventType = parser.next(); + boolean writeConfigToFileNeeded = false; do { if (eventType == XmlPullParser.START_TAG) { tagName = parser.getName(); if (parser.getDepth() == 2) { if ("package".equals(tagName)) { + final int userId = parser.getAttributeInt( + null, "user", USER_NULL); final String name = parser.getAttributeValue(null, "name"); if (name != null) { int flagsInt = parser.getAttributeInt(null, "flags", 0); - mPackageFlags.put(name, flagsInt); + if (userId != USER_NULL) { + final Pair<Integer, String> packageKey = + Pair.create(userId, name); + mPackageFlags.put(packageKey, flagsInt); + } else { + // This is for compatibility with existing configuration + // file written from legacy logic(pre-V) which does not have + // the flags per-user. (b/296334639) + writeConfigToFileNeeded = true; + if (!isVisibleBackgroundUsersEnabled()) { + // To preserve existing behavior of the devices that + // doesn't enable visible background users, populate + // the flags for a package as the system user. + final Pair<Integer, String> packageKey = + Pair.create(USER_SYSTEM, name); + mPackageFlags.put(packageKey, flagsInt); + } else { + // To manage the flags per user in the device that + // enable visible background users, populate the flags + // for all existing non-profile human user. + UserInfo[] users = mUserManagerInternal.getUserInfos(); + for (UserInfo userInfo : users) { + if (!userInfo.isFull()) { + continue; + } + final Pair<Integer, String> packageKey = + Pair.create(userInfo.id, name); + mPackageFlags.put(packageKey, flagsInt); + } + } + } } } } } eventType = parser.next(); } while (eventType != XmlPullParser.END_DOCUMENT); + + if (writeConfigToFileNeeded) { + mWriteConfigTask.schedule(); + } } } catch (XmlPullParserException e) { Slog.w(TAG, "Error reading package metadata", e); diff --git a/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java b/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java index e96208d3d0b3..46b34a1f4e16 100644 --- a/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java +++ b/services/core/java/com/android/server/wm/DeprecatedAbiDialog.java @@ -28,8 +28,8 @@ import com.android.internal.R; class DeprecatedAbiDialog extends AppWarnings.BaseDialog { DeprecatedAbiDialog(final AppWarnings manager, Context context, - ApplicationInfo appInfo) { - super(manager, appInfo.packageName); + ApplicationInfo appInfo, int userId) { + super(manager, context, appInfo.packageName, userId); final PackageManager pm = context.getPackageManager(); final CharSequence label = appInfo.loadSafeLabel(pm, @@ -41,7 +41,7 @@ class DeprecatedAbiDialog extends AppWarnings.BaseDialog { final AlertDialog.Builder builder = new AlertDialog.Builder(context) .setPositiveButton(R.string.ok, (dialog, which) -> manager.setPackageFlag( - mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_ABI, true)) + mUserId, mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_ABI, true)) .setMessage(message) .setTitle(label); diff --git a/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java b/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java index 1a7a9b258400..ce4238582b26 100644 --- a/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java +++ b/services/core/java/com/android/server/wm/DeprecatedTargetSdkVersionDialog.java @@ -31,8 +31,8 @@ import com.android.server.utils.AppInstallerUtil; class DeprecatedTargetSdkVersionDialog extends AppWarnings.BaseDialog { DeprecatedTargetSdkVersionDialog(final AppWarnings manager, Context context, - ApplicationInfo appInfo) { - super(manager, appInfo.packageName); + ApplicationInfo appInfo, int userId) { + super(manager, context, appInfo.packageName, userId); final PackageManager pm = context.getPackageManager(); final CharSequence label = appInfo.loadSafeLabel(pm, @@ -44,7 +44,7 @@ class DeprecatedTargetSdkVersionDialog extends AppWarnings.BaseDialog { final AlertDialog.Builder builder = new AlertDialog.Builder(context) .setPositiveButton(R.string.ok, (dialog, which) -> manager.setPackageFlag( - mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_SDK, true)) + mUserId, mPackageName, AppWarnings.FLAG_HIDE_DEPRECATED_SDK, true)) .setMessage(message) .setTitle(label); diff --git a/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java b/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java index f376e8b1f9ed..0655068aae86 100644 --- a/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java +++ b/services/core/java/com/android/server/wm/UnsupportedCompileSdkDialog.java @@ -32,8 +32,8 @@ import com.android.server.utils.AppInstallerUtil; class UnsupportedCompileSdkDialog extends AppWarnings.BaseDialog { UnsupportedCompileSdkDialog(final AppWarnings manager, Context context, - ApplicationInfo appInfo) { - super(manager, appInfo.packageName); + ApplicationInfo appInfo, int userId) { + super(manager, context, appInfo.packageName, userId); final PackageManager pm = context.getPackageManager(); final CharSequence label = appInfo.loadSafeLabel(pm, @@ -68,6 +68,6 @@ class UnsupportedCompileSdkDialog extends AppWarnings.BaseDialog { final CheckBox alwaysShow = mDialog.findViewById(R.id.ask_checkbox); alwaysShow.setChecked(true); alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> manager.setPackageFlag( - mPackageName, AppWarnings.FLAG_HIDE_COMPILE_SDK, !isChecked)); + mUserId, mPackageName, AppWarnings.FLAG_HIDE_COMPILE_SDK, !isChecked)); } } diff --git a/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java b/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java index b11c22de4286..5e40d9c3e1b0 100644 --- a/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java +++ b/services/core/java/com/android/server/wm/UnsupportedDisplaySizeDialog.java @@ -30,8 +30,8 @@ import com.android.internal.R; class UnsupportedDisplaySizeDialog extends AppWarnings.BaseDialog { UnsupportedDisplaySizeDialog(final AppWarnings manager, Context context, - ApplicationInfo appInfo) { - super(manager, appInfo.packageName); + ApplicationInfo appInfo, int userId) { + super(manager, context, appInfo.packageName, userId); final PackageManager pm = context.getPackageManager(); final CharSequence label = appInfo.loadSafeLabel(pm, @@ -59,6 +59,6 @@ class UnsupportedDisplaySizeDialog extends AppWarnings.BaseDialog { final CheckBox alwaysShow = mDialog.findViewById(R.id.ask_checkbox); alwaysShow.setChecked(true); alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> manager.setPackageFlag( - mPackageName, AppWarnings.FLAG_HIDE_DISPLAY_SIZE, !isChecked)); + mUserId, mPackageName, AppWarnings.FLAG_HIDE_DISPLAY_SIZE, !isChecked)); } } |