Android應(yīng)用生死輪回的那些事兒(2) - PackageManager
PMS對(duì)外的接口
如我們上節(jié)所講,在Android中,為應(yīng)用包的安裝,刪除各種操作服務(wù)的,是PackageManagerSerivce,簡(jiǎn)稱PMS.
如果想要調(diào)用PMS的服務(wù),則可以通過Context去調(diào)用getPackageManager方法。
這個(gè)定義于Context.java中:
/** Return PackageManager instance to find global package information. */
public abstract PackageManager getPackageManager();
我們先來(lái)看一張圖,了解PackageManager與PMS的關(guān)系:

package_manager_gv
PackageManager中定義的方法的前因后果
我們下面先以PackageManager中所提供的getApplicationInfo方法為例,看看它是如何被實(shí)現(xiàn)的。
PackageManager中的定義
ApplicationInfo getApplicationInfo (String packageName,int flags)
- packageName:包名
- flags:支持下面的標(biāo)志:
支持的標(biāo)志如下:
- GET_SHARED_LIBRARY_FILES:獲取so庫(kù)的安裝路徑,然后可以通過ApplicationInfo的sharedLibraryFiles屬性來(lái)讀取相關(guān)信息。
- MATCH_SYSTEM_ONLY:只包括帶有系統(tǒng)屬性的
- MATCH_UNINSTALLED_PACKAGES:即使是應(yīng)用被uninstall了,但只要保留了數(shù)據(jù),也可以被搜出來(lái)。
public abstract PackageInfo getPackageInfo(String packageName, int flags)
throws NameNotFoundException;
PackageManager的實(shí)現(xiàn) - ApplicationPackageManager
ApplicationPackageManager繼承了抽象類PackageManager.
final class ApplicationPackageManager extends PackageManager
ApplicationPackageManager是在ContextImpl中被new出來(lái)的:
@Override
public PackageManager getPackageManager() {
if (mPackageManager != null) {
return mPackageManager;
}
IPackageManager pm = ActivityThread.getPackageManager();
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;
}
ApplicationPackageManager中的第二個(gè)參數(shù)pm是溝通PMS的橋梁。
我們來(lái)看ActivityThread中g(shù)etPackageManager的實(shí)現(xiàn):
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
return sPackageManager;
}
IBinder b = ServiceManager.getService("package");
sPackageManager = IPackageManager.Stub.asInterface(b);
return sPackageManager;
}
ApplicationPackageManager中的實(shí)現(xiàn)
在ApplicationPackageManager類中,其實(shí)還是對(duì)PMS的對(duì)應(yīng)功能的封裝。
public ApplicationInfo getApplicationInfo(String packageName, int flags)
throws NameNotFoundException {
try {
ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, mContext.getUserId());
...
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(packageName);
}
PackageManagerService中真正落地
真正的實(shí)現(xiàn)還是要看PMS:
@Override
public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info");
// writer
synchronized (mPackages) {
PackageParser.Package p = mPackages.get(packageName);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getApplicationInfo " + packageName
+ ": " + p);
if (p != null) {
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) return null;
// Note: isEnabledLP() does not apply here - always return info
return PackageParser.generateApplicationInfo(
p, flags, ps.readUserState(userId), userId);
}
if ("android".equals(packageName)||"system".equals(packageName)) {
return mAndroidApplication;
}
if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
}
}
return null;
}