app clear data源码追踪

clear data 会重启app 因为AMS调用了 forceStopPackageLocked

1.入口 setting

packages\apps\TvSettings\Settings\src\com\android\tv\settings\device\apps\ClearDataPreference.java

  @Override
        public void onOk() {
            final AppManagementFragment fragment =
                    (AppManagementFragment) getTargetFragment();
            fragment.clearData();
        }

2.进入 AppManagementFragment 

packages\apps\TvSettings\Settings\src\com\android\tv\settings\device\apps\AppManagementFragment.java

    public void clearData() {
        if (!clearDataAllowed()) {
            Log.e(TAG, "Attempt to clear data failed. Clear data is disabled for " + mPackageName);
            return;
        }

        mClearDataPreference.setClearingData(true);
        String spaceManagementActivityName = mEntry.info.manageSpaceActivityName;
        if (spaceManagementActivityName != null) {
            if (!ActivityManager.isUserAMonkey()) {
                Intent intent = new Intent(Intent.ACTION_DEFAULT);
                intent.setClassName(mEntry.info.packageName, spaceManagementActivityName);
                startActivityForResult(intent, REQUEST_MANAGE_SPACE);
            }
        } else {
            // Disabling clear cache preference while clearing data is in progress. See b/77815256
            // for details.
            mClearCachePreference.setClearingCache(true);
            ActivityManager am = (ActivityManager) getActivity().getSystemService(
                    Context.ACTIVITY_SERVICE);
            boolean success = am.clearApplicationUserData(
                    mEntry.info.packageName, new IPackageDataObserver.Stub() {
                        public void onRemoveCompleted(
                                final String packageName, final boolean succeeded) {
                            mHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    mClearDataPreference.setClearingData(false);
                                    mClearCachePreference.setClearingCache(false);
                                    if (succeeded) {
                                        dataCleared(true);
                                    } else {
                                        dataCleared(false);
                                    }
                                }
                            });
                        }
                    });
            if (!success) {
                mClearDataPreference.setClearingData(false);
                dataCleared(false);
            }
        }
        mClearDataPreference.refresh();
    }

3.进入ActivityManager

frameworks\base\core\java\android\app\ActivityManager.java

    @RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA,
            Manifest.permission.ACCESS_INSTANT_APPS})
    @UnsupportedAppUsage
    public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
        try {
            return getService().clearApplicationUserData(packageName, false,
                    observer, mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    @UnsupportedAppUsage
    public static IActivityManager getService() {
        return (IActivityManager)IActivityManagerSingleton.get();
    }

4.进入  IActivityManager 

frameworks\base\core\java\android\app\IActivityManager.aidl

    boolean clearApplicationUserData(in String packageName, boolean keepState,
            in IPackageDataObserver observer, int userId);

5.具体方法实现在AMS

frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

    @Override
    public boolean clearApplicationUserData(final String packageName, boolean keepState,
            final IPackageDataObserver observer, int userId) {
        enforceNotIsolatedCaller("clearApplicationUserData");
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        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();
            synchronized(this) {
                // Instant packages are not protected
                if (getPackageManagerInternalLocked().isPackageDataProtected(
                        resolvedUserId, packageName)) {
                    throw new SecurityException(
                            "Cannot clear data for a protected package: " + packageName);
                }

                ApplicationInfo applicationInfo = null;
                try {
                    applicationInfo = pm.getApplicationInfo(packageName,
                            MATCH_UNINSTALLED_PACKAGES, resolvedUserId);
                } catch (RemoteException e) {
                    /* ignore */
                }
                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 {
                            observer.onRemoveCompleted(packageName, false);
                        } catch (RemoteException e) {
                            Slog.i(TAG, "Observer no longer exists.");
                        }
                    }
                    return false;
                }

                if (appInfo != null) {
                    forceStopPackageLocked(packageName, appInfo.uid, "clear data");
                    mAtmInternal.removeRecentTasksByPackageName(packageName, resolvedUserId);
                }
            }

            final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() {
                @Override
                public void onRemoveCompleted(String packageName, boolean succeeded)
                        throws RemoteException {
                    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, (appInfo != null) ? appInfo.uid : -1);
                    intent.putExtra(Intent.EXTRA_USER_HANDLE, resolvedUserId);
                    if (isInstantApp) {
                        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
                        broadcastIntentInPackage("android", null, SYSTEM_UID, uid, pid, intent,
                                null, null, 0, null, null, permission.ACCESS_INSTANT_APPS, null,
                                false, false, resolvedUserId, false);
                    } else {
                        broadcastIntentInPackage("android", null, SYSTEM_UID, uid, pid, intent,
                                null, null, 0, null, null, null, null, false, false, resolvedUserId,
                                false);
                    }

                    if (observer != null) {
                        observer.onRemoveCompleted(packageName, succeeded);
                    }
                }
            };

            try {
                // Clear application user data
                pm.clearApplicationUserData(packageName, localObserver, resolvedUserId);

                if (appInfo != null) {
                    // Restore already established notification state and permission grants,
                    // so it told us to keep those intact -- it's about to emplace app data
                    // that is appropriate for those bits of system state.
                    if (!keepState) {
                        // Remove all permissions granted from/to this package
                        mUgmInternal.removeUriPermissionsForPackage(packageName, resolvedUserId,
                                true, false);

                        // Reset notification state
                        INotificationManager inm = NotificationManager.getService();
                        inm.clearData(packageName, appInfo.uid, uid == appInfo.uid);
                    }

                    // Clear its scheduled jobs
                    JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
                    js.cancelJobsForUid(appInfo.uid, "clear data");

                    // Clear its pending alarms
                    AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
                    ami.removeAlarmsForUid(appInfo.uid);
                }
            } catch (RemoteException e) {
            }
        } finally {
            Binder.restoreCallingIdentity(callingId);
        }
        return true;
    }

6.进入 IPackageManager

frameworks/base/core/java/android/content/pm/IPackageManager.aidl

void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);

7.具体实现在PMS

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

    @Override
    public void clearApplicationUserData(final String packageName,
            final IPackageDataObserver observer, final int userId) {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.CLEAR_APP_USER_DATA, null);

        final int callingUid = Binder.getCallingUid();
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                true /* requireFullPermission */, false /* checkShell */, "clear application data");

        final PackageSetting ps = mSettings.getPackageLPr(packageName);
        final boolean filterApp =
                (ps != null && shouldFilterApplicationLocked(ps, callingUid, userId));
        if (!filterApp && mProtectedPackages.isPackageDataProtected(userId, packageName)) {
            throw new SecurityException("Cannot clear data for a protected package: "
                    + packageName);
        }
        // Queue up an async operation since the package deletion may take a little while.
        mHandler.post(new Runnable() {
            public void run() {
                mHandler.removeCallbacks(this);
                final boolean succeeded;
                if (!filterApp) {
                    try (PackageFreezer freezer = freezePackage(packageName,
                            "clearApplicationUserData")) {
                        synchronized (mInstallLock) {
                            succeeded = clearApplicationUserDataLIF(packageName, userId);
                        }
                        synchronized (mLock) {
                            mInstantAppRegistry.deleteInstantApplicationMetadataLPw(
                                    packageName, userId);
                        }
                    }
                    if (succeeded) {
                        // invoke DeviceStorageMonitor's update method to clear any notifications
                        DeviceStorageMonitorInternal dsm = LocalServices
                                .getService(DeviceStorageMonitorInternal.class);
                        if (dsm != null) {
                            dsm.checkMemory();
                        }
                        if (checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId)
                                == PERMISSION_GRANTED) {
                            unsuspendForSuspendingPackage(packageName, userId);
                            removeAllDistractingPackageRestrictions(userId);
                            flushPackageRestrictionsAsUserInternalLocked(userId);
                        }
                    }
                } else {
                    succeeded = false;
                }
                if (observer != null) {
                    try {
                        observer.onRemoveCompleted(packageName, succeeded);
                    } catch (RemoteException e) {
                        Log.i(TAG, "Observer no longer exists.");
                    }
                } //end if observer
            } //end run
        });
    }
    private boolean clearApplicationUserDataLIF(String packageName, int userId) {
        if (packageName == null) {
            Slog.w(TAG, "Attempt to delete null packageName.");
            return false;
        }

        // Try finding details about the requested package
        AndroidPackage pkg;
        PackageSetting ps;
        synchronized (mLock) {
            pkg = mPackages.get(packageName);
            ps = mSettings.mPackages.get(packageName);
            if (pkg == null) {
                if (ps != null) {
                    pkg = ps.pkg;
                }
            }
        }
        if (pkg == null) {
            Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
            return false;
        }
        mPermissionManager.resetRuntimePermissions(pkg, userId);

        clearAppDataLIF(pkg, userId,
                FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);

        final int appId = UserHandle.getAppId(pkg.getUid());
        removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), userId, appId);

        UserManagerInternal umInternal = mInjector.getUserManagerInternal();
        final int flags;
        if (umInternal.isUserUnlockingOrUnlocked(userId)) {
            flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
        } else if (umInternal.isUserRunning(userId)) {
            flags = StorageManager.FLAG_STORAGE_DE;
        } else {
            flags = 0;
        }
        prepareAppDataContentsLIF(pkg, ps, userId, flags);

        return true;
    }
    private void clearAppDataLIF(AndroidPackage pkg, int userId, int flags) {
        if (pkg == null) {
            Slog.wtf(TAG, "Package was null!", new Throwable());
            return;
        }
        clearAppDataLeafLIF(pkg, userId, flags);

        if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
            clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
        }
    }
    private void clearAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
        final PackageSetting ps;
        synchronized (mLock) {
            ps = mSettings.mPackages.get(pkg.getPackageName());
        }
        for (int realUserId : resolveUserIds(userId)) {
            final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
            try {
                mInstaller.clearAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId,
                        flags, ceDataInode);
            } catch (InstallerException e) {
                Slog.w(TAG, String.valueOf(e));
            }
        }
    }

8.进入 Installer

frameworks/base/services/core/java/com/android/server/pm/Installer.java

public void clearAppData(String uuid, String packageName, int userId, int flags,
            long ceDataInode) throws InstallerException {
        if (!checkBeforeRemote()) return;
        try {
            mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode);
        } catch (Exception e) {
            throw InstallerException.from(e);
        }
    }

9.进入 IInstalld

frameworks/native/cmds/installd/binder/android/os/IInstalld.aidl

void clearAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
            int userId, int flags, long ceDataInode);

10.具体清除动作在InstalldNativeService中定义 

frameworks\native\cmds\installd\InstalldNativeService.cpp

binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::string>& uuid,
        const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_UUID(uuid);
    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    std::lock_guard<std::recursive_mutex> lock(mLock);

    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
    const char* pkgname = packageName.c_str();

    binder::Status res = ok();
    if (flags & FLAG_STORAGE_CE) {
        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
        if (flags & FLAG_CLEAR_CACHE_ONLY) {
            path = read_path_inode(path, "cache", kXattrInodeCache);
        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
            path = read_path_inode(path, "code_cache", kXattrInodeCodeCache);
        }
        if (access(path.c_str(), F_OK) == 0) {
            if (delete_dir_contents(path) != 0) {
                res = error("Failed to delete contents of " + path);
            } else if ((flags & (FLAG_CLEAR_CACHE_ONLY | FLAG_CLEAR_CODE_CACHE_ONLY)) == 0) {
                remove_path_xattr(path, kXattrInodeCache);
                remove_path_xattr(path, kXattrInodeCodeCache);
            }
        }
    }
    if (flags & FLAG_STORAGE_DE) {
        std::string suffix = "";
        bool only_cache = false;
        if (flags & FLAG_CLEAR_CACHE_ONLY) {
            suffix = CACHE_DIR_POSTFIX;
            only_cache = true;
        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
            suffix = CODE_CACHE_DIR_POSTFIX;
            only_cache = true;
        }

        auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix;
        if (access(path.c_str(), F_OK) == 0) {
            if (delete_dir_contents(path) != 0) {
                res = error("Failed to delete contents of " + path);
            }
        }
    }
    if (flags & FLAG_STORAGE_EXTERNAL) {
        std::lock_guard<std::recursive_mutex> lock(mMountsLock);
        for (const auto& n : mStorageMounts) {
            auto extPath = n.second;

            if (android::base::GetBoolProperty(kFuseProp, false)) {
                std::regex re("^\\/mnt\\/pass_through\\/[0-9]+\\/emulated");
                if (std::regex_match(extPath, re)) {
                    extPath += "/" + std::to_string(userId);
                }
            } else {
                if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
                    extPath += StringPrintf("/%d", userId);
                } else if (userId != 0) {
                    // TODO: support devices mounted under secondary users
                    continue;
                }
            }

            if (flags & FLAG_CLEAR_CACHE_ONLY) {
                // Clear only cached data from shared storage
                auto path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname);
                if (delete_dir_contents(path, true) != 0) {
                    res = error("Failed to delete contents of " + path);
                }
            } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
                // No code cache on shared storage
            } else {
                // Clear everything on shared storage
                auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
                if (delete_dir_contents(path, true) != 0) {
                    res = error("Failed to delete contents of " + path);
                }
                path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
                if (delete_dir_contents(path, true) != 0) {
                    res = error("Failed to delete contents of " + path);
                }
                // Note that we explicitly don't delete OBBs - those are only removed on
                // app uninstall.
            }
        }
    }
    return res;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaowang_lj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值