从Activity的启动流程来窥探AMS;
由于启动流程比较长,准备拆分之后细细品尝;
Activity.java中的startActivity;
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
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);
}
}
options参数大多数情况下都是null;在Context.java对这个参数的相应的解释;
如下:
@param options Additional options for how the Activity should be started.
May be null if there are no options. See {@link android.app.ActivityOptions}
for how to build the Bundle supplied here; there are no supported definitions
for building it manually.
这个Bundle有自己固有内容——ActivityOptions;大体浏览之后会发现里面都是一些关于动画之类的东西;由于和启动流程关系不是特别密切,这里暂不展开;
Activity.java中的startActivityForResult;
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
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不会被包含在另一个Activity中,特别是大家早已习惯Fragment之后;故mParent一般都是null;我们暂时先关注mParent为空的情况;
主要涉及以下几个步骤:
- transferSpringboardActivityOptions用来在options用空时获取options;
- Instrumentation的execStartActivity方法是启动的关键;
- ActivityThread的sendActivityResult方法;
- cancelInputsAndStartExitTransition
transferSpringboardActivityOptions
private Bundle transferSpringboardActivityOptions(Bundle options) {
if (options == null && (mWindow != null && !mWindow.isActive())) {
final ActivityOptions activityOptions = getActivityOptions();
if (activityOptions != null &&
activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
return activityOptions.toBundle();
}
}
return options;
}
/**
* Retrieve the ActivityOptions passed in from the launching activity or passed back
* from an activity launched by this activity in its call to {@link
* #convertToTranslucent(TranslucentConversionListener, ActivityOptions)}
*
* @return The ActivityOptions passed to {@link #convertToTranslucent}.
* @hide
*/
ActivityOptions getActivityOptions() {
try {
return ActivityOptions.fromBundle(
ActivityManager.getService().getActivityOptions(mToken));
} catch (RemoteException e) {
}
return null;
}
这部分代码主要是针对Activity切换动画部分的;
Instrumentation的execStartActivity方法
先看下Instrumentation的名字解释;
/**
* Base class for implementing application instrumentation code. When running
* with instrumentation turned on, this class will be instantiated for you
* before any of the application code, allowing you to monitor all of the
* interaction the system has with the application. An Instrumentation
* implementation is described to the system through an AndroidManifest.xml's
* <instrumentation> tag.
*/
也就是说Instrumentation其实是个测试辅助类;
execStartActivity参数:
- who 调用startActivity的Context;
- contextThread 调用startActivity的Context的主线程;
- token 内部token让系统辨认谁启动了activity;可能为空;
- target 启动和接收result的activity;当非activity启动时,可能为空;
- intent 启动时的intent;
- requestCode 大家都懂的;不存在的话设置小于0即可;源码是传入-1;
- options 附加选项;
- 返回值ActivityResult 要强制返回时,会返回一个包含所需数据的ActivityResult,否则返回空 ;基本都返回空;
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), 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;
}
- Uri referrer;默认返回是空的;
如下:
/**
* Override to generate the desired referrer for the content currently being shown
* by the app. The default implementation returns null, meaning the referrer will simply
* be the android-app: of the package name of this activity. Return a non-null Uri to
* have that supplied as the {@link Intent#EXTRA_REFERRER} of any activities started from it.
*/
public Uri onProvideReferrer() {
return null;
}
可以重写这个方法,类似:
@Override
public Uri onProvideReferrer() {
return Uri.parse("http://www.example.com/VoiceInteractionMain");
}
这个Uri会以参数(Intent.EXTRA_REFERRER)的形式传给被这个Activity启动Activity;
但这样做具体有什么用呢?!
这种设计目的是什么?!
有什么好处?!
不明白!!!
- mActivityMonitors相关的一溜代码都是和调试测试相关的,这里不做讨论;
- ActivityManager.getService().startActivity;这个方法负责实际的启动工作;
ActivityManager的getService获取到IActivityManager;其实就是AMS;这块内容在之前已经提到过了;
AMS中的处理放下后面详细讨论;
- checkStartActivityResult检查返回值,抛出各种异常,如常见的ActivityNotFoundException;
/** @hide */
public static void checkStartActivityResult(int res, Object intent) {
if (!ActivityManager.isStartResultFatalError(res)) {
return;
}
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
+ "; have you declared this activity in your AndroidManifest.xml?");
throw new ActivityNotFoundException(
"No Activity found to handle " + intent);
case ActivityManager.START_PERMISSION_DENIED:
throw new SecurityException("Not allowed to start activity "
+ intent);
case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
throw new AndroidRuntimeException(
"FORWARD_RESULT_FLAG used while also requesting a result");
case ActivityManager.START_NOT_ACTIVITY:
throw new IllegalArgumentException(
"PendingIntent is not an activity");
case ActivityManager.START_NOT_VOICE_COMPATIBLE:
throw new SecurityException(
"Starting under voice control not allowed for: " + intent);
case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
throw new IllegalStateException(
"Session calling startVoiceActivity does not match active session");
case ActivityManager.START_VOICE_HIDDEN_SESSION:
throw new IllegalStateException(
"Cannot start voice activity on a hidden session");
case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
throw new IllegalStateException(
"Session calling startAssistantActivity does not match active session");
case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
throw new IllegalStateException(
"Cannot start assistant activity on a hidden session");
case ActivityManager.START_CANCELED:
throw new AndroidRuntimeException("Activity could not be started for "
+ intent);
default:
throw new AndroidRuntimeException("Unknown error code "
+ res + " when starting " + intent);
}
}
ActivityThread的sendActivityResult方法
先看一下ActivityThread的名词解释;这个是类似一个小管家的角色;继承了ClientTransactionHandler;
/**
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
* broadcasts, and other operations on it as the activity
* manager requests.
*
* {@hide}
*/
public final class ActivityThread extends ClientTransactionHandler
sendActivityResult方法;
/** @hide */
public final void sendActivityResult(
IBinder token, String id, int requestCode,
int resultCode, Intent data) {
if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
+ " req=" + requestCode + " res=" + resultCode + " data=" + data);
ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
list.add(new ResultInfo(id, requestCode, resultCode, data));
final ClientTransaction clientTransaction = ClientTransaction.obtain(mAppThread, token);
clientTransaction.addCallback(ActivityResultItem.obtain(list));
try {
mAppThread.scheduleTransaction(clientTransaction);
} catch (RemoteException e) {
// Local scheduling
}
}
ClientTransaction的名词解释;
/**
* A container that holds a sequence of messages, which may be sent to a client.
* This includes a list of callbacks and a final lifecycle state.
*
* @see com.android.server.am.ClientLifecycleManager
* @see ClientTransactionItem
* @see ActivityLifecycleItem
* @hide
*/
public class ClientTransaction implements Parcelable, ObjectPoolItem
addCallback在序列的最后添加一个消息;
/**
* Add a message to the end of the sequence of callbacks.
* @param activityCallback A single message that can contain a lifecycle request/callback.
*/
public void addCallback(ClientTransactionItem activityCallback) {
if (mActivityCallbacks == null) {
mActivityCallbacks = new ArrayList<>();
}
mActivityCallbacks.add(activityCallback);
}
ApplicationThread是ActivityThread的一个内部类;它的scheduleTransaction方法最后还是会调用ActivityThread的scheduleTransaction方法;
private class ApplicationThread extends IApplicationThread.Stub
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
ActivityThread的scheduleTransaction方法来自于它的父类ClientTransactionHandler;
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
ActivityThread的内部类H;
class H extends Handler
其中处理EXECUTE_TRANSACTION部分的代码;
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
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();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
TransactionExecutor的名词解释;
/**
* Class that manages transaction execution in the correct order.
* @hide
*/
public class TransactionExecutor
/**
* Resolve transaction.
* First all callbacks will be executed in the order they appear in the list. If a callback
* requires a certain pre- or post-execution state, the client will be transitioned accordingly.
* Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
* either remain in the initial state, or last state needed by a callback.
*/
public void execute(ClientTransaction transaction) {
final IBinder token = transaction.getActivityToken();
log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
log("End resolving transaction");
}
executeCallbacks,遍历callback序列,然后逐个执行;
/** Cycle through all states requested by callbacks and execute them at proper times. */
@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
if (callbacks == null) {
// No callbacks to execute, return early.
return;
}
log("Resolving callbacks");
final IBinder token = transaction.getActivityToken();
ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
// In case when post-execution state of the last callback matches the final state requested
// for the activity in this transaction, we won't do the last transition here and do it when
// moving to final state instead (because it may contain additional parameters from server).
final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
: UNDEFINED;
// Index of the last callback that requests some post-execution state.
final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
log("Resolving callback: " + item);
final int postExecutionState = item.getPostExecutionState();
final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
item.getPostExecutionState());
if (closestPreExecutionState != UNDEFINED) {
cycleToPath(r, closestPreExecutionState);
}
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
if (r == null) {
// Launch activity request will create an activity record.
r = mTransactionHandler.getActivityClient(token);
}
if (postExecutionState != UNDEFINED && r != null) {
// Skip the very last transition and perform it by explicit state request instead.
final boolean shouldExcludeLastTransition =
i == lastCallbackRequestingState && finalState == postExecutionState;
cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
}
}
}
这里的关键是item.execute(mTransactionHandler, token, mPendingActions);
ClientTransactionItem的execute方法;
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
client.handleSendResult(token, mResultInfoList, "ACTIVITY_RESULT");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
ClientTransactionHandler的handleSendResult方法;
ClientTransactionHandler是个抽象类,handleSendResult是它的抽象方法;
TransactionExecutor的构造方法中,会将ClientTransactionHandler作为参数传入;
ActivityThread中初始化TransactionExecutor时,将ActivityThread本身传入;
而之前就提到过ActivityThread继承了ClientTransactionHandler;
// An executor that performs multi-step transactions.
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
因此,在ActivityThread寻找handleSendResult方法;
@Override
public void handleSendResult(IBinder token, List<ResultInfo> results, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
if (r != null) {
final boolean resumed = !r.paused;
if (!r.activity.mFinished && r.activity.mDecor != null
&& r.hideForNow && resumed) {
// We had hidden the activity because it started another
// one... we have gotten a result back and we are not
// paused, so make sure our window is visible.
updateVisibility(r, true);
}
if (resumed) {
try {
// Now we are idle.
r.activity.mCalled = false;
r.activity.mTemporaryPause = true;
mInstrumentation.callActivityOnPause(r.activity);
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString()
+ " did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
}
checkAndBlockForNetworkAccess();
deliverResults(r, results, reason);
if (resumed) {
r.activity.performResume(false, reason);
r.activity.mTemporaryPause = false;
}
}
}
deliverResults;
private void deliverResults(ActivityClientRecord r, List<ResultInfo> results, String reason) {
final int N = results.size();
for (int i=0; i<N; i++) {
ResultInfo ri = results.get(i);
try {
if (ri.mData != null) {
ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
ri.mData.prepareToEnterProcess();
}
if (DEBUG_RESULTS) Slog.v(TAG,
"Delivering result to activity " + r + " : " + ri);
r.activity.dispatchActivityResult(ri.mResultWho,
ri.mRequestCode, ri.mResultCode, ri.mData, reason);
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Failure delivering result " + ri + " to activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
}
}
最终会调用r.activity.dispatchActivityResult;
查看Activity的dispatchActivityResult方法;
好吧,兜兜转转一圈,又回到了Activity.java;这里会调用各个Case下onActivityResult;
void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data,
String reason) {
if (false) Log.v(
TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
+ ", resCode=" + resultCode + ", data=" + data);
mFragments.noteStateNotSaved();
if (who == null) {
onActivityResult(requestCode, resultCode, data);
} else if (who.startsWith(REQUEST_PERMISSIONS_WHO_PREFIX)) {
who = who.substring(REQUEST_PERMISSIONS_WHO_PREFIX.length());
if (TextUtils.isEmpty(who)) {
dispatchRequestPermissionsResult(requestCode, data);
} else {
Fragment frag = mFragments.findFragmentByWho(who);
if (frag != null) {
dispatchRequestPermissionsResultToFragment(requestCode, data, frag);
}
}
} else if (who.startsWith("@android:view:")) {
ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
getActivityToken());
for (ViewRootImpl viewRoot : views) {
if (viewRoot.getView() != null
&& viewRoot.getView().dispatchActivityResult(
who, requestCode, resultCode, data)) {
return;
}
}
} else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
getAutofillManager().onAuthenticationResult(requestCode, resultData, getCurrentFocus());
} else {
Fragment frag = mFragments.findFragmentByWho(who);
if (frag != null) {
frag.onActivityResult(requestCode, resultCode, data);
}
}
writeEventLog(LOG_AM_ON_ACTIVITY_RESULT_CALLED, reason);
}
cancelInputsAndStartExitTransition
最后一个方法,光看注释就很明了了;
/**
* Cancels pending inputs and if an Activity Transition is to be run, starts the transition.
*
* @param options The ActivityOptions bundle used to start an Activity.
*/
private void cancelInputsAndStartExitTransition(Bundle options) {
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
if (decor != null) {
decor.cancelPendingInputEvents();
}
if (options != null && !isTopOfTask()) {
mActivityTransitionState.startExitOutTransition(this, options);
}
}
小结
Instrumentation | 一个辅助测试类,启动Activity时通过它来调用AMS中的启动方法; |
ActivityThread | 主线程的小管家,继承自ClientTransactionHandler; onActivityResult就是通过它来实现的; |
ApplicationThread | ActivityThread的一个内部类,暂时还没做什么惊天动地的大事情; 但有个关键点,它实现了IBinder接口,能进行进程间通讯; |
- 第一小部分暂不涉及AMS里面内容,相对简答明了;
- TransactionExecutor、ClientTransactionHandler、ClientTransaction 、ClientTransactionItem的消息机制很好玩;
- TransactionExecutor负责按照顺序执行ClientTransaction内的ClientTransactionItem序列;持有ClientTransactionHandler对象;
- ClientTransactionHandler定义消息执行时真正进行的操作;抽象类,需要人继承;这里ActivityThread继承了它;
- ClientTransaction一个持有一系列消息的容器,可以发送给客户端,包括ClientTransactionItem列表和ActivityLifecycleItem;
- ClientTransactionItem消息本身;抽象类,需要人继承;这里ActivityResultItem继承了它;
- ActivityLifecycleItem请求活动应达到的生命周期状态;抽象类,需要人继承;这里没讨论到;
TransactionExecutor的execute方法会把ClientTransaction作为参数传入;
这样就把消息和处理消息的操作关联了起来;