WMSWindowManagerService of Android 11.0 source code series

Posted by errorCode30 on Mon, 17 Jan 2022 03:07:56 +0100

Main codes involved in this chapter:

frameworks\base\services\core\java\com\android\server\SystemServer.java

frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java

frameworks\base\services\core\java\com\android\server\wm\WindowAnimator.java

frameworks\base\services\core\java\com\android\server\AnimationThread.java

frameworks\base\core\java\android\view\Choreographer.java

frameworks\base\services\core\java\com\android\server\wm\RootWindowContainer.java

frameworks\base\services\core\java\com\android\server\wm\SurfaceAnimationRunner.java

frameworks\base\services\core\java\com\android\server\wm\SurfaceAnimationThread.java

As we all know, Android system framework provides many system services, such as AMS (ActivityManagerService) for managing four components, WMS (WindowManagerService) for managing windows, PMS (PackageManagerService) for managing application installation, uninstallation and update, IMS (InputManagerService) for managing input events and input devices, etc. This series will be based on Android 11.0.0_ The R1 code interprets these services one by one from top to bottom (Java - > JNI - > native) in order to deepen the understanding of the whole Android architecture, understand the operation principle of each component in the framework layer, and lay a solid foundation for in-depth performance analysis / system optimization / architecture design in the future.

1.1 creation of windowmanagerservice

Like InputManagerService, WindowManagerService is also created by system server in the start other services stage and added to ServiceManager with window as the alias;

[-> SystemServer.java]

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    InputManagerService inputManager = null;
    // Initialize InputManagerService
    inputManager = new InputManagerService(context);

    WindowManagerService wm = null;
    // Initialize WindowManagerService [see section 1.2]
    wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
            new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
    // Add windowmanagerservice to ServiceManager
    ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
            DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);

    // Save WindowManagerService to AMS and ATMS
    mActivityManagerService.setWindowManager(wm);
    // WindowManagerService initialization [see Section 1.3]
    wm.onInitReady();

    // Setting WindowManagerCallbacks for InputManagerService
    inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());

    try {
        // Update Display related configuration [see section 1.4]
        wm.displayReady();
    } catch (Throwable e) {
        reportWtf("making display ready", e);
    }
    
    try {
        // System startup completed [see subsection 1.5]
        wm.systemReady();
    } catch (Throwable e) {
        reportWtf("making Window Manager Service ready", e);
    }
    
    // Update the configuration for this context by hand, because we're going
    // to start using it before the config change done in wm.systemReady() will
    // propagate to it.
    final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
    DisplayMetrics metrics = new DisplayMetrics();
    context.getDisplay().getMetrics(metrics);
    context.getResources().updateConfiguration(config, metrics);    
}

1.2 construction of windowmanagerservice

[-> WindowManagerService.java]

public static WindowManagerService main(final Context context, final InputManagerService im,
        final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm) {
    return main(context, im, showBootMsgs, onlyCore, policy, atm,
            SurfaceControl.Transaction::new, Surface::new, SurfaceControl.Builder::new);
}

main will pass in InputManagerService and ActivityTaskManagerService, where ActivityTaskManagerService is created in the startBootstrapServices phase;

As the implementation class of WindowManagerPolicy, PhoneWindowManager is mainly used for window policy management;

SurfaceControl.Transaction and Surface generate suppliers through lambda expressions to return corresponding instances;

SurfaceControl. The builder generates a Function through a lambda expression, receives the SurfaceSession parameter and returns surfacecontrol Builder instance;

public static WindowManagerService main(final Context context, final InputManagerService im,
        final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
        Supplier<Surface> surfaceFactory,
        Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
    DisplayThread.getHandler().runWithScissors(() ->
            sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                    atm, transactionFactory, surfaceFactory, surfaceControlFactory), 0);
    return sInstance;
}

Currently system_server main thread, through runWithScissors on Android The display thread creates WindowManagerService: runWithScissors, which is different from the normal post method in that it is synchronous: if the current thread is the same thread as the Handler's thread, the Runnable will be executed directly; otherwise, the Runnable will be posted to the message queue of the Handler's thread, and then wait for its completion through wait(). If the Runnable is executed, it will be returned directly. Otherwise, it will be blocked, The purpose of this is that WindowManagerService is the manager of the graphical window. If it is not started and completed, the subsequent work is impossible. Therefore, it must be blocked synchronously until it completes the initialization structure;

/** Global service lock used by the package the owns this service. */
final WindowManagerGlobalLock mGlobalLock;
final InputManagerService mInputManager;
final DisplayManagerInternal mDisplayManagerInternal;
final DisplayManager mDisplayManager;
final ActivityTaskManagerService mAtmService;

WindowManagerPolicy mPolicy;

Function<SurfaceSession, SurfaceControl.Builder> mSurfaceControlFactory;
Supplier<SurfaceControl.Transaction> mTransactionFactory;
final Supplier<Surface> mSurfaceFactory;
private final SurfaceControl.Transaction mTransaction;

// The root of the device window hierarchy.
RootWindowContainer mRoot;
final WindowAnimator mAnimator;
SurfaceAnimationRunner mSurfaceAnimationRunner;

private WindowManagerService(Context context, InputManagerService inputManager,
        boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
        Supplier<Surface> surfaceFactory,
        Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
    // system_ A lock shared by server, which is mainly used for ATMS and WMS
    mGlobalLock = atm.getGlobalLock();
    // Save ActivityTaskManagerService
    mAtmService = atm;
    // Save InputManagerService
    mInputManager = inputManager; // Must be before createDisplayContentLocked.
    // Get for system_ LocalService called inside server
    mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
    
    // Save Supplier and Function
    mSurfaceControlFactory = surfaceControlFactory;
    mTransactionFactory = transactionFactory;
    mSurfaceFactory = surfaceFactory;
    // Get surfacecontrol Transaction instance
    mTransaction = mTransactionFactory.get();

    // Save PhoneWindowManager
    mPolicy = policy;
    // Create WindowAnimator [see section 1.2.1]
    mAnimator = new WindowAnimator(this);
    // Create RootWindowContainer [see section 1.2.2]
    mRoot = new RootWindowContainer(this);

    // Using PhoneWindowManager with system_server internal call
    LocalServices.addService(WindowManagerPolicy.class, mPolicy);
    // Get DisplayManager
    mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

    // Create a surface automation runner [see section 1.2.3]
    mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
            mPowerManagerInternal);

    // Use the internal class LocalService for system_server internal call
    LocalServices.addService(WindowManagerInternal.class, new LocalService());
}

The constructor of WindowManagerService mainly creates classes related to window animation, window management, Surface management, etc;

1.2.1 creation of windowanimator

[-> WindowAnimator.java]

/**
 * Singleton class that carries out the animations and Surface operations in a separate task
 * on behalf of WindowManagerService.
 */
public class WindowAnimator {
    final Choreographer.FrameCallback mAnimationFrameCallback;
    
    private Choreographer mChoreographer;
    
    WindowAnimator(final WindowManagerService service) {
        // Call the mmanimationhandler of WindowManagerService to obtain the Choreographer synchronously [see section 1.2.1.1]
        service.mAnimationHandler.runWithScissors(
                // Get SF Choreographer [see section 1.2.1.2]
                () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
        // Implement FrameCallback interface
        mAnimationFrameCallback = frameTimeNs -> {
            synchronized (mService.mGlobalLock) {
                mAnimationFrameCallbackScheduled = false;
                animate(frameTimeNs);
                if (mNotifyWhenNoAnimation && !mLastRootAnimating) {
                    mService.mGlobalLock.notifyAll();
                }
            }
        };
    }
}

WindowAnimator is mainly used to perform window animation and Surface related operations on behalf of WindowManagerService in an independent thread: this separate thread is AnimationThread. At the same time, the execution of animation, like Input event (CALLBACK_INPUT) and interface rendering (CALLBACK_TRAVERSAL), depends on the arrival of Vsync app signal and passes through CALLBACK_ANIMATION callback to execute;

1.2.1.1 creation of animationthread

[-> WindowManagerService.java]

/**
 * Handler for things to run that have direct impact on an animation, i.e. animation tick,
 * layout, starting window creation, whereas {@link H} runs things that are still important, but
 * not as critical.
 */
final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());

[-> AnimationThread.java]

/**
 * Thread for handling all legacy window animations, or anything that's directly impacting
 * animations like starting windows or traversals.
 */
public final class AnimationThread extends ServiceThread {
    private static AnimationThread sInstance;
    private static Handler sHandler;

    private AnimationThread() {
        super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    }
}

The animationhandler is bound to Android Anim thread, corresponding to Android anim. LF thread SurfaceAnimationThread;

1.2.1.2 acquisition of choreographer

[-> Choreographer.java]

// Thread local storage for the SF choreographer.
private static final ThreadLocal<Choreographer> sSfThreadInstance =
        new ThreadLocal<Choreographer>() {
            @Override
            protected Choreographer initialValue() {
                Looper looper = Looper.myLooper();
                if (looper == null) {
                    throw new IllegalStateException("The current thread must have a looper!");
                }
                return new Choreographer(looper, VSYNC_SOURCE_SURFACE_FLINGER);
            }
        };

public static Choreographer getSfInstance() {
    return sSfThreadInstance.get();
}

The difference between sSfThreadInstance stored through ThreadLocal and sThreadInstance is that it is used to listen to Vsync SF signal, while sThreadInstance is used to listen to Vsync app signal;

1.2.2 creation of rootwindowcontainer

[-> RootWindowContainer.java]

/** Root {@link WindowContainer} for the device. */
class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {
    ActivityStackSupervisor mStackSupervisor;
    
    // Only a separate transaction until we separate the apply surface changes
    // transaction from the global transaction.
    private final SurfaceControl.Transaction mDisplayTransaction;        
        
    private final Handler mHandler;        

    RootWindowContainer(WindowManagerService service) {
        super(service);
        mDisplayTransaction = service.mTransactionFactory.get();
        // Bind windowmanagerservice The thread of MH
        mHandler = new MyHandler(service.mH.getLooper());
        mService = service.mAtmService;
        mStackSupervisor = mService.mStackSupervisor;
        mStackSupervisor.mRootWindowContainer = this;
    }
    
}

As the root node of the window container in the tree structure, RootWindowContainer is used to save DisplayContent;

[-> WindowManagerService.java]

final H mH = new H();

mHandler and system_ The server main thread is bound to the same thread;

1.2.3 creation of surface automation runner

[-> SurfaceAnimationRunner.java]

/**
 * Class to run animations without holding the window manager lock.
 */
class SurfaceAnimationRunner {
    // Get Android Handler for anim thread
    private final Handler mAnimationThreadHandler = AnimationThread.getHandler();
    // Get Android anim. Handler for LF thread
    private final Handler mSurfaceAnimationHandler = SurfaceAnimationThread.getHandler();
    // Create AnimationHandler
    private final AnimationHandler mAnimationHandler;
    
    /**
     * There should only ever be one instance of this class. Usual spot for it is with
     * {@link WindowManagerService}
     */
    SurfaceAnimationRunner(Supplier<Transaction> transactionFactory,
            PowerManagerInternal powerManagerInternal) {
        this(null /* callbackProvider */, null /* animatorFactory */,
                transactionFactory.get(), powerManagerInternal);
    }

    @VisibleForTesting
    SurfaceAnimationRunner(@Nullable AnimationFrameCallbackProvider callbackProvider,
            AnimatorFactory animatorFactory, Transaction frameTransaction,
            PowerManagerInternal powerManagerInternal) {
        // On Android anim. LF thread gets Choreographer
        mSurfaceAnimationHandler.runWithScissors(() -> mChoreographer = getSfInstance(),
                0 /* timeout */);
        mFrameTransaction = frameTransaction;
        mAnimationHandler = new AnimationHandler();
        mAnimationHandler.setProvider(callbackProvider != null
                ? callbackProvider
                : new SfVsyncFrameCallbackProvider(mChoreographer));
        mAnimatorFactory = animatorFactory != null
                ? animatorFactory
                : SfValueAnimator::new;
        mPowerManagerInternal = powerManagerInternal;
    }
}

SurfaceAnimationRunner mainly creates SurfaceAnimationThread and AnimationHandler;

1.2.3.1 creation of surfaceanimationthread

[-> SurfaceAnimationThread.java]

/**
 * Thread for running {@link SurfaceAnimationRunner} that does not hold the window manager lock.
 */
public final class SurfaceAnimationThread extends ServiceThread {
    private static SurfaceAnimationThread sInstance;
    private static Handler sHandler;

    private SurfaceAnimationThread() {
        super("android.anim.lf", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    }

    private static void ensureThreadLocked() {
        // Creating a SurfaceAnimationThread in singleton mode
        if (sInstance == null) {
            sInstance = new SurfaceAnimationThread();
            sInstance.start();
            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
            sHandler = new Handler(sInstance.getLooper());
        }
    }
    
    public static Handler getHandler() {
        synchronized (SurfaceAnimationThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
    }    

Create Android anim. LF thread and provide its bound Handler;

1.3 initialization of windowmanagerservice

[-> WindowMangerService.java]

/**
 * Called after all entities (such as the {@link ActivityManagerService}) have been set up and
 * associated with the {@link WindowManagerService}.
 */
public void onInitReady() {
    // Initialize policy class
    initPolicy();

    // Add ourself to the Watchdog monitors.
    // WindowManagerService also implements watchdog Monitor interface
    Watchdog.getInstance().addMonitor(this);
    // Create window WaterMark processing class WaterMark
    createWatermark();
}
1.3.1 initialization of phonewindowmanager
private void initPolicy() {
    UiThread.getHandler().runWithScissors(new Runnable() {
        @Override
        public void run() {
            // WindowManagerPolicy is used to statically store the thread and Looper where WindowManagerService is located
            WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
            // PhoneWindowManager initialization [see section 1.3.1.1]
            mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
        }
    }, 0);
}

[-> PhoneWindowManager.java]

/** {@inheritDoc} */
@Override
public void init(Context context, IWindowManager windowManager,
        WindowManagerFuncs windowManagerFuncs) {
    mContext = context;
    mWindowManager = windowManager;
    mWindowManagerFuncs = windowManagerFuncs;
    mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
    mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
    mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
    mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
    mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
    mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);

    mHandler = new PolicyHandler();
    // Listening SettingsProvider
    mSettingsObserver = new SettingsObserver(mHandler);
    mSettingsObserver.observe();
    // Shortcut management class
    mShortcutManager = new ShortcutManager(context);
    // Desktop Intent
    mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
    mHomeIntent.addCategory(Intent.CATEGORY_HOME);
    mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

    // register for multiuser-relevant broadcasts
    // Registered user switched broadcast
    filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
    context.registerReceiver(mMultiuserReceiver, filter);

    // Controls rotation and the like.
    // Initialize hdmi related state
    initializeHdmiState();

    // Monitor the changes related to AppTransition and handle the lock screen
    mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
        @Override
        public int onAppTransitionStartingLocked(int transit, long duration,
                long statusBarAnimationStartTime, long statusBarAnimationDuration) {
            return handleStartTransitionForKeyguardLw(transit, duration);
        }

        @Override
        public void onAppTransitionCancelledLocked(int transit) {
            handleStartTransitionForKeyguardLw(transit, 0 /* duration */);
        }
    });
}

During initialization, PhoneWindowManager will mainly read system configuration, monitor user configuration, monitor system broadcast, etc;

1.3.2 WatchDog monitoring
// Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
@Override
public void monitor() {
    synchronized (mGlobalLock) { }
}

Check whether mGlobalLock is deadlocked;

1.4 Display configuration update

[-> WindowManagerService.java]

public void displayReady() {
    synchronized (mGlobalLock) {
        if (mMaxUiWidth > 0) {
            mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
        }
        applyForcedPropertiesForDefaultDisplay();
        mAnimator.ready();
        mDisplayReady = true;
        // Reconfigure all displays to make sure that forced properties and
        // DisplayWindowSettings are applied.
        mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
        mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_TOUCHSCREEN);
    }

    try {
        mActivityTaskManager.updateConfiguration(null);
    } catch (RemoteException e) {
    }
}

1.5 PHASE_SYSTEM_SERVICES_READY stage

[-> WindowManagerService.java]

public void systemReady() {
    mSystemReady = true;
    mPolicy.systemReady();
    mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
    mTaskSnapshotController.systemReady();
    mHasWideColorGamutSupport = queryWideColorGamutSupport();
    mHasHdrSupport = queryHdrSupport();
    UiThread.getHandler().post(mSettingsObserver::loadSettings);
    IVrManager vrManager = IVrManager.Stub.asInterface(
            ServiceManager.getService(Context.VR_SERVICE));
    if (vrManager != null) {
        try {
            final boolean vrModeEnabled = vrManager.getVrModeState();
            synchronized (mGlobalLock) {
                vrManager.registerListener(mVrStateCallbacks);
                if (vrModeEnabled) {
                    mVrModeEnabled = vrModeEnabled;
                    mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
                }
            }
        } catch (RemoteException e) {
            // Ignore, we cannot do anything if we failed to register VR mode listener
        }
    }
}

Topics: Java Android