android6.0原始碼分析之Activity啟動過程
Activity最為android開發者最熟悉的元件,由ActivityManagerService服務進行排程管理,而ActivityManagerService的啟動過程在activitymanagerservice服務原始碼分析一文中進行了詳細分析,本文基於其對Activity的啟動過程進行分析,同時也將分析AMS對Activity的排程管理。
1、 Activity的啟動模式
啟動模式實際上就是為了控制Activity與Task之間的關係,目前共有一下四種模式:standard、singleTop、singleTask以及singleInstance,預設的模式為standard模式。
注意:建議一般的開發者不要輕易使用後兩種模式,因為不同的模式,其出棧的順序不同,可能會導致使用者按下返回鍵時,會有不一樣的使用者體驗
2、Activity的啟動時機
Activity作為android非常重要的元件,那麼我們會在哪些時機啟動它呢?
通常有如下幾種情形:
1. android AM命令
android系統為開發者提供了adb工具,而在adb的基礎上執行adb shell就可以從PC上對手機側執行shell命令。如啟動瀏覽器:am start -n com.android.browser/com.android.browser.BrowserActivity。
2. 啟動AMS服務時
在啟動AMS服務時,在最後呼叫AMS的systemReady的最後階段會啟動Home介面,此時就會啟動一個Activity。
3. 呼叫startActivity()和startActivityForResult()方法時
這是我們最常用也最熟悉的啟動Activity的方式。
3、AM命令列啟動Activity的過程分析
在adb中可以使用AM命令,同時在應用程式中,也可以通過AM命令來啟動指定的Activity,AM是一個指令碼命令,它還可以啟動Service,傳送廣播等。
3.1 Am 框架層呼叫流程分析
adb執行Am命令後,最終會執行Am.java的main方法,其程式碼如下:
//Am.java
public static void main(String[] args){
(new Am()).run(args);
}
它呼叫的是抽象父類BaseCommand類的run方法:
//BaseCommand.java
public void run(String[] args){
if(args.length<1){
//顯示命令使用說明
onShowUsage(System.out);
return;
}
mArgs = args;
mNextArg = 0;
mCurArgData = null;
try{
onRun();
}catch(...){...}
}
跟其他命令指令碼類似,如果引數為空,顯示使用說明,否則呼叫onRun()方法,它是一個抽象方法,在Am.java中有實現:
//Am.java
@Override
public void onRun() throws Exception{
//獲取AMS
mAm = ActivityManagerNative.getDefault();
...
String op = nextArgRequired();
if(op.equals("start")){
//啟動Activity
runStart();
}else if(op.equals("startService")){
//啟動服務
runStartService();
}else if(op.equals("force-stop")){
//強制停止
runForceStop();
}else if(op.equals("kill")){
//殺死程序
runKill();
}else if{
...
}else{
...
}
}
命令引數不同,其執行的操作不同,就本節來說,其引數為start,所以將會執行runStart()方法來啟動Activity:
//Am.java
private void runStart() throws Exception{
Intent intent = makeIntent(UserHandle.USER_CURRENT);
...
do{
//獲取包資訊
...
//設定intent的標誌位FLAG_ACTIVITY_NEW_TASK,即將啟動一個新任務
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ParcelFileDescriptor fd = null;
ProfilerInfo profilerInfo = null;
if(mProfileFile != null){//處理-P選項,統計效能
try{
fd = openForSystemServer(new File(mProfileFile),ParcelFileDescriptior.MODE_CREATE|
ParcelFileDescriptor.MODE_TRUNCATE|ParcelFileDescriptor.MODE_READ_WRITE);
}catch(...){...}
profilerInfo = new ProfilerInfo(mProfileFile,fd,mSamplingInterval,mAutoStop);
}
...
int res;
...
if(mWaitOption){//控制是否等待啟動結果,如果有-W選項,則該值為true
result = mAm.startActivityAndWait(null,null,intent,mimeType,null,null,0,mStartFlags,
profilerInfo,null,mUserId);
res = result.result;
}else{
res = mAm.startActivityAsUser(null,null,intent,mimeType,null,null,0,mStartFlags,
profilerInfo,null,mUserId);
}
//處理一些返回結果
...
}while(mRepeat > 1);
}
startActivityAsUser()最後也是呼叫AMS的startActivityAndWait()方法,所以Am命令框架層的呼叫結束,其呼叫時序如下:
3.2 AMS啟動Activity流程分析
Am命令將啟動Activity的工作交給了AMS來進行,首先看startActivityAndWait()方法,它直接呼叫StackSupervisor類的startActivityMayWait()方法,其程式碼如下:
//ActivityStackSupervisor.java
final int startActivityMayWait(...){
...
//為了不改變使用者的intent
intent = new Intent(intent);
//收集目標intent的資訊,在resolveActivity方法中與PKMS互動獲得
ActivityInfo aInfo = resolveActivity(intent,resolvedType,startFlags,profilerInfo,userId);
ActivityContainer container = (ActivityContainer)iContainer;
synchronized(mService){
...
final ActivityStack stack;
//取得需要啟動的ActivityStack棧
if(container == null || container.mStack.isOnHomeDisplay()){
stack = mFocusedStack;
}else{
stack = container.mStack;
}
...
if(aInfo!=null&&(aInfo.applicationInfo.privateFlags&
ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)!=0){
//Androidmanifest.xml中的Application標籤可以宣告一個cantSaveState屬性,若設定,其將不享受系統提
//供的狀態儲存/恢復功能。主要是為了保證使用者體驗的連續性
...
}
//啟動Activity
int res = startActivityLocked(caller,intent,resolvedType,aInfo,voiceSession,
voiceInteractor,resultTo,resultWho,requestCode,callingPid,callingUid,callingPackage,
realCallingPid,realCallingUid,startFlags,options,ignoreTargetSecurity,
componentSpecified,null,container,inTask);
...
//如果配置Configration發生變化,則呼叫AMS的updateConfigurationLocked進行處理
if(stack.mConfigWillChange){
mService.enforceCallingPermission(...);
mConfigWillChange = false;
mService.updateConfigurationLocked(config,null,false);
}
if(outResult != null){
outResult.result = res;
if(res == IActivityManager.START_SUCCESS){
//將結果放入mWaitingActivityLaunced中儲存
mWaitingActivityLaunched.add(outResult);
do{
try{
//等待啟動結果
mService.wait();
}
}while(!outResult.timeout&&outResult.who == null);
}else if{
...
}
...
}
return res;
}
}
首先通過PKMS查詢匹配的ActivityInfo,然後獲取呼叫者的pid,uid等資訊,由於本文的caller為空,得到的是Am所在程序的pid和uid。接著呼叫startActivityLocked()方法啟動Activity,最後再呼叫mService.wait()方法來等待啟動結果,並對返回值進行一些處理,此處的等待主要是Am引數中有一個-W選項,若無此選項,則不會有這個等待,最後再將啟動結果res返回。
繼續分析startActivityLocked()方法:
//ActivityStackSupervisor.java
final int startActivityLocked(...){
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
if (caller != null) {//如果caller不為空,從AMS中找到它所屬的ProcessRecord即程序,本文此處為null
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
err = ActivityManager.START_PERMISSION_DENIED;
}
}
...
//sourceRecord用於描述啟動目標Activity的那個Activity
ActivityRecord sourceRecord = null;
//resultRecord用於描述接收啟動結果的Activity,即onActivityResult將被呼叫以通知啟動結果
ActivityRecord resultRecord = null;
...
//獲取Intent設定的啟動標誌
final int launchFlags = intent.getFlags();
//此部分與LaunchMode類似,它用於控制Activity啟動結果的通知
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
...
}
...
//檢查許可權
final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid);
...
//可為AMS設定IActivityController型別的監聽者,AMS有任何動靜都將回調該監聽者
if (mService.mController != null) {
try {
Intent watchIntent = intent.cloneFilter();
//交給回撥物件處理,由它判斷能否繼續後面的行程
abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
}
if (abort) {//通知resultRecord
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
return ActivityManager.START_SUCCESS;
}
//建立一個ActivityRecord物件
ActivityRecord r = new ActivityRecord(mService,this,callerApp,callingUid,...);
...
final ActivityStack stack = mFocusedStack;
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
//判斷是否有許可權切換Application
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,realCallingPid,
realCallingUid, "Activity start")) {
PendingActivityLaunch pal =new PendingActivityLaunch(r, sourceRecord,startFlags,
stack);
//將Pending的請求儲存到AMS的mPendingActivityLaunches變數中
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
if (mService.mDidAppSwitch) {
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true;
}
//啟動處於Pending狀態的Activity
doPendingActivityLaunchesLocked(false);
//呼叫此函式繼續啟動Activity
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,startFlags,
true, options, inTask);
//做一些結果處理
...
return err;
}
此段程式碼的主要工作就是處理sourceRecord和resultRecord,然後再處理app switch屬性,如果當前禁止app switch,則將本次啟動儲存起來,等允許app switch時再處理,最後再呼叫startActivityUncheckedLocked()方法處理本次Activity啟動請求:
//ActivityStackSupervisor.java
final int startActivityUncheckedLocked(...) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
...
//獲取啟動標誌
int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&(launchSingleInstance
|| launchSingleTask)) {
//如果Intent和AndroidManifest.xml的啟動模式有衝突,以AndroidManifest.xml為準
launchFlags &=~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
} else {
...
}
...
if (sourceRecord != null) {//如果請求的發起者為空,則需要建立一個新的Task
if (sourceRecord.finishing) {
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
newTaskInfo = sourceRecord.info;
newTaskIntent = sourceRecord.task.intent;
}
sourceRecord = null;
sourceStack = null;
} else {
sourceStack = sourceRecord.task.stack;
}
} else {
sourceStack = null;
}
...
if(inTask==null){
if(sourceRecord==null){
//如果不是從另外的Activity啟動的,則需建立新的Task
if((launchFlags&Intent.FLAG_ACTIVITY_MEW_TASK)==0&&inTask==null){
launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
}
}else if(sourceRecord.launchMode==ActivityInfo.LAUNCH_SINGLE_INSTANCE){
//如果此Activity在系統中已經有例項在執行,則需要為此Activity額外建立一個Task
launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
}else if(launchSingleInstance||launchSingleTask){
//如果是SingleInstance或者SingleTask的啟動模式,同樣需要建立新的Task
launchFlags|=Intent.FLAG_ACTIVITY_NEW_TASK;
}
}
...
targetStack.startActivityLocked(r,newTask,doResume,keepCurTransition,options);
...
return ActivityManager.START_SUCCESS;
}
首先根據Activity的啟動模式以及傳入的引數來確定是否需要建立新的Task以及launchFlags,然後呼叫startActivityLocked()方法繼續啟動(這裡的方法引數與前面同名方法的不一樣,屬於過載函式),繼續分析啟動過程:
//ActivityStackSupervisor.java
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options){
...
TaskRecord task = null;
if (!newTask) {//如果不是已經存在的任務,則找到它在哪裡
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task.getTopActivity() == null) {
//此task下的Activity全部執行結束
continue;
}
if (task == r.task) {
if (!startIt) {//如果它對使用者是不可見的,只需將其加入未啟動的
task.addActivityToTop(r);
r.putInHistory();
...
ActivityOptions.abort(options);
return;
}
break;
}else if(task.numFullScreen > 0){
startIt = false;
}
}
}
...
//將Activity資訊加入到history stack中並處理
task = r.task;
task.addActivityToTop(r);
task.setFrontOfTask();
r.putInHistory();
...
if(doResume){
mStackSupervisor.resumeTopActivitiesLocked(this,r,options);
}
}
此方法將根據傳入的引數來找到此Activity所在的任務,以及進行相應判斷將其加入到相應的history stack的最頂端(棧頂),最後再呼叫ActivityStack的resumeTopActivitiesLocked方法來啟動棧頂的Activity,繼續分析resumeTopActivitiesLocked方法:
//ActivityStack.java
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions){
if (targetStack == null) {//如果目的任務為NULL,則啟動當前聚焦的任務
targetStack = mFocusedStack;
}
//啟動targetStack
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack == targetStack) {
//上面已經啟動了
continue;
}
if (isFrontStack(stack)) {
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}
此方法很簡單就是根據當前任務,呼叫相應的resumeTopActivityLocked()方法來啟動,而resumeTopActivityLocked也只是簡單的呼叫了resumeTopActivityInnerLocked方法,所以分析resumeTopActivityInnerLocked方法:
//ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options){
//找到第一個還沒有結束的Activity
final ActivityRecord next = topRunningActivityLocked(null);
...
//確保擁有此Activity的任務已經啟動
if (mService.mStartedUsers.get(next.userId) == null) {
return false;
}
...
//設定啟動的Uid
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
...
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {//程序,執行緒都存在
//將此Activity置為Visible
mWindowManager.setAppVisibility(next.appToken, true);
// schedule launch ticks to collect information about slow apps.
next.startLaunchTickingLocked();
ActivityRecord lastResumedActivity =
lastStack == null ? null :lastStack.mResumedActivity;
ActivityState lastState = next.state;
next.state = ActivityState.RESUMED;
mResumedActivity = next;
next.task.touchActiveTime();
mRecentTasks.addLocked(next.task);
mService.updateLruProcessLocked(next.app, true, null);
updateLRUListLocked(next);
mService.updateOomAdjLocked();
...
try {
// Deliver all pending results.
ArrayList<ResultInfo> a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
...
next.sleeping = false;
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
//因為程序,執行緒都存在,所以只需恢復此Activity
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
} catch (Exception e) {
// 如果發生異常,需要重啟此Activity,注意此方法最後一個引數為false
mStackSupervisor.startSpecificActivityLocked(next, true, false);
return true;
}
} else {
//因為程序或者執行緒為空,所以需要重新啟動activity,此處最後一個引數為true
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
return true;
}
如程式碼可知:如果當前需要啟動的Activity所在的程序和執行緒都已經建立,則呼叫ActivityThread的scheduleResumeActivity方法來恢復此Activity,此時如果發生異常,則呼叫startSpecificActivityLocked來重新啟動此Activity,當然,我們注意到,當Activity所在的程序或者執行緒為啟動時,它也是呼叫startSpecificActivityLocked方法來重新啟動此Activity,但區別在此方法的最後一個引數,即程序和執行緒已經啟動了的為flase,否則為true,下面分析startSpecificActivityLocked()方法:
//ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
//先獲取app,據此app來判斷Activity所在的Application是否已經啟動
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {//程序和執行緒不為空,即已經啟動好
try {
...
//真正啟動Activity的函式,注意checkConfig引數
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {...}
}
//程序或者執行緒未啟動
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
由程式碼可知,它同樣會先判斷執行緒和程序是否已啟動,如果已啟動,呼叫realStartActivityLocked來啟動Activity,否則呼叫AMS的startProcessLocked來啟動程序,由於Am命令和AMS的Hone介面啟動都是程序未啟動的情況,所以此處先分析分兩個階段分析,此階段的時序圖如下:
3.2.1 AMS啟動Activity所在程序的流程分析
由於android下的Java程序都是由Zygote程序fork出來的,所以分析此流程之前,需要對Zygote的原理有一些瞭解,對Zygote程序的分析請參考android原始碼分析之Zygote程序分析,先從AMS的startProcessLocked方法進行分析:
//ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr,
String abiOverride, String entryPoint, String[] entryPointArgs){
long startTime = SystemClock.elapsedRealtime();
if (app.pid > 0 && app.pid != MY_PID) {//如果不是當前程序,則移除
checkTime(startTime, "startProcess: removing from pids map");
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
checkTime(startTime, "startProcess: done removing from pids map");
app.setPid(0);
}
...
//啟動程序
Process.ProcessStartResult startResult = Process.start(entryPoint,app.processName, uid, uid,
gids, debugFlags, mountExternal,app.info.targetSdkVersion, app.info.seinfo,
requiredAbi, instructionSet,app.info.dataDir, entryPointArgs);
...
//通知BatteryStatsService服務此程序啟動
mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
...//對程序啟動結果進行處理
}
由程式碼可知,它呼叫了Process的start方法來啟動程序,繼續分析start方法:
//Process.java
public static final ProcessStartResult start(...){
try {
return startViaZygote(processClass, niceName, uid, gid, gids,debugFlags, mountExternal,
targetSdkVersion, seInfo, abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG, "Starting VM process through Zygote failed");
throw new RuntimeException("Starting VM process through Zygote failed", ex);
}
}
繼續看startViaZygote方法:
//Process.java
private static ProcessStartResult startViaZygote(...){
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
//引數處理
...
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
同樣,它首先進行一些引數處理,如runtime的引數等等,繼續分析zygoteSendArgsAndGetResult方法:
//Process.java
private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState,
ArrayList<String> args) throws ZygoteStartFailedEx{
try {
//通過socket通訊,此處將程序啟動的啟動寫進socket的輸出流
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
result.pid = inputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
此方法,將會與ZygoteInit中runSelectLoop()方法啟動的socket程序通訊,而Zygote程序將會為此Activity建立新的程序,而子程序建立好後,會呼叫ActivityThread的主執行緒的main方法,所以繼續分析ActivityThread的main方法:
//ActivityThread.java
public static void main(String[] args){
...
AndroidKeyStoreProvider.install();
...
//啟動Looper
Looper.prepareMainLooper();
//建立ActivityThread,即主執行緒
ActivityThread thread = new ActivityThread();
thread.attach(false);
//獲取主Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
Looper.loop();
}
此段程式碼將會建立一個主執行緒物件ActivityThread,並將啟動Looper以及獲取主執行緒的Handler來進行訊息處理,並呼叫attach方法來進行執行緒處理,繼續分析attach方法:
//ActivityThread.java
//此處的system引數為false,即不是系統程序,而在分析AMS的時候,其啟動Home介面時,此處為true
private void attach(boolean system){
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
...
}
}
它呼叫了AMS的attachApplication方法來對執行緒進行包裝,繼續檢視attachApplication方法:
//ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
只是呼叫了attachApplicationLocked方法:
//ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,int pid){
//首先獲取相應的app
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
...
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
...
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
...
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
...
// 檢視該程序是否有棧頂可視的Activity等待執行
if (normalMode) {
try {
//如果有,會呼叫realStartActivityLocked方法啟動此Activity
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
return true;
}
此處回調了ActivityThread的bindApplication方法,通過bindApplication方法來對應用進行相應的初始化,然後呼叫了ActivityStackSupervisor的attachApplicationLocked方法,它最後會呼叫realStartActivityLocked方法來真正啟動Activity,本節不對Activity的排程做分析,所以先分析bindApplication方法。
//ActivityThread.java
public final void bindApplication(...){
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
...
IPackageManager pm = getPackageManager();
android.content.pm.PackageInfo pi = null;
...
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
...
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
//傳送BIND_APPLICATION訊號給ApplicationThread的H的handler處理
sendMessage(H.BIND_APPLICATION, data);
...
if (andResume) {
app.hasShownUi = true;
app.pendingUiClean = true;
}
app.forceProcessStateUpTo(mService.mTopProcessState);
//通過ActivityThread呼叫scheduleLaunchActivity來啟動Activity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r),
r.info, new Configuration(mService.mConfiguration),
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,newIntents,
...
}
首先通過sendMessage傳送BIND_APPLICATION訊號給ApplicationThread,ApplicationThread的handler會對此進行處理。至此,有關程序和執行緒的流程分析結束,其時序圖如下:
3.2.2 AMS對Activity的排程分析
上一節分析了程序的建立和主執行緒的初始化過程,本節將分析AMS對Activity生命週期的管理排程,此處涉及到的主要有如下幾個類:ActivityStackSupervisor,ActivityStack,ActivityThread,ApplicationThread,ApplicationThread.H,Instrumentation等。
系統通過AMS來管理應用程序的生命週期,當然包括應用的Activity、Service等的生命週期。AMS是一個獨立的程序,因此它要管理應用程序,必然要進行跨程序互動。其互動如下圖:
其中:
ActivityManagerProxy——AMS的代理,供應用程序呼叫。通過ActivityManagerNative.getDefault()獲取。
ApplicationThreadProxy——應用程序的代理,供AMS程序呼叫。應用啟動時,會將應用程序的代理傳遞到AMS跨程序通訊,一般都會用到遠端代理。ActivityManagerService繼承於Binder即它實現了IBinder介面,所以它可以用於程序間通訊。在app程序啟動時,會建立一個Binder執行緒池,專門用來處理Binder IPC事物。
在3.2.1節中已經分析了:AMS在啟動好了程序之後,會呼叫realStartActivityLocked方法來啟動Activity,所以先看realStartActivityLocked方法:
//ActivityStackSupervisor.java
final boolean realStartActivityLocked(ActivityRecord r,ProcessRecord app, boolean andResume,
boolean checkConfig) throws RemoteException{
...
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r),
r.info, new Configuration(mService.mConfiguration),new Configuration(stack.mOverrideConfig),
r.compat, r.launchedFromPackage,task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results,newIntents, !andResume, mService.isNextTransitionForward(),
profilerInfo);
...
}
由程式碼可知:它是通過呼叫ActivityThread.ApplicationThread類的scheduleLaunchActivity方法來啟動Activity的:
//ActivityThread.java/ApplicationThread內部類
@Override
public final void scheduleLaunchActivity(...){
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
...
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
此方法將傳送一個LAUNCH_ACTIVITY的Message給ApplicationThread.H的handler進行處理,而此handler將會呼叫ApplicationThread的handleLaunchActivity進行啟動處理:
//ActivityThread.java/ApplicationThread內部類
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent){
...
//確保執行的是最近的配置
handleConfigurationChanged(null, null);
...
//在create Activity之前intialize
WindowManagerGlobal.initialize();
//啟動Activity,即OnCreate()
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//呼叫OnResume()
handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished
&& !r.startsNotResumed);
...
}
...
}
如程式碼:首先呼叫performLaunchActivity來啟動Activity,即呼叫OnCreate()生命週期,然後會呼叫handleResumeActivity方法來呼叫OnResume()生命週期。首先看performLaunchActivity():
//ActivityThread.java/ApplicationThread內部類
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
//如果packageInfo為空,從ActivityInfo中獲取包資訊
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//從ActivityClientRecord中獲取元件名字
ComponentName component = r.intent.getComponent();
if (component == null) {
//獲取元件
component = r.intent.resolveActivity(mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
//新建元件
component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);
}
Activity activity = null;
//建立Activity
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {...}
...
if (r.isPersistable()) {
//呼叫OnCreate()方法
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
...
return activity;
}
此方法將會通過類載入器載入元件並新建Activity,然後通過呼叫Instrumentation的callActivityOnCreate方法來啟動Activity,其方法定義如下:
//Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
此方法裡呼叫了performCreate方法:
//Activity.java
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
顯然,它最後會呼叫定義的Activity的OnCreate()方法,即執行了OnCreate生命週期,同理其他生命週期的執行過程與此類似。OnCreate生命週期的時序圖如下:
4、startActivity方法啟動Activity的過程分析
本節將對我們熟悉的呼叫startActivity的啟動方式進行分析,同樣基於的原始碼版本是android 6.0,這種情況下,應用程序已經存在,不需要進行應用程序的建立啟動(區別於AMS啟動Home桌面等啟動新應用的方式),首先看startActivity()程式碼:
@Override
public void startActivity(Intent intent,@Nullable Bundle options){
if(options != null){
startActivityForResult(intent,-1,options);
}else{
startActivityForResult(intent,-1);
}
}
由程式碼可知,startActivity()最終只是對startActivityForResult()方法進行簡單呼叫,所以只需對startActivityForResult()繼續分析:
public void startActivityForResult(Intent intent,int requestCode,@Nullable Bundle options){
if(mParent == null){
//執行Activity啟動,並返回啟動結果
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this,
mMainThread.getApplicationThread(),mToken,this,intent,requestCode,options);
if(ar != null){
//向主執行緒傳送啟動結果
mMainThread.sendActivityResult(mToken,mEmbeddedID,requestCode,ar.getResultCode(),
ar.getResultData());
}
if(requestCode > 0){
//啟動成功
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
}else{
//如果mParent不為空,此時最後還是會呼叫Instrumentation的execStartActivity()方法
if(options != null){
mParent.startActivityFromChild(this,intent,requestCode,options);
}else{
mParent.startActivityFromChild(this,intent,requestCode);
}
}
}
最後還是會呼叫Instrumentation的execStartActivity()方法來啟動Activity,並將啟動的結果返回給該應用的主執行緒,繼續分析execStartActivity()方法:
public ActivityResult execStartActivity(Context who,IBinder contextThread,IBinder token,String
target,Intent intent,int requestCode,Bundle options){
//獲取通訊存根類,它派發訊息給ActivityThread主執行緒,而主執行緒的mH的handler會進行相應處理
IApplicationThread whoThread = (IApplicationThread)contextThread;
...
try{
intent.migrateExtraStreanToClipData();
intent.prepareToLeaveProcess();
//呼叫AMS的startActivity()方法,即進入AMS的排程管理
int result = ActivityManagerNative.getDefault().startActivity(whoThread,
who.getBasePackageName(),intent,intent.resolveTypeIfNeeded(
who.getContentResolver()),token,target,requestCode,0,null,options);
//檢查啟動結果
checkStartActivityResult(result,intent);
}catch(RemoteException e){
throw new RuntimeException("Failure from system",e);
}
return null;
}
首先獲得IApplicationThread物件,它用於與主執行緒進行通訊,ActivityManagerNative.getDefault()獲取的是AMS物件,所以此處將啟動任務交給了AMS進行排程管理。startActivity方法會呼叫startActivityAsUser()方法:
@Override
public final int startActivityAsUser(...){
userId = handleIncomingUser(Binder.getCallingPid(),Binder.getCallingUid(),userId,false,
ALLOW_FULL_ONLY,"startActivity",null);
return mStackSupervisor.startActivityMayWait(caller,-1,callingPackage,intent,resolvedType,
null,null,resultTo,resultWho,requestCode,startFlags,profierInfo,null,null,options,false,
userId,null,null);
}
至此,它的分析同第3節中的過程一致,此處不再做分析,只是本節的啟動不需要啟動程序,所以它的執行分支不一致。