Android 中追踪Token

参考:<Android 内核剖析>
最近看WMS, 很多地方都会出现Token的身影, 因为AMS中也有Token, 想试着总结下.

Activity中mToken由来
//第一 Activity.java
//第始于在Activity中调用startActivity()
public void startActivity(Intent intent) {
    startActivityForResult(intent, -1);
}
//第二 Activity.java
public void startActivityForResult(Intent intent, int requestCode) {
     ...
    Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
            this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode);
     ...
}
//第三 Instrumentation.java
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode) {
    try {
        // getDefault() 获取AMS代理对象,执行AMS中的startActivity()
        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;
}
//第四 ActivityManagerService.java
public final int startActivity(IApplicationThread caller,
        Intent intent, String resolvedType, Uri[] grantedUriPermissions,
        int grantedMode, IBinder resultTo,
        String resultWho, int requestCode, boolean onlyIfNeeded,
        boolean debug) {
    // WMS很多具体的操作都会交由它来处理
    return mMainStack.startActivityMayWait(caller, intent, resolvedType,
            grantedUriPermissions, grantedMode, resultTo, resultWho,
            requestCode, onlyIfNeeded, debug, null, null);
} 
//第五 ActivityStack.java 
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) {
     ...
    //看这里面
    int res = startActivityLocked(caller, intent, resolvedType,
            grantedUriPermissions, grantedMode, aInfo,
            resultTo, resultWho, requestCode, callingPid, callingUid,
            onlyIfNeeded, componentSpecified);
    
    ...
    return res;
}
// 第六 ActivityStack.java 
final int startActivityLocked(IApplicationThread caller,
        Intent intent, String resolvedType,
        Uri[] grantedUriPermissions,
        int grantedMode, ActivityInfo aInfo, IBinder resultTo,
        String resultWho, int requestCode,
        int callingPid, int callingUid, boolean onlyIfNeeded,
        boolean componentSpecified) {
     ...
     //ActivityRecord构造方法中会创建一个token
     ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
            intent, resolvedType, aInfo, mService.mConfiguration,
            resultRecord, resultWho, requestCode, componentSpecified);
     ...
     // 第八 其中r是想要启动的Activity组件对应的ActivityRecord对象
     // sourceRecord是已经启动的Activity组件对应的ActivityRecord对象
     err = startActivityUncheckedLocked(r, sourceRecord,grantedUriPermissions, grantedMode, onlyIfNeeded, true);
    ...
}
// 第七 ActivityRecord.java
 ActivityRecord(ActivityManagerService _service, ActivityStack _stack, ProcessRecord _caller,
         int _launchedFromUid, Intent _intent, String _resolvedType,
         ActivityInfo aInfo, Configuration _configuration,
         ActivityRecord _resultTo, String _resultWho, int _reqCode,
         boolean _componentSpecified) {
    ...
    // 该Token是一个binder本地对象,还在WMS中, 如何传入到Activity中的呢?
    appToken = new Token(this);
    ...
 }
//第八 ActivityStack.java中startActivityUncheckedLocked()
final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
        int grantedMode, boolean onlyIfNeeded, boolean doResume) {
     ...
    //上面还有一个 startActivityLocked(), 只是传入的参数不一样.
    // 传入r 是目标ActivityRecord.
    startActivityLocked(r, newTask, doResume, keepCurTransition);
    return START_SUCCESS;
}
//第九 ActivityStack.java 
private final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition) {
    ...
    mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
            r.info.screenOrientation, r.fullscreen);
    ...
     resumeTopActivityLocked(null);
    ...
}
//第十 ActivityStack.java
final boolean resumeTopActivityLocked(ActivityRecord prev) {
    ...
    startPausingLocked(userLeaving, false);
} 
// 第十一 ActivityStack.java
private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
    //被点击的Activity组件,已经启动显示在屏幕中. 
    ActivityRecord prev = mResumedActivity; 
    ...
    // 这里下一步就回到Client进程中了 
    // 注意:prev.appToken是已经启动了的APP的Token,不要弄混淆了, 
    prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,userLeaving, prev.configChangeFlags);
}
// 第十二 ActivityThread.ApplicationThread.java
public final void schedulePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges) {
    queueOrSendMessage(
            finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
            token,
            (userLeaving ? 1 : 0),
            configChanges);
}
// 第十三 ActivityThread.java 
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
    synchronized (this) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        mH.sendMessage(msg);
    }
}
// 第十四 ActivityThread.H.java
public void handleMessage(Message msg) {
    ...
    case PAUSE_ACTIVITY:
        handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
        maybeSnapshot();
        break;
    ...
} 
//第十五 ActivityThread.java
private void handlePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges) {
    // 这里的token 是被点击的Activity组件,已经在屏幕中显示着,
    // 现在是要让这个Activity暂停
    //ActivityClientRecord 与WMS中的ActivityClient是一一对应关系,
    ActivityClientRecord r = mActivities.get(token);
    //暂停当前Activity
    performPauseActivity(token, finished, r.isPreHoneycomb());
    //从这里又跳到AMS中去了
    ActivityManagerNative.getDefault().activityPaused(token);
}
//第十六 ActivityManagerService.java
public final void activityPaused(IBinder token) {
    final long origId = Binder.clearCallingIdentity();
    mMainStack.activityPaused(token, false);
    Binder.restoreCallingIdentity(origId);
}
//第十七 ActivityStack.java
final void activityPaused(IBinder token, boolean timeout) {
    ...
    completePauseLocked();
}
//第十八 ActivityStack.java
private final void completePauseLocked() {
    ActivityRecord prev = mPausingActivity;
    ...
    // prev 指的是当前已经被暂停后的Activity组件 
    resumeTopActivityLocked(prev);
}
//第十九 ActivityStack.java
final boolean resumeTopActivityLocked(ActivityRecord prev) {
    //这里的next就是目标Activity组件对应的ActivityRecord对象
    ActivityRecord next = topRunningActivityLocked(null);
    startSpecificActivityLocked(next, true, true);
}
//第二十 ActivityStack.java
private final void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    //用目标Activity对应的ActivityRecord组件获取到目标APP进程
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid);
    //此时目标APP进程肯定是存在的
    if (app != null && app.thread != null) {
        try {
            app.addPackage(r.info.packageName);
            //执行到此处继续往下看
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
    }
}
//第二十一 ActivityStack.java
final boolean realStartActivityLocked(ActivityRecord r,
        ProcessRecord app, boolean andResume, boolean checkConfig)
        throws RemoteException {
     // 到这里下一步就又回到了Client进程中去了, 
    // 注意r.appToken值,马上就结束Activity中token的探索旅程了.
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
            System.identityHashCode(r), r.info,
            new Configuration(mService.mConfiguration),
            r.compat, r.icicle, results, newIntents, !andResume,
            mService.isNextTransitionForward(), profileFile, profileFd,
            profileAutoStop);
}
//第二十二 ActivityThread.java
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
        Bundle state, List<ResultInfo> pendingResults,
        List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
        String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
    ActivityClientRecord r = new ActivityClientRecord(); 
     //将 AMS中ActivityRecord对象中的appToken,传到Client进程中来,存储到ActivityClientRecord中token变量中.
    r.token = token;
    ...
    // 将带有token的 ActivityClientRecord传递出去了
    queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
//第二十三 ActivityThread.java
private void queueOrSendMessage(int what, Object obj) {
    queueOrSendMessage(what, obj, 0, 0);
}
//第二十四 ActivityThread.java
public void handleMessage(Message msg) {
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            ActivityClientRecord r = (ActivityClientRecord)msg.obj; 
            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            //  将带有token的 ActivityClientRecord传递出去了    
            handleLaunchActivity(r, null);
        } break;
}
//第二十五 ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // 该方法是创建一个Activity对象
    Activity a = performLaunchActivity(r, customIntent);
}
//第二十六 ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo; 
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    //创建Activity 
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    //创建Application 
    Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    //看看这个关键的东西 r.token,这个就是当初在AMS中创建ActivityRecord对象时候创建的token对象了.
    activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config);
}
//第二十六 Activity.java
final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config) {
    ...
    //这里终于Activity把token保存起来了.    
    mToken = token;
}
Window中的mAppToken
// Activity.java
final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config) {
    attachBaseContext(context);
    ...
    //TODO 第一步 创建PhoneWindow对象
    mWindow = PolicyManager.makeNewWindow(this);
    ...
    //TODO 第四步
    mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

    // 题外话
    // 可以看出来这个mParent也是从AMS传过来的
    mParent = parent;
    if (mParent != null) {
        // 现在一般很少见到Activity中包含一个Activity,比如很早以前的`TabActivity`,现在都被`Fragment`替代了.
        mWindow.setContainer(mParent.getWindow());
    }
    ...
}
//TODO 第二步 PolicyManager.java
//private static final String POLICY_IMPL_CLASS_NAME = "com.android.internal.policy.impl.Policy";
public static Window makeNewWindow(Context context) {
   //这个sPolicy对象需要看Policy.java类
   return sPolicy.makeNewWindow(context);
}
//TODO 第三步 Policy.java
public Window makeNewWindow(Context context) {
    //可以看到在attach()方法中创建Window最终得到一个PhoneWindow
    //PhoneWindow 是Window唯一实现类
    return new PhoneWindow(context);
}
//TODO 第四步 Window.java
//Window.setWindowManager()方法中传入的mToken就是Activity中的mToken,上面追了二十多步捋清楚它的来历.
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
        boolean hardwareAccelerated) {
   //看这里就知道了 Window中的mAppToken一般就是Activity中的mToken变量了.
   mAppToken = appToken;
   mAppName = appName;
   if (wm == null) {
       wm = WindowManagerImpl.getDefault();
   }
   mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);
}
WindowManager.LayoutParams中的Token
  • 当执行Activity.java中的attach()时候,会创建WindowPhone对象,此时会在Window类中创建一个WindowManager.LayoutParams的变量.
  • Activity准备好了会通知AMS,AMS最终经过各种条件判断最后调用到ActivitymakeVisible().
public class Activity extends ContextThemeWrapperimplements LayoutInflater.Factory,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks {
    // TODO 第一步
    final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config) {
        ...
        // 调用setWindowManager()会创建WM对象.
        mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        ...
        // 获取LocalWindowManager对象
        mWindowManager = mWindow.getWindowManager();
    }
    // TODO 第二步
    // 等到Activity的一切工作准备完毕,现在就开始展示具体View了.
    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            //通过LocalWindowManager对象执行addView()
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }
    
    //获取Window.LocalWindowManager对象
    public WindowManager getWindowManager() {
        return mWindowManager;
    }
}
//Window.java
public abstract class Window {
    // 创建 mWindowAttributes变量
    private final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
    
    private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper {
        // TODO 第三步
        // view是上面传入的mDecor
        // params是上面传入的WindowManager.LayoutParams对象.
        public final void addView(View view, ViewGroup.LayoutParams params) {
            WindowManager.LayoutParams wp = (WindowManager.LayoutParams)params;
            //在创建WindowManager.LayoutParams对象的时候, 它默认是应用窗口.
            //首先根据params的Type对象判断是否是子窗口
            if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                //假如现在创建的是子窗口,且WindowManager.LayoutParams对象的token为空
                if (wp.token == null) {
                    //peekDecorView()这个方法的具体实现是PhoneWindow中
                    //返回的就是PhoneWindow中的mDecor对象
                    View decor = peekDecorView();
                    if (decor != null) {
                        // 从这里可以知道,如果创建的是子窗口,当使用父窗口的LocalWindowManager对象添加子窗口的时候,
                        // 经过一系列判断最终会将父窗口中的decorView的token赋值给WindowManager.LayoutParams中的token变量.
                        // 这里是WindowManager.LayoutParams中的token由来的第一个情况
                        // 其实这里还有一个疑问, decorView中的token是如何来的呢?这个后面会分析.
                        // 先弄清楚WindowManager.LayoutParams中的token.
                        wp.token = decor.getWindowToken();
                    }
                }
                ...
            } else {
                // 假如现在创建的不是子窗口,且WindowManager.LayoutParams对象的token为空
                if (wp.token == null) {
                    // mContainer这个是表示父Activity.这里一般是没有父Activity的.
                    // 所以如果创建的不是子窗口,那么就将Activity中的token赋值给WindowManager.LayoutParams中的token.
                    // 到这里WindowManager.LayoutParams两种token的由来就说清楚了.
                    wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
                }
                ...
            }
            ...
        }
    }
    //获取WindowManager.LayoutParams对象
    public final WindowManager.LayoutParams getAttributes() {
        return mWindowAttributes;
    }
    //创建WM对象
    public void setWindowManager(WindowManager wm, IBinder appToken, String appName
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        if (wm == null) {
            wm = WindowManagerImpl.getDefault();
        }
        ...
        //getWindowManager()方法获取的就是LocalWindowManager
        mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);
    }
}
//WindowManager.java
public interface WindowManager extends ViewManager {
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
        //在LayoutParams中,它有一个token变量, 现在就要找这个token是从哪儿来的.
        public IBinder token = null;
        //从这里可以看出mWindowAttributes对象的Type是一个应用窗口.
        public LayoutParams() {
            super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            type = TYPE_APPLICATION;
            format = PixelFormat.OPAQUE;
        }
    }
}
View中的Token
  • 探索WindowManager.LayoutParams中的Token的时候,如果是子窗体,那么WindowManager.LayoutParams中的Token是由decorView的token提供的.那decorView的token是怎么来的呢.
// Window.java
public abstract class Window {
    private class LocalWindowManager extends WindowManagerImpl.CompatModeWrapper {
         public final void addView(View view, ViewGroup.LayoutParams params) {
             // TODO 第一步
             //这一步会调用WindowManagerImpl.CompatModeWrapper中的addView()
             super.addView(view, params);
         }   
    }
}
// WindowManagerImpl.CompatModeWrapper.java
public class WindowManagerImpl implements WindowManager {
    static class CompatModeWrapper implements WindowManager {
        @Override
        public void addView(View view, android.view.ViewGroup.LayoutParams params) {
            // TODO 第二步
            // 这里会调用WindowManagerImpl中的addView() 主要是这个方法
            mWindowManager.addView(view, params, mCompatibilityInfo);
        }
    }
    
    private void addView(View view, ViewGroup.LayoutParams params,CompatibilityInfoHolder cih, boolean nest) {
        ViewRootImpl root;
        //这个对象是在添加addView时候创建的
        root = new ViewRootImpl(view.getContext());
        ...
        // TODO 第三步
        //继续向下看
        root.setView(view, wparams, panelParentView);
    }
}
//ViewRootImpl.java
//是ViewRootImpl还是ViewRoot影响不大
@SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
public final class ViewRootImpl extends Handler implements ViewParent,View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    final View.AttachInfo mAttachInfo;
    final W mWindow;
    public ViewRootImpl(Context context) {
        // TODO 注意这里
        //当ViewRootImpl对象被创建后,它内部的变量mAttachInfo也会自动被创建.
        mWindow = new W(this);
        //看AttachInfo构造方法可以知道,mWindow调用asBinder()得到的值最后赋值给AttachInfo中变量mWindowToken.
        mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
    }
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
                //这个mView就是需要新添加的View
                mView = view;
                ...
                // TODO 第四步
                // 让窗口变得可见
                requestLayout();
                ...
            }
        }
    }
    public void requestLayout() {
        checkThread();
        mLayoutRequested = true;
        // TODO 第五步
        //接着向下看
        scheduleTraversals();
    }
    
    public void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            // TODO 第六步 
            //接着向下看
            sendEmptyMessage(DO_TRAVERSAL);
        }
    }
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        ...
        case DO_TRAVERSAL:
            ...
            // TODO 第七步 
            performTraversals();
            ...
            break;
    }
    private void performTraversals() {
        //这个host就是需要新添加的View
        final View host = mView;
        // TODO 第八步     
        //接着往下看
        host.dispatchAttachedToWindow(attachInfo, 0);
    }
}
//View.java
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    // TODO 第九步 
    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
        //这一步会将ViewRootImpl中的mAttachInfo变量传递到View中.
        mAttachInfo = info;
        ...
    }
    // TODO 到这里就清楚了.
    // 当ViewRootImp被创建后,会在它的构造方法中创建mAttachInfo对象, 这个对象中有一个mWindowToken变量.
    // 在执行ViewRootImp.setView()的一系列方法调度之后,ViewRootImp中的变量mAttachInfo对象最终会传入到View对象中.
    // 当在别的地方通过View调用getWindowToken()时候,获取的token就是在ViewRootImp构造中创建的.
    public IBinder getWindowToken() {
        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
    }
    // 这个构造方法在创建ViewRootImp对象时候被调用.
    static class AttachInfo {
        AttachInfo(IWindowSession session, IWindow window,Handler handler, Callbacks effectPlayer) {
            mSession = session;
            mWindow = window;
            mWindowToken = window.asBinder();
            mHandler = handler;
            mRootCallbacks = effectPlayer;
        }
    }
}

至此,Activity中的token,Window中的mAppToken,WindowManager.LayoutParams中的Token,View中的mWindowToken都探索了一遍.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值