深入理解Activity——Token之旅

原创 2015年07月09日 17:15:02
    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);
        ........
}
在ActivityRecord的构造函数中创建,标识着当前这个ActivityRecord,即间接代表着一个Activity。

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();
        }
    }

3、AMS跨Binder调用应用进程的scheduleLaunchActivity()将Token传递给上层应用进程
    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);
        }
函数中创建一个ActivityClientRecord对象,然后将Token的代理对象保存在ActivityClientRecord.token中。ActivityClientRecord也代表着一个Activity,不过是在应用进程中,而ActivityRecord是在ActivityManagerService中代表一个Activity。

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关联上了。

Android客户端与服务器交互中的token

学习TokenToken是什么? Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个To...
  • watermusicyes
  • watermusicyes
  • 2015年07月23日 07:45
  • 51254

Android使用token维持登陆状态

什么是tokentoken(令牌)是一串唯一的字符串,通常由服务端生成,在注册完成时返回给客户端,用来标识此用户,客户端将此字符串存储在本地。在以后的网络请求时,客户端先查询本地的token,如果有则...
  • kevinjqy
  • kevinjqy
  • 2017年01月19日 15:45
  • 2413

Android Token的作用

一、学习Token1、token是什么Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个To...
  • u010545480
  • u010545480
  • 2017年04月26日 15:21
  • 502

Android4.0窗口机制token分析以及activitiy, dialog, toast 窗口创建过程分析

一  前言 在谈到这个话题的时候,脑海里面千头万绪,因为它涉及到了方方面面的知识… 比如Activity管理,窗口添加,Token权限验证等等… 既然这么复杂,那么我们就复杂的问题简单化,...
  • ritterliu
  • ritterliu
  • 2014年09月16日 16:25
  • 8403

应用Token的流程和作用

应用程序Token的联系 android系统中,Binder有两个重要的用途: 获取Binder地址,进行跨进程调用; 在多个进程中标识身份,确保调用安全。 android中Token就是以...
  • neu_zhsh
  • neu_zhsh
  • 2017年06月16日 21:46
  • 539

Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析

在Android系统中,Activity组件在启动之后,并且在它的窗口显示出来之前,可以显示一个启动窗口。这个启动窗口可以看作是Activity组件的预览窗口,是由WindowManagerServi...
  • Luoshengyang
  • Luoshengyang
  • 2013年02月18日 00:56
  • 48496

WmS详解(一)之token到底是什么?基于Android7.0源码

做Android有些年头了,Framework层三大核心View系统,WmS、AmS最近在研究中,这三大块,每一块都够写一个小册子来介绍,其中View系统的介绍,我之前有一个系列的博客(不过由于时间原...
  • u012702547
  • u012702547
  • 2016年11月18日 18:05
  • 2763

android中的token

token顾命思意,象征符号,到底是什么的象征呢?我们在看andorid源码的时候,经常会碰到程序与系统service之间的通信,我们也知道进程间通信会用binder机制! 而这个token就是一...
  • congqingbin
  • congqingbin
  • 2016年05月15日 22:30
  • 2829

Android启动Activity流程中的Token分析

以下分析基于Android4.3.
  • leopard21
  • leopard21
  • 2014年04月29日 13:58
  • 1664

Activity的代表ActivityRecord

ActivityRecord
  • u010479969
  • u010479969
  • 2015年08月28日 09:25
  • 4300
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入理解Activity——Token之旅
举报原因:
原因补充:

(最多只允许输入30个字)