【安卓12源码】WMS的作用及其启动流程

news2024/10/6 19:29:27

 一、WMS 的作用

WMS 在 Android 系统的地位,它作为中间层,连接了上层的 View 框架和下层的 SurfaceFingler。

  • WMS 主要职责
  • 窗口管理:负责启动、添加、删除窗口,管理窗口大小、层级,核心成员有:WindowContainer、RootWindowContainer、DisplayContent、TaskStack、Task、AppWindowToken、WindowState;
  • 窗口动画:由其子系统 WindowAnimator 管理;
  • 输入系统中转站:通过对窗口的触摸从而产生触摸事件,由 InputMethodService(IMS)对触摸事件进行处理,它会寻找一个最合适的窗口处理触摸反馈信息;
  • Surface 管理:为每个窗口分配一块 Surface,用于绘制要显示的内容。

  •  WMS重要的类

  • WMS继承于IWindowManager.Stub,作为Binder服务端
  • 成员变量mSessions保存所有的Session对象,Session继承于IWindowSession.Stub,作为Binder服务端.Session的创建在 WindowState 的attach方法中:mSession.windowAddedLocked
  • 成员变量mPolicy,实例是PhoneWindowManager,用于实现各种窗口相关的策略
  • 成员变量mWindowMap,保存所有的WindowState对象;以IBinder为key, 是IWindow的Bp端;
  • 每个窗口都对应一个WindowState对象, 该对象的成员变量mClient用于跟应用端交互,成员变量mToken用于跟AMS交互,WindowState的attach方法与SurfaceFlinger通信。
  • WindowManager与WindowManagerService通过Session进行通信,具体的实现由WMS处理。
  • WindowManager实现类是WindowManagerImpl ;
  • WindowManagerImpl 中成员变量 mParentWindow (Window),mGlobal (WindowManagerGlobal)

AMS,WMS之间数据是对应的,通过token值可以在AMS,WMS,应用程序之后来唯一确定一组Window,token是关联着一组窗口的,可能有多个WindowState的token值是相同的. 

二、WMS 的启动流程

wms 是运行在systemsever 系统进程的,在启动system  进程的时候,去初始化了 WMS

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

    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startOtherServices");

        WindowManagerService wm = null;

            t.traceBegin("StartInputManagerService");

// wms与 InputManagerService 息息相关,创建 InputManagerService 对象
            inputManager = new InputManagerService(context);
            t.traceEnd();

            t.traceBegin("StartWindowManagerService");
            // WMS needs sensor service ready
            mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);

// 1. 创建 WindowManagerService 对象
            wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);

// 将 WindowManagerService 和 InputManagerService 添加到服务中
            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);

// 2. wms 与 ams 关联
            mActivityManagerService.setWindowManager(wm);

// 3. 初始化完成
            wm.onInitReady();

// 4. InputManagerService 设置回调,并启动 InputManagerService 
            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            inputManager.start();

// 5. 调用 displayReady 方法
            wm.displayReady();

// 6. 系统准备完毕,调用 systemReady
            wm.systemReady();

        final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);

1. 创建 WindowManagerService 对象

WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);

    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm) {

// policy 是值是 new PhoneWindowManager(),继承了 WindowManagerPolicy
        return main(context, im, showBootMsgs, onlyCore, policy, atm,

// 一个Supplier可以通过lambda表达式、方法引用或默认构造函数来实例化。
// Supplier在Java 8中被引入,属于java.util.function包
// transactionFactory 为 SurfaceControl.Transaction::new,创建 Transaction 对象
// 通过get 可以获取到对象 Transaction
                new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new,
                SurfaceControl.Builder::new);
    }


==========
    @VisibleForTesting
    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, DisplayWindowSettingsProvider
            displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
            Supplier<Surface> surfaceFactory,
            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {

// 在 android.display 实例化 wms,所以wms 跑在android.display线程中 
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                        atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
                        surfaceControlFactory), 0);
        return sInstance;
    }

PhoneWindowManager,主要是负责窗口管理的各种策略。在 android.display 实例化 wms,所以wms 跑在android.display线程中 

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

// ServiceThread 继承了 HandlerThread 

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

    private DisplayThread() {
        // DisplayThread runs important stuff, but these are not as important as things running in
        // AnimationThread. Thus, set the priority to one lower.

// 线程名字为 "android.display",优先级为 -3
        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);

// 创建handler,looper 为 thread "android.display" 的looper
            sHandler = new Handler(sInstance.getLooper());
        }
    }

// 获取到handler
    public static Handler getHandler() {
        synchronized (DisplayThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
    }

handler 执行 runWithScissors 方法

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

    public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
        if (r == null) {
            throw new IllegalArgumentException("runnable must not be null");
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must be non-negative");
        }

// 当前looper 不相等
        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }

// 将其pos 到 BlockingRunnable
        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }

===========
        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) {
。。
                } else {
                    while (!mDone) {
                        try {
// 阻塞systemserver 主线程
                            wait();
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            }
            return true;
        }
    }

DisplayThread 给系统使用的共享单例前台线程类,线程名字为 android.display,专门提供给WindowManager, DisplayManager, and InputManager来执行快速响应的实时操作。

执行构造函数

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, DisplayWindowSettingsProvider
            displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
            Supplier<Surface> surfaceFactory,
            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
        installLock(this, INDEX_WINDOW);

// 锁机制与 atm 一致
        mGlobalLock = atm.getGlobalLock();
// 缓存 AtmS
        mAtmService = atm;
        mContext = context;
。。。
// 是否允许在低电量开启动画
        mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
                com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);

// 缓存 inputManager
        mInputManager = inputManager; // Must be before createDisplayContentLocked.
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);

        mSurfaceControlFactory = surfaceControlFactory;
        mTransactionFactory = transactionFactory;
        mSurfaceFactory = surfaceFactory;
// 获取 Transaction  对象
        mTransaction = mTransactionFactory.get();

// policy 为:PhoneWindowManager
        mPolicy = policy;
// 创建 WindowAnimator 对象
        mAnimator = new WindowAnimator(this);
// 创建 RootWindowContainer 对象
        mRoot = new RootWindowContainer(this);

        final ContentResolver resolver = context.getContentResolver();
        mUseBLAST = Settings.Global.getInt(resolver,
            Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR, 1) == 1;

        mSyncEngine = new BLASTSyncEngine(this);

        mWindowPlacerLocked = new WindowSurfacePlacer(this);
// 任务快照控制类
        mTaskSnapshotController = new TaskSnapshotController(this);

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

        LocalServices.addService(WindowManagerPolicy.class, mPolicy);

        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

// mH 为  final H mH = new H();
        mKeyguardDisableHandler = KeyguardDisableHandler.create(mContext, mPolicy, mH);

        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 (mGlobalLock) {
                        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);

        mDisplayNotificationController = new DisplayWindowListenerController(this);

        mActivityManager = ActivityManager.getService();
        mActivityTaskManager = ActivityTaskManager.getService();
        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
        mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.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);
        mTestUtilityService = LocalServices.getService(TestUtilityService.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(resolver,
                Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
        mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
                Settings.Global.TRANSITION_ANIMATION_SCALE,
                context.getResources().getFloat(
                        R.dimen.config_appTransitionAnimationDurationScaleDefault));

        setAnimatorDurationScale(Settings.Global.getFloat(resolver,
                Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));

        mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver,
                DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;

        final String displaySettingsPath = Settings.Global.getString(resolver,
                DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH);
        mDisplayWindowSettingsProvider = displayWindowSettingsProvider;
        if (displaySettingsPath != null) {
            mDisplayWindowSettingsProvider.setBaseSettingsFilePath(displaySettingsPath);
        }
        mDisplayWindowSettings = new DisplayWindowSettings(this, mDisplayWindowSettingsProvider);

        IntentFilter filter = new IntentFilter();
        // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
        filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);

        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(mTransactionFactory,
                mPowerManagerInternal);

        mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);

        mTaskPositioningController = new TaskPositioningController(
                this, mInputManager, mActivityTaskManager, mH.getLooper());
        mDragDropController = new DragDropController(this, mH.getLooper());

        mHighRefreshRateDenylist = HighRefreshRateDenylist.create(context.getResources());

        mConstants = new WindowManagerConstants(this, DeviceConfigInterface.REAL);
        mConstants.start(new HandlerExecutor(mH));

        LocalServices.addService(WindowManagerInternal.class, new LocalService());
        mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);

        mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources(
                mContext.getResources());

        mDisplayHashController = new DisplayHashController(mContext);
        setGlobalShadowSettings();

// anr 控制类,无响应,无焦点等
        mAnrController = new AnrController(this);
        mStartingSurfaceController = new StartingSurfaceController(this);

        mBlurController = new BlurController(mContext, mPowerManager);
    }

mH 为 final H mH = new H() 成员变量,因此WMS后面的消息也是运行在 android.display 线程中的。

2. wms 与 ams 关联

mActivityManagerService.setWindowManager(wm);

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

973      public void setWindowManager(WindowManagerService wm) {
974          synchronized (mGlobalLock) {
975              mWindowManager = wm;
// 缓存 RootWindowContainer
976              mRootWindowContainer = wm.mRoot;
977              mTempConfig.setToDefaults();
978              mTempConfig.setLocales(LocaleList.getDefault());
979              mConfigurationSeq = mTempConfig.seq = 1;
980              mRootWindowContainer.onConfigurationChanged(mTempConfig);
981              mLockTaskController.setWindowManager(wm);
982              mTaskSupervisor.setWindowManager(wm);

// RootWindowContainer 设置 WindowManager
983              mRootWindowContainer.setWindowManager(wm);
984          }
985      }

3. 初始化完成 onInitReady

wm.onInitReady();

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

    public void onInitReady() {
        initPolicy();

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        createWatermark();
        showEmulatorDisplayOverlayIfNeeded();
    }

=========
    private void initPolicy() {

// 在ui 线程执行下列函数,"android.ui"
        UiThread.getHandler().runWithScissors(new Runnable() {
            @Override
            public void run() {
                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());

// 初始化 PhoneWindowManager
                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
            }
        }, 0);
    }

// 初始化 PhoneWindowManager

 /frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    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);
        mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
        mDisplayManager = mContext.getSystemService(DisplayManager.class);
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
        mPackageManager = mContext.getPackageManager();
        mHasFeatureWatch = mPackageManager.hasSystemFeature(FEATURE_WATCH);
        mHasFeatureLeanback = mPackageManager.hasSystemFeature(FEATURE_LEANBACK);
        mHasFeatureAuto = mPackageManager.hasSystemFeature(FEATURE_AUTOMOTIVE);
        mHasFeatureHdmiCec = mPackageManager.hasSystemFeature(FEATURE_HDMI_CEC);
        mAccessibilityShortcutController =
                new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
        mLogger = new MetricsLogger();

        mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
                .createSleepTokenAcquirer("ScreenOff");

        Resources res = mContext.getResources();
        mWakeOnDpadKeyPress =
                res.getBoolean(com.android.internal.R.bool.config_wakeOnDpadKeyPress);
        mWakeOnAssistKeyPress =
                res.getBoolean(com.android.internal.R.bool.config_wakeOnAssistKeyPress);
        mWakeOnBackKeyPress =
                res.getBoolean(com.android.internal.R.bool.config_wakeOnBackKeyPress);

        // Init display burn-in protection
        boolean burnInProtectionEnabled = context.getResources().getBoolean(
                com.android.internal.R.bool.config_enableBurnInProtection);
        // Allow a system property to override this. Used by developer settings.
        boolean burnInProtectionDevMode =
                SystemProperties.getBoolean("persist.debug.force_burn_in", false);
        if (burnInProtectionEnabled || burnInProtectionDevMode) {
            final int minHorizontal;
            final int maxHorizontal;
            final int minVertical;
            final int maxVertical;
            final int maxRadius;
            if (burnInProtectionDevMode) {
                minHorizontal = -8;
                maxHorizontal = 8;
                minVertical = -8;
                maxVertical = -4;
                maxRadius = (isRoundWindow()) ? 6 : -1;
            } else {
....

// handler是跑在ui 线程
        mHandler = new PolicyHandler();

4. InputManagerService 设置回调,并启动 InputManagerService 

            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            inputManager.start();

    public InputManagerCallback getInputManagerCallback() {
        return mInputManagerCallback;
    }

// mInputManagerCallback 的值为对象 InputManagerCallback(this)
    final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);

setWindowManagerCallbacks 设置回调

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

    public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {

// 保证只有一个 callback
        if (mWindowManagerCallbacks != null) {
            unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks);
        }
        mWindowManagerCallbacks = callbacks;
        registerLidSwitchCallbackInternal(mWindowManagerCallbacks);
    }

========
    void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
        synchronized (mLidSwitchLock) {

// 将 callback 保存到 mLidSwitchCallbacks
            mLidSwitchCallbacks.add(callback);

            // Skip triggering the initial callback if the system is not yet ready as the switch
            // state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in
            // systemRunning().
            if (mSystemReady) {
                boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID)
                        == KEY_STATE_UP;
                callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen);
            }
        }
    }

然后启动inputmanagerservice

    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);

5. 调用 displayReady 方法

          wm.displayReady();

    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);
            mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_FAKETOUCH);
        }

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

6. 系统准备完毕,调用 systemReady


           wm.systemReady();

    public void systemReady() {
        mSystemReady = true;

// 调用 PhoneWindowManager.java 的 systemReady
        mPolicy.systemReady();
        mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
// 快照控制类
        mTaskSnapshotController.systemReady();
        mHasWideColorGamutSupport = queryWideColorGamutSupport();
        mHasHdrSupport = queryHdrSupport();
// ui线程执行 loadSettings
        UiThread.getHandler().post(mSettingsObserver::loadSettings);

 整个启动过程有3个线程,systemserver主线程,”android.display”,”android.ui”,整个过程采用阻塞的方式(利用runWithScissors)执行,WMS.mH的Looper运行在”android.display”进程。

参考:

WMS启动流程分析 | Skytoby

WMS—启动过程 - Gityuan博客 | 袁辉辉的技术博客

Android渲染(一)_系统服务WMS启动过程(基于Android10) - 掘金


 

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

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

相关文章

短视频矩阵系统源码开发规则

抖音seo源码部署&#xff08;前端vue jquery layui 后端php&#xff09;组成 抖音SEO源码开发规则是为了提高抖音内容在搜索引擎的排名&#xff0c;增加曝光和流量而制定的一系列准则。 这些开发规则包括但不限于以下几点&#xff1a; 首先&#xff0c;优化关键词&#xff…

Mac OS 源码编译安装Nginx

下载软件 访问地址&#xff1a; https://nginx.org 根据自己的需求下载合适的安装包 首先建个临时目录 nginx-src 并下载所需软件的源码进行配置 mkdir nginx-src cd nginx-src wget https://nginx.org/download/nginx-1.18.0.tar.gz wget https://ftp.pcre.org/pub/p…

前端框架Layui的使用讲解(Layui搭建登录注册页面)

目录 一、前言 1.什么是Layui 2.Layui的背景 3.为什么要使用Layui 4.Layui的模块化 二、Layui使用讲解 1.初识Layui 2.搭建登录页面 静态效果图​ 封装引入文件页面&#xff08;公用页面&#xff09; jsp页面搭建 userDao编写 Servlet页面编写 xml文件配置 3.搭…

DevOps(一)

DevOps 1. DevOps起源1.1 瀑布开发模型1.2 敏捷开发模型 2. DevOps到底是什么&#xff1f;3. DevOps与虚拟化、容器、微服务4. CI/CD是什么 &#xff1f;4.1 CI 持续集成&#xff08;Continuous Integration&#xff09;4.2 CD 持续交付&#xff08;Continuous Delivery&#x…

JAVA基础方法-substring+indexof

substring用法&#xff1a; 1.public String substring(int beginIndex, int endIndex) 第一个参数int为开始的索引&#xff0c;对应String数字中的开始位置&#xff0c; 第二个参数是截止的索引位置&#xff0c;对应String中的结束位置。 public static void main(String[]…

react中styled-components 全局样式设置

前言 使用 styled-components 库时&#xff0c;你可以使用它的 createGlobalStyle 函数来设置全局样式。下面是一个示例&#xff1a; 安装 styled-components npm install styled-components导入 createGlobalStyle 在你的代码文件中导入 createGlobalStyle&#xff1a; i…

信息安全-应用安全-软件成分安全分析(SCA)能力的建设与演进

1. 前言 SCA 概念出现其实很久了。简单来说&#xff0c;就是针对现有的软件系统生成粒度非常细的 SBOM&#xff08;Software Bill of Materials 软件物料单&#xff09;清单&#xff0c;然后通过⻛险数据去匹配有没有存在⻛险组件被引用。目前&#xff0c;市面上比较出色的商业…

laravel6.x文档阅读手册

laravel中文文档6.x 目录 一、入门指南 安装 服务器要求 安装 Laravel Laravel 使用 Composer 来管理项目依赖。因此&#xff0c;在使用 Laravel 之前&#xff0c;请确保你的机器已经安装了 Composer。 通过 Laravel 安装器 首先&#xff0c;通过使用 Composer 安装 Lara…

Django_加载settings配置

当使用下面命令启动django服务时&#xff0c;setting会自动加载 python manage.py runserver 通过查看manage.py可以找到加载代码为 os.environ.setdefault(DJANGO_SETTINGS_MODULE, settings的路径id) 知道settings加载原理后&#xff0c;在调试时可以不用启动http服务&…

如何用 Jenkins+Docker 实现一键自动化部署

本文章实现最简单全面的Jenkinsdockerspringboot 一键自动部署项目&#xff0c;步骤齐全&#xff0c;少走坑路。 环境&#xff1a;centos7git(gitee) 简述实现步骤&#xff1a;在docker安装jenkins&#xff0c;配置jenkins基本信息&#xff0c;利用Dockerfile和shell脚本实现…

滴...这里有一道数据库操作型面试题,已到达,请查收~

系列文章传送门&#xff1a; 【七天入门数据库】第一天 MySQL的安装部署 【七天入门数据库】第二天 数据库理论基础 【七天入门数据库】第三天 MySQL的库表操作 题目&#xff1a;单表查询&#xff0c;根据提供的素材&#xff0c;按下列要求查询相关数据。 题目素材&#x…

前端vue入门(纯代码)27_路由的query参数

安静地努力&#xff01;&#xff01;&#xff01; 【25.Vue Router--路由的query参数】 多级路由在src/router/index.js中【三级路由】的配置如下&#xff1a; // 该文件专门用于创建整个应用的路由器 import VueRouter from "vue-router"; //引入组件 import Abo…

接口自动化测试要做什么?

先了解下接口测试流程&#xff1a; 1、需求分析2、Api文档分析与评审 3、测试计划编写 4、用例设计与评审5、环境搭建&#xff08;工具&#xff09; 6、执行用例 7、缺陷管理 8、测试报告 接口流程详细内容&#xff0c;请狠狠点击下面这篇文章&#xff0c; 《做接口测试的流程…

关于Vue 、vue2、vue3

vue优点&#xff1f;vue2、vue3响应式比较&#xff1f; &#xff08;1&#xff09; 响应式编程 Vue 会自动对页面中某些数据的变化做出响应。通过 MVVM 思想实现数据的双向绑定&#xff0c;让开发者不用再操作 DOM 对象&#xff0c;有更多的时间去思考业务逻辑。 组件化开发…

程序员,你喜欢写文档吗?

博主&#xff1a;爱码叔 个人博客站点&#xff1a; icodebook 公众号&#xff1a;漫话软件设计 微博&#xff1a;程序员涛哥 专注于软件设计与架构、技术管理。擅长用通俗易懂的语言讲解技术。对技术管理工作有自己的一定见解。文章会第一时间首发在个站上&#xff0c;欢迎大家…

【论文解读】A Fast Sub-pixel Motion Estimation Algorithm for H.264/AVC Video Coding

简介 题目&#xff1a;A Fast Sub-pixel Motion Estimation Algorithm for H.264/AVC Video Coding 原文&#xff1a;https://ieeexplore.ieee.org/document/5688303 级别&#xff1a;SCI 年份&#xff1a;2011 年 机构&#xff1a;上海交通大学 结论&#xff1a;亚像素搜索计…

【C++】unordered_map、unordered_set 模拟实现

文章目录 概念框架实现正反迭代器Find()、Insert() 、Erase()unordered_map 的 operator[ ] 源代码HashTable.hunordered_map.hunordered_set.h 概念 unordered_set 是含有 Key 类型唯一对象集合的关联容器。搜索、插入和移除拥有平均常数时间复杂度。在内部&#xff0c;元素并…

HTML页面通过Web3JS连接智能合约并调用其中接口

之前我们学习solidity 并用它编写了智能合约 登上区块链 然后也做了基本的测试 但是 其实在web3时代 前端依旧扮演者非常重要的角色 我们现在就来打通web3 从合约到页面的一个管理 首先 我们还是将自己的ganache环境起起来 然后 在我们之前智能合约的项目终端执行 truffle m…

Python-Go 文件操作和异常操作

目录 python的异常操作 异常是什么&#xff1f; 错误与异常的区别&#xff1a; 常见异常 Traceback 错误回溯 异常处理 异常处理的定义&#xff08;try - except&#xff09; 扩展&#xff08;可以捕获不同的错误、多except语句&#xff09;&#xff08;else - finall…

PFC离散元仿真,3DEC非连续岩石力学与结构问题分析

一、背景&#xff1a; 随着我国经济的发展&#xff0c;岩土工程涉及的要求从材料、理论到施工工艺都提出了全方位的系统升级。在岩土工程分析设计中&#xff0c;3DEC和PFC软件快速建模也一直是岩土工作者所关注的问题。3DEC是非连续岩石力学与结构问题的首选分析程序&#xff0…