【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 )

article/2025/11/5 6:00:39

文章目录

  • 一、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 10 10 10 个参数的方法 , 在该方法中又掉了 11 11 11 个参数的 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 中 , 调用了 24 24 24 个参数的 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 参数 ) 方法


24 24 24 个参数的 startActivity 的重载方法中 , 又调用了 23 23 23 个参数的 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 参数 ) 方法


23 23 23 个参数的 startActivity 的重载方法中 , 又调用了 9 9 9 个参数的 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 参数 ) 方法


9 9 9 个参数的 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 可以启动多次 , 1 1 1 个 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 ;


http://chatgpt.dhexx.cn/article/LrgJnZpu.shtml

相关文章

Android 中你碰不到但是很重要的类之ActivityThread

作者&#xff1a;Drummor 通过本文能了解一下内容 1、和系统进程打交道的桥头堡 应用进程起来之后ART(Android Runtime)第一站就是ActivityThread&#xff0c;代码层面上就是ActivityThread的main()方法&#xff0c;是不是很熟悉&#xff0c;爷青回啊&#xff0c;这不就是java…

浅析ActivityThread#main()方法和生命周期事务处理(代码基于Android-12)

浅析ActivityThread#main()方法和生命周期事务处理&#xff08;代码基于Android-12&#xff09; 问题&#xff1a; Activity、Application的onCreate()在哪被调用的&#xff1f; ContentProvider为什么比Application先创建&#xff1f; Activity#attach()在哪里被调用的&#…

Android中的ActivityThread和ApplicationThread

一&#xff1a;ActivityThread和ApplicationThread 1.ActivityThread&#xff1a;主线程、UI线程&#xff0c;程序的入口&#xff08;main函数&#xff09;&#xff0c;不是线程是运行在主线程中的一个对象 主要的成员变量如下&#xff1a; mActivities、mServices和mProvide…

一文读懂ActivityThread

ActivityThread是什么&#xff0c;是主线程吗&#xff1f;它是如何被创建的&#xff0c;以及它的作用又是什么呢&#xff1f;带着这些问题&#xff0c;我们一起来分析下ActivityThread。 全文分为以下几个部分&#xff0c;大家可根据需求阅读 文章目录 ActivityThread是什么Act…

Android ActivityThread(主线程或UI线程)简介

1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数)&#xff0c;并根据AMS的要求&#xff08;通过IApplicationThread接口&#xff0c;AMS为Client、ActivityThread.ApplicationThread为Server&#xff09;负责调度和执行activities、broa…

ActivityThread的理解和APP的启动过程

ActivityThread的理解和APP的启动过程 ActivityThreadActivityThread的初始化主线程Looper的初始化主线程Handler的初始化ApplicationThread及Activity的创建和启动 APP的启动系统的启动过程APP的启动过程APP启动过程的部分代码思考 总结 ActivityThread ActivityThread就是我…

validate中remote返回函数中+号导致submitHandler无法执行

validate中remote返回函数中号导致submitHandler无法执行 这是2017年以来我遇到的最无语的bug&#xff0c;现在暂时还没想到原因&#xff0c;但是这个错误真的很无语。 这是我的validate中rule的定义&#xff0c;其中 new Date; 采用至慕课网上validate插件视频中的例子。 rul…

jQuery(六)插件、Validate验证提交表单、submitHandler、更改错误信息显示的位置、required、Validator、内置验证方式表、validate ()的可选项汇总

jQuery&#xff08;六&#xff09;插件、Validate验证提交表单、submitHandler、更改错误信息显示的位置、required、Validator、内置验证方式表、validate ()的可选项汇总 文章目录 jQuery&#xff08;六&#xff09;插件、Validate验证提交表单、submitHandler、更改错误信息…

ajax post 不起作用,jQuery验证submitHandler在$ .ajax post表单数据中不起作用

我使用$.ajax发送数据并使用jQuery验证插件进行验证&#xff0c;如下所示&#xff1a; Send JS&#xff1a; jQuery(document).ready(function ($) { $(#myform).validate({ rules: { name: { required: true, rangelength: [4, 20], }, }, submitHandler: function (form) { $…

FileReader()用法

FileReader()用法HTML5定义了FileReader作为文件API的重要成员用于读文件&#xff0c;根据W3C的定义&#xff0c;FileReaderr接口提供了读取文件的方法和包含读取 结果的事件模型。 FileReader的方法使用比较简单&#xff0c;可以按照以下步骤创建FileReader对象并调用其他的方…

read/write/fsync与fread/fwrite/fflush的关系和区别

read/write/fsync&#xff1a; 1. linux底层操作&#xff1b; 2. 内核调用&#xff0c; 涉及到进程上下文的切换&#xff0c;即用户态到核心态的转换&#xff0c;这是个比较消耗性能的操作。 fread/fwrite/fflush&#xff1a; 1. c语言标准规定的io流操作&#xff0c;建立…

FileReader详解

我在Google Chrome Web Store上发布了一个案例hahaOCR&#xff0c;该扩展程序可以帮助用户识别出图片中的文字信息&#xff0c;并以文本形式显示&#xff0c;大家可以在chrome网上应用商店中找到我发布的应用程序&#xff0c;如图所示&#xff1a; 图1 - hahaOCR 该扩展程序支持…

f.readlines()

f.readlines() ftext open(1299_wangyifei_edit.pinyin, r, encodingutf-8)lines ftext.readlines()print("lines",lines)l ftext.readlines()print("l",l)输出结果&#xff1a; 原因&#xff1a; readlines() 方法用于读取所有行(直到结束符 EOF)并返…

FileReader的用法

FileReader是一种异步文件读取机制&#xff0c;结合input:file可以很方便的读取本地文件。 input:file input的file类型会渲染为一个按钮和一段文字。点击按钮可打开文件选择窗口&#xff0c;文字表示对文件的描述&#xff08;大部分情况下为文件名&#xff09;&#xff1b;…

【原创】通过 ioctl + FIONREAD 判定数据可读

【原创】通过 ioctl FIONREAD 判定数据可读 摩云飞 2016-05-12 09:57:51 浏览470 评论0 libevent ioctl FIONREAD 摘要&#xff1a; 在排查业务 bug 的过程中&#xff0c;看到如下两种输出信息&#xff1a; TCP 连接正常情况下&#xff0c;进行数据读取 14:00:38 epoll_ctl…

fread函数详解

文章迁移&#xff1a; fread函数详解 - 码到城攻fread函数详解&#xff0c;C函数使用注意事项&#xff0c;freadhttps://www.codecomeon.com/posts/93/ 函数原型&#xff1a; size_t fread( void *buffer, size_t size, size_t count, FILE *stream ) buf…

SQLSTATE: Insert value list does not match column list: 1136 Column count doesn‘t match value count

使用thinkphp5的insertAll的批量新增函数&#xff0c;提示SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesnt match value count at row 2 其意思就是&#xff1a;在第二行数据开始&#xff0c;插入的&#xff0c;每行数据的值的个数和…

Column-Stores vs. Row-Stores: How Different Are They Really

概述 从论文的标题可以看出这篇论文不是陈述一种新的技术、架构&#xff0c;而更偏议论文一点&#xff0c;它主要的目的在于搞清楚对于分析类的查询为什么Column-Store比Row-Store好那么多&#xff1f;好在哪里&#xff1f;一般认为原因是: 分析类查询往往只查询一个表里面很少…

Android应用开发之( TableLayout中stretchColumns、shrinkColumns的用法)

从字面上来看&#xff0c;TableLayout也比较简单&#xff0c;关键是要对相关的属性要熟悉&#xff0c;先看一个简单的例子&#xff08;后面为效果图&#xff09;&#xff1a; <?xml version"1.0" encoding"utf-8"?> <TableLayout xmlns:android…

CollenctionList

1.Collection集合 1.1集合体系结构【记忆】 集合类的特点 提供一种存储空间可变的存储模型&#xff0c;存储的数据容量可以随时发生改变 集合类的体系图 1.2Collection集合概述和基本使用【应用】 Collection集合概述 是单例集合的顶层接口&#xff0c;它表示一组对象&#xff…