文章目录

  • 如果在手机中卸载会有提示卸载页面等,这个一般是 UninstallerActivity;在这里点击卸载调用的是下面代码:
ActivityThread.getPackageManager().getPackageInstaller().uninstall(
                        new VersionedPackage(mDialogInfo.appInfo.packageName,
                                PackageManager.VERSION_CODE_HIGHEST),
                        getPackageName(), flags, pendingIntent.getIntentSender(),
                        mDialogInfo.user.getIdentifier());

上面代码是IPC操作 getPackageManager() 为下面代码

    public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
            return sPackageManager;
        }
        IBinder b = ServiceManager.getService("package");
        //Slog.v("PackageManager", "default service binder = " + b);
        sPackageManager = IPackageManager.Stub.asInterface(b);
        //Slog.v("PackageManager", "default service = " + sPackageManager);
        return sPackageManager;
    }

对应的IPackageManager 就是 PMS;所以调用的 PMS 中的 getPackageInstaller() ,代码如下:

    @Override
    public IPackageInstaller getPackageInstaller() {
        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
            return null;
        }
        return mInstallerService;
    }

mInstallerService 为 PackageInstallerService ,所以看一下 PackageInstallerService 中的 uninstall() 方法

PackageInstallerService >> uninstall()

@Override
 	private final PackageManagerService mPm;
    public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags,
                IntentSender statusReceiver, int userId) throws RemoteException {
        // 先获取 UID
        final int callingUid = Binder.getCallingUid();
        // 检查执行权限
        mPermissionManager.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
        if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
            mAppOps.checkPackage(callingUid, callerPackageName);
        }

        // Check whether the caller is device owner or affiliated profile owner, in which case we do
        // it silently.
        final int callingUserId = UserHandle.getUserId(callingUid);
        DevicePolicyManagerInternal dpmi =
                LocalServices.getService(DevicePolicyManagerInternal.class);
        final boolean isDeviceOwnerOrAffiliatedProfileOwner =
                dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
                        DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)
                        && dpmi.isUserAffiliatedWithDevice(callingUserId);

        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
                statusReceiver, versionedPackage.getPackageName(),
                isDeviceOwnerOrAffiliatedProfileOwner, userId);
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                    == PackageManager.PERMISSION_GRANTED) {
            // Sweet, call straight through!
            // 调用 mPm mPm.deletePackageVersioned 
            mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
        } else if (isDeviceOwnerOrAffiliatedProfileOwner) {
            // Allow the device owner and affiliated profile owner to silently delete packages
            // Need to clear the calling identity to get DELETE_PACKAGES permission
            long ident = Binder.clearCallingIdentity();
            try {
                mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        } else {
       		 // 需要和用户确认卸载消息
            ApplicationInfo appInfo = mPm.getApplicationInfo(callerPackageName, 0, userId);
            if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) {
                mContext.enforceCallingOrSelfPermission(Manifest.permission.REQUEST_DELETE_PACKAGES,
                        null);
            }

            // Take a short detour to confirm with user
            final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
            intent.setData(Uri.fromParts("package", versionedPackage.getPackageName(), null));
            intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder());
            adapter.onUserActionRequired(intent);
        }
    }

最后卸载调用了 mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags); 所以走到了 PackageManagerService 的 deletePackageVersioned()

  • deletePackageVersioned() 主要功能
    @Override
    public void deletePackageVersioned(VersionedPackage versionedPackage,
            final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
		// 获取 UID
        final int callingUid = Binder.getCallingUid();
        // 检查权限
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.DELETE_PACKAGES, null);
		// 。。。
		// 。。。
		// 卸载应用是耗时的 所以开启异步线程
		mHandler.post(new Runnable() {
            public void run() {
            	// 为了防止重复发送
                mHandler.removeCallbacks(this);
                int returnCode;
                // ...
                // ...
                // 最后就是调用了 deletePackageX 
                returnCode = deletePackageX(internalPackageName, versionCode,
                                userId, deleteFlags);
        });
	}
  • deletePackageX()
    int deletePackageX(String packageName, long versionCode, int userId, int deleteFlags) {
        final PackageRemovedInfo info = new PackageRemovedInfo(this);
        final boolean res;

        final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
                ? UserHandle.USER_ALL : userId;
        // 检查该用户是否有删除这个应用的权限
        if (isPackageDeviceAdmin(packageName, removeUser)) {
            Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
            return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
        }

        PackageSetting uninstalledPs = null;
        PackageParser.Package pkg = null;

        // for the uninstall-updates case and restricted profiles, remember the per-
        // user handle installed state
        int[] allUsers;
        synchronized (mPackages) {
            // 获取应用在 mSettings 中的信息
            uninstalledPs = mSettings.mPackages.get(packageName);
            if (uninstalledPs == null) {
                return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
            }
            if (versionCode != PackageManager.VERSION_CODE_HIGHEST
                    && uninstalledPs.versionCode != versionCode) {
                return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
            }
            pkg = mPackages.get(packageName);
            allUsers = sUserManager.getUserIds();

            if (pkg != null && pkg.staticSharedLibName != null) {
                SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(pkg.staticSharedLibName,
                        pkg.staticSharedLibVersion);
                if (libEntry != null) {
                    for (int currUserId : allUsers) {
                        if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
                            continue;
                        }
                        List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
                                libEntry.info, 0, currUserId);
                        if (!ArrayUtils.isEmpty(libClientPackages)) {
                            return PackageManager.DELETE_FAILED_USED_SHARED_LIBRARY;
                        }
                    }
                }
            }
            info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
        }

        final int freezeUser;
        if (isUpdatedSystemApp(uninstalledPs)
                && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
            freezeUser = UserHandle.USER_ALL;
        } else {
            freezeUser = removeUser;
        }
        synchronized (mInstallLock) {
            try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
                    deleteFlags, "deletePackageX")) {
                // 调用 deletePackageLIF 完成卸载应用
                res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
                        deleteFlags | PackageManager.DELETE_CHATTY, info, true, null);
            }
            synchronized (mPackages) {
                if (res) {
                    if (pkg != null) {
                        mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
                    }
                    updateSequenceNumberLP(uninstalledPs, info.removedUsers);
                    updateInstantAppInstallerLocked(packageName);
                }
            }
        }
        if (res) {
            final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
            info.sendPackageRemovedBroadcasts(killApp);
            info.sendSystemPackageUpdatedBroadcasts();
            info.sendSystemPackageAppearedBroadcasts();
        }
        // Force a gc here.
        Runtime.getRuntime().gc();
        // Delete the resources here after sending the broadcast to let
        // other processes clean up before deleting resources.
        if (info.args != null) {
            synchronized (mInstallLock) {
                info.args.doPostDeleteLI(true);
            }
        }
        return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
    }
  • deletePackageLIF()
    private boolean deletePackageLIF(String packageName, UserHandle user,
            boolean deleteCodeAndResources, int[] allUserHandles, int flags,
            PackageRemovedInfo outInfo, boolean writeSettings,
            PackageParser.Package replacingPackage) {
		// ...
		// ...
		if (((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
                && user.getIdentifier() != UserHandle.USER_ALL)) {
            // 调用者要求仅为单个用户删除包。
            // 为此,我们只需标记其已卸载状态并删除其数据。
            // 如果这是一个系统应用程序,只是标记状态和删除数据
            // 如果他们设置了特殊的DELETE_SYSTEM_APP,则将调用不同的方式卸载系统app
            
			// 设置一些状态属性
            markPackageUninstalledForUserLPw(ps, user);
            // 判断是不是系统 app
            if (!isSystemApp(ps)) {
                // Do not uninstall the APK if an app should be cached
                boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
                // 如果调用者只要求卸载某个用户下的应用
                if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
                    // Other user still have this package installed, so all
                    // we need to do is clear this user's data and save that
                    // it is uninstalled.
                    // 其他用户仍然安装了这个包,所以我们需要做的就是清除该用户的数据,并将其保存为已卸载。
                    if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
                    if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
                        return false;
                    }
                    scheduleWritePackageRestrictionsLocked(user);
                    return true;
                } else {
                    // We need to set it back to 'installed' so the uninstall
                    // broadcasts will be sent correctly.
                    if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
                    ps.setInstalled(true, user.getIdentifier());
                    mSettings.writeKernelMappingLPr(ps);
                }
            } else {
                // This is a system app, so we assume that the
                // other users still have this package installed, so all
                // we need to do is clear this user's data and save that
                // it is uninstalled.
                // 如果是系统应用程序,因此我们假设其他用户仍然安装了这个包,因此我们需要做的就是清除该用户的数据,并保存为已卸载。
                if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
                if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
                    return false;
                }
                scheduleWritePackageRestrictionsLocked(user);
                return true;
            }
        }
	
	// 安装的时候有安装包集 卸载也一样 查看packageSetting 下是否是复合包
	if (ps.childPackageNames != null && outInfo != null) {
            synchronized (mPackages) {
                final int childCount = ps.childPackageNames.size();
                outInfo.removedChildPackages = new ArrayMap<>(childCount);
                for (int i = 0; i < childCount; i++) {
                    String childPackageName = ps.childPackageNames.get(i);
                    PackageRemovedInfo childInfo = new PackageRemovedInfo(this);
                    childInfo.removedPackage = childPackageName;
                    childInfo.installerPackageName = ps.installerPackageName;
                    outInfo.removedChildPackages.put(childPackageName, childInfo);
                    PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
                    if (childPs != null) {
                        childInfo.origUsers = childPs.queryInstalledUsers(allUserHandles, true);
                    }
                }
            }
        }

	        boolean ret = false;
        if (isSystemApp(ps)) {
            if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
            // 当一个更新的系统应用程序被删除时,我们也会删除现有的资源 设置一下分区
            ret = deleteSystemPackageLIF(ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings);
        } else {
            // kill app ; 删除非系统的包和资源 ;删除各种缓存 和 为package.xml  packageSetting 修改对应的数据等
            ret = deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
                    outInfo, writeSettings, replacingPackage);
        }
		// ...
		// ...
	}

整体流程是根据不用用户删除app和数据;包括 package 和 PMS 等缓存数据等。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐