Android 12系统源码_窗口管理(一)WindowManagerService的启动流程

news2024/11/28 3:02:52

前言

WindowManagerService是Android系统中重要的服务,它是WindowManager的管理者,WindowManagerService无论对于应用开发还是Framework开发都是重要的知识点,究其原因是因为WindowManagerService有很多职责,每个职责都会涉及重要且复杂的系统,这使得WindowManagerService就像一个十字路口的交通灯一样,没有了这个交通灯,十字路口就无法正常通车,WindowManagerService的职责只要有以下几点。

1)窗口管理
WindowManagerService是窗口的管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由WMS进行管理的。窗口管理的核心成员由DisplayContent、WindowToken和WindowState。
2)窗口动画
窗口间进行切换时,使用窗口动画可以显得更炫一些,窗口动画由WMS的动画子系统来负责,动画子系统的管理者为WindowAnimator。
3)输入系统的中转站
通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WindowManagerService是窗口的管理者,它作为输入系统的中转站再合适不过。
4)Surface管理
窗口并不具备绘制的功能,因此每个窗口都需要有一块Surface来供自己绘制,为每个窗口分配Surface时由WMS来完成的。
WindowManagerService的职责
从上图可以看出WindowManagerService很复杂,与它关联的有窗口管理、窗口动画、输入系统和Surface,它们每一个都是重要且负责的系统,在具体讲述这些功能之前,我们需要先梳理一下WindowManagerService的启动流程,这样才能更好的理解这个服务。

一、SystemServer的启动WindowManagerService

1、系统启动后会启动JVM虚拟机,SystemServer 是虚拟机的第一个进程,由init 进程fork 产生。主要用来启动frameworks层中的服务。SystemServer进程里面有个main()方法,main 方法如下:

frameworks/base/service/java/com/android/server/SystemServer.java

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

2、main 方法里启动了 run() 方法,而在 run 方法中调用了startOtherServices() 方法:

public final class SystemServer {
   private void run() {
    	...代码省略...
        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();
        }
    	...代码省略...
    }
}

3、startOtherServices方法和WindowManagerService服务启动相关的代码如下所示。

public final class SystemServer {
  
  private ActivityManagerService mActivityManagerService;
  private boolean mOnlyCore;
  private boolean mFirstBoot;

  private void startOtherServices() {
           ...代码省略...
           WindowManagerService wm = null;
           InputManagerService inputManager = null;
           ...代码省略...
           boolean isWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
           ...代码省略...
           traceBeginAndSlog("StartInputManagerService");
           inputManager = new InputManagerService(context);//创建InputManagerService
           traceEnd();
           traceBeginAndSlog("StartWindowManagerService");
           // WMS needs sensor service ready
           ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
           mSensorServiceStart = null;
           //执行WMS的main方法,其内部会创建WMS对象实例
           wm = WindowManagerService.main(context, inputManager,
                 mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                 !mFirstBoot, mOnlyCore, new PhoneWindowManager());
           //将WMS注册到服务管理器中        
           ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                 DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
           //将IMS注册到服务管理器中        
           ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                 /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
           traceEnd();
           traceBeginAndSlog("SetWindowManagerService");
           mActivityManagerService.setWindowManager(wm);
           traceEnd();
           traceBeginAndSlog("WindowManagerServiceOnInitReady");
           wm.onInitReady();//调用WMS的onInitReady方法
           traceEnd();
           ...代码省略...        
        try {
            wm.displayReady();//初始化屏幕显示信息
        } catch (Throwable e) {
            reportWtf("making display ready", e);
        }
          ...代码省略...      
       if (!isWatch) {
          traceBeginAndSlog("StartStatusBarManagerService");
           try {
                //状态栏管理服务
                statusBar = new StatusBarManagerService(context, wm);
                ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
            } catch (Throwable e) {
                reportWtf("starting StatusBarManagerService", e);
            }
            traceEnd();
        }
         ...代码省略...       
        try {
            wm.systemReady();//通知WMS,系统的初始化工作已经完成
        } catch (Throwable e) {
            reportWtf("making Window Manager Service ready", e);
        }
         ...代码省略...       
    }
}     

二、WindowManagerService的启动

1、WindowManagerService的main方法如下

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

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
        
    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
            WindowManagerPolicy policy) {
        DisplayThread.getHandler().runWithScissors(() ->
                //创建WMS对象实例
                sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                        onlyCore, policy), 0);
        return sInstance;
    }
}

DisplayThread的run方法中创建了WMS的实例,这就意味着WMS的创建是运行在android.display线程中的。
关于DisplayThread对象我们主要关注以下几点:
1)DisplayThread其实是一个名为android.display的单例前台线程。

frameworks/base/services/core/java/com/android/server/DisplayThread.java

public final class DisplayThread extends ServiceThread {
    private static DisplayThread sInstance;
    private static Handler sHandler;

    private DisplayThread() {
        super("android.display", Process.THREAD_PRIORITY_DISPLAY + 1, false /*allowIo*/);
    }

    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new DisplayThread();
            sInstance.start();
            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
            sHandler = new Handler(sInstance.getLooper());
        }
    }

    public static DisplayThread get() {
        synchronized (DisplayThread.class) {
            ensureThreadLocked();
            return sInstance;
        }
    }

    public static Handler getHandler() {
        synchronized (DisplayThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
    }
}

DisplayThread线程主要用来处理需要低延时显示的相关操作,并只能由WindowManager、DisplayManager和InputManager实时执行快速操作。
2)DisplayThread调用静态方法getHandler返回一个Handler对象实例,并调用了该对象的runWithScissors方法。

frameworks/base/core/java/android/os/Handler.java

public class Handler {
    public final boolean runWithScissors(final Runnable r, long timeout) {
        if (r == null) {
            throw new IllegalArgumentException("runnable must not be null");
        }
        //对传入的Runnable的timeout进行判断,如果Runnable为null或者timeout小于0则抛出异常。
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must be non-negative");
        }
		//根据每个线程只有一个Looper的原理来判断当前线程(system_server线程)是否是Handler所指向的线程(android.display线程),如果是则直接执行Runnable的run方法。
        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }
		//否则调用BlockingRunnable的postAndWait方法,并将当前线程的Runnable作为参数传递进去。
        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }
}

runWithScissors方法会对传入的Runnable的timeout进行判断,如果Runnable为null或者timeout小于0则抛出异常;并根据每个线程只有一个Looper的原理来判断当前线程(system_server线程)是否是Handler所指向的线程(android.display线程),如果是则直接执行Runnable的run方法;否则调用BlockingRunnable的postAndWait方法,并将当前线程的Runnable作为参数传递进去。

3)BlockingRunnable是Handler的内部类。

public class Handler {
 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 {
            	//执行传入的Runnable的run方法,其实就是执行前面创建WindowManagerService对象实例的那段代码
                mTask.run();
            } finally {
                synchronized (this) {
                    mDone = true;
                    notifyAll();
                }
            }
        }
		
        public boolean postAndWait(Handler handler, long timeout) {
			//将当前自己发送给Handler
            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 {
                            //timeout为0,且mDone为false,则会将当前自己挂起
                            wait();
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            }
            return true;
        }
    }
 }
  • BlockingRunnable的postAndWait方法首先将当前的BlockingRunnable添加到Handler的任务队列中,前面第2步我们知道runWithScissors方法的第二个参数为0,因此timeout等于0,这样如果mDone为false的话会一直调用注释3处的wait方法使得当前线程(system_server线程)进入等待状态。
  • 在BlockingRunnable将自身传给Handler之后,在合适的时机会执行传入的Runnable的run方法,其实就是创建WMS对象实例(运行在android.display线程中),执行完毕后finally代码块中将mDone设置为true,并调用noifyAll方法唤醒处于等待状态的线程,这样就不会继续调用注释3处的wait方法。

结合以上两点可以得出一个结论,system_server线程会一直等待android.display线程执行完毕才开始执行system_server线程,这是因为android.display线程内部执行了WMS的创建,而WMS的创建优先级要更高。

2、接下来我们来查看一下WMS的构造方法。

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

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
    
	    private WindowManagerService(Context context, InputManagerService inputManager,
	            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
	            WindowManagerPolicy policy) {
	        installLock(this, INDEX_WINDOW);
	        mContext = context;
	        mHaveInputMethods = haveInputMethods;
	        mAllowBootMessages = showBootMsgs;
	        mOnlyCore = onlyCore;
	        mLimitedAlphaCompositing = context.getResources().getBoolean(
	                com.android.internal.R.bool.config_sf_limitedAlpha);
	        mHasPermanentDpad = context.getResources().getBoolean(
	                com.android.internal.R.bool.config_hasPermanentDpad);
	        mInTouchMode = context.getResources().getBoolean(
	                com.android.internal.R.bool.config_defaultInTouchMode);
	        mDrawLockTimeoutMillis = context.getResources().getInteger(
	                com.android.internal.R.integer.config_drawLockTimeoutMillis);
	        mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
	                com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
	        mMaxUiWidth = context.getResources().getInteger(
	                com.android.internal.R.integer.config_maxUiWidth);
	        mDisableTransitionAnimation = context.getResources().getBoolean(
	                com.android.internal.R.bool.config_disableTransitionAnimation);
	        //保存传递进来的InputManagerService,这样WMS就持有了IMS的引用。
	        mInputManager = inputManager; // Must be before createDisplayContentLocked.
	        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
	        //读取显示设备的设置
	        mDisplaySettings = new DisplaySettings();
	        mDisplaySettings.readSettingsLocked();
	        //policy其实就是PhoneWindowManager的对象实例,将其赋值给mPolicy
	        mPolicy = policy;
	        //创建WindowAnimator对象实例,用于管理所有的窗口动画
	        mAnimator = new WindowAnimator(this);
	        mRoot = new RootWindowContainer(this);
	        mWindowPlacerLocked = new WindowSurfacePlacer(this);
	        mTaskSnapshotController = new TaskSnapshotController(this);
	        mWindowTracing = WindowTracing.createDefaultAndStartLooper(context);
	        LocalServices.addService(WindowManagerPolicy.class, mPolicy);
	        if(mInputManager != null) {
	            final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
	            mPointerEventDispatcher = inputChannel != null
	                    ? new PointerEventDispatcher(inputChannel) : null;
	        } else {
	            mPointerEventDispatcher = null;
	        }
	        //获取显示设备管理服务实例对象
	        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
	        mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
	        //获取电源管理服务实例对象
	        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
	        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
	
	        if (mPowerManagerInternal != null) {
	            mPowerManagerInternal.registerLowPowerModeObserver(
	                    new PowerManagerInternal.LowPowerModeListener() {
	                @Override
	                public int getServiceType() {
	                    return ServiceType.ANIMATION;
	                }
	
	                @Override
	                public void onLowPowerModeChanged(PowerSaveState result) {
	                    synchronized (mWindowMap) {
	                        final boolean enabled = result.batterySaverEnabled;
	                        if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
	                            mAnimationsDisabled = enabled;
	                            dispatchNewAnimatorScaleLocked(null);
	                        }
	                    }
	                }
	            });
	            mAnimationsDisabled = mPowerManagerInternal
	                    .getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
	        }
	        mScreenFrozenLock = mPowerManager.newWakeLock(
	                PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
	        mScreenFrozenLock.setReferenceCounted(false);
	        mAppTransition = new AppTransition(context, this);
	        mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
	        final AnimationHandler animationHandler = new AnimationHandler();
	        animationHandler.setProvider(new SfVsyncFrameCallbackProvider());
	        mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
	                AnimationThread.getHandler(), animationHandler);
	        //获得AMS实例对象,并赋值给mActivityManager。
	        mActivityManager = ActivityManager.getService();
	        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
	        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
	        AppOpsManager.OnOpChangedInternalListener opListener =
	                new AppOpsManager.OnOpChangedInternalListener() {
	                    @Override public void onOpChanged(int op, String packageName) {
	                        updateAppOpsState();
	                    }
	                };
	        mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
	        mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
	        mPmInternal = LocalServices.getService(PackageManagerInternal.class);
	        final IntentFilter suspendPackagesFilter = new IntentFilter();
	        suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
	        suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
	        context.registerReceiverAsUser(new BroadcastReceiver() {
	            @Override
	            public void onReceive(Context context, Intent intent) {
	                final String[] affectedPackages =
	                        intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
	                final boolean suspended =
	                        Intent.ACTION_PACKAGES_SUSPENDED.equals(intent.getAction());
	                updateHiddenWhileSuspendedState(new ArraySet<>(Arrays.asList(affectedPackages)),
	                        suspended);
	            }
	        }, UserHandle.ALL, suspendPackagesFilter, null, null);
	        // Get persisted window scale setting
	        mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
	                Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
	        mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
	                Settings.Global.TRANSITION_ANIMATION_SCALE,
	                context.getResources().getFloat(
	                        R.dimen.config_appTransitionAnimationDurationScaleDefault));
	        setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
	                Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
	        IntentFilter filter = new IntentFilter();
	        // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
	        filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
	        mContext.registerReceiver(mBroadcastReceiver, filter);
	        mLatencyTracker = LatencyTracker.getInstance(context);
	        mSettingsObserver = new SettingsObserver();
	        mHoldingScreenWakeLock = mPowerManager.newWakeLock(
	                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
	        mHoldingScreenWakeLock.setReferenceCounted(false);
	        mSurfaceAnimationRunner = new SurfaceAnimationRunner();
	        mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
	                com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
	        mTaskPositioningController = new TaskPositioningController(
	                this, mInputManager, mInputMonitor, mActivityManager, mH.getLooper());
	        mDragDropController = new DragDropController(this, mH.getLooper());
	        LocalServices.addService(WindowManagerInternal.class, new LocalService());
	    }
    }

对于WindowManagerService的构造方法主要提一下以下几点。
1)保存传递进来的IMS,这样WMS就持有了IMS的引用。
2)读取显示设备的设置。
3) 保存传递近来的policy,其实就是PhoneWindowManager的对象实例,将其赋值给mPolicy。
4)创建WindowAnimator对象实例,赋值给mAnimator,用于管理所有的窗口动画。
5)获取显示设备管理服务,并赋值给mDisplayManager。
6)获取电源管理服务,并复制给mPowerManager。
7)获得AMS实例对象,并赋值给mActivityManager。

3、结合SystemServer的startOtherServices方法,在创建WindowManagerService对象实例之后,会执行该对象的onInitReady方法。

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
        
	    public void onInitReady() {
	        //窗口管理策略的接口类WindowManagerPolicy(WMP),它用来定义一个窗口策略所要遵循的通用规范。
	        initPolicy();
	        // 调用addMonitor方法将自身添加到watchdog中,Watchdog用来监控系统的一些关键服务的运行状况,
	        // 这些被监控的服务都会实现Watchdog.Monitor接口。Watchdog每分钟都会对被监控的系统服务进行检查,
	        // 如果被监控的系统服务出现了死锁,就会杀死Watchdog所在的进程,也就是SystemServer进程。
	        Watchdog.getInstance().addMonitor(this);
	
	        openSurfaceTransaction();
	        try {
	            createWatermarkInTransaction();
	        } finally {
	            closeSurfaceTransaction("createWatermarkInTransaction");
	        }
	
	        showEmulatorDisplayOverlayIfNeeded();
	    }
	    
}
	

调用initPolicy方法初始化窗口管理策略的接口类WindowManagerPolicy(WMP),它用来定义一个窗口策略所要遵循的通用规范。调用addMonitor方法将自身添加到watchdog中,Watchdog用来监控系统的一些关键服务的运行状况,这些被监控的服务都会实现Watchdog.Monitor接口。Watchdog每分钟都会对被监控的系统服务进行检查,如果被监控的系统服务出现了死锁,就会杀死Watchdog所在的进程,也就是SystemServer进程。

4、继续来看WindowManagerService的initPolicy方法。

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
	    private void initPolicy() {
	        UiThread.getHandler().runWithScissors(new Runnable() {
	            @Override
	            public void run() {
	                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
	                //前面有提过,mPolicy其实就是PhoneWindowManager对象实例。
	                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
	            }
	        }, 0);
	    }
    }

WMS的initPolicy方法和前面讲的WMS的main方法的实现类似,调用UiThread的静态方法getHandler,然后执行runWithScissors方法,传入需要执行的Runnable对象。

1)UiThread其实是一个名为android.ui的前台线程。

frameworks/base/services/core/java/com/android/server/UiThread.java

public final class UiThread extends ServiceThread {
    private static final long SLOW_DISPATCH_THRESHOLD_MS = 100;
    private static final long SLOW_DELIVERY_THRESHOLD_MS = 200;
    private static UiThread sInstance;
    private static Handler sHandler;

    private UiThread() {
        super("android.ui", Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    }
    @Override
    public void run() {
        // Make sure UiThread is in the fg stune boost group
        Process.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);
        super.run();
    }

    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new UiThread();
            sInstance.start();
            final Looper looper = sInstance.getLooper();
            looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
            looper.setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
            sHandler = new Handler(sInstance.getLooper());
        }
    }

    public static UiThread get() {
        synchronized (UiThread.class) {
            ensureThreadLocked();
            return sInstance;
        }
    }

    public static Handler getHandler() {
        synchronized (UiThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
    }
}

2)关于UiThread.getHandler().runWithScissors方法的调用流程这里不做具体分析了,请类比前面的DisplayThread.getHandler().runWithScissors。总之会执行Runnable的run方法,调用WMP的init方法,WMP是一个接口,具体实现类是PhoneWindowManager,这里调用的其实就是PhoneWindowManager的init方法。PhoneWindowManager的init方法运行在android.ui线程中,它的优先级要高于initPolicy方法所在的android.display线程,因此android.display线程要等PhoneWindowManager的init方法执行完毕后,处于等待状态的android.display线程才会被唤醒从而继续执行下面的代码。

三、WMS的创建过程的3个线程

上面WMS创建的过程中有提到3个线程,分别是system_server、android.display和android.ui,下图是关于这三个线程的三个步骤。
三个线程之间的关系

1、首先在system_server线程中执行了SystemServer的startOtherServices方法,在startOtherServices方法中会调用WMS的main方,main方法会创建WMS,创建的过程是在android.display线程中实现的,由于创建WMS的优先级更高,因此system_server线程要等WMS创建完成后,处于等待状态的system_server线程才会被唤醒从而继续执行下面的代码。

2、在WMS的构造方法中会调用WMS的initPolicy方法,在initPolicy方法中又会调用PWM的init方法,PWM的init方法在android.ui线程中运行,它的优先级要高于android.display线程,因此"android.display"线程要等PWM的init方法执行完毕后,处于等待状态的android.display线程才会被唤醒从而继续执行下面的代码。

3、PWM的init方法执行完毕后,android.display线程就完成了WMS的创建,等待的system_server线程被唤醒后继续执行WMS的main方法后的代码逻辑,比如在前面第二部分第2步的注释7的地方,WMS的displayReady方法用来初始化屏幕显示信息。

四、总结

WindowManagerService的启动流程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/566891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ发送方确认机制

1、前言 RabbitMQ消息首先发送到交换机&#xff0c;然后通过路由键【routingKey】和【bindingKey】比较从而将消息发送到对应的队列【queue】上。在这个过程有两个地方消息可能会丢失&#xff1a; 消息发送到交换机的过程。消息从交换机发送到队列的过程。 而RabbitMQ提供了…

中国移动董宁:深耕区块链的第八年,我仍期待挑战丨对话MVP

区块链技术对于多数人来说还是“新鲜”的代名词时&#xff0c;董宁已经成为这项技术的老朋友。 董宁2015年进入区块链领域&#xff0c;现任中国移动研究院技术总监、区块链首席专家。作为“老友”&#xff0c;董宁见证了区块链技术多个爆发式增长和平稳发展的阶段&#xff0c;…

基于STC8G1K08A的水压检测系统

基于STC8G1K08A的水压检测系统 前言先来一饱眼福设计和硬件的选型压力传感器选择单片机的选择WIFI透传模块选择 核心代码的开发STC8G1K08A单片机代码读取水压传感器的电压计算对应电压水的压力值猪场水压正常、漏水、喝光水提醒功能的实现 数据通过ESP8266上报到云端代码的实现…

低功耗定时器(LPTIMER)

概述 LPTIM 是运行在Always-On 电源域下的16bits 低功耗定时/计数器模块。通过选择合适的工作时钟&#xff0c;LPTIM 在在各种低功耗模式下保持运行&#xff0c;并且只消耗很低的功耗。LPTIM 甚至可以在没有内部时钟的条件下工作&#xff0c;因此可实现休眠模式下的外部脉冲计数…

新手怎么玩转Linux

Linux是一个非常强大、灵活和可定制的操作系统&#xff0c;这使得它成为了程序员的首选操作系统之一。程序员喜欢使用Linux的原因有以下几点&#xff1a;开源、稳定性、安全性、命令行界面、社区支持。那么新手改如何玩转Linux呢&#xff1f;跟着我一起来看看吧。 以下是对新…

Meta 开源语音 AI 模型支持 1,100 多种语言

自从ChatGPT火爆以来&#xff0c;各种通用的大型模型层出不穷&#xff0c;GPT4、SAM等等&#xff0c;本周一Meta 又开源了新的语音模型MMS&#xff0c;这个模型号称支持4000多种语言&#xff0c;并且发布了支持1100种语言的预训练模型权重&#xff0c;最主要的是这个模型不仅支…

行业报告 | 2022文化科技十大前沿应用趋势(上)

文 | BFT机器人 前言 Introduction 文化科技是文化科技融合过程中诞生的系列新技术成果&#xff0c;是文化强国和科技强国两大战略的交又领域。2012 年 8月&#xff0c;科技部会同中宣部、财政部、文化部、广电总局、新闻出版总署发布《文化科技创新工程纲要》&#xff0c;开启…

为何AI无法完全理解人类情感?GPT-4能否理解人类的情绪?

在科幻小说和电影里&#xff0c;我们经常看到超级AI人工智能机器人可以理解、感知甚至模拟人类的情感&#xff0c;但在现实世界中&#xff0c;我们距离这个目标还有一段相当长的距离&#xff0c;即使是强大的GPT-4甚至未来的GPT-5。过高夸大AI的体验和性能&#xff0c;往往并不…

gin框架返回json

一、使用gin web框架开发的两种模式&#xff1a; 前端浏览器去请求服务器&#xff0c;服务器把完整的HTML文件的内容返回给前端浏览器Vue、reactor等前端框架都自己提前定义好模板&#xff0c;后端&#xff08;服务器&#xff09;只需要返回JSON格式的数据给前端框架即可&…

如何在MyEclipse中使用JavaScript编写代码?

MyEclipse v2022.1.0正式版下载 JavaScript 项目 在 MyEclipse 2021 及更高版本中&#xff0c;JavaScript 支持对大多数 JavaScript 源代码都是开箱即用的——不需要特殊的 JavaScript Eclipse 项目或 JavaScript facet。但是&#xff0c;我们建议使用jsconfig.json文件来指定…

SAP 物料主数据基本数据1视图 参数有效值 字段的作用测试 <转载>

原文链接&#xff1a;https://blog.csdn.net/weixin_40672823/article/details/104773643 1.在物料主数据基本数据1视图中有个字段 参数有效值 如下图 有什么用途? 这个字段作用主要用在 BOM里面&#xff0c;官方说明如下 看说明很难理解下面通过一个业务实例来说明 业务要…

HOOPS平台助力Xometry数字化转型:即时报价产品实现三维模型轻量化、Web端可视化!

所属行业&#xff1a;制造业 挑战&#xff1a;为在线客户的制造平台提供流畅的客户体验、支持使用多种类型CAD文件格式的不同客户群、根据模型提供准确的报价和可制造性反馈、快速准确地可视化定制零 解决方案&#xff1a; HOOPS Platform 提供web端和移动设备的3D数据转换、…

擎创技术流 | 一文读懂eBPF对kubernetes可观测的重要性

一、云原生技术发展的背景与问题 当前&#xff0c;云原生技术主要是以容器技术为基础围绕着 Kubernetes的标准化技术生态&#xff0c;通过标准可扩展的调度、网络、存储、容器运行时接口来提供基础设施&#xff0c;同时通过标准可扩展的声明式资源和控制器来提供运维能力。两层…

Servlet【最复杂的hello world】

目录 一、Hello World 1.创建项目 2.引入依赖 3.创建目录 4.编写代码 4.1 继承 HttpServlet 父类&#xff0c;重写 doGet 方法 4.2 在 doGet 中编写代码&#xff0c;打印 hello world 4.3 给 HelloServlet 加上注解 4.4 完整代码 5.打包代码 6.部署 7.验证程序 二…

分享一个403界面给大家

先看效果图&#xff08;说明&#xff1a;小鬼影会飘来飘去&#xff0c;长时间停留会有小惊喜&#xff0c;具体大家跑一下就知道&#xff09;&#xff1a; 代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UT…

depends_on 解决 docker 容器依赖问题

如果你经常使用docker-compose启动服务的话&#xff0c;可能会遇到下面的问题&#xff1a;服务 B 依赖服务 A&#xff0c;需要服务 A 先启动&#xff0c;再启动服务 B 举个例子&#xff0c;在部署 kafka 集群的时候&#xff0c;需要启动两个kafka&#xff0c;并使用zookeeper做…

基于云计算和物联网技术开发的智慧校园云平台源码

智慧校园系统是利用物联网和云计算&#xff0c;强调对教学、科研、校园生活和管理的数据采集、智能处理、为管理者和各个角色按需提供智能化的数据分析、教学、学习的智能化服务环境。它包含“智慧环境、智慧学习、智慧服务、智慧管理”等层面的内容。 文末获取联系 它描绘的是…

准备搞个大动作!

目前我们的会员群的同学越来越多&#xff0c;然后我们提供的内容已经从起步篇&#xff0c;趣味篇&#xff0c;工具篇到高级篇了。但是到了高级篇很多内容都跟编程相关&#xff0c;有一点门槛&#xff0c;如果单单看文字是肯定无法满足大家的需求。为了更好的服务大家&#xff0…

跃升数字生产力,九州云受邀出席闵行国际人才月

5月22日&#xff0c;由闵行人才工作领导小组办公室指导、中共闵行区马桥镇委员会及闵行区马桥镇人民政府主办、上海人工智能研究院协办的首届“大零号湾”国际人才月马桥人工智能周成功召开。 本届大会以“AI才共赢 智敬未来”为主题&#xff0c;探讨科技创新的最新动态和趋势&…

如何使用Linux Top命令

Linux中的top命令允许您监视当前正在运行的进程及其使用的系统资源。作为系统管理员&#xff0c;它可能是工具箱中最有用的工具&#xff0c;特别是如果您知道如何使用它的话。所有Linux发行版都预装了top实用程序。通过这个交互式命令&#xff0c;您可以自定义如何浏览进程列表…