Loading core/java/android/content/pm/PackageManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -2399,6 +2399,14 @@ public abstract class PackageManager { */ public static final int DELETE_FAILED_APP_PINNED = -7; /** * Deletion failed return code: this is passed to the * {@link IPackageDeleteObserver} if the system failed to delete the package * for any child profile with {@link UserProperties#getDeleteAppWithParent()} as true. * @hide */ public static final int DELETE_FAILED_FOR_CHILD_PROFILE = -8; /** * Return code that is passed to the {@link IPackageMoveObserver} when the * package has been successfully moved by the system. Loading core/java/android/content/pm/UserProperties.java +46 −4 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ public final class UserProperties implements Parcelable { "mediaSharedWithParent"; private static final String ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT = "credentialShareableWithParent"; private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent"; /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { Loading @@ -73,7 +74,8 @@ public final class UserProperties implements Parcelable { INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY, INDEX_MEDIA_SHARED_WITH_PARENT, INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT, INDEX_DELETE_APP_WITH_PARENT, }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { Loading @@ -88,6 +90,7 @@ public final class UserProperties implements Parcelable { private static final int INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = 7; private static final int INDEX_MEDIA_SHARED_WITH_PARENT = 8; private static final int INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT = 9; private static final int INDEX_DELETE_APP_WITH_PARENT = 10; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; Loading Loading @@ -312,6 +315,7 @@ public final class UserProperties implements Parcelable { setCrossProfileIntentFilterAccessControl( orig.getCrossProfileIntentFilterAccessControl()); setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy()); setDeleteAppWithParent(orig.getDeleteAppWithParent()); } if (hasManagePermission) { // Add items that require MANAGE_USERS or stronger. Loading Loading @@ -417,6 +421,24 @@ public final class UserProperties implements Parcelable { } private boolean mStartWithParent; /** * Returns whether an app in the profile should be deleted when the same package in * the parent user is being deleted. * This only applies for users that have parents (i.e. for profiles). * @hide */ public boolean getDeleteAppWithParent() { if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) return mDeleteAppWithParent; if (mDefaultProperties != null) return mDefaultProperties.mDeleteAppWithParent; throw new SecurityException("You don't have permission to query deleteAppWithParent"); } /** @hide */ public void setDeleteAppWithParent(boolean val) { this.mDeleteAppWithParent = val; setPresent(INDEX_DELETE_APP_WITH_PARENT); } private boolean mDeleteAppWithParent; /** * Return whether, and how, select user restrictions or device policies should be inherited * from other user. Loading Loading @@ -609,6 +631,7 @@ public final class UserProperties implements Parcelable { + getCrossProfileIntentResolutionStrategy() + ", mMediaSharedWithParent=" + isMediaSharedWithParent() + ", mCredentialShareableWithParent=" + isCredentialShareableWithParent() + ", mDeleteAppWithParent=" + getDeleteAppWithParent() + "}"; } Loading @@ -634,6 +657,7 @@ public final class UserProperties implements Parcelable { pw.println(prefix + " mMediaSharedWithParent=" + isMediaSharedWithParent()); pw.println(prefix + " mCredentialShareableWithParent=" + isCredentialShareableWithParent()); pw.println(prefix + " mDeleteAppWithParent=" + getDeleteAppWithParent()); } /** Loading Loading @@ -697,6 +721,9 @@ public final class UserProperties implements Parcelable { case ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT: setCredentialShareableWithParent(parser.getAttributeBoolean(i)); break; case ATTR_DELETE_APP_WITH_PARENT: setDeleteAppWithParent(parser.getAttributeBoolean(i)); break; default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } Loading Loading @@ -752,6 +779,10 @@ public final class UserProperties implements Parcelable { serializer.attributeBoolean(null, ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT, mCredentialShareableWithParent); } if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) { serializer.attributeBoolean(null, ATTR_DELETE_APP_WITH_PARENT, mDeleteAppWithParent); } } // For use only with an object that has already had any permission-lacking fields stripped out. Loading @@ -768,6 +799,7 @@ public final class UserProperties implements Parcelable { dest.writeInt(mCrossProfileIntentResolutionStrategy); dest.writeBoolean(mMediaSharedWithParent); dest.writeBoolean(mCredentialShareableWithParent); dest.writeBoolean(mDeleteAppWithParent); } /** Loading @@ -788,6 +820,7 @@ public final class UserProperties implements Parcelable { mCrossProfileIntentResolutionStrategy = source.readInt(); mMediaSharedWithParent = source.readBoolean(); mCredentialShareableWithParent = source.readBoolean(); mDeleteAppWithParent = source.readBoolean(); } @Override Loading Loading @@ -825,6 +858,7 @@ public final class UserProperties implements Parcelable { CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT; private boolean mMediaSharedWithParent = false; private boolean mCredentialShareableWithParent = false; private boolean mDeleteAppWithParent = false; public Builder setShowInLauncher(@ShowInLauncher int showInLauncher) { mShowInLauncher = showInLauncher; Loading Loading @@ -886,6 +920,12 @@ public final class UserProperties implements Parcelable { return this; } /** Sets the value for {@link #mDeleteAppWithParent}*/ public Builder setDeleteAppWithParent(boolean deleteAppWithParent) { mDeleteAppWithParent = deleteAppWithParent; return this; } /** Builds a UserProperties object with *all* values populated. */ public UserProperties build() { return new UserProperties( Loading @@ -898,7 +938,8 @@ public final class UserProperties implements Parcelable { mCrossProfileIntentFilterAccessControl, mCrossProfileIntentResolutionStrategy, mMediaSharedWithParent, mCredentialShareableWithParent); mCredentialShareableWithParent, mDeleteAppWithParent); } } // end Builder Loading @@ -912,8 +953,8 @@ public final class UserProperties implements Parcelable { @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl, @CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy, boolean mediaSharedWithParent, boolean credentialShareableWithParent) { boolean credentialShareableWithParent, boolean deleteAppWithParent) { mDefaultProperties = null; setShowInLauncher(showInLauncher); setStartWithParent(startWithParent); Loading @@ -925,5 +966,6 @@ public final class UserProperties implements Parcelable { setCrossProfileIntentResolutionStrategy(crossProfileIntentResolutionStrategy); setMediaSharedWithParent(mediaSharedWithParent); setCredentialShareableWithParent(credentialShareableWithParent); setDeleteAppWithParent(deleteAppWithParent); } } services/core/java/com/android/server/pm/DeletePackageHelper.java +13 −8 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.SharedLibraryInfo; import android.content.pm.UserInfo; import android.content.pm.UserProperties; import android.content.pm.VersionedPackage; import android.net.Uri; import android.os.Binder; Loading Loading @@ -776,19 +777,23 @@ final class DeletePackageHelper { userId, deleteFlags, false /*removedBySystem*/); // Get a list of child user profiles and delete if package is // present in clone profile. // present in that profile. int[] childUserIds = mUserManagerInternal.getProfileIds(userId, true); int returnCodeOfChild; for (int childId : childUserIds) { if (childId != userId) { UserInfo userInfo = mUserManagerInternal.getUserInfo(childId); if (userInfo != null && userInfo.isCloneProfile()) { returnCode = deletePackageX(internalPackageName, versionCode, if (childId == userId) continue; UserProperties userProperties = mUserManagerInternal .getUserProperties(childId); if (userProperties != null && userProperties.getDeleteAppWithParent()) { returnCodeOfChild = deletePackageX(internalPackageName, versionCode, childId, deleteFlags, false /*removedBySystem*/); break; if (returnCodeOfChild != PackageManager.DELETE_SUCCEEDED) { Slog.w(TAG, "Package delete failed for user " + childId + ", returnCode " + returnCodeOfChild); returnCode = PackageManager.DELETE_FAILED_FOR_CHILD_PROFILE; } } } } else { int[] blockUninstallUserIds = getBlockUninstallForUsers(innerSnapshot, internalPackageName, users); Loading services/core/java/com/android/server/pm/UserTypeFactory.java +1 −1 Original line number Diff line number Diff line Loading @@ -136,7 +136,7 @@ public final class UserTypeFactory { .CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING) .setMediaSharedWithParent(true) .setCredentialShareableWithParent(true) ); .setDeleteAppWithParent(true)); } /** Loading services/tests/servicestests/res/xml/usertypes_test_profile.xml +3 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ crossProfileIntentResolutionStrategy='0' mediaSharedWithParent='true' credentialShareableWithParent='false' showInSettings='23' inheritDevicePolicy='450' deleteAppWithParent='false' /> </profile-type> <profile-type name='custom.test.1' max-allowed-per-parent='14' /> Loading Loading
core/java/android/content/pm/PackageManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -2399,6 +2399,14 @@ public abstract class PackageManager { */ public static final int DELETE_FAILED_APP_PINNED = -7; /** * Deletion failed return code: this is passed to the * {@link IPackageDeleteObserver} if the system failed to delete the package * for any child profile with {@link UserProperties#getDeleteAppWithParent()} as true. * @hide */ public static final int DELETE_FAILED_FOR_CHILD_PROFILE = -8; /** * Return code that is passed to the {@link IPackageMoveObserver} when the * package has been successfully moved by the system. Loading
core/java/android/content/pm/UserProperties.java +46 −4 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ public final class UserProperties implements Parcelable { "mediaSharedWithParent"; private static final String ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT = "credentialShareableWithParent"; private static final String ATTR_DELETE_APP_WITH_PARENT = "deleteAppWithParent"; /** Index values of each property (to indicate whether they are present in this object). */ @IntDef(prefix = "INDEX_", value = { Loading @@ -73,7 +74,8 @@ public final class UserProperties implements Parcelable { INDEX_CROSS_PROFILE_INTENT_FILTER_ACCESS_CONTROL, INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY, INDEX_MEDIA_SHARED_WITH_PARENT, INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT, INDEX_DELETE_APP_WITH_PARENT, }) @Retention(RetentionPolicy.SOURCE) private @interface PropertyIndex { Loading @@ -88,6 +90,7 @@ public final class UserProperties implements Parcelable { private static final int INDEX_CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY = 7; private static final int INDEX_MEDIA_SHARED_WITH_PARENT = 8; private static final int INDEX_CREDENTIAL_SHAREABLE_WITH_PARENT = 9; private static final int INDEX_DELETE_APP_WITH_PARENT = 10; /** A bit set, mapping each PropertyIndex to whether it is present (1) or absent (0). */ private long mPropertiesPresent = 0; Loading Loading @@ -312,6 +315,7 @@ public final class UserProperties implements Parcelable { setCrossProfileIntentFilterAccessControl( orig.getCrossProfileIntentFilterAccessControl()); setCrossProfileIntentResolutionStrategy(orig.getCrossProfileIntentResolutionStrategy()); setDeleteAppWithParent(orig.getDeleteAppWithParent()); } if (hasManagePermission) { // Add items that require MANAGE_USERS or stronger. Loading Loading @@ -417,6 +421,24 @@ public final class UserProperties implements Parcelable { } private boolean mStartWithParent; /** * Returns whether an app in the profile should be deleted when the same package in * the parent user is being deleted. * This only applies for users that have parents (i.e. for profiles). * @hide */ public boolean getDeleteAppWithParent() { if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) return mDeleteAppWithParent; if (mDefaultProperties != null) return mDefaultProperties.mDeleteAppWithParent; throw new SecurityException("You don't have permission to query deleteAppWithParent"); } /** @hide */ public void setDeleteAppWithParent(boolean val) { this.mDeleteAppWithParent = val; setPresent(INDEX_DELETE_APP_WITH_PARENT); } private boolean mDeleteAppWithParent; /** * Return whether, and how, select user restrictions or device policies should be inherited * from other user. Loading Loading @@ -609,6 +631,7 @@ public final class UserProperties implements Parcelable { + getCrossProfileIntentResolutionStrategy() + ", mMediaSharedWithParent=" + isMediaSharedWithParent() + ", mCredentialShareableWithParent=" + isCredentialShareableWithParent() + ", mDeleteAppWithParent=" + getDeleteAppWithParent() + "}"; } Loading @@ -634,6 +657,7 @@ public final class UserProperties implements Parcelable { pw.println(prefix + " mMediaSharedWithParent=" + isMediaSharedWithParent()); pw.println(prefix + " mCredentialShareableWithParent=" + isCredentialShareableWithParent()); pw.println(prefix + " mDeleteAppWithParent=" + getDeleteAppWithParent()); } /** Loading Loading @@ -697,6 +721,9 @@ public final class UserProperties implements Parcelable { case ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT: setCredentialShareableWithParent(parser.getAttributeBoolean(i)); break; case ATTR_DELETE_APP_WITH_PARENT: setDeleteAppWithParent(parser.getAttributeBoolean(i)); break; default: Slog.w(LOG_TAG, "Skipping unknown property " + attributeName); } Loading Loading @@ -752,6 +779,10 @@ public final class UserProperties implements Parcelable { serializer.attributeBoolean(null, ATTR_CREDENTIAL_SHAREABLE_WITH_PARENT, mCredentialShareableWithParent); } if (isPresent(INDEX_DELETE_APP_WITH_PARENT)) { serializer.attributeBoolean(null, ATTR_DELETE_APP_WITH_PARENT, mDeleteAppWithParent); } } // For use only with an object that has already had any permission-lacking fields stripped out. Loading @@ -768,6 +799,7 @@ public final class UserProperties implements Parcelable { dest.writeInt(mCrossProfileIntentResolutionStrategy); dest.writeBoolean(mMediaSharedWithParent); dest.writeBoolean(mCredentialShareableWithParent); dest.writeBoolean(mDeleteAppWithParent); } /** Loading @@ -788,6 +820,7 @@ public final class UserProperties implements Parcelable { mCrossProfileIntentResolutionStrategy = source.readInt(); mMediaSharedWithParent = source.readBoolean(); mCredentialShareableWithParent = source.readBoolean(); mDeleteAppWithParent = source.readBoolean(); } @Override Loading Loading @@ -825,6 +858,7 @@ public final class UserProperties implements Parcelable { CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT; private boolean mMediaSharedWithParent = false; private boolean mCredentialShareableWithParent = false; private boolean mDeleteAppWithParent = false; public Builder setShowInLauncher(@ShowInLauncher int showInLauncher) { mShowInLauncher = showInLauncher; Loading Loading @@ -886,6 +920,12 @@ public final class UserProperties implements Parcelable { return this; } /** Sets the value for {@link #mDeleteAppWithParent}*/ public Builder setDeleteAppWithParent(boolean deleteAppWithParent) { mDeleteAppWithParent = deleteAppWithParent; return this; } /** Builds a UserProperties object with *all* values populated. */ public UserProperties build() { return new UserProperties( Loading @@ -898,7 +938,8 @@ public final class UserProperties implements Parcelable { mCrossProfileIntentFilterAccessControl, mCrossProfileIntentResolutionStrategy, mMediaSharedWithParent, mCredentialShareableWithParent); mCredentialShareableWithParent, mDeleteAppWithParent); } } // end Builder Loading @@ -912,8 +953,8 @@ public final class UserProperties implements Parcelable { @CrossProfileIntentFilterAccessControlLevel int crossProfileIntentFilterAccessControl, @CrossProfileIntentResolutionStrategy int crossProfileIntentResolutionStrategy, boolean mediaSharedWithParent, boolean credentialShareableWithParent) { boolean credentialShareableWithParent, boolean deleteAppWithParent) { mDefaultProperties = null; setShowInLauncher(showInLauncher); setStartWithParent(startWithParent); Loading @@ -925,5 +966,6 @@ public final class UserProperties implements Parcelable { setCrossProfileIntentResolutionStrategy(crossProfileIntentResolutionStrategy); setMediaSharedWithParent(mediaSharedWithParent); setCredentialShareableWithParent(credentialShareableWithParent); setDeleteAppWithParent(deleteAppWithParent); } }
services/core/java/com/android/server/pm/DeletePackageHelper.java +13 −8 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.SharedLibraryInfo; import android.content.pm.UserInfo; import android.content.pm.UserProperties; import android.content.pm.VersionedPackage; import android.net.Uri; import android.os.Binder; Loading Loading @@ -776,19 +777,23 @@ final class DeletePackageHelper { userId, deleteFlags, false /*removedBySystem*/); // Get a list of child user profiles and delete if package is // present in clone profile. // present in that profile. int[] childUserIds = mUserManagerInternal.getProfileIds(userId, true); int returnCodeOfChild; for (int childId : childUserIds) { if (childId != userId) { UserInfo userInfo = mUserManagerInternal.getUserInfo(childId); if (userInfo != null && userInfo.isCloneProfile()) { returnCode = deletePackageX(internalPackageName, versionCode, if (childId == userId) continue; UserProperties userProperties = mUserManagerInternal .getUserProperties(childId); if (userProperties != null && userProperties.getDeleteAppWithParent()) { returnCodeOfChild = deletePackageX(internalPackageName, versionCode, childId, deleteFlags, false /*removedBySystem*/); break; if (returnCodeOfChild != PackageManager.DELETE_SUCCEEDED) { Slog.w(TAG, "Package delete failed for user " + childId + ", returnCode " + returnCodeOfChild); returnCode = PackageManager.DELETE_FAILED_FOR_CHILD_PROFILE; } } } } else { int[] blockUninstallUserIds = getBlockUninstallForUsers(innerSnapshot, internalPackageName, users); Loading
services/core/java/com/android/server/pm/UserTypeFactory.java +1 −1 Original line number Diff line number Diff line Loading @@ -136,7 +136,7 @@ public final class UserTypeFactory { .CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_NO_FILTERING) .setMediaSharedWithParent(true) .setCredentialShareableWithParent(true) ); .setDeleteAppWithParent(true)); } /** Loading
services/tests/servicestests/res/xml/usertypes_test_profile.xml +3 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,9 @@ crossProfileIntentResolutionStrategy='0' mediaSharedWithParent='true' credentialShareableWithParent='false' showInSettings='23' inheritDevicePolicy='450' deleteAppWithParent='false' /> </profile-type> <profile-type name='custom.test.1' max-allowed-per-parent='14' /> Loading