赞
踩
开新坑了。这篇文章将从ams/atms启动,activity的启动,activity的栈结构和activity的生命周期出发,来更全面的了解activty与ams服务。
1.ams/atms简单介绍
应该是在android10之前,android的四大组件统一由ams进行管理,在android10之后,atms负责activity的相关管理,剩下的三大组件还是由ams管理,不过在ams中持有atms。
2.ams/atms启动流程
ams与atms的启动流程将直接从SystemServiceManager开始梳理,至于之前的流程涉及到android系统的启动流程,本文将不做重点说明。
Activity的启动流程可以大致可以分为三个过程:从用户操作启动Activity,到发送消息给ATMS的过程;ATMS接收到启动请求处理过程;ApplicationThread接收到调度请求的处理过程,以下分别分析。
Activity的启动可以分为两种:冷启动,热启动。
接下来我们着重分析冷启动。
冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。
热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动
1.从用户操作启动Activity到ATMS
点击桌面图标,Launcher会启动程序默认的Acticity,总体的流程如下:
接下来进入到代码中分析,假设我们Launcher点击应用图标是通过Activity的startActivity()去启动一个新的Activity。
Activity.java public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback, AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient { ... @Override public void startActivity(Intent intent) { this.startActivity(intent, null); // 到这里 } @Override public void startActivity(Intent intent, @Nullable Bundle options) { if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN) && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) { if (TextUtils.equals(getPackageName(), intent.resolveActivity(getPackageManager()).getPackageName())) { // Apply Autofill restore mechanism on the started activity by startActivity() final IBinder token = mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN); // Remove restore ability from current activity mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN); mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY); // Put restore token intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token); intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true); } } if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); // 到这里 } } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); // 到这里,requestCode>=0 // 时,要返回结果 } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { options = transferSpringboardActivityOptions(options); // 到这里,通过Instrumentation.execStartActivity()来启动activity // 有必要说明的是mMainThread.getApplicationThread(),这个的具体分析见下文 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) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } } }
以上的代码,Activity的startActivity()一路经过调用最后交给Instrumentation,那Instrumentation这个类有什么作用呢?nstrumentation这个类,我的理解是:Instrumentation是一个用来监视Activity的监测类,Activity的生命周期的函数也是Instrumentation来调用的
Instrumentation.java public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { ... try { intent.migrateExtraStreamToClipData(who); intent.prepareToLeaveProcess(who); // whoThread被传递过去,用于在ATMS中传递消息到ActivityThread int result = ActivityTaskManager.getService().startActivity(whoThread, who.getOpPackageName(), who.getAttributionTag(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
在上面代码的 ActivityTaskManager.getService().startActivity中,这个调用了ActivityTaskManager的getservice方法,这个方法其实获取的是IActivityTaskManager这个AIDL接口,ActivityTaskManagerService.startActivity(),接下就进入到了ActivityTaskManagerService中去分析
ActivityTaskManagerService.java @Override public final int startActivity(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { // 到这里 return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, @Override public int startActivityAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { // 到这里 return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId, true /*validateIncomingUser*/); } private int startActivityAsUser(IApplicationThread caller, String callingPackage, @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) { assertPackageMatchesCallingUid(callingPackage); enforceNotIsolatedCaller("startActivityAsUser"); userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser"); // TODO: Switch to user app stacks here. // 注释一 关键步骤,具体分析见下文 return getActivityStartController().obtainStarter(intent, "startActivityAsUser") .setCaller(caller) .setCallingPackage(callingPackage) .setCallingFeatureId(callingFeatureId) .setResolvedType(resolvedType) .setResultTo(resultTo) .setResultWho(resultWho) .setRequestCode(requestCode) .setStartFlags(startFlags) .setProfilerInfo(profilerInfo) .setActivityOptions(bOptions) .setUserId(userId) .execute(); }
以上代码中,经过调用一系列的重载函数,最后调用到最下面的这个函数,这段代码关键的部分是注释1处,这个里构建了一个ActivityStarter并设置了一些配置,最终执行了ActivityStarter的execute()方法,接下来我们就看一下execute方法的具体实现。代码如下:
class ActivityStarter { /* *ActivityStarter 用于解释如何启动活动,然后启动活动。 *此类收集用于确定如何将意图和标志转换为的所有逻辑 *活动以及相关的任务和堆栈。 */ // 省略了一些代码 try { // Refuse possible leaked file descriptors if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } ... // 注意这里 注释1 分析见下文 res = executeRequest(mRequest); ... return getExternalResult(mRequest.waitResult == null ? res : waitForResult(res, mLastStartActivityRecord)); } } finally { onExecutionComplete(); } /* *执行活动启动请求并开始启动活动的过程。在这里 *首先执行几个初步检查。正常情况下,活动启动流程将 *通过{@link#startActivityUnchecked}到{@link#startActivityInner}。 */ private int executeRequest(Request request) { }
其实这个的mRequest是在我们上面构建ActivityStarter的时候就会被创建,并且上面的对ActivityStarter的一些参数设置其实是设置给了Request这个内部类。最终回调用ActivityStarter的executeRequest方法。接下我们看一下executeRequest方法内部是怎么实现的。代码如下:
private int executeRequest(Request request) { 省略了很多校验的代码 // 在这里通过Binder机制调用pkms的resolveIntent // PackageManagerService.resolveIntent(intent) //根据给定的 Intent 从 PackageManagerService 中查找与之 // Intent.ComponentName 相匹配的 Activity 集合; // 从查出来的集合中获取最为匹配的 Activity; rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0, computeResolveFilterUid( callingUid, realCallingUid, request.filterCallingUid)); aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); //注释1 在这里根据我们找处的acticvity信息创建出ActivityRecord final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, callingFeatureId, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); mLastStartActivityRecord = r; if (r.appTimeTracker == null && sourceRecord != null) { // If the caller didn't specify an explicit time tracker, we want to continue // tracking under any it has. r.appTimeTracker = sourceRecord.appTimeTracker; } final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack(); // If we are starting an activity that is not from the same uid as the currently resumed // one, check whether app switches are allowed. if (voiceSession == null && stack != null && (stack.getResumedActivity() == null || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) { mController.addPendingActivityLaunch(new PendingActivityLaunch(r, sourceRecord, startFlags, stack, callerApp, intentGrants)); } ActivityOptions.abort(checkedOptions); return ActivityManager.START_SWITCHES_CANCELED; } } mService.onStartActivitySetDidAppSwitch(); mController.doPendingActivityLaunches(false); //注释2 这里 mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, restrictedBgActivity, intentGrants); if (request.outActivity != null) { request.outActivity[0] = mLastStartActivityRecord; } return mLastStartActivityResult; }
在注释1的位置创建出了和这个我们要启动的activity相关的ActivityRecord,关于ActivityRecord已经栈的分析本文不再赘述推荐阅读ActivityStackSupervisor,ActivityStack,ActivityRecord,TaskRecord的关系的分析
然后在注释2 的位置执行 startActivityUnchecked,进入到 startActivityUnchecked分析
ActivityStarter.java /** *在大多数初步检查已完成且调用方已被调用的情况下启动活动 *已确认拥有执行此操作所需的权限。 *这里还可以确保在启动失败时删除启动活动。 */ private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { int result = START_CANCELED; final ActivityStack startedActivityStack; try { mService.deferWindowLayout(); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); // 注释1 注意这里 result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); startedActivityStack = handleStartResult(r, result); mService.continueWindowLayout(); } postStartActivityProcessing(r, result, startedActivityStack); return result; }
在注释1处调用了startActivityInner
ActivityStarter.java int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor, restrictedBgActivity); // 在这里计算出activity的启动模式 computeLaunchingTaskFlags(); // 计算源task 就是调用者所在的stack computeSourceStack(); final Task reusedTask = getReusableTask(); // If requested, freeze the task list if (mOptions != null && mOptions.freezeRecentTasksReordering() && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid) && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) { mFrozeTaskList = true; mSupervisor.mRecentTasks.setFreezeTaskListReordering(); } // Compute if there is an existing task that should be used for //计算是否存在应用于的现有任务. final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask(); final boolean newTask = targetTask == null; mTargetTask = targetTask; // 计算启动参数 computeLaunchParams(r, sourceRecord, targetTask); // Check if starting activity on given task or on a new task is allowed. // 检查是否允许在给定任务或新任务上启动活动 int startResult = isAllowedToStart(r, newTask, targetTask); if (startResult != START_SUCCESS) { return startResult; } final ActivityRecord targetTaskTop = newTask ? null : targetTask.getTopNonFinishingActivity(); if (targetTaskTop != null) { // Recycle the target task for this launch. // 回收 startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } else { mAddingToTask = true; } // If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. //如果正在启动的活动与当前位于顶部的活动相同,则 //我们需要检查它是否应该只启动一次。 final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack(); if (topStack != null) { startResult = deliverToCurrentTopIfNeeded(topStack, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } ... // 注释1 注意这里 // 获取栈顶activity并恢复,即将设置成resume状态。 mRootWindowContainer.resumeFocusedStacksTopActivities( mTargetStack, mStartActivity, mOptions);
这个方法的作用主要是,启动一个活动,并确定该活动是否应该添加到现有活动的顶部,省略了一些关于任务栈的判断逻辑,关键部分是注释1处,可以看出它调用了RootWindowContainer这个类的resumeFocusedStacksTopActivities方法。这个方法的代码如下:
RootWindowContainer.java boolean resumeFocusedStacksTopActivities( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (!resumedOnDisplay) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume // of top activity in focused stack explicitly will make sure that at least home // activity is started and resumed, and no recursion occurs. final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack != null) { // 注释1 focusedStack是一个ActivityStack,在这里进入到了下一个流程, result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } else if (targetStack == null) { result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); } } }
在注释1的地方通过ocusedStack.resumeTopActivityUncheckedLocked进入到下一个流程:
class ActivityStack extends Task { boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mInResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mInResumeTopActivity = true; // 注释 1注意这里 result = resumeTopActivityInnerLocked(prev, options); // When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here // to ensure any necessary pause logic occurs. In the case where the Activity will be // shown regardless of the lock screen, the call to // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. final ActivityRecord next = topRunningActivity(true /* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { checkReadyForSleep(); } } finally { mInResumeTopActivity = false; } return result; } }
在注释1处 进入到下一个步骤
ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
// Protect against recursion.
mInResumeTopActivity = true;
// 注释1
result = resumeTopActivityInnerLocked(prev, options);
...
return result;
}
在注释1处调用resumeTopActivityInnerLocked(),这个方法非常的长,但是在他里面有一个非常关键的调用,下面的代码例子只截取一部分分析:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
}
...
ActivityRecord next = topRunningActivity(true /* focusableOnly */);
...
//mStackSupervisor类型为ActivityStackSupervisor,
// mStackSupervisor.startSpecificActivity 中开始对是否新建进程进行判断,非常的关键
mStackSupervisor.startSpecificActivity(next, true, true);
}
return true;
}
ActivityStackSupervisor.java void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? final WindowProcessController wpc = mService.getProcessController(r.processName, r.info.applicationInfo.uid); boolean knownToBeDead = false; // 热启动,即app的进程存在时 if (wpc != null && wpc.hasThread()) { try { // 这个后面的分析中也会遇到 realStartActivityLocked(r, wpc, 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. knownToBeDead = true; } r.notifyUnknownVisibilityLaunchedForKeyguardTransition(); final boolean isTop = andResume && r.isTopRunningActivity(); // 注释 1 去启动一个新的进程 需要知道的是,这里的mService指的是ATMS mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity"); }
这篇文章中关于activity的启动流程的分析,只涉及冷启动(实际上冷启动和热启动的过程大同小异,只是冷启动更复杂一点)。在注释一处 ,因为当前app并未启动,还没有自己的进程,用下面的步骤将围绕进程的创建展开。
ActivityTaskManagerService.java void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop, String hostingType) { try { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:" + activity.processName); } // Post message to start process to avoid possible deadlock of calling into AMS with the // ATMS lock held. //注释1 在这里会执行到 AMS里面的startProcess的函数 final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess, mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead, isTop, hostingType, activity.intent.getComponent()); mH.sendMessage(m); } finally { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } }
在注释1位置会进入到AMS中
ActivityManagerService.java public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName) { try { if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:" + processName); } synchronized (ActivityManagerService.this) { // If the process is known as top app, set a hint so when the process is // started, the top priority can be applied immediately to avoid cpu being // preempted by other processes before attaching the process of top app. startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */, new HostingRecord(hostingType, hostingName, isTop), ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */, false /* isolated */, true /* keepIfLarge */); } } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }
接下来ams会和Zygote取得联系,AMS通过Sockt的方式和Zygote建立连接并请求Zygote创建处一个新的进程
省略Zygote建立新进程的分析,当Zygote通过fork生成新的进程后,会通过反射的当时调用我们需要启动Activity的 ActivityThread.main方法。接下来着重分析ActivityThread.java
ActivityThread就是我们常说的主线程或UI线程,ActivityThread的main方法是整个APP的入口,在ActivityThread的面方法里面首先会通过 Looper.prepareMainLooper();创建出Handler机制中一个重要的角色:Looper,
public final class ActivityThread { //... private static ActivityThread sCurrentActivityThread; public static ActivityThread currentActivityThread() { return sCurrentActivityThread; } private void attach(boolean system) { sCurrentActivityThread = this; //... } public static void main(String[] args) { //.... //创建Looper和MessageQueue对象,用于处理主线程的消息 Looper.prepareMainLooper(); //创建ActivityThread对象 ActivityThread thread = new ActivityThread(); //建立Binder通道 (创建新线程) // 注釋1 thread.attach(false); Looper.loop(); //消息循环运行 throw new RuntimeException("Main thread loop unexpectedly exited"); } }
需要注意的是在注释1处 thread.attach(false);即执行了ActivityThread的attach方法,这里比较中要,因为接下里来就会建立需要启动的activity与ATMS的通信(是的atms可以调用和这个activity相关的一些方法),进入到 thread.attach(false)看看。
ActivityThread.java
private void attach(boolean system, long startSeq) {
....
// we can't display an alert, we just want to die die die.
// 在这里获得atms在本地的代理
final IActivityManager mgr = ActivityManager.getService();
try {
// 把mAppThread传给atms
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
....
如上的代码首先通过binder机制获得atms在本地的代理,然后通过这个代理调用ams的attachApplication,参数里的attachApplication是一个ApplicationThread类型的对象,ApplicationThread是ActivityThread 的一个内部类,继承自IApplicationThread.Stub,所有了binder通信的能力,这个类的主要作用是,通过mgr.attachApplication(mAppThread, startSeq);把ApplicationThread交给AMS,然后AMS通过ApplicationThread来执行ActivityThread类中的一些方法。分析如下
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
ActivityManagerService.java public final void attachApplication(IApplicationThread thread, long startSeq) { if (thread == null) { throw new SecurityException("Invalid application interface"); } synchronized (this) { int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); // 这里 attachApplicationLocked(thread, callingPid, callingUid, startSeq); Binder.restoreCallingIdentity(origId); } } private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { // 注意这里,这里的thread就是我们刚才传进来的ApplicationThread,这里会调用 // ApplicationThread的bindApplication方法,就会从AMS 的进程回到我们要启动的那个Activity // 所在的进程,去启动Application thread.bindApplication(processName, appInfo, providerList, instr2.mClass, profilerInfo, instr2.mArguments, instr2.mWatcher, instr2.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, autofillOptions, contentCaptureOptions, app.mDisabledCompatChanges); } // 省略了大量的代码 if (normalMode) { try { // 注意这里他会执行到ATMS的attachApplication方法 didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } }
以上的代码,首先ActivityThread会通过binder把ApplicationThread交给AMS,然后AMS 又会通过binder机制让ActivityThread去启动Application,之后AMS 又会 didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());通过ATMS来完成一些操作,可以让ATMS来管理新建的进程了,接下来进入到ATMS的attachApplication方法中。
ActivityTaskManagerService.java @HotPath(caller = HotPath.PROCESS_CHANGE) @Override public boolean attachApplication(WindowProcessController wpc) throws RemoteException { synchronized (mGlobalLockWithoutBoost) { if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName); } try { // 会执行到这里 return mRootWindowContainer.attachApplication(wpc); } finally { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } } }
RootWindowContainer.java final String processName = app.mName; boolean didSomething = false; for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { final DisplayContent display = getChildAt(displayNdx); final ActivityStack stack = display.getFocusedStack(); if (stack == null) { continue; } mTmpRemoteException = null; mTmpBoolean = false; // Set to true if an activity was started. final PooledFunction c = PooledLambda.obtainFunction( // 执行到这里 RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this, PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity()); stack.forAllActivities(c); c.recycle(); if (mTmpRemoteException != null) { throw mTmpRemoteException; } didSomething |= mTmpBoolean; } if (!didSomething) { ensureActivitiesVisible(null, 0, false /* preserve_windows */); } return didSomething; }
private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r, WindowProcessController app, ActivityRecord top) { if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) { return false; } try { // 执行到这里 哦吼 这个函数好眼熟啊,不是刚才activity热启动时遇到的函数 if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/, true /*checkConfig*/)) { mTmpBoolean = true; } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting activity " + top.intent.getComponent().flattenToShortString(), e); mTmpRemoteException = e; return true; } return false; }
以上代码走后走到我们熟悉的realStartActivityLocked,activity冷启动和热启动的时间线在此收束,不同的是这次app有了对应的进程。realStartActivityLocked开始真实的启动一个activity,接下来着重分析realStartActivityLocked的相关流程:
ActivityStackSupervisor.java boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException { ... // 注释1 . final ClientTransaction clientTransaction = ClientTransaction.obtain( proc.getThread(), r.appToken); // 注释2 clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(), r.assistToken, r.createFixedRotationAdjustmentsIfNeeded())); // Set desired final state. final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); // Schedule transaction. mService.getLifecycleManager().scheduleTransaction(clientTransaction); ...
这一段代码注释1处创建ClientTransaction对象,然后在注释2处通过clientTransaction.addCallback添加一个LaunchActivityItem对象,(LaunchActivityItem.obtain方法返回的是一个LaunchActivityItem对象)此处尤为重要,因为下面的流程会回调到这LaunchActivityItem这个类中。
然后调用ClientLifecycleManager的scheduleTransaction方法把当前的是事务进行提交。接下来看一下ClientLifecycleManager的scheduleTransaction的具体实现,代码如下:
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
...
}
这里是引用
这里调用了ClientTransaction的schedule()方法,schedule方法的代码如下:
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
这里调用了mClient的scheduleTransaction()方法,那mClient是谁呢?其实mClient其实就是
IApplicationThread这个AIDL接口,具体的实现类其实是ActivityThread的内部类ApplicationThread,
从这个类继承自IApplicationThread.Stub我们就可以看出IApplicationThread是一个AIDL接口。那接下来我们看一下ApplicationThread的scheduleTransaction方法。代码如下
public abstract class ClientTransactionHandler {
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
// 在这里回想handler发出一个消息
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
...
// 在这里handler会多收到的EXECUTE_TRANSACTION消息进行处理,做一些操作
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
// 会执行到 mTransactionExecutor.execute(transaction); 具体分析见下文
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
...
//1
executeCallbacks(transaction);
//2
executeLifecycleState(transaction);
...
}
这个方法主要关键部分是注释1和注释2,注释2是Activity声明周期的,我们主要还是来看注释1处,这里调用自己的executeCallbacks方法,具体代码如下:
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
...
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
...
//注意这里 :
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
...
}
}
从注释1可以看到这里调用ClientTransactionItem的execute方法,这就是我为什么在上面分析realStartActivityLocked方法是说,ClientTransactionItem这个类很重要,就体现在这里。我们发现这个类是一个抽象类,具体的实现类其实就是我们上面realStartActivityLocked中注释2中构建的LaunchActivityItem,所以我们看一下LaunchActivityItem的execute方法。
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
//1
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
在这里我们终于看到我们熟悉的东西了handleLaunchActivity方法(注释1),那这个client是谁呢?通过上面的分析我们可以知道这个client其实就是ActivityThread这个类,ActivityThread继承自ClientTransactionHandler。接下来我们看一下ActivityThread的handleLaunchActivity方法的具体实现。代码如下:
ApplicationThread extends IApplicationThread.Stub
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
// 在这里调用= performLaunchActivity(r, customIntent);创建出activity对象
// 接下来分析performLaunchActivity
final Activity a = performLaunchActivity(r, customIntent);
....
return a;
}
在注释的地方总算创建出了我们需要启动的activity,具体流程如下:
ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 在这里通过mInstrumentation创建出activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......
// 执行activity的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
通过mInstrumentation.callActivityOnCreate,让activity执行onCreate()到这里activiy 的启动就分析完了,
需要注意的是每一个应用的进程都有一个ActivityThread对象,而每一个ActivityThread对象都有一个Instrumentation,mInstrumentation是在之前的bindApplication过程中创建的。
在了解完Activity的启动流程后,思考一个问题,如何启动后一个没有在清单文件中注册过的Activity呢?这里就要通过HOOK技术来实现了,Android Hook技术底层原理其实说白了就是java的反射和动态代理,而接下来要说明的就是通过HOOK技术取启动一个未注册的Activity。
1.未使用HOOK,直接启动一个未注册的Activity
MainActivity
package com.example.hmxxx; import androidx.appcompat.app.AppCompatActivity; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(); intent.setComponent(new ComponentName(" com.example.hmxxx"," com.example.hmxxx.UnregisteredActivity")); startActivity(intent); } }); } }
MainActivity的布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:text="启动一个新的Activity"
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
未注册的activity
package com.example.hmxxx;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class UnregisteredActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_unregistered);
}
}
清单文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.hmxxx"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Hmxxx"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
主界面
以上就是未使用HOOK,直接启动一个未注册的Activity的主要文件,和主界面,当我们点击按钮,尝试去启动UnregisteredActivity 是肯定是启动不了的,并会报错,具体一些,为什么会报错呢?
Instrumentation.java public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { ... try { intent.migrateExtraStreamToClipData(who); intent.prepareToLeaveProcess(who); // whoThread被传递过去,用于在ATMS中传递消息到ActivityThread int result = ActivityTaskManager.getService().startActivity(whoThread, who.getOpPackageName(), who.getAttributionTag(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent);// 注释1 在这里会对result进行检查,有异常机会报错 } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
如上的代码,在注释1处会对result进行检查,有异常机会报错,我们在启动一个未注册的activity时的报错就是这里产生的,换句话说就是result 的结果有问题,然后checkStartActivityResult在检查Result,发现了问题并抛了出来,根据之前分析的activity启动流程,可以知道result 是在ActivityStarter的executeRequest产生的:
private int executeRequest(Request request) {
....
int err = ActivityManager.START_SUCCESS;
....
// 后面有一对代码对启动的activity进行检查,我们要启动的activity未注册的秘密
// 也就是在这里被发现的,当发现我么你要启动的acticvit未注册时,err 就是被赋予一个错误的值
// 并返回回去
return err
如上的代码就已经说明了为什么我们在启动一个未注册的activity时会报错,那么如何启动有个未注册的activity呢?打哪很明显了 ,那就是绕过atms的检查。
简单的思路如上图所描绘的:们在AndroidManifest里面申明一个代理activity,然后在启动真实Activity的地方,将Intent里面的Activity替换成我们代理activity。然后带atms检查完我们的acitivity是否在AndroidManifest文件中注册后,替换成我们需要启动的便实现了启动一个未注册过的Activity的效果。
接下来找HOOK点,找HOOK点尽量 静态变量 单例(方便反射调用),public(因为public的就是谷歌鼓励使用的)
按照上文中的思路,要在我们startActivity(intent);之后,在intent交给atms检查之前,把我们要启动的一个未注册的activity换成一个已经注册的代理activity
第一步 我们在intent交给atms之前偷偷换掉intent的内容,(使用反射和动态代理)
新建一个进行hook的工具类
public class HookUtil { private static final String TAG ="HookUtil" ; public static void hookAMS() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class <?> clazz = Class.forName("android.app.ActivityTaskManager"); Field singletonField = clazz.getDeclaredField("IActivityTaskManagerSingleton"); singletonField.setAccessible(true); Object singleton = singletonField.get(null); Class<?> singletonClass = Class.forName("android.util.Singleton"); Field mInstanceField = singletonClass.getDeclaredField("mInstance"); mInstanceField.setAccessible(true); Method getMethod = singletonClass.getMethod("get"); Object mInstance = getMethod.invoke(singleton); Log.d(TAG, "invoke: hm test1"); Class IActivityTaskManagerClass = Class.forName("android.app.IActivityTaskManager"); Object InstanceProxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{IActivityTaskManagerClass}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("startActivity".equals(method.getName())) { // 当方法名是 startActivity时 int index = -1; Log.d(TAG, "invoke: hm test"); // 获取Itent参数在args 数组中的index值 for (int i = 0; i < args.length; i++) { if (args[i] instanceof Intent) { index = i; break; } } // 生成代理proxyIntent Intent proxyIntent = new Intent(); // 这个包名是宿主的 proxyIntent.setClassName("com.example.hmxxx","ProxyActivity"); // 原始的Intent丢掉吗? 保留原始的Intent对象 Intent intent = (Intent) args[index]; proxyIntent.putExtra("TARGET_INTENT",intent); } return method.invoke(mInstance,args); } }); // 用代理的对象 替换系统的对象 mInstanceField.set(singleton,InstanceProxy); } }
mainActivity:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { HookUtil.hookAMS(); // 注意这里 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(); intent.setComponent(new ComponentName(" com.example.hmxxx"," com.example.hmxxx.UnregisteredActivity")); startActivity(intent); } }); } }
以上的代码是在activity交给atms之前把未注册的activity替换成一个代理activity,最后我们还有想办法在返回回来的时候,把代理activity替换成我们要启动的未注册的activity,思路就是在atms检测之后,这个activity的生命周期开始执行之前,把我们想要启动的activity替换回来。
try { Class<?> clazz = Class.forName("android.app.ActivityThread"); Field activityThreadField = clazz.getDeclaredField("sCurrentActivityThread"); activityThreadField.setAccessible(true); Object activityThread = activityThreadField.get(null); Field mHField = clazz.getDeclaredField("mH"); mHField.setAccessible(true); final Handler mH = (Handler) mHField.get(activityThread); Field mCallbackField = Handler.class.getDeclaredField("mCallback"); mCallbackField.setAccessible(true); mCallbackField.set(mH, new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 159: // msg.obj = ClientTransaction try { // 获取 List<ClientTransactionItem> mActivityCallbacks 对象 Field mActivityCallbacksField = msg.obj.getClass() .getDeclaredField("mActivityCallbacks"); mActivityCallbacksField.setAccessible(true); List mActivityCallbacks = (List) mActivityCallbacksField.get(msg.obj); for (int i = 0; i < mActivityCallbacks.size(); i++) { // 打印 mActivityCallbacks 的所有item: //android.app.servertransaction.WindowVisibilityItem //android.app.servertransaction.LaunchActivityItem // 如果是 LaunchActivityItem,则获取该类中的 mIntent 值,即 proxyIntent if (mActivityCallbacks.get(i).getClass().getName() .equals("android.app.servertransaction.LaunchActivityItem")) { Object launchActivityItem = mActivityCallbacks.get(i); Field mIntentField = launchActivityItem.getClass() .getDeclaredField("mIntent"); mIntentField.setAccessible(true); Intent proxyIntent = (Intent) mIntentField.get(launchActivityItem); // 获取启动插件的 Intent,并替换回来 Intent intent = proxyIntent.getParcelableExtra(TARGET_INTENT); if (intent != null) { mIntentField.set(launchActivityItem, intent); } } } } catch (Exception e) { e.printStackTrace(); } break; } return false; } }); } catch (Exception e) { e.printStackTrace(); }
上面的代码对handler进行了修改以实现我们的目的,具体分析日后补上。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。