Android_WMS_啟動(dòng)窗口_StartingWindow

1:概述

應(yīng)用程序在冷啟動(dòng)過(guò)程中通常會(huì)顯示一個(gè)預(yù)覽窗口,接著在顯示要啟動(dòng)的activity的窗口,因?yàn)閍ctivity的窗口顯示渲染到屏幕上是需要時(shí)間的,特別是在性能比較差的設(shè)備上,這樣有了預(yù)覽窗口之后屏幕上看到的可能不是黑屏,增強(qiáng)了用戶(hù)體驗(yàn)
本文主要是基于android_10.0.0來(lái)講述的

2:StartingWindow添加流程

ActivityStarter.java::startActivity
ActivityStarter.java::startActivityUnchecked
ActivityStack.java::startActivityLocked

我們主要是從startActivityLocked來(lái)跟蹤

 //第一個(gè)條件滿(mǎn)足,一般我們是從桌面啟動(dòng)應(yīng)用
 if (!isHomeOrRecentsStack() || numActivities() > 0) {
            final DisplayContent dc = getDisplay().mDisplayContent;
            .......................................
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                mStackSupervisor.mNoAnimActivities.add(r);//是否需要啟動(dòng)動(dòng)畫(huà)
            } else {
              ...................................省去部分代碼  
            boolean doShow = true;
            if (newTask) {
                ..............................
                //桌面啟動(dòng)一般不帶有此flag
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeededLocked(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && options.getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                doShow = false;
            }
           // mLaunchTaskBehind = options.getLaunchTaskBehind();賦值,桌面啟動(dòng)不帶有此參數(shù)
            if (r.mLaunchTaskBehind) {
                r.setVisibility(true);
                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {//成立doShow=true
                TaskRecord prevTask = r.getTaskRecord();
                ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
                if (prev != null) {
                    // We don't want to reuse the previous starting preview if:
                    // (1) The current activity is in a different task.
                    if (prev.getTaskRecord() != prevTask) {
                        prev = null;
                    }
                    // (2) The current activity is already displayed.
                    else if (prev.nowVisible) {
                        prev = null;
                    }
                }
               //r為ActivityRecord,直接調(diào)用showStartingWindow
                r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
            }
        } else {
            // If this is the first activity, don't do any fancy animations,
            // because there is nothing for it to animate on top of.
            ActivityOptions.abort(options);
        }

我們?cè)谶@里分析是桌面啟動(dòng)一個(gè)應(yīng)用的情況

2.1:ActivityRecord::showStartingWindow
 void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
            boolean fromRecents) {
        if (mAppWindowToken == null) {
            return;
        }
        if (mTaskOverlay) {
            // We don't show starting window for overlay activities.
            return;
        }
        if (pendingOptions != null
                && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
            // Don't show starting window when using shared element transition.
            return;
        }
        final CompatibilityInfo compatInfo =
                mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
        final boolean shown = addStartingWindow(packageName, theme,
                compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
                allowTaskSnapshot(),
                mState.ordinal() >= RESUMED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
                fromRecents);
        if (shown) {
            mStartingWindowState = STARTING_WINDOW_SHOWN;
        }
    }
    boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
            IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
        ..................................................
        if (mAppWindowToken == null) {
            Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + appToken);
            return false;
        }
        if (mAppWindowToken.getTask() == null) {//不會(huì)為null,AppWindowToken被Task管理
            return false;
        }
        return mAppWindowToken.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
                labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
                processRunning, allowTaskSnapshot, activityCreated, fromRecents);
    }
2.2:AppWindowToken::addStartingWindow
 boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
            IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
            boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
        if (!okToDisplay()) {//還沒(méi)準(zhǔn)備好顯示
            return false;
        }
        if (mStartingData != null) {//如果之前已經(jīng)有啟動(dòng)窗口的數(shù)據(jù)
            return false;
        }
        final WindowState mainWin = findMainWindow();
        if (mainWin != null && mainWin.mWinAnimator.getShown()) {
            // App already has a visible window...why would you want a starting window?
            return false;
        }
        final ActivityManager.TaskSnapshot snapshot =
                mWmService.mTaskSnapshotController.getSnapshot(
                        getTask().mTaskId, getTask().mUserId,
                        false /* restoreFromDisk */, false /* reducedResolution */);
        final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
                allowTaskSnapshot, activityCreated, fromRecents, snapshot);
        if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
            return createSnapshot(snapshot);
        }
        if (theme != 0) {//主題,對(duì)應(yīng)的activity的主題
            AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
                    com.android.internal.R.styleable.Window,
                    mWmService.mCurrentUserId);
            if (ent == null) {
                // Whoops!  App doesn't exist. Um. Okay. We'll just pretend like we didn't
                // see that.
                return false;
            }
            final boolean windowIsTranslucent = ent.array.getBoolean(
                    com.android.internal.R.styleable.Window_windowIsTranslucent, false);
            final boolean windowIsFloating = ent.array.getBoolean(
                    com.android.internal.R.styleable.Window_windowIsFloating, false);
            final boolean windowShowWallpaper = ent.array.getBoolean(
                    com.android.internal.R.styleable.Window_windowShowWallpaper, false);
            final boolean windowDisableStarting = ent.array.getBoolean(
                    com.android.internal.R.styleable.Window_windowDisablePreview, false);
            if (windowIsTranslucent) {//如果是半透明
                return false;
            }
            if (windowIsFloating || windowDisableStarting) {//如果是懸浮的或是禁止顯示啟動(dòng)窗口
                return false;
            }
            if (windowShowWallpaper) {//顯示壁紙
                if (getDisplayContent().mWallpaperController
                        .getWallpaperTarget() == null) {
                    windowFlags |= FLAG_SHOW_WALLPAPER;
                } else {//表示的壁紙窗口已經(jīng)被其他的目標(biāo)窗口占用,則不顯示
                    return false;
                }
            }
        }
        if (transferStartingWindow(transferFrom)) {
            return true;
        }
        if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
            return false;
        }
       //窗口啟動(dòng)數(shù)據(jù)
        mStartingData = new SplashScreenStartingData(mWmService, pkg,
                theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                getMergedOverrideConfiguration());
        scheduleAddStartingWindow();//發(fā)送消息到android.anim線(xiàn)程對(duì)應(yīng)的消息隊(duì)列中
        return true;
    }
2.3:scheduleAddStartingWindow
    void scheduleAddStartingWindow() {
        if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
            mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
        }//放在消息對(duì)應(yīng)的頭部,mAnimationHandler對(duì)應(yīng)的是android.anim線(xiàn)程
    }
2.4:Runnable對(duì)象mAddStartingWindow
private final Runnable mAddStartingWindow = new Runnable() {
        @Override
        public void run() {
            // Can be accessed without holding the global lock
            final StartingData startingData;
            synchronized (mWmService.mGlobalLock) {//同步鎖
                // There can only be one adding request, silly caller!
                mWmService.mAnimationHandler.removeCallbacks(this);//消息隊(duì)列中移除
                if (mStartingData == null) {
                    // Animation has been canceled... do nothing.
                    return;
                }
                startingData = mStartingData;
            }
            WindowManagerPolicy.StartingSurface surface = null;
            try {//創(chuàng)建一個(gè)surface繪圖表面startingData是SplashScreenStartingData
                surface = startingData.createStartingSurface(AppWindowToken.this);
            } catch (Exception e) {
                Slog.w(TAG, "Exception when adding starting window", e);
            }
            if (surface != null) {
                boolean abort = false;
                synchronized (mWmService.mGlobalLock) {
                    // If the window was successfully added, then
                    // we need to remove it.
                    if (removed || mStartingData == null) {
                        startingWindow = null;
                        mStartingData = null;
                        abort = true;
                    } else {
                        startingSurface = surface;
                    }
                }
                if (abort) {
                    surface.remove();
                }
            } else if (DEBUG_STARTING_WINDOW) {
                Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
            }
        }
    };
2.5:SplashScreenStartingData::createStartingSurface
    StartingSurface createStartingSurface(AppWindowToken atoken) {
        return mService.mPolicy.addSplashScreen(atoken.token, mPkg, mTheme, mCompatInfo,
                mNonLocalizedLabel, mLabelRes, mIcon, mLogo, mWindowFlags,
                mMergedOverrideConfiguration, atoken.getDisplayContent().getDisplayId());
    }

mPolicy數(shù)據(jù)類(lèi)型是PhoneWindowManager

2.6:PhoneWindowManager::addSplashScreen
 public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
            int logo, int windowFlags, Configuration overrideConfig, int displayId) {
        if (!SHOW_SPLASH_SCREENS) {
            return null;
        }
        if (packageName == null) {//包名信息
            return null;
        }
        WindowManager wm = null;
        View view = null;
        try {
            Context context = mContext;
            // Obtain proper context to launch on the right display.
            final Context displayContext = getDisplayContext(context, displayId);
            if (displayContext == null) {
                // Can't show splash screen on requested display, so skip showing at all.
                return null;
            }
            context = displayContext;
            if (theme != context.getThemeResId() || labelRes != 0) {
                try {
                    context = context.createPackageContext(packageName, CONTEXT_RESTRICTED);
                    context.setTheme(theme);
                } catch (PackageManager.NameNotFoundException e) {
                    // Ignore
                }
            }
            if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
                final Context overrideContext = context.createConfigurationContext(overrideConfig);
                overrideContext.setTheme(theme);
                final TypedArray typedArray = overrideContext.obtainStyledAttributes(
                        com.android.internal.R.styleable.Window);
                final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
                if (resId != 0 && overrideContext.getDrawable(resId) != null) {
                    context = overrideContext;
                }
                typedArray.recycle();
            }
            final PhoneWindow win = new PhoneWindow(context);//創(chuàng)建一個(gè)PhoneWindow
            win.setIsStartingWindow(true);
            CharSequence label = context.getResources().getText(labelRes, null);
            // Only change the accessibility title if the label is localized
            if (label != null) {
                win.setTitle(label, true);
            } else {
                win.setTitle(nonLocalizedLabel, false);
            }
           //窗口類(lèi)型
            win.setType(
                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
            synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
                if (displayId == DEFAULT_DISPLAY && mKeyguardOccluded) {
                    windowFlags |= FLAG_SHOW_WHEN_LOCKED;//鎖屏的時(shí)候顯示
                }
            }
           //窗口flag
            win.setFlags(
                windowFlags|
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                windowFlags|
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
            win.setDefaultIcon(icon);
            win.setDefaultLogo(logo);
            win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
                    WindowManager.LayoutParams.MATCH_PARENT);
            final WindowManager.LayoutParams params = win.getAttributes();
            params.token = appToken;//appToken,共有activity的token
            params.packageName = packageName;
            params.windowAnimations = win.getWindowStyle().getResourceId(
                    com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
            params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
            if (!compatInfo.supportsScreen()) {
                params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
            }
            params.setTitle("Splash Screen " + packageName);
            addSplashscreenContent(win, context);
            wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
            view = win.getDecorView();
            wm.addView(view, params);//添加到窗口管理器
            return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null;
        } catch (WindowManager.BadTokenException e) {
        } catch (RuntimeException e) {
            Log.w(TAG, appToken + " failed creating starting window", e);
        } finally {
            if (view != null && view.getParent() == null) {
                Log.w(TAG, "view not successfully added to wm, removing view");
                wm.removeViewImmediate(view);
            }
        }
        return null;
    }

這個(gè)方法主要是創(chuàng)建一個(gè)PhoneWindow對(duì)象,然后設(shè)置一些窗口屬性,最后將DecorView添加到窗口管理器

3:啟動(dòng)窗口的移除

我們都知道一個(gè)窗口既然被添加到窗口管理器了,那么肯定也有被銷(xiāo)毀(移除)的時(shí)機(jī),它移除的時(shí)機(jī)就是被啟動(dòng)的組件已經(jīng)可見(jiàn)了,那么啟動(dòng)窗口就需要被移除,我們知道窗口只要有內(nèi)容或是屬性發(fā)生了變化都會(huì)觸發(fā)更新,其更新都會(huì)調(diào)到WindowSurfacePlacer::performSurfacePlacement

3.1:performSurfacePlacement
   final void performSurfacePlacement(boolean force) {
        if (mDeferDepth > 0 && !force) {
            return;
        }
        int loopCount = 6;
        do {
            mTraversalScheduled = false;
            performSurfacePlacementLoop();
            mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
            loopCount--;
        } while (mTraversalScheduled && loopCount > 0);
        mService.mRoot.mWallpaperActionPending = false;
    }
3.2:performSurfacePlacementLoop
 private void performSurfacePlacementLoop() {
        if (mInLayout) {
            return;
        }
        // TODO(multi-display):
        final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
        if (defaultDisplay.mWaitingForConfig) {
            return;
        }
        if (!mService.mDisplayReady) {
            // Not yet initialized, nothing to do.
            return;
        }
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
        mInLayout = true;
        boolean recoveringMemory = false;
        if (!mService.mForceRemoves.isEmpty()) {
            recoveringMemory = true;
            // Wait a little bit for things to settle down, and off we go.
            while (!mService.mForceRemoves.isEmpty()) {
                final WindowState ws = mService.mForceRemoves.remove(0);
                Slog.i(TAG, "Force removing: " + ws);
                ws.removeImmediately();
            }
            Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
            Object tmp = new Object();
            synchronized (tmp) {
                try {
                    tmp.wait(250);
                } catch (InterruptedException e) {
                }
            }
        }
        try {
            //mRoot是RootWindowContainer.java
            mService.mRoot.performSurfacePlacement(recoveringMemory);
            mInLayout = false;
            if (mService.mRoot.isLayoutNeeded()) {
                if (++mLayoutRepeatCount < 6) {
                    requestTraversal();
                } else {
                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
                    mLayoutRepeatCount = 0;
                }
            } else {
                mLayoutRepeatCount = 0;
            }
            if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
                mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
                mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
            }
        } catch (RuntimeException e) {
            mInLayout = false;
            Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
        }
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
    }
3.3RootWindowContainer::performSurfacePlacement
    void performSurfacePlacement(boolean recoveringMemory) {
        try {
            performSurfacePlacementNoTrace(recoveringMemory);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
3.4:performSurfacePlacementNoTrace
 void performSurfacePlacementNoTrace(boolean recoveringMemory) {
        int i;
        if (mWmService.mFocusMayChange) {//如果焦點(diǎn)窗口可能改變
            mWmService.mFocusMayChange = false;
            mWmService.updateFocusedWindowLocked(//更新焦點(diǎn)窗口
                    UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
        }
        final int numDisplays = mChildren.size();
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            final DisplayContent displayContent = mChildren.get(displayNdx);
            displayContent.setExitingTokensHasVisible(false);
        }
        mHoldScreen = null;
        mScreenBrightness = -1;
        mUserActivityTimeout = -1;
        mObscureApplicationContentOnSecondaryDisplays = false;
        mSustainedPerformanceModeCurrent = false;
        mWmService.mTransactionSequence++;
        // TODO(multi-display): recents animation & wallpaper need support multi-display.
        final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
        mWmService.openSurfaceTransaction();
        try {
            //執(zhí)行/應(yīng)用surface改變事務(wù)
            applySurfaceChangesTransaction(recoveringMemory);
        } catch (RuntimeException e) {
            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
        } finally {
           //關(guān)閉事務(wù)
            mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        mWmService.mAnimator.executeAfterPrepareSurfacesRunnables();
        checkAppTransitionReady(surfacePlacer);//檢查app切換是否準(zhǔn)備完畢
        // Defer starting the recents animation until the wallpaper has drawn
        final RecentsAnimationController recentsAnimationController =
                mWmService.getRecentsAnimationController();
        if (recentsAnimationController != null) {
       recentsAnimationController.checkAnimationReady(defaultDisplay.mWallpaperController);
        }
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            final DisplayContent displayContent = mChildren.get(displayNdx);
            if (displayContent.mWallpaperMayChange) {//壁紙窗口層級(jí)是否可能改變
                displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;//重新布局壁紙窗口
            }
        }
        if (mWmService.mFocusMayChange) {
            mWmService.mFocusMayChange = false;
 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
                    false /*updateInputWindows*/);
        }
        if (isLayoutNeeded()) {//是否需要重新layout
            defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
           handleResizingWindows();
        if (mOrientationChangeComplete) {//旋轉(zhuǎn)
            if (mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
                mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
                mWmService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
                mWmService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
            }
            mWmService.stopFreezingDisplayLocked();
        }
        // Destroy the surface of any windows that are no longer visible.
        i = mWmService.mDestroySurface.size();
        if (i > 0) {
            do {
                i--;
                WindowState win = mWmService.mDestroySurface.get(i);
                win.mDestroying = false;
                final DisplayContent displayContent = win.getDisplayContent();
                if (displayContent.mInputMethodWindow == win) {//如果是輸入法窗口
                    displayContent.setInputMethodWindowLocked(null);
                }
                if (displayContent.mWallpaperController.isWallpaperTarget(win)) {
                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;//如果當(dāng)前窗口是壁紙窗口的目標(biāo)窗口,那么需要重新布局壁紙,改變壁紙窗口的層級(jí)和顯示位置
                }
                win.destroySurfaceUnchecked();
                win.mWinAnimator.destroyPreservedSurfaceLocked();
            } while (i > 0);
            mWmService.mDestroySurface.clear();
        }
        // Time to remove any exiting tokens?
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            final DisplayContent displayContent = mChildren.get(displayNdx);
            displayContent.removeExistingTokensIfPossible();
        }
        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
            final DisplayContent displayContent = mChildren.get(displayNdx);
            if (displayContent.pendingLayoutChanges != 0) {
                displayContent.setLayoutNeeded();
            }
        }
        mWmService.setHoldScreenLocked(mHoldScreen);
        if (!mWmService.mDisplayFrozen) {
            final int brightness = mScreenBrightness < 0 || mScreenBrightness > 1.0f
                    ? -1 : toBrightnessOverride(mScreenBrightness);
            mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, brightness, 0).sendToTarget();
            mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget();
        }
        if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
            mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
            mWmService.mPowerManagerInternal.powerHint(
                    PowerHint.SUSTAINED_PERFORMANCE,
                    (mSustainedPerformanceModeEnabled ? 1 : 0));
        }
        if (mUpdateRotation) {
            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
            mUpdateRotation = updateRotationUnchecked();
        }
        if (mWmService.mWaitingForDrawnCallback != null
                || (mOrientationChangeComplete && !isLayoutNeeded()
                && !mUpdateRotation)) {
            mWmService.checkDrawnWindowsLocked();
        }
        final int N = mWmService.mPendingRemove.size();
        if (N > 0) {
            if (mWmService.mPendingRemoveTmp.length < N) {
                mWmService.mPendingRemoveTmp = new WindowState[N + 10];
            }
            mWmService.mPendingRemove.toArray(mWmService.mPendingRemoveTmp);
            mWmService.mPendingRemove.clear();
            ArrayList<DisplayContent> displayList = new ArrayList();
            for (i = 0; i < N; i++) {
                final WindowState w = mWmService.mPendingRemoveTmp[i];
                w.removeImmediately();
                final DisplayContent displayContent = w.getDisplayContent();
                if (displayContent != null && !displayList.contains(displayContent)) {
                    displayList.add(displayContent);
                }
            }
            for (int j = displayList.size() - 1; j >= 0; --j) {
                final DisplayContent dc = displayList.get(j);
                dc.assignWindowLayers(true /*setLayoutNeeded*/);
            }
        }
        // Remove all deferred displays stacks, tasks, and activities.
        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
            mChildren.get(displayNdx).checkCompleteDeferredRemoval();
        }
        forAllDisplays(dc -> {
            dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
            dc.updateSystemGestureExclusion();
            dc.updateTouchExcludeRegion();
        });
        // Check to see if we are now in a state where the screen should
        // be enabled, because the window obscured flags have changed.
        mWmService.enableScreenIfNeededLocked();//屏幕使能
        mWmService.scheduleAnimationLocked();//準(zhǔn)備開(kāi)啟動(dòng)畫(huà)
    }
3.5:applySurfaceChangesTransaction
 private void applySurfaceChangesTransaction(boolean recoveringMemory) {
        mHoldScreenWindow = null;
        mObscuringWindow = null;
        // TODO(multi-display): Support these features on secondary screens.
        final DisplayContent defaultDc = mWmService.getDefaultDisplayContentLocked();
        final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
        final int defaultDw = defaultInfo.logicalWidth;
        final int defaultDh = defaultInfo.logicalHeight;
        if (mWmService.mWatermark != null) {
            mWmService.mWatermark.positionSurface(defaultDw, defaultDh);
        }
        if (mWmService.mStrictModeFlash != null) {
            mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
        }
        if (mWmService.mCircularDisplayMask != null) {
            mWmService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
                    mWmService.getDefaultDisplayRotation());
        }
        if (mWmService.mEmulatorDisplayOverlay != null) {
            mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
                    mWmService.getDefaultDisplayRotation());
        }
        final int count = mChildren.size();
        for (int j = 0; j < count; ++j) {
            final DisplayContent dc = mChildren.get(j);
            dc.applySurfaceChangesTransaction(recoveringMemory);
        }
        mWmService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
        SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
    }
3.6:applySurfaceChangesTransaction
void applySurfaceChangesTransaction(boolean recoveringMemory) {
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
        mTmpUpdateAllDrawn.clear();
        int repeats = 0;
        do {
            repeats++;
            if (repeats > 6) {
                Slog.w(TAG, "Animation repeat aborted after too many iterations");
                clearLayoutNeeded();
                break;
            }
            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
                mWallpaperController.adjustWallpaperWindows();//調(diào)整壁紙窗口
            }
            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
                if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
                if (updateOrientationFromAppTokens()) {//如果應(yīng)用要求改變顯示方向
                    setLayoutNeeded();//重新布局
                    sendNewConfiguration();//設(shè)置新的配置
                }
            }
            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
                setLayoutNeeded();
            }
            // FIRST LOOP: Perform a layout, if needed.
            if (repeats < LAYOUT_REPEAT_THRESHOLD) {
                performLayout(repeats == 1, false /* updateInputWindows */);
            } else {
                Slog.w(TAG, "Layout repeat skipped after too many iterations");
            }
            pendingLayoutChanges = 0;
            try {
                mDisplayPolicy.beginPostLayoutPolicyLw();
                forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
                pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
            } finally {
                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            }
             mInsetsStateController.onPostLayout();
        } while (pendingLayoutChanges != 0);
        mTmpApplySurfaceChangesTransactionState.reset();
        mTmpRecoveringMemory = recoveringMemory;
        try {
            forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);//重點(diǎn)
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
        prepareSurfaces();
        mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
        mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
                mLastHasContent,
                mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
                mTmpApplySurfaceChangesTransactionState.preferredModeId,
                true /* inTraversal, must call performTraversalInTrans... below */);
        final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
        if (wallpaperVisible != mLastWallpaperVisible) {
            mLastWallpaperVisible = wallpaperVisible;
         mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
        }
        while (!mTmpUpdateAllDrawn.isEmpty()) {
            final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
            atoken.updateAllDrawn();
        }
    }
3.7:mApplySurfaceChangesTransaction
 private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
        final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
        final boolean obscuredChanged = w.mObscured !=
                mTmpApplySurfaceChangesTransactionState.obscured;
        final RootWindowContainer root = mWmService.mRoot;
        // Update effect.
        w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
        if (!mTmpApplySurfaceChangesTransactionState.obscured) {
            final boolean isDisplayed = w.isDisplayedLw();
            if (isDisplayed && w.isObscuringDisplay()) {
                // This window completely covers everything behind it, so we want to leave all
                // of them as undimmed (for performance reasons).
                root.mObscuringWindow = w;
                mTmpApplySurfaceChangesTransactionState.obscured = true;
            }
            mTmpApplySurfaceChangesTransactionState.displayHasContent |=
                    root.handleNotObscuredLocked(w,
                            mTmpApplySurfaceChangesTransactionState.obscured,
                            mTmpApplySurfaceChangesTransactionState.syswin);
            if (w.mHasSurface && isDisplayed) {
                final int type = w.mAttrs.type;
                if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
                        || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                    mTmpApplySurfaceChangesTransactionState.syswin = true;
                }
                if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
                        && w.mAttrs.preferredRefreshRate != 0) {
                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
                            = w.mAttrs.preferredRefreshRate;
                }
                final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
                        .getPreferredModeId(w);
                if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
                        && preferredModeId != 0) {
                    mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
                }
            }
        }
        if (obscuredChanged && w.isVisibleLw() && mWallpaperController.isWallpaperTarget(w)) {
            mWallpaperController.updateWallpaperVisibility();
        }
        w.handleWindowMovedIfNeeded();
        final WindowStateAnimator winAnimator = w.mWinAnimator;
        w.resetContentChanged();
        if (w.mHasSurface) {
            final boolean committed = winAnimator.commitFinishDrawingLocked();
            if (isDefaultDisplay && committed) {
                if (w.mAttrs.type == TYPE_DREAM) {
                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
                }
                if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
                    mWallpaperMayChange = true;
                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                }
            }
        }
        final AppWindowToken atoken = w.mAppToken;
        if (atoken != null) {
            atoken.updateLetterboxSurface(w);
            final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
                mTmpUpdateAllDrawn.add(atoken);
            }
        }
        if (!mLosingFocus.isEmpty() && w.isFocused() && w.isDisplayedLw()) {
            mWmService.mH.obtainMessage(REPORT_LOSING_FOCUS, this).sendToTarget();
        }
        w.updateResizingWindowIfNeeded();
    };
3.8:commitFinishDrawingLocked
    boolean commitFinishDrawingLocked() {
        if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
            return false;
        }
        mDrawState = READY_TO_SHOW;
        boolean result = false;
        final AppWindowToken atoken = mWin.mAppToken;
        if (atoken == null || atoken.canShowWindows()
                || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
            result = mWin.performShowLocked();
        }
        return result;
    }
3.9:performShowLocked
boolean performShowLocked() {
        if (isHiddenFromUserLocked()) {
            clearPolicyVisibilityFlag(VISIBLE_FOR_USER);
            return false;
        }
        logPerformShow("performShow on ");
        final int drawState = mWinAnimator.mDrawState;
        if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW)
                && mAttrs.type != TYPE_APPLICATION_STARTING && mAppToken != null) {
            mAppToken.onFirstWindowDrawn(this, mWinAnimator);
        }
        if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) {
            return false;
        }
        logPerformShow("Showing ");
        mWmService.enableScreenIfNeededLocked();//屏幕使能
        mWinAnimator.applyEnterAnimationLocked();//執(zhí)行進(jìn)入動(dòng)畫(huà)
        mWinAnimator.mLastAlpha = -1;
        mWinAnimator.mDrawState = HAS_DRAWN;
        mWmService.scheduleAnimationLocked();//調(diào)度動(dòng)畫(huà)
        if (mHidden) {
            mHidden = false;
            final DisplayContent displayContent = getDisplayContent();
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                final WindowState c = mChildren.get(i);
                if (c.mWinAnimator.mSurfaceController != null) {
                    c.performShowLocked();
                    if (displayContent != null) {
                        displayContent.setLayoutNeeded();
                    }
                }
            }
        }
        if (mAttrs.type == TYPE_INPUT_METHOD) {
            getDisplayContent().mDividerControllerLocked.resetImeHideRequested();
        }
        return true;
    }
3.10:onFirstWindowDrawn
    void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
        firstWindowDrawn = true;
        // We now have a good window to show, remove dead placeholders
        removeDeadWindows();
        if (startingWindow != null) {
            win.cancelAnimation();//取消動(dòng)畫(huà)播放
        }
        removeStartingWindow();//移除啟動(dòng)窗口
        updateReportedVisibilityLocked();//更新上報(bào)可見(jiàn)性
    }
3.11:removeStartingWindow
 void removeStartingWindow() {
        if (startingWindow == null) {
            if (mStartingData != null) {
                mStartingData = null;
            }
            return;
        }
        final WindowManagerPolicy.StartingSurface surface;
        if (mStartingData != null) {
            surface = startingSurface;
            mStartingData = null;
            startingSurface = null;
            startingWindow = null;
            startingDisplayed = false;
            if (surface == null) {
                return;
            }
        } else {
            return;
        }
        mWmService.mAnimationHandler.post(() -> {
            try {
                surface.remove();//surface是SplashScreenSurface
            } catch (Exception e) {
                Slog.w(TAG_WM, "Exception when removing starting window", e);
            }
        });
    }
3.12:remove
    @Override
    public void remove() {
        final WindowManager wm = mView.getContext().getSystemService(WindowManager.class);
        wm.removeView(mView);//直接移除DecorView
    }

我們從上面可以看到啟動(dòng)窗口的添加和移除是在android.anim線(xiàn)程中完成,添加的邏輯主要是創(chuàng)建一個(gè)PhoneWindow,然后將PhoneWindow的DecorView添加到窗口管理器,移除則是直接removeDecorView來(lái)完成的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 你說(shuō)你想喝酒 就叫了幾個(gè)朋友 找了一張小桌 要了幾個(gè)小菜 推杯換盞 討論起了民主自由 我雖然不能喝酒 但我喜歡吃花...
    王根云閱讀 260評(píng)論 0 2
  • 各位小仙女,你們覺(jué)得森田面膜好用嗎?清楚的來(lái)點(diǎn)評(píng)一下,我這段時(shí)間皮膚挺干燥的,想找個(gè)好點(diǎn)的面膜敷一敷,在網(wǎng)上看了一...
    90斤不是夢(mèng)閱讀 277評(píng)論 0 0
  • 《千與千尋》里有條小白龍,叫做白先生。為了學(xué)魔法來(lái)到湯屋當(dāng)了湯婆婆的助手,被收走了名字,一輩子為湯婆婆賣(mài)命卻不自知...
    帆_船閱讀 117評(píng)論 0 1

友情鏈接更多精彩內(nèi)容