diff options
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 749e19b92a7f..a739e577bca3 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( @@ -6353,7 +6354,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); } } @@ -6361,7 +6362,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)); } } |