App啟動流程分析(下)
我們知道Java中一個能夠獨立執行的java程式的方法入口是main方法,它是被Jvm識別呼叫的。而在Android中一個應用的開始也可說是從ActivityThread的main方法開始的,然而不同的是他不是由Jvm呼叫的。
上一節我們講到在ZygoteInit中通過丟擲MethodAndArgsCaller異常,然後在main方法中,通過捕獲異常,然後呼叫run方法,然後在run方法中通過invoke來反射呼叫到ActivityThread中的main方法。詳見App啟動流程分析(上)
public static void main(String[] args) {
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false );
//設定程序引數
Process.setArgV0("<pre-initialized>");
//建立主執行緒Looper
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
//建立主執行緒Handler
sMainThreadHandler = new Handler();
}
//建立ActivityThread物件
ActivityThread thread = new ActivityThread();
//關鍵的一步,詳見1.1小節。false表示建立的是普通應用的程序。true表示建立的是系統應用程式的程序。
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
//開起主執行緒Looper迴圈。
Looper.loop();
//執行到這裡說明退出了主執行緒Looper迴圈。丟擲異常。
throw new RuntimeException("Main thread loop unexpectedly exited");
}
LAUNCH_ACTIVITY
1.1 ActivityThread.attach
private void attach(boolean system) {
//將ActivityThread物件放入ThreadLocal中儲存。ThreadLocal可以保證每個執行緒中資料獨立。
sThreadLocal.set(this);
mSystemThread = system;
//普通app進入這個if中。
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
//將ApplicationThread物件傳遞給RuntimeInit儲存,setApplicationObject是一個靜態方法,且RuntimeInit中方法多為靜態方法。見1.1.1與1.1.2小節
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//獲得了ActivityManagerService的本地代理物件ActivityManagerProxy,見1.1.3小節
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
//實際上呼叫了ActivityManagerProxy的attachApplication方法,見1.2小節
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
} else {
//系統app會進入else
android.ddm.DdmHandleAppName.setAppName("system_process");
try {
mInstrumentation = new Instrumentation();
ContextImpl context = new ContextImpl();
context.init(getSystemContext().mPackageInfo, null, this);
Application app = Instrumentation.newApplication(Application.class, context);
mAllApplications.add(app);
mInitialApplication = app;
app.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
...
}
對於Binder瞭解較深的就會發現,這裡的ApplicationThread
有點類似於ActivityMangerService
。ActivityMangerService
繼承自ActivityManagerNative
。ActivityManagerNative
繼承自Binder
。ActivityManagerNative
和ActivityMangerProxy
均實現了IApplicationThread
這個介面。而ActivityMangerProxy
就是AMS在客戶端的代理物件。
這裡的ApplicationThread
繼承自ApplicationThreadNative
,ApplicationThreadNative
繼承了Binder
。
ApplicationThreadNative
與ApplicationThreadProxy
均實現了IApplicationThread
介面,典型的是Binder的客戶端代理。
可以推測出,AMS作為系統的服務,執行在SystemServer程序。當app呼叫AMS中的方法時,需要獲得AMS的本地代理物件ActivityManagerProxy
,AMS與AMP均繼承自同一個介面。客戶端呼叫AMP中的方法,通過Binder驅動即可傳遞資料,跨程序呼叫到AMS中的方法。
那麼當AMS要呼叫app中的方法時呢? ApplicationThread
與ApplicationThreadProxy
均實現了IApplicationThread
介面,在這裡通過mgr.attachApplication()
方法(mgr就是AMS在本地的代理物件ActivityManagerProxy
),將ApplicationThread
傳遞給了AMS儲存。
1.1.1
RuntimeInit.setApplicationObject
public static final void setApplicationObject(IBinder app) {
mApplicationObject = app;
}
1.1.2 mAppThread.asBinder
//mAppThread是ApplicationThread的例項物件。ApplicationThread繼承自ApplicationThreadNative。而ApplicationThreadNative是一個Binder。
public final class ActivityThread {
...
final ApplicationThread mAppThread = new ApplicationThread();
...
}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {
...
public IBinder asBinder(){
return this;
}
...
}
1.1.3 ActivityManagerNative.getDefault
//熟悉AIDL的就會發現,這裡的ActivityManagerNative就相當於常規下,我們AIDL建立後自動生成的Stub類,而ActivityManagerProxy類就相當於AIDL建立之後的Proxy內部代理類,當客戶端和服務端在同一程序時,呼叫時直接呼叫服務端的方法,不需要走Proxy中的方法。而當客戶端和服務端不在同一程序時,客戶端呼叫方法時,先呼叫了Proxy中的方法,再走transact過程呼叫服務端的方法。
static public IActivityManager getDefault() {
return gDefault.get();
}
//gDefault是一個泛型為IActivityManager的Singleton型別變數。實際上是一種單例模式的快速實現。
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
//呼叫了這個get方法,當T不存在,也就是IActivityManager不存在時,呼叫create方法來建立這個變數。
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
//通過serviceManger獲得了AMS的Binder,獲得的是BinderProxy這個例項,其中儲存了AMS在Native層BpBinder的Handle。(關於BpBinder和BBinder可以去看binder方面原始碼分析),而ActivityManagerService繼承自ActivityMangerNative。,具體可以看1.1.4小節
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
//呼叫ActivityManagerNative.asInterface,這個方法在客戶端和服務端在同一程序時,返回ActivityManagerNative物件,否則返回的是ActivityManagerProxy這個物件。
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
//返回了ActivityManagerProxy物件。ActivityManagerService的BinderProxy就儲存在了ActivityManagerProxy中的mRemote這個變數中。
return am;
}
};
1.2 ActivityManagerProxy.attachApplication
ActivityManagerProxy是ActivityManagerNative的內部類
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
//這裡的app是ApplicationThread物件
data.writeStrongBinder(app.asBinder());
//呼叫了mRemote的transact方法,mRemote實際上是一個BinderProxy類,它在內部呼叫了一個native方法transact。見1.2.1小節
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
1.2.1 BinderProxy.transact
final class BinderProxy implements IBinder {
...
public native boolean pingBinder();
public native boolean isBinderAlive();
//native的transact方法,最終會通過Binder驅動呼叫到ActivityManagerService中繼承自ActivityManagerNative的onTransact方法。
public native boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
public native void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException;
public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
...
}
1.2.2 ActivityManagerNative.onTransact
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...
//省略了非常多的case分支
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
//見下方說明
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
//呼叫了AMS中的attachApplication方法,見1.2.3小節
attachApplication(app);
}
reply.writeNoException();
return true;
}
...
}
return super.onTransact(code, data, reply, flags);
}
- 這裡的app實際是一個
ApplicationThreadProxy
例項。 readStrongBinder
會返回一個IBinder
物件,實際上是前面寫入的ApplicationThread
經過Binder驅動後在native層轉為一個BpBinder
,同過JNI轉為一個BinderProxy
物件。ApplicationThreadNative
.asInterface呼叫之後會返回一個ApplicationThreadProxy
物件,就像在App程序獲得的AMS代理物件ActivityMangerProxy
一樣,這個ApplicationThreadProxy
就是App程序中ApplicationThread
的代理。- 當app程序呼叫AMS中方法時,app程序是客戶端,AMS所在的SystemServer是服務端。 此時,在AMS中儲存了app端的代理物件
ApplicationThreadProxy
,當AMS要呼叫ApplicationThread
中方法時,AMS就是客戶端,而app程序就是服務端了。
1.2.3 ActivityManagerService.attachApplication
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//獲得遠遠端呼叫程序的程序id
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
//見1.2.4小節
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
1.2.4 ActivityManagerService.attachApplicationLocked
這段程式碼很長,其中部分if判斷提高程式健壯性的程式碼,log日誌程式碼,以及 thread.bindApplication後的一大段程式碼等等已被略去
//在AMS物件被建立時,這個集合就被例項化了
final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
//在上篇中的4.3小節中,我們成功啟動一個新的程序之後,以程序的pid作為鍵,ProcessRecord物件作為值儲存在了mPidsSelfLocked這個SparseArray集合中。
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null) {
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
Process.killProcessQuiet(pid);
} else {
try {
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return false;
}
//app.thread不為null,說明這個ProcessRecord依然繫結的有另一個程序,需要清理乾淨。這裡的thread指的是IApplicationThread物件。實際上是ApplicationThreadProxy例項物件。
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}
//獲得程序名稱
String processName = app.processName;
try {
//設定當app程序死亡,Binder的死亡代理
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList();
startProcessLocked(app, "link fail", processName);
return false;
}
EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
//將ProcessRecord中的thread這個成員變數指向傳遞進來的IApplicationThread例項,即ApplicationThreadProxy。
app.thread = thread;
app.curAdj = app.setAdj = -100;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.forcingToForeground = null;
app.foregroundServices = false;
app.hasShownUi = false;
app.debugging = false;
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
try {
int testMode = IApplicationThread.DEBUG_OFF;
...
String profileFile = app.instrumentationProfileFile;
ParcelFileDescriptor profileFd = null;
boolean profileAutoStop = false;
if (mProfileApp != null && mProfileApp.equals(processName)) {
mProfileProc = app;
profileFile = mProfileFile;
profileFd = mProfileFd;
profileAutoStop = mAutoStopProfiler;
}
boolean isRestrictedBackupMode = false;
ApplicationInfo appInfo = app.instrumentationInfo != null
? app.instrumentationInfo : app.info;
//通過thread,即ApplicationThreadProxy跨程序呼叫了ApplicationThread中的bindApplication方法。從這裡,這裡又到了app程序
thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass, profileFile, profileFd, profileAutoStop,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, true);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
app.resetPackageList();
app.unlinkDeathRecipient();
startProcessLocked(app, "bind fail", processName);
return false;
}
// See if the top visible activity is waiting to run in this process
//啟動即將要被啟動的Activity
ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
if (hr != null && normalMode) {
if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//realStartActivityLocked才是真正啟動Activity的方法。見2.1小節
if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
badApp = true;
}
} else {
mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
}
}
// Find any services that should be running in this process...
//啟動程序中應該被啟動的Services
if (!badApp && mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (app.info.uid != sr.appInfo.uid
|| !processName.equals(sr.processName)) {
continue;
}
mPendingServices.remove(i);
i--;
realStartServiceLocked(sr, app);
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
badApp = true;
}
}
// Check if the next broadcast receiver is in this process...
//啟動程序中應該被啟動的Broadcast
BroadcastRecord br = mPendingBroadcast;
if (!badApp && br != null && br.curApp == app) {
try {
mPendingBroadcast = null;
processCurBroadcastLocked(br, app);
didSomething = true;
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting receiver "
+ br.curComponent.flattenToShortString(), e);
badApp = true;
logBroadcastReceiverDiscardLocked(br);
finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
br.resultExtras, br.resultAbort, true);
scheduleBroadcastsLocked();
// We need to reset the state if we fails to start the receiver.
br.state = BroadcastRecord.IDLE;
}
}
...
return true;
}
這裡主要是通過pid獲得了app程序儲存在AMS中的ProcessRecord
物件。設定了ApplicationThread
這個Binder的死亡代理,通過ProcessRecord
獲得了許多呼叫bindApplication
的必要引數。然後通過Binder跨程序呼叫了ApplicationThread
中的bindApplication
方法。
1.3 ApplicationThread.bindApplication
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
ParcelFileDescriptor profileFd, boolean autoStopProfiler,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
int debugMode, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo,
Map<String, IBinder> services, Bundle coreSettings) {
//這個services是一個HashMap,其中儲存了WindowManagerService,PackageManagersService,AlarmMangerService的Ibinder,見1.3.1小節
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
//一些設定引數,coreSettings是一個Bundle物件,最終通過H Handler傳送訊息,呼叫了ActivityThread.handleSetCoreSettings。 見1.3.2小節
setCoreSettings(coreSettings);
//建立一個dataBean,將資料打包成一個Bean
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.debugMode = debugMode;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfileFile = profileFile;
data.initProfileFd = profileFd;
data.initAutoStopProfiler = false;
//見1.3.3小節
queueOrSendMessage(H.BIND_APPLICATION, data);
}
1.3.1 ActivityMangaerService.getCommonServicesLocked
services是在AMS中作為引數傳入的,檢視AMS中原方法,實際上直接呼叫了getCommonServicesLocked方法,將返回值作為引數傳入,所以我們直接看getCommonServicesLocked這個方法。
private HashMap<String, IBinder> getCommonServicesLocked() {
//mAppBindArgs是一個HashMap,作為AMS中的一個成員變數
if (mAppBindArgs == null) {
mAppBindArgs = new HashMap<String, IBinder>();
//獲得並儲存PackageManagerService的IBInder
mAppBindArgs.put("package", ServiceManager.getService("package"));
//獲得並儲存WindowMangerService的IBInder
mAppBindArgs.put("window", ServiceManager.getService("window"));
//獲得並儲存AlarmMangerService的IBInder
mAppBindArgs.put(Context.ALARM_SERVICE,
ServiceManager.getService(Context.ALARM_SERVICE));
}
return mAppBindArgs;
}
1.3.2 ActivityThread.handleSetCoreSettings
private void handleSetCoreSettings(Bundle coreSettings) {synchronized (mPackages) {
//即,最後將其儲存在了ActivityThread中的mCoreSettings。
mCoreSettings = coreSettings;
}
}
1.3.3 ApplicationThread.queueOrSendMessage(H.BIND_APPLICATION, data);
private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
//最終,將其包裝為一個message。傳送給了mH這個Handler。跳到了1.3.4小節
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
mH這個Handler在AcitivityThread被例項話時,直接作為成員變數被例項化了。
1.3.4 H Handler
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
public static final int REQUEST_THUMBNAIL = 117;
public static final int CONFIGURATION_CHANGED = 118;
public static final int CLEAN_UP_CONTEXT = 119;
public static final int GC_WHEN_IDLE = 120;
public static final int BIND_SERVICE = 121;
public static final int UNBIND_SERVICE = 122;
public static final int DUMP_SERVICE = 123;
public static final int LOW_MEMORY = 124;
public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
public static final int RELAUNCH_ACTIVITY = 126;
public static final int PROFILER_CONTROL = 127;
public static final int CREATE_BACKUP_AGENT = 128;
public static final int DESTROY_BACKUP_AGENT = 129;
public static final int SUICIDE = 130;
public static final int REMOVE_PROVIDER = 131;
public static final int ENABLE_JIT = 132;
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
public static final int SCHEDULE_CRASH = 134;
public static final int DUMP_HEAP = 135;
public static final int DUMP_ACTIVITY = 136;
public static final int SLEEPING = 137;
public static final int SET_CORE_SETTINGS = 138;
public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
public static final int TRIM_MEMORY = 140;
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
switch (msg.what) {
...
//1.3.3傳送的訊息會進入這個case
case BIND_APPLICATION:
AppBindData data = (AppBindData)msg.obj;
//呼叫了ActivityThread的handleBindApplication方法。見1.3.5小節
handleBindApplication(data);
break;
...
}
}
...
}
H Handler是ActivityThread的一個內部類,其中我們可以看到定義了非常多的狀態量,常見的SHOW_WINDOW,CREATE_SERVICE,NEW_INTENT,LAUNCH_ACTIVITY,PAUSE_ACTIVITY,RECEIVER,BIND_SERVICE等等都是android中非常常見的一些操作。 由此可見H Handler是非常重要的一個類,在Window,Activity,Service,Intent,Receiver等等的許多操作中都會用到它來發送訊息。
1.3.5 ActivityThread.handleBindApplication
這又是一個長到爆炸的方法,我們依然是省略部分程式碼,只留下整體中最重要的呼叫程式碼
private void handleBindApplication(AppBindData data) {
//現將打包的data儲存起來,接下來一大段都是獲得data中對應的資料,將其賦值給對應的一些變數。
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
mProfiler = new Profiler();
mProfiler.profileFile = data.initProfileFile;
mProfiler.profileFd = data.initProfileFd;
mProfiler.autoStopProfiler = data.initAutoStopProfiler;
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName);
if (data.persistent) {
Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
if (!ActivityManager.isHighEndGfx(display)) {
HardwareRenderer.disable(false);
}
}
if (mProfiler.profileFd != null) {
mProfiler.startProfiling();
}
//當app版本小於等於12時,設定AsyncTask的預設執行緒池
if (data.appInfo.targetSdkVersion <= 12) {
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
//預設時區設定
TimeZone.setDefault(null);
Locale.setDefault(data.config.locale);
...
if (data.instrumentationName != null) {
//建立ContextImpl,我們知道,在android中,Context是一個抽象類,它的具體實現類就是ContextImpl。而像Application,Service類均繼承自COntextWapper。而ContextWapper雖然也繼承自Context,但它只是ContextImpl的一個包裝類,它裡面很多具體的處理都是直接丟給了ContextImpl。
ContextImpl appContext = new ContextImpl();
appContext.init(data.info, null, this);
InstrumentationInfo ii = null;
try {
ii = appContext.getPackageManager().
getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
}
if (ii == null) {
throw new RuntimeException(
"Unable to find instrumentation info for: "
+ data.instrumentationName);
}
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationAppPackage = ii.packageName;
mInstrumentedAppDir = data.info.getAppDir();
ApplicationInfo instrApp = new ApplicationInfo();
instrApp.packageName = ii.packageName;
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true);
ContextImpl instrContext = new ContextImpl();
instrContext.init(pi, null, this);
//建立ClassLoader,建立Instrumentation例項
try {
java.lang.ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
if (mProfiler.profileFile != null && !ii.handleProfiling
&& mProfiler.profileFd == null) {
mProfiler.handlingProfiling = true;
File file = new File(mProfiler.profileFile);
file.getParentFile().mkdirs();
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
} else {
mInstrumentation = new Instrumentation();
}
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
}
//建立Application例項,見1.3.6小節
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
if (!data.restrictedBackupMode){
List<ProviderInfo> providers = data.providers;
if (providers != null) {
//建立本程序的ContentProvider,並啟動ContentProvider,見1.3.7小節
installContentProviders(app, providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
//呼叫了application的oncreate方法
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
主要做了一下幾件事:
- 解包AMS傳過來的資料。
- 建立Instrumentation例項物件。
- 建立Application例項物件。
- 建立所在程序的ContentProvider例項物件,並呼叫它的onCreate方法
- 呼叫了Application的onCreate方法。
1.3.6 Loaded.makeApplication
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//存在Application就直接返回
if (mApplication != null) {
return mApplication;
}
Application app = null;
//Application的包名,如果不存在就使用預設包名路徑
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
//建立ApplicationContext中的ContextImpl物件
ContextImpl appContext = new ContextImpl();
appContext.init(this, null, mActivityThread);
//建立了Application物件。最終通過包名路徑,clazz.newInstance()的方式獲得Application物件,並將appContext繫結到Application中。(Application繼承自ContextWapper)
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
//instrumentation不為null的情況下,呼叫Application的onCreate方法,但在前面傳入時,傳的值就是null,所以這裡不會呼叫onCreate
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
return app;
}
1.3.7 ActivityThread.installContentProviders
private void installContentProviders(Context context, List<ProviderInfo> providers) {
final ArrayList<IActivityManager.ContentProviderHolder> results =
new ArrayList<IActivityManager.ContentProviderHolder>();
Iterator<ProviderInfo> i = providers.iterator();
while (i.hasNext()) {
ProviderInfo cpi = i.next();
StringBuilder buf = new StringBuilder(128);
buf.append("Pub ");
buf.append(cpi.authority);
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
//通過ClassLoder建立ContentProvider物件並呼叫了ContentProvider的onCreate方法
IContentProvider cp = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/);
if (cp != null) {
IActivityManager.ContentProviderHolder cph =
new IActivityManager.ContentProviderHolder(cpi);
cph.provider = cp;
cph.noReleaseNeeded = true;
results.add(cph);
}
}
//將ContentProvider的Binder 儲存到AMS中,方便其他程序呼叫。
try {
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
}
}
2.1 ActivityStack.realStartActivityLocked
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
...
try {
...
//啟動Activity。這裡的thread從1.2.4小節可以知道是ApplicationThreadProxy例項,它實際上是一個IBinder物件,最終通過Bind而跨程序呼叫了ApplicationThread中的對應方法,見2.2.1小節
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration),
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
...
}
} catch (RemoteException e) {
相關推薦
App啟動流程分析(下)
我們知道Java中一個能夠獨立執行的java程式的方法入口是main方法,它是被Jvm識別呼叫的。而在Android中一個應用的開始也可說是從ActivityThread的main方法開始的,然而不同的是他不是由Jvm呼叫的。
上一節我們講到在ZygoteIn
iOS作業系統-- App啟動流程分析與優化
背景知識:
mach-o檔案為基於Mach核心的作業系統的可執行檔案、目的碼或動態庫,是.out的代替,其提供了更強的擴充套件性並提升了符號表中資訊的訪問速度,
符號表,用於標記原始碼中包括識別符號、宣告資訊、行號、函式名稱等元素的具體資訊,比如說資料型別、作用域以及記憶體地址,iOS符號表在dS
深入淺出Android中的App啟動流程分析
App啟動是指使用者點選手機桌面的app對應的icon開始,所以我們需要明白幾點基礎知識:
1.桌面也是一個Activity叫Launcher.java
2.在桌面點選icon啟動app跟在app內部啟動另一個Activity是一樣的都是呼叫startAct
App啟動流程分析(上)
App啟動流程分析
一.概述流程
在LAUNCH介面,點選一個app的圖示之後,會呼叫startActivity來啟動對應的Activity。
通過Binder遠端通知AMS啟動新的Activity。
AMS進行一系列的許可權判斷,建立Activity
Android5 Zygote 與 SystemServer 啟動流程分析
進一步 null 正常的 rtb 這樣的 ket constant vml resp
Android5 Zygote 與 SystemServer 啟動流程分析
Android5 Zygote 與 SystemServer 啟動流程分析
前言
zy
開機啟動流程分析
boot 啟動流程 本節索引 在對系統啟動流程進行分析的時候,我想你一定是對系統有了一定的了解。系統的啟動目前來講大都為串行接力的方式來啟動。而所謂的並行方式的啟動方式也是某一個階段的並行。所以我按照系統啟動的順序來把文章連綴起來。 * BIOS階段 * BootLoader階段
kexec 內核快速啟動流程分析
-- 令行 並且 內存 tab 執行過程 family use -a 一、命令行
1. kexec -l $kpwd --append="$arg"
其中$kpwd =目標內核的路徑
$arg =傳給內核的參數,與/proc/cmdline一致時表示重啟現有內核
從0移植uboot (二) _啟動流程分析
title tco ret 沒有 返回 ips css location config
來源:Linux社區 作者:xiaojiang1025 : http://www.linuxidc.com/Linux/2017-02/141019.htm
經過
u-boot.2012.10——mini2440(二、啟動流程分析)
我們 分享 默認 從數據 中斷 改變 處理 mini2440 https 參考資料:https://blog.csdn.net/suiyuan19840208/article/details/7239949
1、第一階段功能
* 硬件設備初始化
* 加載u-boot
GEF入門實例_總結_04_Eclipse插件啟動流程分析
理解 viso inf targe get ica order workbench 註意 一、前言
本文承接上一節:GEF入門實例_總結_03_顯示菜單和工具欄
註意到app目錄下的6個類文件。
這6個文件對RCP應用程序而言非常重要,可能我們現在對這幾個文件的理
[Abp 源碼分析] 一、Abp 框架啟動流程分析
arch rep man job dsi 法則 依賴 gconf dep
Abp 不一定僅用於 Asp.Net Core 項目,他也可以在 Console 與 WinFrom 項目當中進行使用,所以關於啟動流程可以分為兩種,一種是 Asp.Net Core 項目的啟動流程
linux-2.6.22.6內核啟動流程分析之配置
linux 分享圖片 src image 比較 文件包含 子目錄 2.6 config 配置過程最終結果是生成.config文件,我們想要對配置的目的有很清楚的了解,必須先對.config文件進行分析。通過cd命令切換到linux-2.6.22.6內核目錄,輸入vi .co
Flink on Yarn模式啟動流程分析
cin XML images ont list action -i 多個 信息 此文已由作者嶽猛授權網易雲社區發布。歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。Flink On Yarn 架構Paste_Image.png前提條件首先需要配置YARN_CONF_DIR
App啟動流程
目錄介紹
1.什麼是Zygote程序
1.1 簡單介紹
1.2 各個程序的先後順序
1.3 程序作用說明
2.Zygote程序的啟動流程
2.1 原始碼位置
2.2 ZygoteInit類的main方法
2.3 regist
Spark2.2.2原始碼解析: 3.啟動worker節點啟動流程分析
本文啟動worker節點啟動流程分析
啟動命令:
${SPARK_HOME}/sbin/start-slave.sh spark://sysadmindeMacBook-Pro.local:7077
檢視start-slave.sh
Android9.0 Activity啟動流程分析(二)
文章目錄
1、ActivityThread的main函式
2. AMS的attachApplication函式
2.1 Part-I
2.2 Part-II
2.2.1 ApplicationThread的bindApp
Android9.0 Activity啟動流程分析(一)
1、ActivityRecord、TaskRecord、ActivityStack和ActivityDisplay介紹
本篇文章是基於Android refs/tags/android-9.0.0_r8分支的程式碼進行分析的 在分析Activity啟動的原始碼之前先介紹一下Act
s5pv210 -uboot(三)SD卡啟動流程分析
https://blog.csdn.net/wangweijundeqq/article/details/78886155 --------------------- 本文來自 MrT_WANG 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net
Android 虛擬機器簡單介紹——ART、Dalvik、啟動流程分析
Android 虛擬機器方面的知識,我是通過《深入理解 Android 核心設計思想》來學習的,內容特別多(只有一章,但有 160 頁),但感覺和 Android 開發有些偏了,因此很多內容都沒有認真去看,比如 EFL 格式等,這裡只是選取了一些感覺比較重要的做
Linux核心啟動流程分析(一)
1. 依據arch/arm/kernel/vmlinux.lds 生成linux核心原始碼根目錄下的vmlinux,這個vmlinux屬於未壓縮,帶除錯資訊、符號表的最初的核心,大小約23MB;
命令:arm-linux-gnu-ld -o vmlinux -T a