Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e03f73e3 authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge "Merge "Allow clearing instant app meta-data" into oc-mr1-dev am: e3911753 am: a8037074"

parents 03ee1cc3 50f75df6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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,
+6 −1
Original line number Diff line number Diff line
@@ -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
+7 −1
Original line number Diff line number Diff line
@@ -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);
}
+69 −40
Original line number Diff line number Diff line
@@ -5845,26 +5845,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 {
@@ -5875,45 +5902,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);
@@ -5923,16 +5950,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 {
+33 −1
Original line number Diff line number Diff line
@@ -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(),
Loading