首页 > 学院 > 开发设计 > 正文

pms包管理服务分析-apk卸载流程

2019-11-09 17:27:01
字体:
来源:转载
供稿:网友

apk的卸载流程相对比较简单,总结大方向就两步,一个是删除安装的文件和数据,另外一个是清除内存信息。另外要注意的是在多用户模式下,apk的卸载删除则不是单纯的删除文件。

下面来看看apk的卸载流程。

[/frameworks/base/core/java/android/app/applicationPackageManager.java]

    @Override    public void deletePackage(String packageName, ipackageDeleteObserver observer, int flags) {        try {            mPM.deletePackageAsUser(packageName, observer, UserHandle.myUserId(), flags);        } catch (RemoteException e) {            // Should never happen!        }    }

Client端调用PackageManager的deletePackage方法删除对应包名的apk,其中通过注册IPackageDeleteObserver监听卸载结果。实际上通过binder调用pms的deletePackageAsUser方法,在服务中执行卸载动作。

[/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java]

@Overridepublic void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int userId,		int flags) {	deletePackage(packageName, new LegacyPackageDeleteObserver(observer).getBinder(), userId,			flags);}

@Override

public void deletePackage(final String packageName,

final IPackageDeleteObserver observer, final int userId, final int flags) {

mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES, null);

if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {

try {

observer.onPackageDeleted(packageName,PackageManager.DELETE_FAILED_USER_RESTRICTED, null);

} catch (RemoteException re) {

}

return;

}

// 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 int returnCode = deletePackageX(packageName, userId, flags);

if (observer != null) {

try {

observer.onPackageDeleted(packageName, returnCode, null);

} catch (RemoteException e) {

Log.i(TAG, "Observer no longer exists.");

} //end catch

} //end if

} //end run

});

}

deletePackageAsUser调用delePackage方法,先校验调用方是否有DELETE_PACKAGE权限,再检查UserRestriction行为限制,都pass以后异步执行deletePackageX方法,最后将结果通过IpackageDeleteObserver返回。下面来看看deletePackageX方法的内容。

    PRivate int deletePackageX(String packageName, int userId, int flags) {        final PackageRemovedInfo info = new PackageRemovedInfo();        final boolean res;        if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {            return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;        }        synchronized (mInstallLock) {            res = deletePackageLI(packageName, removeForUser,true, allUsers, perUserInstalled,                    flags | REMOVE_CHATTY, info, true);            systemUpdate = info.isRemovedPackageSystemUpdate;            if (res && !systemUpdate && mPackages.get(packageName) == null) {                removedForAllUsers = true;            }        }        // Force a gc here.        Runtime.getRuntime().gc();        if (info.args != null) {            synchronized (mInstallLock) {                info.args.doPostDeleteLI(true);            }        }        return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;    }

deletePackageX方法中首先创建PackageRemoveInfo实例,PackageRemoveInfo类结构如下图,主要保存删除应用的基本信息。

然后检查删除的应用是否已激活的DeviceManager,如果是则返回卸载失败,要求先取消激活。

如果没问题继续执行deletePackageLI方法,传入PackageRemoveInfo实例用于记录卸载后应用的基本信息。

    private boolean deletePackageLI(String packageName, UserHandle user,            boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,            int flags, PackageRemovedInfo outInfo,            boolean writeSettings) {        if (packageName == null) {            Slog.w(TAG, "Attempt to delete null packageName.");            return false;        }        PackageSetting ps;        boolean dataOnly = false;        int removeUser = -1;        int appId = -1;        synchronized (mPackages) {            ps = mSettings.mPackages.get(packageName);        }        boolean ret = false;        if (isSystemApp(ps)) {            ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,flags, outInfo, writeSettings);        } else {            killApplication(packageName, ps.appId, "uninstall pkg");            ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags,                    allUserHandles, perUserInstalled,                    outInfo, writeSettings);        }        return ret;    }

针对系统应用的卸载我们暂时不跟,来跟下最普遍的第三方应用的卸载过程。在deletePackageLI方法中根据包名获得对应的PackageSetting实例,首先调用killApplication方法杀死应用进程后执行deleteInstalledPackageLI方法删除应用数据。

    private boolean deleteInstalledPackageLI(PackageSetting ps, boolean deleteCodeAndResources, int flags,            int[] allUserHandles, boolean[] perUserInstalled, PackageRemovedInfo outInfo, boolean writeSettings) {        if (outInfo != null) {            outInfo.uid = ps.appId;        }        // Delete package data from internal structures and also remove data if flag is set        removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings);        return true;    }

最后调用removePakcageDataLI方法。

    private void removePackageDataLI(PackageSetting ps, int[] allUserHandles, boolean[] perUserInstalled,            PackageRemovedInfo outInfo, int flags, boolean writeSettings) {        String packageName = ps.name;        if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);        removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);        final PackageSetting deletedPs;        synchronized (mPackages) {            deletedPs = mSettings.mPackages.get(packageName);            if (outInfo != null) {                outInfo.removedPackage = packageName;                outInfo.removedUsers = deletedPs != null                        ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true) : null;            }        }        if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {            removeDataDirsLI(ps.volumeUuid, packageName);            schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);        }        if (outInfo != null) {            // A user ID was deleted here. Go through all users and remove it            // from KeyStore.            removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId);        }    }

removePakcageDataLI方法是重点,这里主要和开头说的两点,删除内存数据,删除安装文件。

首先调用removePackageLI方法删除应用的内存数据,主要有在mPackages总安装应用列表中删除对应实例,清除所有应用组件,如activity, provider, service, contentresolver, receiver, permissions等,方法内容如下:

    void removePackageLI(PackageSetting ps, boolean chatty) {        // writer        synchronized (mPackages) {            mPackages.remove(ps.name);            final PackageParser.Package pkg = ps.pkg;            if (pkg != null) {                cleanPackageDataStructuresLILPw(pkg, chatty);            }        }    }    void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {        int N = pkg.providers.size();        int i;        for (i=0; i<N; i++) {            PackageParser.Provider p = pkg.providers.get(i);            mProviders.removeProvider(p);	  }        N = pkg.services.size();        r = null;        for (i=0; i<N; i++) {            PackageParser.Service s = pkg.services.get(i);            mServices.removeService(s);        }        …}

然后调用removeDataDirsLI删除应用的安装和数据文件。

    private int removeDataDirsLI(String volumeUuid, String packageName) {        int[] users = sUserManager.getUserIds();        int res = 0;        for (int user : users) {            int resInner = mInstaller.remove(volumeUuid, packageName, user);            if (resInner < 0) {                res = resInner;            }        }        return res;    }

至此第三方应用的卸载过程如上所述,当然还有很多细节内容需要一点点的发散去学习。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表