連結https://mp.weixin.qq.com/s?__biz=MzIwNjQ1NzQxNA==&mid=2247484150&idx=1&sn=4007a9cff85df88941e73869b89b1ed4&chksm=97201ddfa05794c9e33c8d0d9e83f407922d24282dc9bd8d67c72debf9713abb1b0586f00bc9&scene=21#wechat_redirect
續 深入理解Activity啟動流程和AMS框架(一)
由此我們可以得到ActivityThread框架圖:
通常ApplicationThread中的介面方法都是以“schedule”開頭,而ActivityThread中對應的處理方法則以“handle”開頭。
6、Activity的建立並回撥onCreate()
ActivityThread中的成員變數mActivities中儲存了所有ActivityClientRecord物件,該類中重要的成員變數如下:
static final class ActivityClientRecord {
IBinder token; // Activity物件的全域性唯一標示
Intent intent; // 啟動Activity的Intent
Activity activity; // Activity物件
Window window; // Activity的視窗物件
boolean paused; // 是否在暫停狀態的標誌
boolean stopped; // 是否在停止狀態的標誌
ActivityInfo activityInfo; // Activity的資訊
LoadedApk packageInfo; // 包的資訊
}
token的型別是IBinder,在ActivityManagerService中會為每個應用程式中的Activity物件建立了一個對應的ActivityRecord物件,ActivityRecord會建立一個token物件來作為Activity的標識。這個token是個Binder物件,但是它不是為提供Binder服務而建立的,這裡只是利用Binder物件的 系統全域性唯一性 來作為識別符號。 每一個Activity都包含了一個Window物件,Window物件關聯著應用框架的一大塊內容。
從上面的框架圖我們可以得知:啟動一個Activity,首先會經過AMS和ActivityThread之間又長又臭的呼叫和回撥,最終才會調到ActivityThread的handleLaunchActivity()方法。下面我們看一下接下來的流程。
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
// 執行Activity建立和onCreate流程
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
// 執行Activity的onResume流程
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
......
} else {
// If there was an error, for any reason, tell the activity
// manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
// Ignore
}
}
}
handleLaunchActivity()再呼叫performLaunchActivity()方法來建立Activity並執行onCreate流程,返回後再執行Activity的onResume流程。繼續深入,不要慫。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 首先,從ActivityClientRecord中獲取待啟動的Activity的元件資訊
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
// 獲取Activity的packageInfo
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
// 獲取Activity的ComponentName
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;
try {
// 拿到載入Activity的ClassLoader, 建立Activity物件
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 (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
// 拿到當前程序中的Application物件
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
// 建立Activity的ApplicationContext
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
// 呼叫Activity的attach方法在其內部儲存一些ActivityClientRecord內的屬性
// 來完成一些重要的資料初始化
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
......
// 透過mInstrumentation呼叫Activity的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
// 將ActivityClientRecord中的activity屬性設定為當前activity
r.activity = activity;
......
}
r.paused = true;
// 以ActivityClientRecord中的token為key,mActivities中新增待啟動的activity
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
從上面程式碼我們發現,ActivityThread最後呼叫了mInstrumentation變數的newActivity()方法來建立Activity物件,並回撥了callActivityOnCreate()方法,走完Activity的onCreate流程。
public class Instrumentation {
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle); // 回撥Activity.onCreate()
postPerformCreate(activity);
}
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState); // 回撥Activity.onCreate()
postPerformCreate(activity);
}
}
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback {
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
}
這樣Activity在應用端程序ActivityThread的啟動流程和生命週期回撥流程都簡單分析完了。
Instrumentation是什麼?和ActivityThread是什麼關係?
Instrumentation可以理解為應用程序的管家,ActivityThread要執行建立或暫停某個Activity等操作時,都需要透過Instrumentation來進行具體的實現(回撥Activity的生命週期)。每一個應用程式只有一個Instrumentation物件,每個Activity內都有一個對該物件的引用。 另外,當我們在Activity中呼叫startActivity()的 時候,實際上呼叫的還是Instrumentation的相關的方法mInstrumentation.execStartActivity()。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
// 通知AMS執行startActivity的流程
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;
}
ActivityManagerNative.getDefault返回的就是ActivityManagerService的遠端介面,即ActivityManagerProxy。 除了啟動Activity之外,還有很多方法,有興趣的可以深入瞭解一下:
通俗的理解,ActivityThread負責建立這個“家庭”,並負責對外打交道,比如接收AMS的通知等。Instrumentation負責管理這個家庭,安排每個Activity的日常流程等工作。
四、小結
AMS透過Binder進行IPC通訊,通知應用程序ActivityThread啟動指定Activity
-
呼叫ApplicationThread.scheduleLaunchActivity()。
-
經過Handler訊息傳動,呼叫ActivityThread.handleLaunchActivity()。
-
呼叫ActivityThread.performLaunchActivity()完成Activity的載入,並最終呼叫Activity生命週期的onCreate()方法
-
performLaunchActivity返回,繼續呼叫ActivityThread.handleResumeActivity(),該方法內部又呼叫ActivityThread.performResumeActivity(),其內部僅僅呼叫了目標Activity的onResume()方法。到此Activity啟動完成。
-
Activity的其他生命週期方法onRestart等,可以根據onCreate流程為類推,舉一反三。
五、ActivitymanagerService(AMS)框架
ActivitymanagerService是Android Framework的一個核心繫統服務,它管理著Android系統中的4大元件:Activity、Service、ContentProvider和BroadcastReceiver。前面已經介紹了,Android希望模糊程序的作用,取而代之以元件的概念,AMS正是這一理念的實現。AMS除了管理這4大元件之外,同時也管理和排程所有使用者程序。
1、ActivityManager、ActivityManagerService、ActivityManagerNative、ActivityManagerProxy的關係
AMS是一個Binder服務,但是AMS的Binder框架程式碼不是透過AIDL自動生成的。AMS從ActivityManagerNative類派生,這個類加上IActivityManager、ActivityManagerProxy和ActivityManager共同實現了AMS Binder框架。它們的關係如下圖:
-
ActivityManagerNative類的程式碼雖然也很龐大,但只是實現Binder的框架,我們可以不用關心這個類的實現細節。
-
ActivityManagerProxy類是作為ActivityManagerNative的嵌入類來實現的,它是代理物件,起介面作用。
-
ActivityManager透過呼叫ActivityManagerNative的getDefault()方法來得到ActivityManagerProxy物件的引用。
理解了AMS的Binder框架類的作用,後面分析AMS服務的時候,可以不用關係這些類,只需要集中精力在AMS類的本身上。
2、AMS的初始化
AMS執行在SystemServer程序中,物件的建立是在SystemServer類初始化時完成的。
public final class SystemServer {
......
private ActivityManagerService mActivityManagerService;
private void startBootstrapServices() {
...
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService(); // 建立AMS服務
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
...
}
......
}
從程式碼中可以看到,這裡呼叫了mSystemServiceManager.startService()方法,這個方法將根據傳入的引數(類的class)來建立類的例項物件,並註冊到ServiceManager中。 接下來我們看一下AMS的構造方法做了些什麼:
public ActivityManagerService(Context systemContext) {
mContext = systemContext;
mFactoryTest = FactoryTest.getMode();
// 獲取執行在SystemServer中的ActivityThread物件
mSystemThread = ActivityThread.currentActivityThread();
// 建立用於處理訊息的執行緒和Handler物件
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
// 建立用於UI操作相關的Handler物件
mUiHandler = new UiHandler();
// 建立管理廣播的資料結構
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", BROADCAST_BG_TIMEOUT, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue;
mServices = new ActiveServices(this); // 建立管理元件Service的物件
mProviderMap = new ProviderMap(this); // 建立管理元件Provider的物件
// 獲取系統的data和system目錄
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
systemDir.mkdirs();
// 建立BatteryStatsService服務
mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.scheduleWriteToDisk();
mOnBattery = DEBUG_POWER ? true
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
// 建立ProcessStatsService服務
mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
// 建立AppOpsService應用許可權管理服務
mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
// 開啟檔案urigrants.xml
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
// 設定0號使用者作為第一個使用者
mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));
mUserLru.add(UserHandle.USER_OWNER);
updateStartedUserArrayLocked();
// 獲取OpenglES的版本
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
// 設定mConfiguration配置項為系統預設值
mConfiguration.setToDefaults();
mConfiguration.setLocale(Locale.getDefault());
mConfigurationSeq = mConfiguration.seq = 1;
mProcessCpuTracker.init();
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
// 建立Intent “防火牆”
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
// 建立最近工作列的棧管理物件
mRecentTasks = new RecentTasks(this);
// 建立Activity棧的管理物件mStackSupervisor
mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);
mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);
// 建立統計CPU使用情況的執行緒
mProcessCpuThread = new Thread("CpuTracker") {
......
}
// 把服務加到watchdog的監控中
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
AMS構造方法的主要作用是建立了4大元件Activity、Service、BroadcastReceiver和ContentProvider的管理物件以及一些內部物件,邏輯比較簡單。
3、如何啟動程序
AMS中啟動一個程序呼叫的是addAppLocked()方法。
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
String abiOverride) {
ProcessRecord app;
// isolated為true表示要啟動一個新程序
if (!isolated) { // 在已經啟動的程序列表中查詢
app = getProcessRecordLocked(info.processName, info.uid, true);
} else {
app = null;
}
if (app == null) {
// 建立一個ProcessRecord物件
app = newProcessRecordLocked(info, null, isolated, 0);
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
......
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
// 啟動程序
startProcessLocked(app, "added application", app.processName, abiOverride,
null /* entryPoint */, null /* entryPointArgs */);
}
return app;
}
addAppLocked()方法會根據引數isolated來決定是否啟動一個新程序,如果為true,即使系統中可能已經有一個同名的程序存在,也會再建立一個新程序。getProcessRecordLocked()方法用來在當前執行的程序列表中查詢程序。newProcessRecordLocked()方法用來建立一個ProcessRecord的資料結構。updateLruProcessLocked方法用來更新執行中的程序的狀態,updateOomAdjLocked用來更新程序的優先順序,這兩個方法是Process管理的核心。篇幅有限,這裡不再展開分析咯。
4、ActivityRecord、TaskRecord、ActivityStack的關係
(1)、ActivityRecord
final class ActivityRecord {
// AMS的引用
final ActivityManagerService service; // owner
// token用來和WMS互動
final IApplicationToken.Stub appToken; // window manager token
final ActivityInfo info; // all about me
final ApplicationInfo appInfo; // information about activity's app
final ComponentName realActivity; // the intent component, or target of an alias.
...
//Activity資源資訊
CharSequence nonLocalizedLabel; // the label information from the package mgr.
int labelRes; // the label information from the package mgr.
int icon; // resource identifier of activity's icon.
int logo; // resource identifier of activity's logo.
int theme; // resource identifier of activity's theme.
int realTheme; // actual theme resource we will use, never 0.
int windowFlags; // custom window flags for preview window.
// ActivityRecord所在的TaskRecord
TaskRecord task; // the task this is in.
...
// ActivityRecord所在程序
ProcessRecord app; // if non-null, hosting application
ActivityState state; // current state we are in
...
}
ActivityRecord就是Activity在AMS中的代表,ActivityRecord和應用中的Activity一一對應,並且包含了Activity的所有資訊。(就好比Activity在ActivityThread中對應ActivityClientRecord一樣) 每一個ActivityRecord都會有一個Activity與之對應,一個Activity可能會有多個ActivityRecord,因為Activity可以被多次例項化,取決於其Launchmode。 其中task物件標識了其所歸屬的TaskRecord,這樣ActivityRecord和TaskRecord就聯絡起來了。
(2)TaskRecord
final class TaskRecord {
// TaskRecord的唯一標識
final int taskId; // Unique identifier for this task.
.....
// This represents the last resolved activity values for this task
// NOTE: This value needs to be persisted with each task
TaskDescription lastTaskDescription = new TaskDescription();
// TaskRecord裡所有的ActivityRecord資訊
/** List of all activities in the task arranged in history order */
final ArrayList<ActivityRecord> mActivities;
// TaskRecord所在的stack
ActivityStack stack;
......
}
TaskRecord中我列出來三個成員變數:
-
taskId:唯一標示的id號
-
mActivities:當前棧中所有的ActivityRecord
-
stack:ActivityStack的引用,為了回撥ActivityStack的方法
從TaskRecord 的資料結構我們可以看到,mActivities儲存了一組ActivityRecord資訊,同時每一個ActivityRecord都有其所在TaskRecord的引用。TaskRecord都有一個唯一標示taskId,還包含了ActivityStack的引用物件。 因此,TaskRecord可以理解為一個mActivities組成的棧,也可以理解為一個由一系列Activity組成的活動。
(3)、 ActivityStack
final class ActivityStack {
/**
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
*/
private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
...
final int mStackId;
...
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
}
-
mStackId:唯一標示的id號
-
mTaskHistory:這個記錄的是一組TaskRecord的棧資訊
-
mStackSupervisor:ActivityStack的管理類,也是為了方便管理Task,被AMS呼叫等
從名字上看,ActivityStack更像是一個棧,實際上它就是一個Manager的角色。 ActivityStack負責管理協調ActivityRecord和TaskRecord,透過mStackId來唯一標識,持有ActivityStackSupervisor的引用。
(4)、關係圖
每一個ActivityRecord都會有一個Activity與之對應。一系列相關的ActivityRecord組成了一個TaskRecord,TaskRecord是存在於ActivityStack中,ActivityStackSupervisor是用來管理這些ActivityStack的。 下面是一個簡單的關係圖
Task 是Activity的集合。Android把使用者一次相關操作用使用的Activity按照先後順序儲存在Task中,這樣當使用者按back鍵的時候就能按照相反的順序依次返回退出。Task像一個棧,以先進後出的方式管理著Activity。系統執行時記憶體中會存在多個Task,當我們檢視最近工作列時,會彈出一個列表讓你選擇,這個列表就是系統中存在的Task集合,選擇一個Task會將它所包含的Activity作為一個整體帶到前臺。Task中的Activity的順序通常是不能改變的,只能壓棧和出棧。
AMS中使用ActivityStack 類來管理Task,它管理的Task都存放在成員變數mTaskHistory中。mTaskHistory也是一個列表,儲存的是TaskRecord物件。TaskRecord物件代表一個Task,他的成員變數mActivities也是一個列表,儲存了屬於該Task中的所有ActivityRecord物件。