美文网首页
Activity Token从AMS到WMS的传递

Activity Token从AMS到WMS的传递

作者: android_coder | 来源:发表于2019-02-20 19:45 被阅读0次

    本文是基于android_9.0.0_r4
    我们都知道Activity在AMS端的描述是ActivityRecord,ActivityRecord初始化过程会创建一个token对象,这个token对象会保存在三个位置:app端,ams,wms端,本文主要是分析这个token值从ams传递到wms的流程
    Activity启动过程中有会执行到ActivityStatck的startActivityLocked方法中
    ActivityStack.java::startActivityLocked
    if (r.getWindowContainerController() == null) {
    r.createWindowContainer();
    }
    其中r的数据类型是ActivityRecord
    进入到ActivityRecord的createWindowContainer方法

    ActivityRecord::createWindowContainer
            if (mWindowContainerController != null) {
                throw new IllegalArgumentException("Window container=" + mWindowContainerController
                        + " already created for r=" + this);
            }
    
            inHistory = true;
    
            final TaskWindowContainerController taskController = task.getWindowContainerController();
    
            // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
            task.updateOverrideConfigurationFromLaunchBounds();
            // Make sure override configuration is up-to-date before using to create window controller.
            updateOverrideConfiguration();
    
            mWindowContainerController = new AppWindowContainerController(taskController, appToken,
                    this, Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen,
                    (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
                    task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
                    appInfo.targetSdkVersion, mRotationAnimationHint,
                    ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
    
            task.addActivityToTop(this);
    
            // When an activity is started directly into a split-screen fullscreen stack, we need to
            // update the initial multi-window modes so that the callbacks are scheduled correctly when
            // the user leaves that mode.
            mLastReportedMultiWindowMode = inMultiWindowMode();
            mLastReportedPictureInPictureMode = inPinnedWindowingMode();
    

    在该过程中会创建AppWindowContainerController对象,进入到AppWindowContainerController的构造方法中

        public AppWindowContainerController(TaskWindowContainerController taskController,
                IApplicationToken token, AppWindowContainerListener listener, int index,
                int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
                boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
                int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) {
            this(taskController, token, listener, index, requestedOrientation, fullscreen,
                    showForAllUsers,
                    configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable,
                    targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos,
                    WindowManagerService.getInstance());
        }
    

    继续调用同名的方法

        public AppWindowContainerController(TaskWindowContainerController taskController,
                IApplicationToken token, AppWindowContainerListener listener, int index,
                int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
                boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
                int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
                WindowManagerService service) {
            super(listener, service);
            mHandler = new H(service.mH.getLooper());
            mToken = token;
            synchronized(mWindowMap) {
                AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
                if (atoken != null) {
                    // TODO: Should this throw an exception instead?
                    Slog.w(TAG_WM, "Attempted to add existing app token: " + mToken);
                    return;
                }
    
                final Task task = taskController.mContainer;
                if (task == null) {
                    throw new IllegalArgumentException("AppWindowContainerController: invalid "
                            + " controller=" + taskController);
                }
    
                atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
                        inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
                        requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
                        alwaysFocusable, this);
                if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
                        + " controller=" + taskController + " at " + index);
                task.addChild(atoken, index);
            }
        }
    

    在此过程中会创建一个AppWindowToken的对象,createAppWindow的实现为

        AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
                boolean alwaysFocusable, AppWindowContainerController controller) {
            return new AppWindowToken(service, token, voiceInteraction, dc,
                    inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
                    rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
                    controller);
        }
    

    进入到AppWindowToken的构造方法

        AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
                DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
                boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
                int configChanges, boolean launchTaskBehind, boolean alwaysFocusable,
                AppWindowContainerController controller) {
            this(service, token, voiceInteraction, dc, fullscreen);
            setController(controller);
            mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
            mShowForAllUsers = showForAllUsers;
            mTargetSdk = targetSdk;
            mOrientation = orientation;
            layoutConfigChanges = (configChanges & (CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION)) != 0;
            mLaunchTaskBehind = launchTaskBehind;
            mAlwaysFocusable = alwaysFocusable;
            mRotationAnimationHint = rotationAnimationHint;
    
            // Application tokens start out hidden.
            setHidden(true);
            hiddenRequested = true;
    

    继续调用同名的方法

        AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
                DisplayContent dc, boolean fillsParent) {
            super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
                    false /* ownerCanManageAppTokens */);
            appToken = token;
            mVoiceInteraction = voiceInteraction;
            mFillsParent = fillsParent;
            mInputApplicationHandle = new InputApplicationHandle(this);
        }
    

    由于AppWindowToken的父类是WindowToken,进入到WindowToken的构造方法

        WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
                DisplayContent dc, boolean ownerCanManageAppTokens) {
            this(service, _token, type, persistOnEmpty, dc, ownerCanManageAppTokens,
                    false /* roundedCornersOverlay */);
        }
    

    继续进入到同名方法

        WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
                DisplayContent dc, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {
            super(service);
            token = _token;
            windowType = type;
            mPersistOnEmpty = persistOnEmpty;
            mOwnerCanManageAppTokens = ownerCanManageAppTokens;
            mRoundedCornerOverlay = roundedCornerOverlay;
            onDisplayChanged(dc);
        }
    

    继续分析onDisplayChanged的方法

        void onDisplayChanged(DisplayContent dc) {
            dc.reParentWindowToken(this);
            mDisplayContent = dc;
    
            // The rounded corner overlay should not be rotated. We ensure that by moving it outside
            // the windowing layer.
            if (mRoundedCornerOverlay) {
                mDisplayContent.reparentToOverlay(mPendingTransaction, mSurfaceControl);
            }
    
            // TODO(b/36740756): One day this should perhaps be hooked
            // up with goodToGo, so we don't move a window
            // to another display before the window behind
            // it is ready.
    
            super.onDisplayChanged(dc);
        }
    

    进而分析DisplayContent的reParentWindowToken方法

        void reParentWindowToken(WindowToken token) {
            final DisplayContent prevDc = token.getDisplayContent();
            if (prevDc == this) {
                return;
            }
            if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null
                    && token.asAppWindowToken() == null) {
                // Removed the token from the map, but made sure it's not an app token before removing
                // from parent.
                token.getParent().removeChild(token);
            }
    
            addWindowToken(token.token, token);
        }
    

    addWindowToken的实现是

        private void addWindowToken(IBinder binder, WindowToken token) {
            final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
            if (dc != null) {
                // We currently don't support adding a window token to the display if the display
                // already has the binder mapped to another token. If there is a use case for supporting
                // this moving forward we will either need to merge the WindowTokens some how or have
                // the binder map to a list of window tokens.
                throw new IllegalArgumentException("Can't map token=" + token + " to display="
                        + getName() + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
            }
            if (binder == null) {
                throw new IllegalArgumentException("Can't map token=" + token + " to display="
                        + getName() + " binder is null");
            }
            if (token == null) {
                throw new IllegalArgumentException("Can't map null token to display="
                        + getName() + " binder=" + binder);
            }
    
            mTokenMap.put(binder, token);
    
            if (token.asAppWindowToken() == null) {
                // Add non-app token to container hierarchy on the display. App tokens are added through
                // the parent container managing them (e.g. Tasks).
                switch (token.windowType) {
                    case TYPE_WALLPAPER:
                        mBelowAppWindowsContainers.addChild(token);
                        break;
                    case TYPE_INPUT_METHOD:
                    case TYPE_INPUT_METHOD_DIALOG:
                        mImeWindowsContainers.addChild(token);
                        break;
                    default:
                        mAboveAppWindowsContainers.addChild(token);
                        break;
                }
            }
        }
    

    mTokenMap.put(binder, token);便是将ActivityRecord对应的token值保存到一个hashmap中
    这样wms便存储了Activity对应的token值了,通过该token值便可以找到该activity了

    相关文章

      网友评论

          本文标题:Activity Token从AMS到WMS的传递

          本文链接:https://www.haomeiwen.com/subject/iihkyqtx.html