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

1,120 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

一、概述

我们知道WMS是在system server进程中启动的。 zygote进程fork()出system server进程后,会进入到SystemServer.java的 main()方法。 然后会调用其run()方法,最终调用 startOtherServices()来启动WMS服务,具体流程可以看看system server启动篇

一、SystemServer.startOtherServices() 方法

SystemServer.java

 private void startOtherServices() {
  WindowManagerService wm = null;
  //...
    traceBeginAndSlog("StartWindowManagerService");
    // WMS needs sensor service ready
    ConcurentUtils.waitForFutureNoInterrupt
    (mSensorServiceStart, 
    START_SENSOR_SERVICE);
    mSensorServiceStart = null;
    // 1 创建 WMS,传入了system上下文、一个 inputManager对象、一个PhoneWindowManager 对象、atm对象 
    wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
            new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
    // 2 发布 WMS到 SM
    ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
            DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
    // 发布inputManagerService 到SM      
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
            /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    traceEnd();

    traceBeginAndSlog("SetWindowManagerService");
    // 3 让AMS持有 WMS的引用 ,方便后续调用 
    mActivityManagerService.setWindowManager(wm);
|
    traceBeginAndSlog("WindowManagerServiceOnInitReady");
    // 4 回调WMS的 onInitReady()方法 
    wm.onInitReady();
    
    
    traceEnd();
    // 5 回调WMS的
    wm.displayReady();
   // 6 回调WMS的
    wm.systemReady();
        
    //...      
 }

只看WMS相关的部分。

  1. 创建 WMS对象。传入了system的上下文、inputManager对象、PhoneWindowManager对象、atm对象
  2. 把WMS和IMS加入到 ServiceManager进行管理
  3. AMS持有WMS的引用,方便后续调用
  4. 回调WMS的 onInitReady()方法
  5. 回调WMS的displayReady()
  6. 回调WMS的systemReady()

1.1 WindowManagerService.main()方法

WindowManagerService.java

传入了system上下文、inputManagerService 对象、PhoneWindowManager对象、atm对象。

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

在后面追加了一个 SurfaceControl.Transaction 对象。继续调用另一个main()方法。

SurfaceControl 通过long型的handler值,指向了native层的surface对象(该对象被系统合成器来管理)。SurfaceControl包含了buffer源数据,以及如何展示这个buffer的一些元数据。当从SurfaceControl构造出来一个surface对象,可以通过它提交buffer给系统合成器。通过 SurfaceControl.Transaction,可以调整buffer如何在屏幕上显示的参数。此外,SurfaceControl 也是一个树形结构,可能会有parent,因此像转换、裁剪、z轴等属性都会继承自父亲的约束。

1.2 main()

@VisibleForTesting
public static WindowManagerService main(final Context context, final InputManagerService im,
        final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
        // runnable 提交到 DisplayThread 线程 
    DisplayThread.getHandler().runWithScissors(() ->
            sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                    atm, transactionFactory), 0);
    return sInstance;
}
  • 调用Handler的 runWithScissors()方法,第二个参数 0 表示立即执行。
  • WindowManagerPolicy policy: 实现类是 PhoneWindowManager 对象。
  • 创建一个WMS对象,并且返回该实例。

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

1.3 Handler.runWithScissors()

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与当前handler一样
    if (Looper.myLooper() == mLooper) {
        r.run();
        return true;
    }
    // 不一样,则新建 BlockingRunnable对象
    BlockingRunnable br = new BlockingRunnable(r);
    return br.postAndWait(this, timeout);
}

如果线程不一致,则新建 BlockingRunnable,post到 Handler的线程,调用wait()进入等待,直到被唤醒。 注意,此时调用方线程是system server的主线程。创建WMS的代码需要执行在 android.display 线程。因此,不一致,继续看下面的逻辑。

1.3.1 BlockingRunnable

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;
                // 唤醒 system server主线程
                notifyAll();
            }
        }
    }

    public boolean postAndWait(Handler handler, long timeout) {
        // 把task放入 Android.display线程
        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 {
                        // system server主线程进入等待
                        wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }
        return true;
    }
}

system server主线程进入 wait()状态,等待唤醒。当android.display线程run()方法执行完后,在finally中 notifyAll()唤醒。

为什么要这么设计呢? 因为WMS作为非常重要的服务,必须要等它初始化完成,system server主线程才能进行下一步操作。

接下来,就可以看看WMS的构造方法了。

1.3.2 WindowManagerService构造方法

private WindowManagerService(Context context, InputManagerService inputManager,
        boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
    installLock(this, INDEX_WINDOW);
    mGlobalLock = atm.getGlobalLock();
    mAtmService = atm;
    mContext = context;
    mAllowBootMessages = showBootMsgs;
    mOnlyCore = onlyCore;
    mLimitedAlphaCompositing = context.getResources().getBoolean(
            com.android.internal.R.bool.config_sf_limitedAlpha);
    //... 属性
    mInputManager = inputManager; // Must be before createDisplayContentLocked.
    // 获取本进程 display 服务
    mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
    mDisplayWindowSettings = new DisplayWindowSettings(this);

    mTransactionFactory = transactionFactory;
    mTransaction = mTransactionFactory.make();
    // 是 PhoneWindowManager对象
    mPolicy = policy;
    // window窗口动画
    mAnimator = new WindowAnimator(this);
    // root 窗口容器??
    mRoot = new RootWindowContainer(this);
    // 窗口的surface占位? 
    mWindowPlacerLocked = new WindowSurfacePlacer(this);
    mTaskSnapshotController = new TaskSnapshotController(this);

    mWindowTracing = WindowTracing.createDefaultAndStartLooper(this,
            Choreographer.getInstance());
    // 添加本进程的 windowPolicy 服务
    LocalServices.addService(WindowManagerPolicy.class, mPolicy);
    // 获取本系统 displayManager 服务
    mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    // 键盘
    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);
    // AMS ATM 服务
    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);
    // PMS服务
    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);

    //...
    //加入到本进程,作为本地服务
    LocalServices.addService(WindowManagerInternal.class, new LocalService());
}

总结:

初始化 display、了AMS、ATM、MPolicy等成员。mH 为 final H mH = new H() 成员变量,因此WMS后面的消息也是运行在 android.display 线程中的。

1.4 wm.onInitReady()

在AMS与WMS绑定后,就会调用该方法。 此时是system server的 主线程。

public void onInitReady() {
    initPolicy();

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

    openSurfaceTransaction();
    try {
        createWatermarkInTransaction();
    } finally {
        closeSurfaceTransaction("createWatermarkInTransaction");
    }

    showEmulatorDisplayOverlayIfNeeded();
}

1.4.1 WMS.initPolicy()

private void initPolicy() {
    UiThread.getHandler().runWithScissors(new Runnable() {
        @Override
        public void run() {
            WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
            mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
        }
    }, 0);
}

UiThread 也是系统的单例共享后台线程,名字为 android.ui。 同理,此时system server的主线程也会 wait(),等 android.ui 线程执行了run()方法后,才会唤醒 system server 主线程。

mPolicy 是 WindowManagerPolicy 类型,具体实现类是 PhoneWindowManager。

1.4.2 PhoneWindowManager.init()

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);
    mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
    mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
    mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    ...

    mHandler = new PolicyHandler(); //运行在"android.ui"线程
    mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
    mOrientationListener = new MyOrientationListener(mContext, mHandler);
    ...

    mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
            "PhoneWindowManager.mBroadcastWakeLock");
    mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
            "PhoneWindowManager.mPowerKeyWakeLock");
    ...
   
    mGlobalKeyManager = new GlobalKeyManager(mContext);
    ...
    
    if (!mPowerManager.isInteractive()) {
        startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
        finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
    }

    mWindowManagerInternal.registerAppTransitionListener(
            mStatusBarController.getAppTransitionListener());
}

1.5 WMS.displayReady()

public void displayReady() {
    synchronized (mGlobalLock) {
        if (mMaxUiWidth > 0) {
            mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
        }
        final boolean changed = applyForcedPropertiesForDefaultDisplay();
        mAnimator.ready();
        mDisplayReady = true;
        if (changed) {
            reconfigureDisplayLocked(getDefaultDisplayContentLocked());
        }
        mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_TOUCHSCREEN);
    }

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

    updateCircularDisplayMaskIfNeeded();
}

1.6 WMS.systemReady()

public void systemReady() {
    mSystemReady = true;
    mPolicy.systemReady();
    
    //...
}

1.6.1 PhoneWindowManager.systemReady()

public void systemReady() {
    // In normal flow, systemReady is called before other system services are ready.
    // So it is better not to bind keyguard here.
    mKeyguardDelegate.onSystemReady();

    mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
    if (mVrManagerInternal != null) {
        mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
    }

    readCameraLensCoverState();
    updateUiMode();
    mDefaultDisplayRotation.updateOrientationListener();
    synchronized (mLock) {
        mSystemReady = true;
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                updateSettings();
            }
        });
        // If this happens, for whatever reason, systemReady came later than systemBooted.
        // And keyguard should be already bound from systemBooted
        if (mSystemBooted) {
            mKeyguardDelegate.onBootCompleted();
        }
    }

    mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
}

二、总结

  • system server主线程开始执行,准备创建 WMS 对象
  • system server主线程进入wait(),等待 android.display线程去创建WMS对象,因此,WMS中的 mH 发送的消息都在该线程处理。
  • 唤醒system server主线程,继续执行onInitReady()方法
  • system server主线程进入wait(),切换到 android.ui线程 ,PhoneWindowManager.init()执行完毕
  • 唤醒system server主线程,继续执行后续代码。

关键点是 三个线程的切换逻辑。

三、参考

liuwangshu.cn/framework/w…

gityuan.com/2017/01/08/…