追踪Android源码演变——Activity启动全流程
主要参考的源码为Android2.3与8.0,从姜饼到奥瑞奥,Activity的主要逻辑并没有根本性的改变,更多是做了一些封装和优化,下文会在版本变化中对相关变化的代码进行对比和说明。
主要从事网页设计、PC网站建设(电脑版网站建设)、wap网站建设(手机版网站建设)、成都响应式网站建设、程序开发、微网站、微信平台小程序开发等,凭借多年来在互联网的打拼,我们在互联网网站建设行业积累了丰富的成都网站设计、做网站、网络营销经验,集策划、开发、设计、营销、管理等多方位专业化运作于一体,具备承接不同规模与类型的建设项目的能力。
Launcher发送start请求
1 Launcher.startActivitySafely
系统启动时 PackageManagerService 解析 Androidmainfest文件, 会获取启动需要的laucher等信息,详情见《安卓源码分析与演变——PackageManager全流程》
之后根据flag走相应的启动流程
public ListqueryIntentActivities(Intent intent,
String resolvedType, int flags) {
ComponentName comp = intent.getComponent();
if (comp != null) {
Listlist = new ArrayList (1);
ActivityInfo ai = getActivityInfo(comp, flags);
if (ai != null) {
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
list.add(ri);
}
return list;
}
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
return (List)mActivities.queryIntent(intent,
resolvedType, flags);
}
PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
return (List) mActivities.queryIntentForPackage(intent,
resolvedType, flags, pkg.activities);
}
return null;
}
}
void startActivitySafely(Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
} catch (SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Launcher does not have the permission to launch " + intent +
". Make sure to create a MAIN intent-filter for the corresponding activity " +
"or use the exported attribute for this activity. "
+ "tag="+ tag + " intent=" + intent, e);
}
}
2 Activity.startActivity
@Override
public void startActivity(Intent intent) {
startActivityForResult(intent, -1);
}
3 startActivityForResult
Instrument 监护系统和应用交互
ActivityThread 每个应用进程启动持有,拥有ApplicationThread变量(Binder本地对象),作为参数传递给ActivityManagerService,通知组件进入
paused状态
Activity的mToken为Ibinder(代理对象),指向ActivityManagerService的ActivityRecord
public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
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;
}
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
4 Instrument.execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i final ActivityMonitor am = mActivityMonitors.get(i);if (am.match(who, null, intent)) {am.mHits++;if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;}break;}}}}try {int result = ActivityManagerNative.getDefault().startActivity(whoThread, intent,intent.resolveTypeIfNeeded(who.getContentResolver()),null, 0, token, target != null ? target.mEmbeddedID : null,requestCode, false, false);checkStartActivityResult(result, intent);} catch (RemoteException e) {}return null;}
版本变化
2.3版本
ActivityManagerNative.getDefalt获取ActivityManagerService的代理对象,封装为ActivityManagerProxy
static public IActivityManager getDefault(){if (gDefault != null) {//if (Config.LOGV) Log.v(// "ActivityManager", "returning cur default = " + gDefault);return gDefault;}IBinder b = ServiceManager.getService("activity");if (Config.LOGV) Log.v("ActivityManager", "default service binder = " + b);gDefault = asInterface(b);if (Config.LOGV) Log.v("ActivityManager", "default service = " + gDefault);return gDefault;}8.0版本
int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);取代了之前的ActivityManagerNative和proxy类,直接获取封装过的单例aidl接口IActivityManager,包括startservice等大量方法
调用asInterface()将服务端的Binder对象转换为客户端所需要的AIDL接口类型。如果客户端和服务端在同一个进程他返回的就是服务端Stub对象本身,否则返回封装的Stub.proxy对象。
private static final SingletonIActivityManagerSingleton = new Singleton() { @Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};//ServiceManager实质上是管理缓存的Ibinder对象public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return Binder.allowBlocking(getIServiceManager().getService(name));}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}5 ActivityManagerNative.ActivityManagerProxy.startActivity
参数传递为Parcel,反序列化对象
通过ActivityManagerProxy的mRemote发送START_ACTIVITY_TRANSACTION,即进程间通信请求
(Proxy类实现IActivityManager接口,而8.0将中转的代理类去除,精简了流程)
public int startActivity(IApplicationThread caller, Intent intent,String resolvedType, Uri[] grantedUriPermissions, int grantedMode,IBinder resultTo, String resultWho,int requestCode, boolean onlyIfNeeded,boolean debug) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(caller != null ? caller.asBinder() : null);intent.writeToParcel(data, 0);data.writeString(resolvedType);data.writeTypedArray(grantedUriPermissions, 0);data.writeInt(grantedMode);data.writeStrongBinder(resultTo);data.writeString(resultWho);data.writeInt(requestCode);data.writeInt(onlyIfNeeded ? 1 : 0);data.writeInt(debug ? 1 : 0);mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);reply.readException();int result = reply.readInt();reply.recycle();data.recycle();return result;}
AMS处理start请求并发送paused
6 ActivityManagerService.startActivity
成员函数ActivityStack处理IPC请求,启动组件
public final int startActivity(IApplicationThread caller,Intent intent, String resolvedType, Uri[] grantedUriPermissions,int grantedMode, IBinder resultTo,String resultWho, int requestCode, boolean onlyIfNeeded,boolean debug) {return mMainStack.startActivityMayWait(caller, intent, resolvedType,grantedUriPermissions, grantedMode, resultTo, resultWho,requestCode, onlyIfNeeded, debug, null, null);}版本变化
8.0 使用了ActivityStarter,封装了ActivityStack、ActivityRecord、flag,intent相关的处理
@Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}
@Overridepublic final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {enforceNotIsolatedCaller("startActivity");userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),userId, false, ALLOW_FULL_ONLY, "startActivity", null);// TODO: Switch to user app stacks here.return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,profilerInfo, null, null, bOptions, false, userId, null, null,"startActivityAsUser");}7 ActivityStack.startActivityMayWait
解析intent信息
final int startActivityMayWait(IApplicationThread caller,Intent intent, String resolvedType, Uri[] grantedUriPermissions,int grantedMode, IBinder resultTo,String resultWho, int requestCode, boolean onlyIfNeeded,boolean debug, WaitResult outResult, Configuration config) {ActivityInfo aInfo;try {ResolveInfo rInfo =AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,PackageManager.MATCH_DEFAULT_ONLY| ActivityManagerService.STOCK_PM_FLAGS);aInfo = rInfo != null ? rInfo.activityInfo : null;} catch (RemoteException e) {aInfo = null;}...int res = startActivityLocked(caller, intent, resolvedType,grantedUriPermissions, grantedMode, aInfo,resultTo, resultWho, requestCode, callingPid, callingUid,8 ActivityStack.startActivityLocked
ActivityManagerService获取Caller对应的Proce***ecord对象,该对象指向Launcher所在进程,获取pid和uid
从mHistory寻找ActivityRecord信息,保存变量sourceActivity
9 ActivityStack.startActivityUnCheckedLocked
判断标志位,是否新task,是否用户操作,根据taskAffinity属性判断新Activity的task组归属
重载方法startActivityLocked,加入栈顶,保存history
final int startActivityUncheckedLocked(ActivityRecord r,ActivityRecord sourceRecord, Uri[] grantedUriPermissions,int grantedMode, boolean onlyIfNeeded, boolean doResume) {final Intent intent = r.intent;final int callingUid = r.launchedFromUid;int launchFlags = intent.getFlags();ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)!= 0 ? r : null;// Should this be considered a new task?if (r.resultTo == null && !addingToTask&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {// todo: should do better management of integers.mService.mCurTask++;if (mService.mCurTask <= 0) {mService.mCurTask = 1;}r.task = new TaskRecord(mService.mCurTask, r.info, intent,(r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r+ " in new task " + r.task);newTask = true;if (mMainStack) {mService.addRecentTaskLocked(r.task);}} else if (sourceRecord != null) {if (!addingToTask &&(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {10 ActivityStack.resumeTopActivityLocked
如果将要启动的Activity已经resume或者pause直接返回,否则通知进入pause状态准备启动
final boolean resumeTopActivityLocked(ActivityRecord prev) {// Find the first activity that is not finishing.ActivityRecord next = topRunningActivityLocked(null);...// If the top activity is the resumed one, nothing to do.if (mResumedActivity == next && next.state == ActivityState.RESUMED) {// Make sure we have executed any pending transitions, since there// should be nothing left to do at this point.mService.mWindowManager.executeAppTransition();mNoAnimActivities.clear();return false;}// If we are sleeping, and there is no resumed activity, and the top// activity is paused, well that is the state we want.if ((mService.mSleeping || mService.mShuttingDown)&& mLastPausedActivity == next && next.state == ActivityState.PAUSED) {// Make sure we have executed any pending transitions, since there// should be nothing left to do at this point.mService.mWindowManager.executeAppTransition();mNoAnimActivities.clear();return false;}// The activity may be waiting for stop, but that is no longer// appropriate for it.mStoppingActivities.remove(next);mWaitingVisibleActivities.remove(next);// We need to start pausing the current activity so the top one// can be resumed...if (mResumedActivity != null) {if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");startPausingLocked(userLeaving, false);return true;}...}版本变化
8.0
ActivityStackSupervisor封装了ActivityStack有关的方法
boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {if (targetStack != null && isFocusedStack(targetStack)) {return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);}final ActivityRecord r = mFocusedStack.topRunningActivityLocked();if (r == null || r.state != RESUMED) {mFocusedStack.resumeTopActivityUncheckedLocked(null, null);} else if (r.state == RESUMED) {// Kick off any lingering app transitions form the MoveTaskToFront operation.mFocusedStack.executeAppTransition(targetOptions);}return false;}11 startPausingLocked
调用AMP通知主Activity,进入pause状态。延时发送handler超时消息
private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {ActivityRecord prev = mResumedActivity;...if (prev.app != null && prev.app.thread != null) {if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);try {EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,System.identityHashCode(prev),prev.shortComponentName);prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,prev.configChangeFlags);if (mMainStack) {mService.updateUsageStats(prev, false);}} catch (Exception e) {// Ignore exception, if process died other code will cleanup.Slog.w(TAG, "Exception thrown during pause", e);mPausingActivity = null;mLastPausedActivity = null;}} else {mPausingActivity = null;mLastPausedActivity = null;}...if (mPausingActivity != null) {// Schedule a pause timeout in case the app doesn't respond.// We don't give it much time because this directly impacts the// responsiveness seen by the user.Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);msg.obj = prev;mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");} else {// This activity failed to schedule the// pause, so just treat it as being paused now.if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");resumeTopActivityLocked(null);}}
case PAUSE_TIMEOUT_MSG: {IBinder token = (IBinder)msg.obj;// We don't at this point know if the activity is fullscreen,// so we need to be conservative and assume it isn't.Slog.w(TAG, "Activity pause timeout for " + token);activityPaused(token, null, true);}12 APN.ApplicationThreadProxy.scheduePauseActivity
Ibinder发往Laucher组件(异步请求)
public final void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges) throws RemoteException {Parcel data = Parcel.obtain();data.writeInterfaceToken(IApplicationThread.descriptor);data.writeStrongBinder(token);data.writeInt(finished ? 1 : 0);data.writeInt(userLeaving ? 1 :0);data.writeInt(configChanges);mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,IBinder.FLAG_ONEWAY);data.recycle();}Launcher进入Pause状态
以上过程都在Laucher完成
13 ApplicationThread.scedulePauseActivity
binder指向ActivityRecord
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Bundle state, ListpendingResults, ListpendingNewIntents, boolean notResumed, boolean isForward) { ActivityClientRecord r = new ActivityClientRecord();r.token = token;r.ident = ident;r.intent = intent;r.activityInfo = info;r.state = state;r.pendingResults = pendingResults;r.pendingIntents = pendingNewIntents;r.startsNotResumed = notResumed;r.isForward = isForward;queueOrSendMessage(H.LAUNCH_ACTIVITY, r);}14 ActivityThread.queueOrSendMessage
mH处理主线程pause操作
15 ActivityThread.handleMessage
16 ActivityThread.handlePauseActivity
通知Launcher 用户离开
通知Launcher onPause
queueWork wait数据写入(以备onResume恢复)
通知ActivityManagerService pause
private final void handlePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges) {ActivityClientRecord r = mActivities.get(token);if (r != null) {//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);if (userLeaving) {performUserLeavingActivity(r);}&nbs
文章题目:追踪Android源码演变——Activity启动全流程
分享链接:http://scjbc.cn/article/jgesds.html