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

 一、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) - 掘金


 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
WMS(Warehouse Management System,仓库管理系统)是一种用于管理仓库运营的软件系统,旨在优化仓库内的流程、提高效率、降低成本。WMS码net是指使用WMS系统的代码基于.NET框架进行开发的情况。 .NET(.NET Framework)是由微软开发的软件框架,提供了一个平台,使开发人员能够构建和运行各种类型的应用程序。使用.NET框架进行WMS系统的开发,可以充分利用.NET的优势,如面向对象的编程、可扩展性和跨平台性。 WMS码net的开发过程通常包括以下步骤: 1. 需求分析:了解用户的需求和业务流程。通过与仓库管理人员的沟通和调研,确定系统的功能和架构设计。 2. 数据库设计:根据需求分析的结果,设计数据库模型。定义仓库管理所需的实体和关系,如货物、仓库、入库出库等。 3. 功能开发:根据需求设计,使用.NET框架编写代码。这包括实现基本业务功能,如订单管理、货物跟踪、库存管理等。 4. 用户界面开发:设计用户友好的界面,使用户能够方便地操作系统。使用.NET的GUI组件进行界面设计和开发。 5. 系统测试:对开发的系统进行测试,包括单元测试和集成测试。确保系统的功能正常运行,满足用户需求。 6. 部署和维护:将开发好的系统部署到生产环境中。定期维护和更新系统,以确保其安全性和可用性。 总的来说,WMS码net是基于.NET框架进行开发的仓库管理系统的代码。通过使用.NET的优势,如面向对象编程和可扩展性,可以构建高效、可靠的WMS系统,以提升仓库运营效率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值