最近項目中有個需求需要在PackageManagerService添加一個方法蝌以,然后進行調(diào)用却妨。
我們知道PackageManagerService作為系統(tǒng)的核心服務,由SystemServer在系統(tǒng)啟動時創(chuàng)建,我們先看看SystemServer是如何創(chuàng)建的:
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
原來是通過一個靜態(tài)方法創(chuàng)建的佣赖,再看看這個靜態(tài)方法:
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
ServiceManager.addService("package", m);
return m;
}
這個方法比較簡單,就是new一個PackageManagerService的實例记盒,然后向ServiceManager注冊憎蛤。既然注冊到ServiceManager里面,我們在獲取PackageManagerService時就不必new或者調(diào)用那個main方法纪吮,因為PackageManagerService在構(gòu)造函數(shù)執(zhí)行了大量邏輯俩檬。
在ServiceManager中既然有addService方法,那么就應該有getService方法碾盟。(整個ServiceManager代碼邏輯比較簡單棚辽,就是維護了一個HashMap,用于保存各項系統(tǒng)服務)
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
看到這里我們是不是就可以這樣獲取
(PackageManagerService)ServiceManager.getService("package")
然而在編譯時報如下錯誤
看來是PackageManagerService所在的這個包無法訪問冰肴。
是不是在外部就無法獲取了呢屈藐。這時想到榔组,我們經(jīng)常在Acticity中通過getPackageManager獲取一個PackageManager,而PackageManager其實就是IPackageManager的一個客戶端代理联逻。于是搓扯,我們?nèi)タ纯磄etPackageManager是如何實現(xiàn)的。
在ContextImpl中:
@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;
}
這里調(diào)用了ActivityThread的一個也叫getPackageManager的方法包归,繼續(xù)看下去:
在ActivityThread中
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;
}
這里就很清晰了锨推,也是通過ServiceManager.getService獲取,然后通過這樣的方法IPackageManager.Stub.asInterface(b);來獲取到PackageManagerService的公壤。
這樣就比較簡單了换可,我們就可以這樣獲取:
IPackageManager.Stub.asInterface(ServiceManager.getService("package")).***
類似的厦幅,我們也可以通過這種形式獲取一些其他的系統(tǒng)服務沾鳄,比如:
ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)).endCall();