深入理解Activity——Token之旅
Token是ActivityRecord的內部靜態類,我們先來看下Token的繼承關係,Token extends IApplicationToken.Stub,從IApplicationToken.Stub類進行繼承,根據Binder的機制可以知道Token是一個匿名Binder實體類,這個匿名Binder實體會傳遞給其他程式,其他程式會拿到Token的代理端。
我們知道匿名Binder有兩個比較重要的用途,一個是拿到Binder代理端後可跨Binder呼叫實體端的函式介面,另一個作用便是在多個程式中標識同一個物件。往往這兩個作用是同時存在的,比如我們這裡研究的Token就同時存在這兩個作用,但最重要的便是後者,Token標識了一個ActivityRecord物件,即間接標識了一個Activity。
下面這個圖是Token的傳遞,首先會傳遞到WMS中,接著會傳遞到應用程式ActivityThread中,下面來具體分析這個傳遞流程。
1、Token物件的建立
- ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
- int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
- ActivityInfo aInfo, Configuration _configuration,
- ActivityRecord _resultTo, String _resultWho, int _reqCode,
- boolean _componentSpecified, ActivityStackSupervisor supervisor,
- ActivityContainer container, Bundle options) {
- service = _service;
- appToken = new Token(this);
- ........
2、AMS呼叫WMS的addAPPToken()介面
在啟動一個Activity時,會呼叫startActivityLocked()來在WMS中新增一個AppWindowToken物件;
- final void startActivityLocked(ActivityRecord r, boolean newTask,
- boolean doResume, boolean keepCurTransition, Bundle options) {
- ......
- mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
- r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
- (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
- r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
- ......
- }
- public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
- int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
- int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
- ......
- synchronized(mWindowMap) {
- AppWindowToken atoken = findAppWindowToken(token.asBinder());
- if (atoken != null) {
- Slog.w(TAG, "Attempted to add existing app token: " + token);
- return;
- }
- atoken = new AppWindowToken(this, token, voiceInteraction);
- ......
- Task task = mTaskIdToTask.get(taskId);
- if (task == null) {
- createTask(taskId, stackId, userId, atoken);
- } else {
- task.addAppToken(addPos, atoken);
- }
- mTokenMap.put(token.asBinder(), atoken);
- // Application tokens start out hidden.
- atoken.hidden = true;
- atoken.hiddenRequested = true;
- //dump();
- }
- }
- final boolean realStartActivityLocked(ActivityRecord r,
- ProcessRecord app, boolean andResume, boolean checkConfig)
- throws RemoteException {
- ......
- app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
- System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
- r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
- r.icicle, r.persistentState, results, newIntents, !andResume,
- mService.isNextTransitionForward(), profilerInfo);
- ......
- }
這個是通過呼叫app.thread.scheduleLaunchActivity()完成的,可以知道對端接收到的便是Token的代理物件。
我們來看下ApplicationThread中scheduleLaunchActivity()的實現:
- public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
- String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
- PersistableBundle persistentState, List<ResultInfo> pendingResults,
- List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
- ProfilerInfo profilerInfo) {
- updateProcessState(procState, false);
- ActivityClientRecord r = new ActivityClientRecord();
- r.token = token;
- r.ident = ident;
- r.intent = intent;
- r.referrer = referrer;
- r.voiceInteractor = voiceInteractor;
- r.activityInfo = info;
- r.compatInfo = compatInfo;
- r.state = state;
- r.persistentState = persistentState;
- r.pendingResults = pendingResults;
- r.pendingIntents = pendingNewIntents;
- r.startsNotResumed = notResumed;
- r.isForward = isForward;
- r.profilerInfo = profilerInfo;
- updatePendingConfiguration(curConfig);
- sendMessage(H.LAUNCH_ACTIVITY, r);
- }
4、Activity視窗新增
ViewRootImpl.setView()函式中新增Activity視窗時在引數mWindowAttributes中攜帶Token代理物件。
- public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- mView = view;
- ......
- mWindowAttributes.copyFrom(attrs);
- ......
- try {
- ......
- res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(),
- mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
- } catch (RemoteException e) {
- ......
- } finally {
- ......
- }
- ......
- }
- }
- }
- public int addWindow(Session session, IWindow client, int seq,
- WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
- Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
- ......
- boolean addToken = false;
- WindowToken token = mTokenMap.get(attrs.token);
- ......
- win = new WindowState(this, session, client, token,
- attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
- mWindowMap.put(client.asBinder(), win);
- ......
- }
根據Binder機制可以知道從上層應用傳遞過來的Token代理物件會轉換成SystemServer程式中的Token本地物件,後者與第2步中從Token物件是同一個物件,所以上面呼叫mTokenMap.get(attrs.token)時便能返回正確返回一個WindowToken(這個WindowToken其實是一個APPWindowToken),這樣新增的視窗也就跟Activity關聯上了。
轉自:http://blog.csdn.net/guoqifa29/article/details/46819377#comments
相關文章
- Activity生命週期深入理解2
- 完全理解android Activity啟動模式LauchMode (深入Activity與任務棧)Android模式
- 深入理解Activity啟動流程和AMS框架(一)框架
- 深入理解Activity啟動流程和AMS框架(二)框架
- 深入理解Activity啟動流程和AMS框架(三)框架
- 深入理解Android 之 Activity啟動流程(Android 10)Android
- 理解 cookie、session、tokenCookieSession
- CSS之旅(2):如何更深入的理解各種選擇器CSS
- 理解JSON Web TokenJSONWeb
- JSON Web Token 的理解JSONWeb
- 徹底理解cookie,session,tokenCookieSession
- 理解JSON Web Token (一)JSONWeb
- CSS之旅——第二站 如何更深入的理解各種選擇器CSS
- 深入淺出 JSON Web TokenJSONWeb
- Android Activity的基本理解Android
- 深入學習Activity生命週期
- 從Activity的啟動流程理解Binder
- Android中Activity設計思想個人理解Android
- 深入理解Isolate
- 深入理解HashMapHashMap
- 深入理解TransformORM
- 深入理解KVO
- 深入理解 JVMJVM
- 深入理解 GitGit
- 深入理解AQSAQS
- 深入理解JVMJVM
- 深入理解 TypeScriptTypeScript
- 深入理解JavaScriptCoreJavaScript
- 深入理解MVCMVC
- 深入理解 PWA
- 深入理解margin
- 深入理解ReactReact
- 深入理解BFC
- 深入理解reduxRedux
- BFC深入理解
- 深入理解 GCDGC
- 深入理解 requestAnimationFramerequestAnimationFrame
- 深入理解Eureka