开新坑了。这篇文章将从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 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进行了修改以实现我们的目的,具体分析日后补上。