当前位置:网站首页>Window management learn more about windowmanagerservice

Window management learn more about windowmanagerservice

2022-06-11 10:32:00 Smile and see the exit

I have already introduced WindowManage( To understand all aspects WindowManager), Today let's get to know WindowManager The manager of WMS, stay Android In the system , Managing all windows in the system is a window management service WindowManagerService Responsibility for .

You can know App From Startup to main window display , Main needs AppActivityManagerServiceWindowManagerService and SurfaceFlinger Wait for these modules to cooperate with each other .

Among these App Mainly responsible for business logic , Draw view ,AMS Responsible for managing component and process information and stack information ,WMS Responsible for managing the Activity Windows, sub windows and system windows ,SF Is used to manage the graphics buffer , Render the screen . This analysis is based on Android 10.0 On .

One 、WMS The birth of

just as AMS equally ,WMS Also in SystemServer Of main() Born in :

public static void main(String[] args) {
    
        new SystemServer().run();
    }

private void run() {
    
  ......
  //  Opening service .
        try {
    
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
    
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
    
            traceEnd();
        }
  ......
}

As can be seen from the above , Created a SystemServer Object will be called run Method . Three types of system services will be enabled in the method , They are guided services , Core services and other services , and WMS It is a kind of other services .

Then let's take a look WMS stay startOtherService How to produce :

private void startOtherServices() {
    
 ......
  // Code 1
  wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
  ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
  ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    traceEnd();

    traceBeginAndSlog("SetWindowManagerService");
  // Code 2
    mActivityManagerService.setWindowManager(wm);
    traceEnd();

    traceBeginAndSlog("WindowManagerServiceOnInitReady");
  // Code 3
            wm.onInitReady();
  ......
    // Code 4
    try {
    
            wm.displayReady();
        } catch (Throwable e) {
    
            reportWtf("making display ready", e);
        }
  ......
    // Code 5
    try {
    
            wm.systemReady();
        } catch (Throwable e) {
    
            reportWtf("making Window Manager Service ready", e);
        }
}

In the code 1 It's about , call WindowManagerServiice.main() establish wms object , And add the object to ServiceManager in , Code 2 It's about , by AMS Set up wms, Then in the code 3 And code 4 Initialize the display information in , In the code 5 Chu Hong ou, come and beat up your senses wms, The initialization of the system has been completed , Internally it will call mPolicy.systemReady Method .

As you can see from the above, when wms Of main Method time , Will create wms Examples come out :

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);
    }

 public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
    
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                        atm, transactionFactory), 0);
        return sInstance;
    }

stay main In the method , Will use DisplayThread.getHandle Of runWithSciissors Method , explain WMS The creation of is run on android.display In the thread .

DisplayThread A thread is a system foreground thread , It is used to perform some operations on the display with a very small delay

stay Handle Of runWithScissors In the method :

public final boolean runWithScissors(final Runnable r, long timeout) {
    
        ......

        if (Looper.myLooper() == mLooper) {
    
            r.run();
            return true;
        }

        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }

Here we will judge whether it is current looper, there looper It also means whether you are in android.display in . When if not , Will be runnable The incoming to BlockingRunnable, And implement postAndWait Method .

    private static final class BlockingRunnable implements Runnable {
    
        private final Runnable mTask;
        private boolean mDone;

        public BlockingRunnable(Runnable task) {
    
            mTask = task;
        }

        @Override
        public void run() {
    
            try {
    
                mTask.run();
            } finally {
    
                synchronized (this) {
    
                    mDone = true;
                    notifyAll();
                }
            }
        }

        public boolean postAndWait(Handler handler, long timeout) {
    
            if (!handler.post(this)) {
    
                return false;
            }

            synchronized (this) {
    
                if (timeout > 0) {
    
                    final long expirationTime = SystemClock.uptimeMillis() + timeout;
                    while (!mDone) {
    
                        long delay = expirationTime - SystemClock.uptimeMillis();
                        if (delay <= 0) {
    
                            return false; // timeout
                        }
                        try {
    
                            wait(delay);
                        } catch (InterruptedException ex) {
    
                        }
                    }
                } else {
    
                    while (!mDone) {
    
                        try {
    
                            wait();
                        } catch (InterruptedException ex) {
    
                        }
                    }
                }
            }
            return true;
        }
    }
}

stay postAndWait In the method , stay mDone Not set to trrue when , It keeps the thread waiting , until run Method is executed . Love will be set up at this time mDone by true, And at the same time notifyAll Wake up the thread . It can also be seen from here wms The priority of creating will be higher .

Then it will be executed to wms Construction method of , The construction method is very long, so we intercept some key points :

private WindowManagerService(Context context, InputManagerService inputManager,
            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
    
  			......   
        // Code 1
  			mPolicy = policy;
  
  			// Code 2
        mAnimator = new WindowAnimator(this);
        mRoot = new RootWindowContainer(this);

        mWindowPlacerLocked = new WindowSurfacePlacer(this);
        mTaskSnapshotController = new TaskSnapshotController(this);

        mWindowTracing = WindowTracing.createDefaultAndStartLooper(this,
                Choreographer.getInstance());

        LocalServices.addService(WindowManagerPolicy.class, mPolicy);
  
  			......
  			// Code 3
  		  mActivityManager = ActivityManager.getService();
        mActivityTaskManager = ActivityTaskManager.getService();
  
  
}

In the code 1 It's about ,mPolicy The object is wms It plays a very important role in , It's an interface ,WMS The operations in are wmp What to do with . And its real implementation class is PhoneWindowManager,PhoneWindowManager The processing thread is in ui In the thread .

Two 、WMS Key members

name meaning
mPolicy: WiindoowMangerPolicy Is the interface class of window management policy , It is used to define the general specification to be followed by a window
mSessions: ArraySet It is mainly used for inter process communication , Other application processes need to work with WMS Process communication needs to go through Session, Each application process corresponds to a Session, To save it is to record all the records to WMS The client of window management service is proposed .
mWindowMap:WindowHashMapkey The corresponding value is IBinder,value The corresponding value is WindowState.Window Is a window in window management
mAnimator:WindowAnimatorwindowAnimatoor Variable of type , Used to manage window animation and special effects animation
mH:H Systematic Handler, Used to add tasks to the message queue of the main thread

3、 ... and 、WMS The process of adding

From above ViewRootImpl Calling setView Method addToDisplay Method , It will be called internally again WMS Of addWindow Method and put itself, that is Session It's coming in , Let's go straight to WindowManagerService Of addWindow Method :

 public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
            InsetsState outInsetsState) {
    
       ......
   
         synchronized (mGlobalLock) {
    
         //WindowToken Convert to... Specific to the application window AppWindowToken
            AppWindowToken atoken = null;
         // Use the existing parent password card for the child window , Because they have the same token as the parent window , So we can apply the same strategy to them 
         		WindowToken token = displayContent.getWindowToken(
                    hasParent ? parentWindow.mAttrs.token : attrs.token);
         
         // If it doesn't exist token
         if (token == null) {
    
           // If it is Appliation Type of window ,  Don't allow WindowToken by null
           if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
    
                    Slog.w(TAG_WM, "Attempted to add application window with unknown token "
                          + attrs.token + ". Aborting.");
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
           .......
         }
         
         // establish WindowState
          final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], seq, attrs, viewVisibility, session.mUid,
                    session.mCanAddInternalSystemWindow);
         
         // establish InputChanel, be used for Input Reception and transmission of information 
         final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
    
                win.openInputChannel(outInputChannel);
            }
         
         // take WindowState Add to windowMap in 
         		win.attach();
            mWindowMap.put(client.asBinder(), win);

            win.initAppOpsState();
         // take WindowState Object added to WindowToken in ,WindowToken Will serve as a WindowState Parent container of 
         win.mToken.addWindow(win);
        .....
          // Create window animation 
           final WindowStateAnimator winAnimator = win.mWinAnimator;
            winAnimator.mEnterAnimationPending = true;
            winAnimator.mEnteringAnimation = true;
         
         // If you can get the focus , Update the focus window 
         		boolean focusChanged = false;
            if (win.canReceiveKeys()) {
    
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
    
                    imMayMove = false;
                }
            }
         
         // Update input  Window
         if (focusChanged) {
    
                displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                        false /*updateInputWindows*/);
            }
         
            displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);

            ......
              
					// If the direction is updated , Update the global configuration 
            if (win.isVisibleOrAdding() && displayContent.updateOrientationFromAppTokens()) {
    
                reportNewConfig = true;
            }
         ......
       }
   
 }

stay addWindow A lot of checks have been done in the , The main work is as follows :

  1. Check all window types , If you are not satisfied, you will not carry out
  2. Yes windowToken Trace processing , If not, a new one will be created WindowToken
  3. establish windowState object , And with WindowToken Related to , Give Way WindowToken Become WindowStae Object's parent container
  4. Update focus window and update InputWindow

3.1 WindowToken establish

​ WindowToken The role in it is as WindowState Parent container of , Responsible for managing a group of Window. Its construction method is as follows :

WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,
            DisplayContent dc, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {
    
        super(service);
  // assignment IBinder object 
        token = _token;
  // Window type 
        windowType = type;  
  // Whether it is explicitly added WindowToken
        mPersistOnEmpty = persistOnEmpty;  
        mOwnerCanManageAppTokens = ownerCanManageAppTokens;
        mRoundedCornerOverlay = roundedCornerOverlay;
        onDisplayChanged(dc);
    }

void onDisplayChanged(DisplayContent dc) {
    
  // Add the object to DisplayContent in 
        dc.reParentWindowToken(this);
        super.onDisplayChanged(dc);
    }

After doing some property initialization , take WindowToken Passed on to DisplayContent, Finally put token Saved to DisplayContent#mToken in .

//DisplayContent.java
void reParentWindowToken(WindowToken token) {
    
        final DisplayContent prevDc = token.getDisplayContent();
        if (prevDc == this) {
    
            return;
        }
        ......

        addWindowToken(token.token, token);
    }

private void addWindowToken(IBinder binder, WindowToken token) {
    
  //  If it's time to WindowToken Has been associated with DisplayContent object , You can no longer associate other DisplayContent object 
        final DisplayContent dc = mWmService.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);
        }

  // take WindowToken Add to DisplayContent Of TokenMap in 
        mTokenMap.put(binder, token);

  // For not Activity Type of window , Will be based on Window Type is added to the corresponding three container China 
        if (token.asAppWindowToken() == null) {
    
            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;
            }
        }
    }

Come here WindowToken The object is created .

3.2 WindowState establish

WindowToken Manages the windowState, Every WindowState Represents a specific Window, Add one at a time Window The corresponding one will be created windowState, Its construction method is as follows :

//WindowStae 
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
    
        super(service);
        mSession = s;
        mClient = c;
        mAppOp = appOp;
        mToken = token;
        mAppToken = mToken.asAppWindowToken();
       ......

        mWinAnimator = new WindowStateAnimator(this);
        mWinAnimator.mAlpha = a.alpha;

        mRequestedWidth = 0;
        mRequestedHeight = 0;
        mLastRequestedWidth = 0;
        mLastRequestedHeight = 0;
        mLayer = 0;
        mInputWindowHandle = new InputWindowHandle(
                mAppToken != null ? mAppToken.mInputApplicationHandle : null, c,
                    getDisplayId());
    }

It creates WindowStateAnimator, Actually used for WindowState Object to animate and Surface Transformation related operations , In the process of drawing , Animation status and surface The status of the object will be recorded by the object .

from addWindow Methods we learned that WMS Yes 3 Two important classes are WindowToken、WindowState and DisplayContent

Four 、 Summary

stay WMS in ,WindowState Represents a window ,WIndowToken As WIndowState Parent container of , Managing a set of windows . Through wms Of addWindow After the method , You create a relative to system_server Window management object of .

Reference resources

Android analysis WindowManagerService( One )WMS The birth of

In depth understanding of WindowManagerService

WMS— The boot process

原网站

版权声明
本文为[Smile and see the exit]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/162/202206111027099093.html