Android中persistent屬性用法詳解
看見好的東西,不轉載真是罪過
本文例項講述了Android中persistent屬性用法。分享給大家供大家參考,具體如下:
前段時間在研究telephony時,一直沒有在framework下發現對telephony的初始化(PhoneFactory.Java中的makeDefaultPhones函式)的呼叫。結果全域性搜尋之後發現在application PhoneApp(packages/apps/Phone)中呼叫了。但是application PhoneApp既沒有被Broadcast喚醒,也沒有被其他service呼叫,那麼是Android是通過什麼方式來啟動PhoneApp,所以就發現了屬性android:persistent。
在AndroidManifest.xml定義中,application有這麼一個屬性android:persistent,根據字面意思來理解就是說該應用是可持久的,也即是常駐的應用。其實就是這麼個理解,被android:persistent修飾的應用會在系統啟動之後被AM啟動。
AM首先去PM(PackageManagerService)中去查詢設定了Android:persistent的應用
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public
void systemReady( final
Runnable goingCallback) { if
(mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try
{
List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if
(apps != null ) {
int
N = apps.size();
int
i;
for
(i= 0 ; i<N; i++) {
ApplicationInfo info
= (ApplicationInfo)apps.get(i);
if
(info != null
&& !info.packageName.equals( "Android" )) {
addAppLocked(info);
}
}
}
}
catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
}
|
假如該被Android:persistent修飾的應用此時並未執行的話,那麼AM將呼叫startProcessLocked啟動該app,關於startProcessLocked不再描述,另外一篇文章《How to start a new process for Android?》中做了詳細的介紹(這篇英文文件小編就不翻譯了,感興趣的朋友可以搜到看一看)。
app的啟動過程就是啟動app所在的package對應的程序。
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
final
ProcessRecord addAppLocked(ApplicationInfo info) {
ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
if
(app == null ) {
app = newProcessRecordLocked( null , info,
null );
mProcessNames.put(info.processName, info.uid, app);
updateLruProcessLocked(app,
true , true );
}
if
((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
app.persistent =
true ;
app.maxAdj = CORE_SERVER_ADJ;
}
if
(app.thread == null
&& mPersistentStartingProcesses.indexOf(app) < 0 ) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app,
"added application" , app.processName);
}
return
app;
}
|
面介紹app所在的package對應的程序啟動完成之後,app是如何被create的。
從文章《How to start a new process for Android?》中可知,zygote在建立新的程序均會啟動它的mainThread android.app.ActivityThread,因此我們從ActivityThread的main函式中接著分析app的create過程。
在main中有下面這個操作
?1 |
thread.attach( false );
|
在attach過程中,ActivityThread會將對應的application attach到AM中去,交與AM去管理。這裡需要注意一個變數
?1 |
final
ApplicationThread mAppThread = new
ApplicationThread();
|
mAppThread是一個ApplicationThread物件,mAppThread可以看作是當前程序主執行緒的核心,它負責處理本程序與其他程序(主要是AM)之間的通訊,同時通過attachApplication將mAppThread的代理Binder傳遞給AM。
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private
final void attach( boolean
system) {
sThreadLocal.set( this );
mSystemThread = system;
if
(!system) {
ViewRoot.addFirstDrawHandler( new
Runnable() {
public
void run() {
ensureJitEnabled();
}
});
Android.ddm.DdmHandleAppName.setAppName( "<pre-initialized>" );
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try
{
mgr.attachApplication(mAppThread);
}
catch (RemoteException ex) {
}
}
}
|
上面的attach程式碼中,我們順著IPC呼叫AM的attachApplication過程再往下看。
在該過程中,AM呼叫到了IPC通訊呼叫mAppThread的bindApplication;
1 2 3 4 5 6 7 8 9 10 11 |
private
final boolean attachApplicationLocked(IApplicationThread thread,
int
pid) {
thread.bindApplication(processName, app.instrumentationInfo !=
null
? app.instrumentationInfo : app.info, providers,
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode,
mConfiguration, getCommonServicesLocked());
updateLruProcessLocked(app,
false , true );
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
}
|
mAppThread的bindApplication再通過訊息機制向ActivityThread自身維護的handler傳送BIND_APPLICATION訊息。下面看看ActivityThread自身維護的handler對訊息BIND_APPLICATION的處理,最終會呼叫到handleBindApplication函式
你會發現在handleBindApplication函式中有這麼一句
?1 |
mInstrumentation.callApplicationOnCreate(app);
|
我們最終在繞了好大一圈之後,呼叫了app的onCreate函式來啟動這個application。