【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 )
文章目錄
- 一、Activity 啟動源碼分析 ( AMS | ActivityManagerService )
- 1、Instrumentation 調用 AMS 方法
- 2、ActivityStarter 調用 AMS 方法
- 3、Process 啟動新進程
- 二、Activity 啟動源碼分析 ( ActivityStarter )
- 1、ActivityStarter.startActivityMayWait() 方法
- 2、ActivityStarter.startActivity ( 24 參數 ) 方法
- 3、ActivityStarter.startActivity ( 23 參數 ) 方法
- 4、ActivityStarter.startActivity ( 9 參數 ) 方法
- 5、ActivityStarter.startActivityUnchecked 方法
- 6、ActivityStarter.computeLaunchingTaskFlags() 方法
- 三、Activity 啟動源碼分析 ( ActivityRecord )
- 五、ActivityStack
- 六、ActivityStackSupervisor
- 四、ActivityStack、TaskRecord、ActivityRecord
一、Activity 啟動源碼分析 ( AMS | ActivityManagerService )
1、Instrumentation 調用 AMS 方法
在 Instrumentation 中 , 通過調用 ActivityManagerService ( AMS ) 的 startActivity 方法 ,
// 在此處調用 AMS , Binder 機制獲取 AMSint result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);調用的是 AMS 的 startActivity 101010 個參數的方法 , 在該方法中又掉了 111111 個參數的 startActivityAsUser 方法 ; 在 startActivityAsUser 方法中 , 主要是確保要打開的 Activity 在 AndroidManifest.xml 清單文件中注冊過 ;
在插件化中 , 要在執行該 AMS 方法之前 , 使用在清單文件中注冊過的占坑 Activity 替換插件 Activity , 借此騙過 AMS ;
AMS 相關源碼如下 :
public class ActivityManagerService extends IActivityManager.Stubimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {@Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}@Overridepublic final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {enforceNotIsolatedCaller("startActivity");userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),userId, false, ALLOW_FULL_ONLY, "startActivity", null);// TODO: Switch to user app stacks here.return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");} }ActivityManagerService 完整源碼參考 : frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
2、ActivityStarter 調用 AMS 方法
在 ActivityStarter.startActivityUnchecked 中調用了 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); 方法 , 顯示棧頂元素 ,
在 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); 中, 調用了 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); 方法啟動新進程 ;
最終在 private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) 方法中 , 調用了Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs) 方法 , 開啟新的進程 ;
public class ActivityManagerService extends IActivityManager.Stubimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {if (hostingType.equals("webview_service")) {startResult = startWebView(entryPoint,app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, entryPointArgs);} else {startResult = Process.start(entryPoint,app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, invokeWith, entryPointArgs);}} }ActivityManagerService 完整源碼參考 : frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
3、Process 啟動新進程
AMS 的 void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) 方法中 , 調用了 startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs); 啟動新進程 , 該方法原型如下 :
/*** 開始一個新的過程。** <p>如果啟用了流程,則會創建一個新流程,并且* 在那里執行<var>processClass</var>的靜態main()函數。* 此函數返回后,進程將繼續運行。** <p>如果未啟用進程,則在調用方的* 進程被創建,并在那里調用<var>processClass</var>的main()。** <p>niceName參數(如果不是空字符串)是要使用的自定義名稱* 指定給進程,而不是使用processClass。這允許您* 即使使用相同的基礎,也要創建易于識別的流程* <var>processClass</var>啟動它們。** 當invokeWith不為null時,該進程將作為新應用程序啟動* 而不是合子叉。請注意,這僅適用于uid 0或以下情況* runtimeFlags包含調試\啟用\調試器。** @param processClass 要用作進程主項的類* 指向* @param niceName 用于進程的可讀性更強的名稱。* @param uid 進程將在其下運行的用戶id。* @param gid 進程將在其下運行的組id。* @param gids 與進程關聯的其他組ID。* @param runtimeFlags 為運行時添加附加標志。* @param targetSdkVersion 應用程序的目標SDK版本。* @param seInfo null確定新進程的SELinux信息。* @param abi non null此應用程序啟動時應使用的abi。* @param instructionSet null確定要使用的指令集。* @param appDataDir null ok應用程序的數據目錄。* @param invokeWith null ok用于調用的命令。* @param zygoteArgs 為合子進程提供附加參數。** @返回一個對象,該對象描述嘗試啟動進程的結果。* @在致命啟動失敗時引發RuntimeException** {@hide}*/public static final ProcessStartResult start(final String processClass,final String niceName,int uid, int gid, int[] gids,int runtimeFlags, int mountExternal,int targetSdkVersion,String seInfo,String abi,String instructionSet,String appDataDir,String invokeWith,String[] zygoteArgs) {return zygoteProcess.start(processClass, niceName, uid, gid, gids,runtimeFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, invokeWith, zygoteArgs);}完整源碼參考 /frameworks/base/core/java/android/os/Process.java ;
二、Activity 啟動源碼分析 ( ActivityStarter )
1、ActivityStarter.startActivityMayWait() 方法
在 AMS 中調用了 mActivityStarter.startActivityMayWait 方法 , 在 ActivityStarter 中的 startActivityMayWait 中 , 調用了 242424 個參數的 startActivity 方法 ,
class ActivityStarter {private int startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, String resolvedType,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, WaitResult outResult,Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,int userId, TaskRecord inTask, String reason,boolean allowPendingRemoteAnimationRegistryLookup) {// 獲取對應 Activity 信息 , 并處理該信息// 從多個 Activity 中選擇最合適的 Activity // 類似于打開一個文本文件 , 彈出窗口 , 選擇什么應用打開 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,0 /* matchFlags */,computeResolveFilterUid(callingUid, realCallingUid, mRequest.filterCallingUid));// 在 ActivityRecord 對象中 , 記錄了 Activity 的相關活動final ActivityRecord[] outRecord = new ActivityRecord[1];// 啟動 Activity // 調用的是 24 個參數的 startActivity 方法int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,allowPendingRemoteAnimationRegistryLookup);} }完整代碼參考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;
2、ActivityStarter.startActivity ( 24 參數 ) 方法
在 242424 個參數的 startActivity 的重載方法中 , 又調用了 232323 個參數的 startActivity 重載方法 ;
class ActivityStarter {// 24 個參數的 startActivity 的重載方法private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,String callingPackage, int realCallingPid, int realCallingUid, int startFlags,SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,ActivityRecord[] outActivity, TaskRecord inTask, String reason,boolean allowPendingRemoteAnimationRegistryLookup) {// 調用了 23 個參數的 startActivity 的重載方法mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,inTask, allowPendingRemoteAnimationRegistryLookup);} }完整代碼參考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;
3、ActivityStarter.startActivity ( 23 參數 ) 方法
在 232323 個參數的 startActivity 的重載方法中 , 又調用了 999 個參數的 startActivity 重載方法 ,
class ActivityStarter {// 23 個參數的 startActivity 重載方法 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,String callingPackage, int realCallingPid, int realCallingUid, int startFlags,SafeActivityOptions options,boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {// 調用 9 個參數的 startActivity 的重載方法return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,true /* doResume */, checkedOptions, inTask, outActivity);} }完整代碼參考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;
4、ActivityStarter.startActivity ( 9 參數 ) 方法
在 999 個參數的 startActivity 的重載方法中 , 調用了 startActivityUnchecked 方法 ;
class ActivityStarter {// 9 個參數的 startActivity 的重載方法private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,ActivityRecord[] outActivity) {try {mService.mWindowManager.deferSurfaceLayout();// 此處是主要的邏輯 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, outActivity);}} }完整代碼參考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;
5、ActivityStarter.startActivityUnchecked 方法
在 startActivityUnchecked 方法中 , 調用了 computeLaunchingTaskFlags 方法 ,
mTargetStack.startActivityLocked 是將啟動的 Activity 插入到棧頂部 , 調用 ActivityStack 的 startActivityLocked 方法 ;
class ActivityStarter {// 注意:此方法只能從{@link startActivity}調用。private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,ActivityRecord[] outActivity) {// 啟動 Activity 的 Launcher Mode 4 種啟動模式 , 就是在該方法中處理computeLaunchingTaskFlags();computeSourceStack();// 此處將啟動的 Activity 插入到棧頂部// 調用 ActivityStack 的 startActivityLocked 方法 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,mOptions);// 顯示棧頂元素mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,mOptions);}完整代碼查看 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;
6、ActivityStarter.computeLaunchingTaskFlags() 方法
該方法處理 Activity 啟動模式 , 假如啟動 Activity 場景是 Activity A 啟動 Activity B , mSourceRecord 是 Activity A 相關資料 , 是 ActivityRecord 類型對象 , 該對象中保存了 Activity 的所有信息 ;
mSourceRecord == null , 判斷啟動 Activity 的源是否是 Activity , 如果通過 Context 或 Application 啟動 Activity , 則 mSourceRecord 就是空的 ;
mInTask != null 判斷要加入的 TaskRecord 是否為空 ;
調用 isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK) 方法用于判定該 Activity 的啟動模式是否是 LAUNCH_SINGLE_INSTANCE 或 LAUNCH_SINGLE_TASK 中二者之一 ;
class ActivityStarter {// 處理 Activity 啟動模式private void computeLaunchingTaskFlags() {// 如果調用方不是來自另一個 Activity,而是給了我們一個明確的任務,// 他們希望我們在其中啟動新Activity,那么讓我們看看如何執行該任務。// 假如啟動 Activity 場景是 Activity A 啟動 Activity B // mSourceRecord 是 Activity A 相關資料 , 是 ActivityRecord 類型對象// 該對象中保存了 Activity 的所有信息 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {final Intent baseIntent = mInTask.getBaseIntent();final ActivityRecord root = mInTask.getRootActivity();if (baseIntent == null) {ActivityOptions.abort(mOptions);throw new IllegalArgumentException("Launching into task without base intent: "+ mInTask);}// 如果此任務為空,那么我們將添加第一個活動——它確定根,并且必須作為新的_任務啟動。if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {if (root != null) {ActivityOptions.abort(mOptions);throw new IllegalArgumentException("Caller with mInTask " + mInTask+ " has root " + root + " but target is singleInstance/Task");}}} }完整代碼參考 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java ;
三、Activity 啟動源碼分析 ( ActivityRecord )
ActivityRecord 中記錄了所有的 Activity 信息 , 其中的 private TaskRecord task; // the task this is in. 成員 , 記錄該 ActivityRecord 是存儲在哪個 TaskRecord 中 ;
由于 Activity 可以啟動多次 , 111 個 Activity 可能有多個 ActivityRecord 與之對應 , 每個 ActivityRecord 都與當前某個存在的 Activity 對應 ; 如果啟動模式是 Standard , 那么每次啟動該 Activity 都會創建一個新的 Activity , 放在任務棧棧頂 ;
final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;private static final String TAG_STATES = TAG + POSTFIX_STATES;private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;// TODO(b/67864419): Remove once recents component is overriddenprivate static final String LEGACY_RECENTS_PACKAGE_NAME = "com.android.systemui.recents";private static final boolean SHOW_ACTIVITY_START_TIME = true;private static final String ATTR_ID = "id";private static final String TAG_INTENT = "intent";private static final String ATTR_USERID = "user_id";private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";private static final String ATTR_RESOLVEDTYPE = "resolved_type";private static final String ATTR_COMPONENTSPECIFIED = "component_specified";static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";final ActivityManagerService service; // ownerfinal IApplicationToken.Stub appToken; // window manager tokenAppWindowContainerController mWindowContainerController;final ActivityInfo info; // all about me// TODO: This is duplicated state already contained in info.applicationInfo - removeApplicationInfo appInfo; // information about activity's appfinal int launchedFromPid; // always the pid who started the activity.final int launchedFromUid; // always the uid who started the activity.final String launchedFromPackage; // always the package who started the activity.final int userId; // Which user is this running for?final Intent intent; // the original intent that generated usfinal ComponentName realActivity; // the intent component, or target of an alias.final String shortComponentName; // the short component name of the intentfinal String resolvedType; // as per original caller;final String packageName; // the package implementing intent's componentfinal String processName; // process where this component wants to runfinal String taskAffinity; // as per ActivityInfo.taskAffinityfinal boolean stateNotNeeded; // As per ActivityInfo.flagsboolean fullscreen; // The activity is opaque and fills the entire space of this task.// TODO: See if it possible to combine this with the fullscreen field.final boolean hasWallpaper; // Has a wallpaper window as a background.final boolean noDisplay; // activity is not displayed?private final boolean componentSpecified; // did caller specify an explicit component?final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?private CharSequence nonLocalizedLabel; // the label information from the package mgr.private int labelRes; // the label information from the package mgr.private int icon; // resource identifier of activity's icon.private int logo; // resource identifier of activity's logo.private int theme; // resource identifier of activity's theme.private int realTheme; // actual theme resource we will use, never 0.private int windowFlags; // custom window flags for preview window.private TaskRecord task; // the task this is in.private long createTime = System.currentTimeMillis();long displayStartTime; // when we started launching this activitylong fullyDrawnStartTime; // when we started launching this activityprivate long startTime; // last time this activity was startedlong lastVisibleTime; // last time this activity became visiblelong cpuTimeAtResume; // the cpu time of host process at the time of resuming activitylong pauseTime; // last time we started pausing the activitylong launchTickTime; // base time for launch tick messages// Last configuration reported to the activity in the client process.private MergedConfiguration mLastReportedConfiguration;private int mLastReportedDisplayId;private boolean mLastReportedMultiWindowMode;private boolean mLastReportedPictureInPictureMode;CompatibilityInfo compat;// last used compatibility modeActivityRecord resultTo; // who started this entry, so will get our replyfinal String resultWho; // additional identifier for use by resultTo.final int requestCode; // code given by requester (resultTo)ArrayList<ResultInfo> results; // pending ActivityResult objs we have receivedHashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this actArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top modeActivityOptions pendingOptions; // most recently given optionsActivityOptions returningOptions; // options that are coming back via convertToTranslucentAppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activityHashSet<ConnectionRecord> connections; // All ConnectionRecord we holdUriPermissionOwner uriPermissions; // current special URI access perms.ProcessRecord app; // if non-null, hosting applicationprivate ActivityState mState; // current state we are inBundle icicle; // last saved activity statePersistableBundle persistentState; // last persistently saved activity state// TODO: See if this is still needed.boolean frontOfTask; // is this the root activity of its task?boolean launchFailed; // set if a launched failed, to abort on 2nd tryboolean haveState; // have we gotten the last activity state?boolean stopped; // is activity pause finished?boolean delayedResume; // not yet resumed because of stopped app switches?boolean finishing; // activity in pending finish list?boolean deferRelaunchUntilPaused; // relaunch of activity is being deferred until pause is// completedboolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunchint configChangeFlags; // which config values have changedprivate boolean keysPaused; // has key dispatching been paused for it?int launchMode; // the launch mode activity attribute.int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to overrideboolean visible; // does this activity's window need to be shown?boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard// might hide this activity?private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client// process that it is hidden.boolean sleeping; // have we told the activity to sleep?boolean nowVisible; // is this activity's window visible?boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?boolean idle; // has the activity gone idle?boolean hasBeenLaunched;// has this activity ever been launched?boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.boolean immersive; // immersive mode (don't interrupt if possible)boolean forceNewConfig; // force re-create with new config next timeboolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the// activity can enter picture in picture while pausing (only when switching to another task)PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();// The PiP params used when deferring the entering of picture-in-picture.int launchCount; // count of launches since last statelong lastLaunchTime; // time of last launch of this activityComponentName requestedVrComponent; // the requested component for handling VR mode.String stringName; // for caching of toString().private boolean inHistory; // are we in the history stack?final ActivityStackSupervisor mStackSupervisor;static final int STARTING_WINDOW_NOT_SHOWN = 0;static final int STARTING_WINDOW_SHOWN = 1;static final int STARTING_WINDOW_REMOVED = 2;int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.TaskDescription taskDescription; // the recents information for this activityboolean mLaunchTaskBehind; // this activity is actively being launched with// ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.// These configurations are collected from application's resources based on size-sensitive// qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800// and drawable-sw400dp will be added to both as 400.private int[] mVerticalSizeConfigurations;private int[] mHorizontalSizeConfigurations;private int[] mSmallestSizeConfigurations;boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice sessionIVoiceInteractionSession voiceSession; // Voice interaction session for this activity// A hint to override the window specified rotation animation, or -1// to use the window specified value. We use this so that// we can select the right animation in the cases of starting// windows, where the app hasn't had time to set a value// on the window.int mRotationAnimationHint = -1;private boolean mShowWhenLocked;private boolean mTurnScreenOn;/*** Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}*/private final Configuration mTmpConfig = new Configuration();private final Rect mTmpBounds = new Rect(); }完整代碼參考 frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
五、ActivityStack
在 ActivityStarter.startActivityUnchecked 方法中 , 調用了 ActivityStack.startActivityLocked 方法 , 將啟動的 Activity 插入了任務棧的頂部 ;
class ActivityStack<T extends StackWindowController> extends ConfigurationContainerimplements StackWindowListener {void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,boolean newTask, boolean keepCurTransition, ActivityOptions options) {TaskRecord rTask = r.getTask();final int taskId = rTask.taskId;// mLaunchTaskBehind tasks get placed at the back of the task stack.if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {// Last activity in task had been removed or ActivityManagerService is reusing task.// Insert or replace.// Might not even be in.insertTaskAtTop(rTask, r);}} }六、ActivityStackSupervisor
在 ActivityStarter.startActivityUnchecked 方法中 , 調用了 ActivityStackSupervisor.resumeFocusedStackTopActivityLocked 方法 , 作用是重新顯示棧頂 Activity ;
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,RecentTasks.Callbacks {boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {if (!readyToResume()) {return false;}if (targetStack != null && isFocusedStack(targetStack)) {return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);}final ActivityRecord r = mFocusedStack.topRunningActivityLocked();if (r == null || !r.isState(RESUMED)) {mFocusedStack.resumeTopActivityUncheckedLocked(null, null);} else if (r.isState(RESUMED)) {// Kick off any lingering app transitions form the MoveTaskToFront operation.mFocusedStack.executeAppTransition(targetOptions);}return false;}完整代碼參考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;
在 startSpecificActivityLocked 方法中 , 根據 ProcessRecord app 是否為空 , 確定要啟動的 Activity 對應的進程是否存在 , 如果不存在需要創建進程 ;
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,RecentTasks.Callbacks {void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {// Is this activity's application already running?ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);getLaunchTimeTracker().setLaunchTime(r);if (app != null && app.thread != null) {try {if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0|| !"android".equals(r.info.packageName)) {// Don't add this if it is a platform component that is marked// to run in multiple processes, because this is actually// part of the framework so doesn't make sense to track as a// separate apk in the process.app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,mService.mProcessStats);}realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}// If a dead object exception was thrown -- fall through to// restart the application.}mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);} }完整代碼參考 /frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java ;
四、ActivityStack、TaskRecord、ActivityRecord
每個 ActivityStack 中對應多個 TaskRecord ; TaskRecord 對應 " 活動任務棧 "
每個 TaskRecord 對應多個 ActivityRecord ;
對應關系如下圖所示 :
在 ActivityStack 中的 private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>(); 成員存儲的就是若干 TaskRecord ;
/*** 單個堆棧活動的狀態和管理。*/ class ActivityStack<T extends StackWindowController> extends ConfigurationContainerimplements StackWindowListener {/*** 所有以前(可能仍在運行)活動的歷史記錄。它包含#TaskRecord對象。*/private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();}完整代碼參考 /frameworks/base/services/core/java/com/android/server/am/ActivityStack.java ;
在 TaskRecord.java 源碼中 , TaskRecord 類中有 final ArrayList<ActivityRecord> mActivities 成員變量 , 該成員就是存儲多個 ActivityRecord ;
class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {/** 按歷史順序排列的任務中所有活動的列表 */final ArrayList<ActivityRecord> mActivities; }完整代碼參考 /frameworks/base/services/core/java/com/android/server/am/TaskRecord.java ;
總結
以上是生活随笔為你收集整理的【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 返回堆栈管理】打印 A
- 下一篇: 【Android 启动过程】Activi