Loading core/java/android/app/ActivityManager.java +2 −0 Original line number Diff line number Diff line Loading @@ -2907,6 +2907,8 @@ public class ActivityManager { /** * @hide */ @RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA, Manifest.permission.ACCESS_INSTANT_APPS}) public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) { try { return getService().clearApplicationUserData(packageName, Loading core/java/android/content/Intent.java +6 −1 Original line number Diff line number Diff line Loading @@ -2225,7 +2225,12 @@ public class Intent implements Parcelable, Cloneable { * Note that the cleared package does <em>not</em> * receive this broadcast. The data contains the name of the package. * <ul> * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. If the * package whose data was cleared is an uninstalled instant app, then the UID * will be -1. The platform keeps some meta-data associated with instant apps * after they are uninstalled. * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name only if the cleared * data was for an instant app. * </ul> * * <p class="note">This is a protected intent that can only be sent Loading core/java/android/content/pm/PackageManagerInternal.java +7 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.ComponentInfoFlags; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.pm.PackageManager.ResolveInfoFlags; import android.os.Bundle; Loading Loading @@ -372,4 +371,11 @@ public abstract class PackageManagerInternal { /** Whether the binder caller can access instant apps. */ public abstract boolean canAccessInstantApps(int callingUid, int userId); /** * Returns {@code true} if a given package has instant application meta-data. * Otherwise, returns {@code false}. Meta-data is state (eg. cookie, app icon, etc) * associated with an instant app. It may be kept after the instant app has been uninstalled. */ public abstract boolean hasInstantApplicationMetadata(String packageName, int userId); } services/core/java/com/android/server/am/ActivityManagerService.java +69 −40 Original line number Diff line number Diff line Loading @@ -5848,26 +5848,53 @@ public class ActivityManagerService extends IActivityManager.Stub enforceNotIsolatedCaller("clearApplicationUserData"); int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); userId = mUserController.handleIncomingUser(pid, uid, userId, false, final int resolvedUserId = mUserController.handleIncomingUser(pid, uid, userId, false, ALLOW_FULL_ONLY, "clearApplicationUserData", null); final ApplicationInfo appInfo; final boolean isInstantApp; long callingId = Binder.clearCallingIdentity(); try { IPackageManager pm = AppGlobals.getPackageManager(); int pkgUid = -1; synchronized(this) { // Instant packages are not protected if (getPackageManagerInternalLocked().isPackageDataProtected( userId, packageName)) { resolvedUserId, packageName)) { throw new SecurityException( "Cannot clear data for a protected package: " + packageName); } ApplicationInfo applicationInfo = null; try { pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId); applicationInfo = pm.getApplicationInfo(packageName, MATCH_UNINSTALLED_PACKAGES, resolvedUserId); } catch (RemoteException e) { /* ignore */ } if (pkgUid == -1) { appInfo = applicationInfo; final boolean clearingOwnUidData = appInfo != null && appInfo.uid == uid; if (!clearingOwnUidData && checkComponentPermission(permission.CLEAR_APP_USER_DATA, pid, uid, -1, true) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("PID " + pid + " does not have permission " + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data" + " of package " + packageName); } final boolean hasInstantMetadata = getPackageManagerInternalLocked() .hasInstantApplicationMetadata(packageName, resolvedUserId); final boolean isUninstalledAppWithoutInstantMetadata = (appInfo == null && !hasInstantMetadata); isInstantApp = (appInfo != null && appInfo.isInstantApp()) || hasInstantMetadata; final boolean canAccessInstantApps = checkComponentPermission( permission.ACCESS_INSTANT_APPS, pid, uid, -1, true) == PackageManager.PERMISSION_GRANTED; if (isUninstalledAppWithoutInstantMetadata || (isInstantApp && !canAccessInstantApps)) { Slog.w(TAG, "Invalid packageName: " + packageName); if (observer != null) { try { Loading @@ -5878,45 +5905,45 @@ public class ActivityManagerService extends IActivityManager.Stub } return false; } if (uid == pkgUid || checkComponentPermission( android.Manifest.permission.CLEAR_APP_USER_DATA, pid, uid, -1, true) == PackageManager.PERMISSION_GRANTED) { forceStopPackageLocked(packageName, pkgUid, "clear data"); } else { throw new SecurityException("PID " + pid + " does not have permission " + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data" + " of package " + packageName); } if (appInfo != null) { forceStopPackageLocked(packageName, appInfo.uid, "clear data"); // Remove all tasks match the cleared application package and user for (int i = mRecentTasks.size() - 1; i >= 0; i--) { final TaskRecord tr = mRecentTasks.get(i); final String taskPackageName = tr.getBaseIntent().getComponent().getPackageName(); if (tr.userId != userId) continue; if (tr.userId != resolvedUserId) continue; if (!taskPackageName.equals(packageName)) continue; mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS); mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS); } } } final int pkgUidF = pkgUid; final int userIdF = userId; final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() { @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { if (appInfo != null) { synchronized (ActivityManagerService.this) { finishForceStopPackageLocked(packageName, pkgUidF); finishForceStopPackageLocked(packageName, appInfo.uid); } } final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED, Uri.fromParts("package", packageName, null)); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putExtra(Intent.EXTRA_UID, pkgUidF); intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF)); broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, null, null, null, null, false, false, userIdF); intent.putExtra(Intent.EXTRA_UID, (appInfo != null) ? appInfo.uid : -1); intent.putExtra(Intent.EXTRA_USER_HANDLE, resolvedUserId); if (isInstantApp) { intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, null, null, permission.ACCESS_INSTANT_APPS, null, false, false, resolvedUserId); } else { broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, null, null, null, null, false, false, resolvedUserId); } if (observer != null) { observer.onRemoveCompleted(packageName, succeeded); Loading @@ -5926,16 +5953,18 @@ public class ActivityManagerService extends IActivityManager.Stub try { // Clear application user data pm.clearApplicationUserData(packageName, localObserver, userId); pm.clearApplicationUserData(packageName, localObserver, resolvedUserId); if (appInfo != null) { synchronized (this) { // Remove all permissions granted from/to this package removeUriPermissionsForPackageLocked(packageName, userId, true); removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true); } // Reset notification settings. INotificationManager inm = NotificationManager.getService(); inm.clearData(packageName, pkgUidF, uid == pkgUidF); inm.clearData(packageName, appInfo.uid, uid == appInfo.uid); } } catch (RemoteException e) { } } finally { services/core/java/com/android/server/pm/InstantAppRegistry.java +33 −1 Original line number Diff line number Diff line Loading @@ -504,6 +504,11 @@ class InstantAppRegistry { } } boolean hasInstantApplicationMetadataLPr(String packageName, int userId) { return hasUninstalledInstantAppStateLPr(packageName, userId) || hasInstantAppMetadataLPr(packageName, userId); } public void deleteInstantApplicationMetadataLPw(@NonNull String packageName, @UserIdInt int userId) { removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> Loading Loading @@ -547,6 +552,33 @@ class InstantAppRegistry { } } private boolean hasUninstalledInstantAppStateLPr(String packageName, @UserIdInt int userId) { if (mUninstalledInstantApps == null) { return false; } final List<UninstalledInstantAppState> uninstalledAppStates = mUninstalledInstantApps.get(userId); if (uninstalledAppStates == null) { return false; } final int appCount = uninstalledAppStates.size(); for (int i = 0; i < appCount; i++) { final UninstalledInstantAppState uninstalledAppState = uninstalledAppStates.get(i); if (packageName.equals(uninstalledAppState.mInstantAppInfo.getPackageName())) { return true; } } return false; } private boolean hasInstantAppMetadataLPr(String packageName, @UserIdInt int userId) { final File instantAppDir = getInstantApplicationDir(packageName, userId); return new File(instantAppDir, INSTANT_APP_METADATA_FILE).exists() || new File(instantAppDir, INSTANT_APP_ICON_FILE).exists() || new File(instantAppDir, INSTANT_APP_ANDROID_ID_FILE).exists() || peekInstantCookieFile(packageName, userId) != null; } void pruneInstantApps() { final long maxInstalledCacheDuration = Settings.Global.getLong( mService.mContext.getContentResolver(), Loading Loading
core/java/android/app/ActivityManager.java +2 −0 Original line number Diff line number Diff line Loading @@ -2907,6 +2907,8 @@ public class ActivityManager { /** * @hide */ @RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA, Manifest.permission.ACCESS_INSTANT_APPS}) public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) { try { return getService().clearApplicationUserData(packageName, Loading
core/java/android/content/Intent.java +6 −1 Original line number Diff line number Diff line Loading @@ -2225,7 +2225,12 @@ public class Intent implements Parcelable, Cloneable { * Note that the cleared package does <em>not</em> * receive this broadcast. The data contains the name of the package. * <ul> * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. If the * package whose data was cleared is an uninstalled instant app, then the UID * will be -1. The platform keeps some meta-data associated with instant apps * after they are uninstalled. * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name only if the cleared * data was for an instant app. * </ul> * * <p class="note">This is a protected intent that can only be sent Loading
core/java/android/content/pm/PackageManagerInternal.java +7 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.ComponentInfoFlags; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.pm.PackageManager.ResolveInfoFlags; import android.os.Bundle; Loading Loading @@ -372,4 +371,11 @@ public abstract class PackageManagerInternal { /** Whether the binder caller can access instant apps. */ public abstract boolean canAccessInstantApps(int callingUid, int userId); /** * Returns {@code true} if a given package has instant application meta-data. * Otherwise, returns {@code false}. Meta-data is state (eg. cookie, app icon, etc) * associated with an instant app. It may be kept after the instant app has been uninstalled. */ public abstract boolean hasInstantApplicationMetadata(String packageName, int userId); }
services/core/java/com/android/server/am/ActivityManagerService.java +69 −40 Original line number Diff line number Diff line Loading @@ -5848,26 +5848,53 @@ public class ActivityManagerService extends IActivityManager.Stub enforceNotIsolatedCaller("clearApplicationUserData"); int uid = Binder.getCallingUid(); int pid = Binder.getCallingPid(); userId = mUserController.handleIncomingUser(pid, uid, userId, false, final int resolvedUserId = mUserController.handleIncomingUser(pid, uid, userId, false, ALLOW_FULL_ONLY, "clearApplicationUserData", null); final ApplicationInfo appInfo; final boolean isInstantApp; long callingId = Binder.clearCallingIdentity(); try { IPackageManager pm = AppGlobals.getPackageManager(); int pkgUid = -1; synchronized(this) { // Instant packages are not protected if (getPackageManagerInternalLocked().isPackageDataProtected( userId, packageName)) { resolvedUserId, packageName)) { throw new SecurityException( "Cannot clear data for a protected package: " + packageName); } ApplicationInfo applicationInfo = null; try { pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId); applicationInfo = pm.getApplicationInfo(packageName, MATCH_UNINSTALLED_PACKAGES, resolvedUserId); } catch (RemoteException e) { /* ignore */ } if (pkgUid == -1) { appInfo = applicationInfo; final boolean clearingOwnUidData = appInfo != null && appInfo.uid == uid; if (!clearingOwnUidData && checkComponentPermission(permission.CLEAR_APP_USER_DATA, pid, uid, -1, true) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("PID " + pid + " does not have permission " + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data" + " of package " + packageName); } final boolean hasInstantMetadata = getPackageManagerInternalLocked() .hasInstantApplicationMetadata(packageName, resolvedUserId); final boolean isUninstalledAppWithoutInstantMetadata = (appInfo == null && !hasInstantMetadata); isInstantApp = (appInfo != null && appInfo.isInstantApp()) || hasInstantMetadata; final boolean canAccessInstantApps = checkComponentPermission( permission.ACCESS_INSTANT_APPS, pid, uid, -1, true) == PackageManager.PERMISSION_GRANTED; if (isUninstalledAppWithoutInstantMetadata || (isInstantApp && !canAccessInstantApps)) { Slog.w(TAG, "Invalid packageName: " + packageName); if (observer != null) { try { Loading @@ -5878,45 +5905,45 @@ public class ActivityManagerService extends IActivityManager.Stub } return false; } if (uid == pkgUid || checkComponentPermission( android.Manifest.permission.CLEAR_APP_USER_DATA, pid, uid, -1, true) == PackageManager.PERMISSION_GRANTED) { forceStopPackageLocked(packageName, pkgUid, "clear data"); } else { throw new SecurityException("PID " + pid + " does not have permission " + android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data" + " of package " + packageName); } if (appInfo != null) { forceStopPackageLocked(packageName, appInfo.uid, "clear data"); // Remove all tasks match the cleared application package and user for (int i = mRecentTasks.size() - 1; i >= 0; i--) { final TaskRecord tr = mRecentTasks.get(i); final String taskPackageName = tr.getBaseIntent().getComponent().getPackageName(); if (tr.userId != userId) continue; if (tr.userId != resolvedUserId) continue; if (!taskPackageName.equals(packageName)) continue; mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS); mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS); } } } final int pkgUidF = pkgUid; final int userIdF = userId; final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() { @Override public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException { if (appInfo != null) { synchronized (ActivityManagerService.this) { finishForceStopPackageLocked(packageName, pkgUidF); finishForceStopPackageLocked(packageName, appInfo.uid); } } final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED, Uri.fromParts("package", packageName, null)); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); intent.putExtra(Intent.EXTRA_UID, pkgUidF); intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF)); broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, null, null, null, null, false, false, userIdF); intent.putExtra(Intent.EXTRA_UID, (appInfo != null) ? appInfo.uid : -1); intent.putExtra(Intent.EXTRA_USER_HANDLE, resolvedUserId); if (isInstantApp) { intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, null, null, permission.ACCESS_INSTANT_APPS, null, false, false, resolvedUserId); } else { broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0, null, null, null, null, false, false, resolvedUserId); } if (observer != null) { observer.onRemoveCompleted(packageName, succeeded); Loading @@ -5926,16 +5953,18 @@ public class ActivityManagerService extends IActivityManager.Stub try { // Clear application user data pm.clearApplicationUserData(packageName, localObserver, userId); pm.clearApplicationUserData(packageName, localObserver, resolvedUserId); if (appInfo != null) { synchronized (this) { // Remove all permissions granted from/to this package removeUriPermissionsForPackageLocked(packageName, userId, true); removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true); } // Reset notification settings. INotificationManager inm = NotificationManager.getService(); inm.clearData(packageName, pkgUidF, uid == pkgUidF); inm.clearData(packageName, appInfo.uid, uid == appInfo.uid); } } catch (RemoteException e) { } } finally {
services/core/java/com/android/server/pm/InstantAppRegistry.java +33 −1 Original line number Diff line number Diff line Loading @@ -504,6 +504,11 @@ class InstantAppRegistry { } } boolean hasInstantApplicationMetadataLPr(String packageName, int userId) { return hasUninstalledInstantAppStateLPr(packageName, userId) || hasInstantAppMetadataLPr(packageName, userId); } public void deleteInstantApplicationMetadataLPw(@NonNull String packageName, @UserIdInt int userId) { removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> Loading Loading @@ -547,6 +552,33 @@ class InstantAppRegistry { } } private boolean hasUninstalledInstantAppStateLPr(String packageName, @UserIdInt int userId) { if (mUninstalledInstantApps == null) { return false; } final List<UninstalledInstantAppState> uninstalledAppStates = mUninstalledInstantApps.get(userId); if (uninstalledAppStates == null) { return false; } final int appCount = uninstalledAppStates.size(); for (int i = 0; i < appCount; i++) { final UninstalledInstantAppState uninstalledAppState = uninstalledAppStates.get(i); if (packageName.equals(uninstalledAppState.mInstantAppInfo.getPackageName())) { return true; } } return false; } private boolean hasInstantAppMetadataLPr(String packageName, @UserIdInt int userId) { final File instantAppDir = getInstantApplicationDir(packageName, userId); return new File(instantAppDir, INSTANT_APP_METADATA_FILE).exists() || new File(instantAppDir, INSTANT_APP_ICON_FILE).exists() || new File(instantAppDir, INSTANT_APP_ANDROID_ID_FILE).exists() || peekInstantCookieFile(packageName, userId) != null; } void pruneInstantApps() { final long maxInstalledCacheDuration = Settings.Global.getLong( mService.mContext.getContentResolver(), Loading