publicclassWindowManagerServiceextendsIWindowManager.StubimplementsWatchdog.Monitor,WindowManagerPolicy.WindowManagerFuncs{privatestaticfinalStringTAG=TAG_WITH_CLASS_NAME?"WindowManagerService":TAG_WM;finalDisplaySettingsmDisplaySettings;finalDisplayManagerInternalmDisplayManagerInternal;finalDisplayManagermDisplayManager;privatefinalDisplay[]mDisplays;// The root of the device window hierarchy.RootWindowContainermRoot;privateWindowManagerService(Contextcontext,InputManagerServiceinputManager,booleanhaveInputMethods,booleanshowBootMsgs,booleanonlyCore,WindowManagerPolicypolicy){mRoot=newRootWindowContainer(this);mDisplayManagerInternal=LocalServices.getService(DisplayManagerInternal.class);mDisplaySettings=newDisplaySettings();mDisplaySettings.readSettingsLocked();mDisplayManager=(DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);mDisplays=mDisplayManager.getDisplays();for(Displaydisplay:mDisplays){createDisplayContentLocked(display);}}// TODO: All the display method below should probably be moved into the RootWindowContainer...privatevoidcreateDisplayContentLocked(finalDisplaydisplay){if(display==null){thrownewIllegalArgumentException("getDisplayContent: display must not be null");}mRoot.getDisplayContentOrCreate(display.getDisplayId());}}
RootWindowContainer
/** Root {@link WindowContainer} for the device. */classRootWindowContainerextendsWindowContainer<DisplayContent>{privatestaticfinalStringTAG=TAG_WITH_CLASS_NAME?"RootWindowContainer":TAG_WM;WindowManagerServicemService;RootWindowContainer(WindowManagerServiceservice){mService=service;mHandler=newMyHandler(service.mH.getLooper());}/**
* Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
* there is a Display for the displayId.
*
* @param displayId The display the caller is interested in.
* @return The DisplayContent associated with displayId or null if there is no Display for it.
*/DisplayContentgetDisplayContentOrCreate(intdisplayId){DisplayContentdc=getDisplayContent(displayId);if(dc==null){finalDisplaydisplay=mService.mDisplayManager.getDisplay(displayId);if(display!=null){finallongcallingIdentity=Binder.clearCallingIdentity();try{dc=createDisplayContent(display);}finally{Binder.restoreCallingIdentity(callingIdentity);}}}returndc;}DisplayContentgetDisplayContent(intdisplayId){for(inti=mChildren.size()-1;i>=0;--i){finalDisplayContentcurrent=mChildren.get(i);if(current.getDisplayId()==displayId){returncurrent;}}returnnull;}privateDisplayContentcreateDisplayContent(finalDisplaydisplay){finalDisplayContentdc=newDisplayContent(display,mService,mLayersController,mWallpaperController);finalintdisplayId=display.getDisplayId();if(DEBUG_DISPLAY)Slog.v(TAG_WM,"Adding display="+display);finalDisplayInfodisplayInfo=dc.getDisplayInfo();finalRectrect=newRect();//获得Overscan的区域, 这个是配置的 /data/system/display_settings.xmlmService.mDisplaySettings.getOverscanLocked(displayInfo.name,displayInfo.uniqueId,rect);displayInfo.overscanLeft=rect.left;displayInfo.overscanTop=rect.top;displayInfo.overscanRight=rect.right;displayInfo.overscanBottom=rect.bottom;if(mService.mDisplayManagerInternal!=null){mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(displayId,displayInfo);mService.configureDisplayPolicyLocked(dc);// Tap Listeners are supported for:// 1. All physical displays (multi-display).// 2. VirtualDisplays that support virtual touch input. (Only VR for now)// TODO(multi-display): Support VirtualDisplays with no virtual touch input.if((display.getType()!=Display.TYPE_VIRTUAL||(display.getType()==Display.TYPE_VIRTUAL// Only VR VirtualDisplays&&displayId==mService.mVr2dDisplayId))&&mService.canDispatchPointerEvents()){if(DEBUG_DISPLAY){Slog.d(TAG,"Registering PointerEventListener for DisplayId: "+displayId);}// 注册鼠标按键事件监听dc.mTapDetector=newTaskTapPointerEventListener(mService,dc);mService.registerPointerEventListener(dc.mTapDetector);if(displayId==DEFAULT_DISPLAY){mService.registerPointerEventListener(mService.mMousePositionTracker);}}}returndc;}}
DisplayContent
classDisplayContentextendsWindowContainer<DisplayContent.DisplayChildWindowContainer>{privatestaticfinalStringTAG=TAG_WITH_CLASS_NAME?"DisplayContent":TAG_WM;/** Unique identifier of this stack. */privatefinalintmDisplayId;privatefinalDisplayInfomDisplayInfo=newDisplayInfo();privatefinalDisplaymDisplay;// 屏幕上显示的普通应用界面/** The containers below are the only child containers the display can have. */// Contains all window containers that are related to apps (Activities)privatefinalTaskStackContainersmTaskStackContainers=newTaskStackContainers();// 在应用界面上显示的window// Contains all non-app window containers that should be displayed above the app containers// (e.g. Status bar)privatefinalNonAppWindowContainersmAboveAppWindowsContainers=newNonAppWindowContainers("mAboveAppWindowsContainers");// 在界面下显示的window// Contains all non-app window containers that should be displayed below the app containers// (e.g. Wallpaper).privatefinalNonAppWindowContainersmBelowAppWindowsContainers=newNonAppWindowContainers("mBelowAppWindowsContainers");// 输入法window// Contains all IME window containers. Note that the z-ordering of the IME windows will depend// on the IME target. We mainly have this container grouping so we can keep track of all the IME// window containers together and move them in-sync if/when needed.privatefinalNonAppWindowContainersmImeWindowsContainers=newNonAppWindowContainers("mImeWindowsContainers");WindowManagerServicemService;// Mapping from a token IBinder to a WindowToken object on this display.privatefinalHashMap<IBinder,WindowToken>mTokenMap=newHashMap();/** Detect user tapping outside of current focused task bounds .*/TaskTapPointerEventListenermTapDetector;DisplayContent(Displaydisplay,WindowManagerServiceservice,WindowLayersControllerlayersController,WallpaperControllerwallpaperController){mDisplay=display;mDisplayId=display.getDisplayId();// These are the only direct children we should ever have and they are permanent.super.addChild(mBelowAppWindowsContainers,null);super.addChild(mTaskStackContainers,null);super.addChild(mAboveAppWindowsContainers,null);super.addChild(mImeWindowsContainers,null);// Add itself as a child to the root container.mService.mRoot.addChild(this,null);// TODO(b/62541591): evaluate whether this is the best spot to declare the// {@link DisplayContent} ready for use.mDisplayReady=true;// These are the only direct children we should ever have and they are permanent.super.addChild(mBelowAppWindowsContainers,null);super.addChild(mTaskStackContainers,null);super.addChild(mAboveAppWindowsContainers,null);super.addChild(mImeWindowsContainers,null);// Add itself as a child to the root container.mService.mRoot.addChild(this,null);// TODO(b/62541591): evaluate whether this is the best spot to declare the// {@link DisplayContent} ready for use.mDisplayReady=true;}/**
* Base class for any direct child window container of {@link #DisplayContent} need to inherit
* from. This is mainly a pass through class that allows {@link #DisplayContent} to have
* homogeneous children type which is currently required by sub-classes of
* {@link WindowContainer} class.
*/staticclassDisplayChildWindowContainer<EextendsWindowContainer>extendsWindowContainer<E>{intsize(){returnmChildren.size();}Eget(intindex){returnmChildren.get(index);}@OverridebooleanfillsParent(){returntrue;}@OverridebooleanisVisible(){returntrue;}}/**
* Window container class that contains all containers on this display relating to Apps.
* I.e Activities.
*/privatefinalclassTaskStackContainersextendsDisplayChildWindowContainer<TaskStack>{/**
* Adds the stack to this container.
* @see WindowManagerService#addStackToDisplay(int, int, boolean)
*/voidaddStackToDisplay(TaskStackstack,booleanonTop){if(stack.mStackId==HOME_STACK_ID){if(mHomeStack!=null){thrownewIllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");}mHomeStack=stack;}addChild(stack,onTop);stack.onDisplayChanged(DisplayContent.this);}/** Removes the stack from its container and prepare for changing the parent. */voidremoveStackFromDisplay(TaskStackstack){removeChild(stack);stack.onRemovedFromDisplay();}}}
publicfinalclassDisplayManagerGlobal{privatestaticfinalStringTAG="DisplayManager";privatefinalSparseArray<DisplayInfo>mDisplayInfoCache=newSparseArray<DisplayInfo>();/**
* Gets an instance of the display manager global singleton.
*
* @return The display manager instance, may be null early in system startup
* before the display manager has been fully initialized.
*/publicstaticDisplayManagerGlobalgetInstance(){synchronized(DisplayManagerGlobal.class){if(sInstance==null){IBinderb=ServiceManager.getService(Context.DISPLAY_SERVICE);if(b!=null){sInstance=newDisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));}}returnsInstance;}}publicvoidaddView(Viewview,ViewGroup.LayoutParamsparams,Displaydisplay,WindowparentWindow){------------------------------------------------------------------root=newViewRootImpl(view.getContext(),display);-----------------------------------------------------------------}/**
* Get information about a particular logical display.
*
* @param displayId The logical display id.
* @return Information about the specified display, or null if it does not exist.
* This object belongs to an internal cache and should be treated as if it were immutable.
*/publicDisplayInfogetDisplayInfo(intdisplayId){try{synchronized(mLock){DisplayInfoinfo;if(USE_CACHE){info=mDisplayInfoCache.get(displayId);if(info!=null){returninfo;}}info=mDm.getDisplayInfo(displayId);if(info==null){returnnull;}if(USE_CACHE){mDisplayInfoCache.put(displayId,info);}registerCallbackIfNeededLocked();if(DEBUG){Log.d(TAG,"getDisplayInfo: displayId="+displayId+", info="+info);}returninfo;}}catch(RemoteExceptionex){throwex.rethrowFromSystemServer();}}/**
* Gets information about a logical display.
*
* The display metrics may be adjusted to provide compatibility
* for legacy applications or limited screen areas.
*
* @param displayId The logical display id.
* @param resources Resources providing compatibility info.
* @return The display object, or null if there is no display with the given id.
*/publicDisplaygetCompatibleDisplay(intdisplayId,Resourcesresources){DisplayInfodisplayInfo=getDisplayInfo(displayId);if(displayInfo==null){returnnull;}returnnewDisplay(this,displayId,displayInfo,resources);}}
DMS Display
DisplayManagerService
publicfinalclassDisplayManagerServiceextendsSystemService{privatestaticfinalStringTAG="DisplayManagerService";// List of all logical displays indexed by logical display id.privatefinalSparseArray<LogicalDisplay>mLogicalDisplays=newSparseArray<LogicalDisplay>();@VisibleForTestingfinalclassBinderServiceextendsIDisplayManager.Stub{/**
* Returns information about the specified logical display.
*
* @param displayId The logical display id.
* @return The logical display info, or null if the display does not exist. The
* returned object must be treated as immutable.
*/@Override// Binder callpublicDisplayInfogetDisplayInfo(intdisplayId){finalintcallingUid=Binder.getCallingUid();finallongtoken=Binder.clearCallingIdentity();try{returngetDisplayInfoInternal(displayId,callingUid);}finally{Binder.restoreCallingIdentity(token);}}}privateDisplayInfogetDisplayInfoInternal(intdisplayId,intcallingUid){synchronized(mSyncRoot){LogicalDisplaydisplay=mLogicalDisplays.get(displayId);if(display!=null){DisplayInfoinfo=display.getDisplayInfoLocked();if(info.hasAccess(callingUid)||isUidPresentOnDisplayInternal(callingUid,displayId)){returninfo;}}returnnull;}}}
ViewRootImpl
publicfinalclassViewRootImplimplementsViewParent,View.AttachInfo.Callbacks,ThreadedRenderer.DrawCallbacks{@NonNullDisplaymDisplay;finalDisplayManagermDisplayManager;publicViewRootImpl(Contextcontext,Displaydisplay){mDisplay=display;mDisplayManager=(DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);}publicvoidsetView(Viewview,WindowManager.LayoutParamsattrs,ViewpanelParentView){synchronized(this){if(mView==null){mView=view;mAttachInfo.mDisplayState=mDisplay.getState();mDisplayManager.registerDisplayListener(mDisplayListener,mHandler);}}}privatefinalDisplayListenermDisplayListener=newDisplayListener(){@OverridepublicvoidonDisplayChanged(intdisplayId){if(mView!=null&&mDisplay.getDisplayId()==displayId){finalintoldDisplayState=mAttachInfo.mDisplayState;finalintnewDisplayState=mDisplay.getState();if(oldDisplayState!=newDisplayState){mAttachInfo.mDisplayState=newDisplayState;pokeDrawLockIfNeeded();if(oldDisplayState!=Display.STATE_UNKNOWN){finalintoldScreenState=toViewScreenState(oldDisplayState);finalintnewScreenState=toViewScreenState(newDisplayState);if(oldScreenState!=newScreenState){mView.dispatchScreenStateChanged(newScreenState);}if(oldDisplayState==Display.STATE_OFF){// Draw was suppressed so we need to for it to happen here.mFullRedrawNeeded=true;scheduleTraversals();}}}}}}}
trace
D/MMM: getCompatibleDisplay-----2----: DisplayInfo{"内置屏幕", uniqueId "local:0", app 1200 x 1848, real 1200 x 1920, largest app 1920 x 1812, smallest app 1200 x 1092, mode 1, defaultMode 1, modes [{id=1, width=1200, height=1920, fps=60.000004}], colorMode 0, supportedColorModes [0], hdrCapabilities android.view.Display$HdrCapabilities@40f16308, rotation 0, density 240 (320.842 x 320.842) dpi, layerStack 0, appVsyncOff 1000000, presDeadline 16666666, type BUILT_IN, state ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, removeMode 0}
java.lang.Throwable
at android.hardware.display.DisplayManagerGlobal.getCompatibleDisplay(DisplayManagerGlobal.java:187)
at android.app.ResourcesManager.getAdjustedDisplay(ResourcesManager.java:274)
at android.app.ResourcesManager.getDisplayMetrics(ResourcesManager.java:206)
at android.app.ResourcesManager.createResourcesImpl(ResourcesManager.java:512)
at android.app.ResourcesManager.getOrCreateResources(ResourcesManager.java:804)
at android.app.ResourcesManager.createBaseActivityResources(ResourcesManager.java:733)
at android.app.ContextImpl.createActivityContext(ContextImpl.java:2384)
at android.app.ActivityThread.createBaseContextForActivity(ActivityThread.java:3037)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2866)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3087)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1817)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6746)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)