Merge "Allow clearing instant app meta-data" into oc-mr1-dev

am: e391175330

Change-Id: I35fea7acf6bd4084b06cb17c580c75df08ef484c
This commit is contained in:
Svet Ganov
2017-08-22 23:39:07 +00:00
committed by android-build-merger
6 changed files with 124 additions and 43 deletions

View File

@@ -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,

View File

@@ -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

View File

@@ -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;
@@ -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);
}

View File

@@ -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 {
@@ -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);
}
// 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 (!taskPackageName.equals(packageName)) continue;
mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS);
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 != resolvedUserId) continue;
if (!taskPackageName.equals(packageName)) continue;
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 {
synchronized (ActivityManagerService.this) {
finishForceStopPackageLocked(packageName, pkgUidF);
if (appInfo != null) {
synchronized (ActivityManagerService.this) {
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);
@@ -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);
synchronized(this) {
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(packageName, userId, true);
if (appInfo != null) {
synchronized (this) {
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(packageName, resolvedUserId, true);
}
// Reset notification settings.
INotificationManager inm = NotificationManager.getService();
inm.clearData(packageName, appInfo.uid, uid == appInfo.uid);
}
// Reset notification settings.
INotificationManager inm = NotificationManager.getService();
inm.clearData(packageName, pkgUidF, uid == pkgUidF);
} catch (RemoteException e) {
}
} finally {

View File

@@ -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) ->
@@ -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(),
@@ -1071,7 +1103,7 @@ class InstantAppRegistry {
}
private static @NonNull File getInstantApplicationDir(String packageName, int userId) {
return new File (getInstantApplicationsDir(userId), packageName);
return new File(getInstantApplicationsDir(userId), packageName);
}
private static void deleteDir(@NonNull File dir) {

View File

@@ -25452,6 +25452,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
public boolean canAccessInstantApps(int callingUid, int userId) {
return PackageManagerService.this.canViewInstantApps(callingUid, userId);
}
@Override
public boolean hasInstantApplicationMetadata(String packageName, int userId) {
synchronized (mPackages) {
return mInstantAppRegistry.hasInstantApplicationMetadataLPr(packageName, userId);
}
}
}
@Override