Android應用框架之PackageManagerService
系統在啟動的時候會啟動一個叫做PackageManagerService
的服務,顧名思義,這個服務主要管理安裝在裝置上的應用程式,其中最為重要的工作就是在在系統啟動之後,PackageManagerService
會掃描特定目錄下地以apk為字尾的檔案,然後將對應的應用安裝到系統中。注意,這裡的安裝並不是我們平時所說的安裝,它指的的是將存放在磁碟之上的靜態應用程式檔案進行解析,並將相關資訊註冊到系統中。而具體的解析工作實際就是讀取應用的配置檔案manifest.xml
,並將檔案中配置的元件
(Activity
,Service
,BroadcastRecevier
,ContentProvider
),許可權等資訊註冊到PackageManagerService
本篇部落格主要介紹
PackageManagerService
的啟動過程,以及PackageManagerService
如何安裝各個應用程式。
1.PackageManagerService
啟動過程
和ActivityManagerService
,WindowManagerService
一樣,PackageManagerService
是一個系統級的服務,執行在獨立的程序中,而所有的系統級服務都是由SystemServer
啟動的。所以首先來看看SystemServer
的啟動過程。
1) SystemServer
啟動:
SystemServer元件是由Zygote程序負責啟動的,啟動的時候就會呼叫它的main函式,這個函式主要呼叫了JNI方法init1來做一些系統初始化的工作。
public class SystemServer
{
......
native public static void init1(String[] args);
......
public static void main(String[] args) {
......
init1(args);
......
}
......
}
2)SystemServer.system_init
經過一系列呼叫後轉到system_init
方法,這是一個JNI方法
extern "C" status_t system_init()
{
LOGI("Entered system_init()" );
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p\n", sm.get());
sp<GrimReaper> grim = new GrimReaper();
sm->asBinder()->linkToDeath(grim, grim.get(), 0);
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsurfaceflinger", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the SurfaceFlinger
SurfaceFlinger::instantiate();
}
// Start the sensor service
SensorService::instantiate();
// On the simulator, audioflinger et al don't get started the
// same way as on the device, and we need to start them here
if (!proc->supportsProcesses()) {
// Start the AudioFlinger
AudioFlinger::instantiate();
// Start the media playback service
MediaPlayerService::instantiate();
// Start the camera service
CameraService::instantiate();
// Start the audio policy service
AudioPolicyService::instantiate();
}
// And now start the Android runtime. We have to do this bit
// of nastiness because the Android runtime initialization requires
// some of the core system services to already be started.
// All other servers should just start the Android runtime at
// the beginning of their processes's main(), before calling
// the init function.
LOGI("System server: starting Android runtime.\n");
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
LOGI("System server: starting Android services.\n");
runtime->callStatic("com/android/server/SystemServer", "init2");
// If running in our own process, just go into the thread
// pool. Otherwise, call the initialization finished
// func to let this process continue its initilization.
if (proc->supportsProcesses()) {
LOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting thread pool.\n");
}
return NO_ERROR;
}
在這個方法中,建立了SurfaceFlinger、SensorService、AudioFlinger、MediaPlayerService、CameraService和AudioPolicyService這幾個服務,然後就通過系統全域性唯一的AndroidRuntime例項變數runtime的callStatic來呼叫SystemServer的init2函數了。init2函式很簡單,建立一個執行緒,而PackageManagerService
就是在這個執行緒中建立的。
public class SystemServer
{
......
public static final void init2() {
Slog.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
}
3)ServerThread.run
class ServerThread extends Thread {
......
@Override
public void run() {
......
IPackageManager pm = null;
......
// Critical services...
try {
......
Slog.i(TAG, "Package Manager");
pm = PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF);
......
} catch (RuntimeException e) {
Slog.e("System", "Failure starting core service", e);
}
......
}
......
}
在這個執行緒中建立了PackageManagerService
,並同時啟動了其main函式。另外在這個執行緒中還啟動了ActivityManagerService
等其他Service
2.應用安裝
接下來再來看看PackageManagerService
啟動之後如何進行應用程式的安裝。
1)PackageManagerService.main
class PackageManagerService extends IPackageManager.Stub {
......
public static final IPackageManager main(Context context, boolean factoryTest) {
PackageManagerService m = new PackageManagerService(context, factoryTest);
ServiceManager.addService("package", m);
return m;
}
......
}
可以看到,建立完成後,就載入到ServiceManager
中。接下來看看PackageManagerService
的建構函式:
class PackageManagerService extends IPackageManager.Stub {
......
public PackageManagerService(Context context, boolean factoryTest) {
......
synchronized (mInstallLock) {
synchronized (mPackages) {
......
File dataDir = Environment.getDataDirectory();
mAppDataDir = new File(dataDir, "data");
mSecureAppDataDir = new File(dataDir, "secure/data");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
......
mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
mDalvikCacheDir = new File(dataDir, "dalvik-cache");
......
// Find base frameworks (resource packages without code).
mFrameworkInstallObserver = new AppDirObserver(
mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
mFrameworkInstallObserver.startWatching();
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanMode | SCAN_NO_DEX, 0);
// Collect all system packages.
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
// Collect all vendor packages.
mVendorAppDir = new File("/vendor/app");
mVendorInstallObserver = new AppDirObserver(
mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
mVendorInstallObserver.startWatching();
scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
mAppInstallObserver = new AppDirObserver(
mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
mAppInstallObserver.startWatching();
scanDirLI(mAppInstallDir, 0, scanMode, 0);
mDrmAppInstallObserver = new AppDirObserver(
mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
mDrmAppInstallObserver.startWatching();
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
scanMode, 0);
......
}
}
}
......
}
可以看到,在建構函式中,PackageManagerService
(PMS)會掃描特定目錄下的APK檔案,然後進行相關的載入工作,這些目錄包括:
/system/framework
/system/app
/vendor/app
/data/app
/data/app-private
在每個路徑下,都呼叫了scanDirLI
函式,接下來看看對應的函式做了些什麼。
2)PackageParser.parsePackage
scanDirLI
中又經過多次呼叫,具體就是掃描對應目錄的檔案,如果是apk檔案,就找到apk檔案中的manifest檔案,最後再為每一個apk建立一個PackageParser
物件,並將manifest檔案傳遞給PackageParser.parsePackage
。
public class PackageParser {
......
private Package parsePackage(
Resources res, XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
......
String pkgName = parsePackageName(parser, attrs, flags, outError);
......
final Package pkg = new Package(pkgName);
......
int type;
......
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifest);
......
while ((type=parser.next()) != parser.END_DOCUMENT
&& (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == parser.END_TAG || type == parser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("application")) {
......
if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
return null;
}
} else if (tagName.equals("permission-group")) {
......
} else if (tagName.equals("permission")) {
......
} else if (tagName.equals("permission-tree")) {
......
} else if (tagName.equals("uses-permission")) {
......
} else if (tagName.equals("uses-configuration")) {
......
} else if (tagName.equals("uses-feature")) {
......
} else if (tagName.equals("uses-sdk")) {
......
} else if (tagName.equals("supports-screens")) {
......
} else if (tagName.equals("protected-broadcast")) {
......
} else if (tagName.equals("instrumentation")) {
......
} else if (tagName.equals("original-package")) {
......
} else if (tagName.equals("adopt-permissions")) {
......
} else if (tagName.equals("uses-gl-texture")) {
......
} else if (tagName.equals("compatible-screens")) {
......
} else if (tagName.equals("eat-comment")) {
......
} else if (RIGID_PARSER) {
......
} else {
......
}
}
......
return pkg;
}
......
private Package parsePackage(
Resources res, XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
......
String pkgName = parsePackageName(parser, attrs, flags, outError);
......
final Package pkg = new Package(pkgName);
......
int type;
......
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifest);
......
while ((type=parser.next()) != parser.END_DOCUMENT
&& (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == parser.END_TAG || type == parser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("application")) {
......
if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
return null;
}
} else if (tagName.equals("permission-group")) {
......
} else if (tagName.equals("permission")) {
......
} else if (tagName.equals("permission-tree")) {
......
} else if (tagName.equals("uses-permission")) {
......
} else if (tagName.equals("uses-configuration")) {
......
} else if (tagName.equals("uses-feature")) {
......
} else if (tagName.equals("uses-sdk")) {
......
} else if (tagName.equals("supports-screens")) {
......
} else if (tagName.equals("protected-broadcast")) {
......
} else if (tagName.equals("instrumentation")) {
......
} else if (tagName.equals("original-package")) {
......
} else if (tagName.equals("adopt-permissions")) {
......
} else if (tagName.equals("uses-gl-texture")) {
......
} else if (tagName.equals("compatible-screens")) {
......
} else if (tagName.equals("eat-comment")) {
......
} else if (RIGID_PARSER) {
......
} else {
......
}
}
......
return pkg;
}
......
}
這裡就是對AndroidManifest.xml檔案中的application標籤進行解析了,我們常用到的標籤就有activity、service、receiver和provider,這裡解析完成後,一層層返回,呼叫另一個版本的scanPackageLI函式把來解析後得到的應用程式資訊儲存下來。
class PackageManagerService extends IPackageManager.Stub {
......
// Keys are String (package name), values are Package. This also serves
// as the lock for the global state. Methods that must be called with
// this lock held have the prefix "LP".
final HashMap<String, PackageParser.Package> mPackages =
new HashMap<String, PackageParser.Package>();
......
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
// All available receivers, for your resolving pleasure.
final ActivityIntentResolver mReceivers =
new ActivityIntentResolver();
// All available services, for your resolving pleasure.
final ServiceIntentResolver mServices = new ServiceIntentResolver();
// Keys are String (provider class name), values are Provider.
final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
new HashMap<ComponentName, PackageParser.Provider>();
......
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, long currentTime) {
......
synchronized (mPackages) {
......
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
......
int N = pkg.providers.size();
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName, pkg.applicationInfo.uid);
mProvidersByComponent.put(new ComponentName(p.info.packageName,
p.info.name), p);
......
}
N = pkg.services.size();
for (i=0; i<N; i++) {
PackageParser.Service s = pkg.services.get(i);
s.info.processName = fixProcessName(pkg.applicationInfo.processName,
s.info.processName, pkg.applicationInfo.uid);
mServices.addService(s);
......
}
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
mReceivers.addActivity(a, "receiver");
......
}
N = pkg.activities.size();
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
mActivities.addActivity(a, "activity");
......
}
......
}
......
return pkg;
}
......
}
到這裡整個應用的安裝過程就介紹完了。其實整個過程還是很明確,清晰的。
接下來再來總結一下整個啟動過程:
Zygote—>啟動SystemServer—>啟動ServerThread—>啟動PackageManagerService—>掃描特定目錄下的apk檔案,進行載入—>解析APK的manifest檔案,將配置資訊載入到
PackageManagerService
中