Android Framework之WMS

WMS的界说

它是framework层的窗口办理服务,责任是办理android体系中一切的window。其间包含了增加窗口、删去窗口、token办理、输入法办理、体系事情音讯收集和分发、活动窗口办理(FocusWindow)、活动运用办理(FocusApp)、转场动画。

Acitvity和Window

咱们都知道activity和service最大的区别是一个有图画显出,一个是没有图画显现的。activity之一切能有图画显现,便是由于它包含了一个window窗口,而service没有window,所以它只能在后台运转,无法进行图画展示。

window对咱们开发来说是一个展示图画的窗口,对用户来说便是一个界面。从surfaceFlinger的视点来看,它是一个layer图层,承载和界面相关的数据和属性。从WMS来说,它是一个WindowState,用于办理界面相关的数据。

一个actiivty中只要一个window,前者操控生命周期和事情处理,后者只进行视图操控。

一个体系中有许多运用,一个运用有许多activity,而一切运用中关于Acitivity的办理,都是由AMS来进行的,但ams值担任activity,不担任window窗口办理,所以就延伸出了WindowManagerService(WMS),专门用来进行Window的办理,操控window显现躲藏以及显现的方位。

WMS和AMS都是由SystemSerer(SM)来进行发动的,也都运转在一个进程中。

对Window的根底认识:

  • 它是窗口,也是一切View的办理者,任何视图都需求经过window来进行出现,事情传递是Window(PhoneWindow)->DecorView->View
  • window是抽象类,详细的代码完结是在PhoneWindow
  • 创立window经过WindowManager创立
  • Window和WMS的通讯办法是Binder,运用AIDL接口来完结的。
  • 每个Window都需求指定Type,运用窗口type值是【0-99】、运用子窗口type值是【1000-1999】、体系窗口【2000-2999】。详细对应值在WindowManager.LayoutParams类中。咱们熟悉的toast type类型便是2005,体系键盘是2004,体系弹窗是2003,而悬浮窗也是体系弹窗,type值是2038。咱们常见的activity type类型便是2。

WMS相关类功用描绘。

  • WMS:办理窗口的创立、更新、删去、显现顺序等,是WindowManager的完结类。
  • Window: 手机上一块显现区域,增加window的进程便是请求分配一个surface的进程。
  • WindowManager: 运用和window之间的办理接口,办理窗口的顺序、音讯等。
  • PhoneWindowManager:完结、界说窗口的各种战略。如:Home按键、Back按键是在此处理的,帮助wms纠正一些不合理的窗口属性。
  • Token:它是窗口令牌,本质是一个binder,用于窗口的身份验证,如你运用WindowManager.addView的时分将type类型设置成体系值或许toast值,就会报错,它报错的判别根据便是运用token来效验。
  • Seeion: 会话,一个app中只要一个Seeion,运用也是经过session和WMS进行通讯。
  • WindowState:在WMS中保存、记录Window的类,和ActivityRecord一样,记录Activity的作用。
  • DisplayContent:代表屏幕,一个android设备能够有多个屏幕(车载上很常见)
  • WindowAnimator:办理、渲染window动画的类
  • Choreographer:用于操控窗口动画、屏幕旋转等操作。它拥有体系同步事情的能力,所以能够在适宜的机遇告诉渲染动作,防止在渲染的进程中由于产生屏幕重绘而导致的画面撕裂。
  • SurfaceFlinger:担任办理android体系的帧缓冲区(Frame Buffer),android设备的显现屏被抽象为一个帧缓存区,SurfaceFlinger服务经过向这个帧缓冲区写入内容,从而绘制出运用程序的用户界面。
  • InputManager:办理窗口事情通道,向通道上派发事情,它是InputManagerService的实例。
  • WindowContainer:办理window显现的次序,窗口大小。WindowToken、DisplayContent、WindowState都是它的子类。

屏幕改写机制

咱们肉眼能够分辩的的帧率是1秒24帧,只要在每秒中连续的输出不低于24帧,咱们就不会感到卡顿。而android手机最常见的都是60HZ的改写率,苹果手机是120HZ改写率,现在android高端手机90hz和120hz的也有许多。

改写时刻16.67距离的计算办法是:1000/60=16.67,所以咱们手机改写的距离是16.67秒。

当然手机改写率不是越高越好,它是和手机其他硬件功能相关的,假如屏幕改写率很高,那他的改写距离就越短,如120hz的分辩率,改写时刻距离为1000/120=8.3秒,在这么短的时刻内进行改写view,假如硬件功能欠好,处理不过来,那很有可能丢帧,在连续时刻段内持续丢帧,就会形成肉眼可见的卡顿。(持续时刻段内掉帧,用户才会感到卡顿)

Window视图显现结构

网上找的图:

Android Framework之WMS

图形显现数据传输流程如下:

view –> canvas –> surface –> surfaceFlinger –> 图画引擎库(OpenGL、Skia) –> Graphic Buffer–> FrameBuffer –> 屏幕绘制

WMS发动时序

WMS和AMS一样,都出经过SystemService来进行发动的。

SystemService–>startOtherService()

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

WindowManagerService–>main()

Android Framework之WMS

WMS的创立进程伴随着线程切换的进程。线程切换如下:

   SystemServer线程 --> DisplayThread线程

在android中,普通的handle.post 是异步机制的的(发送音讯后,持续履行下面的代码,然后在onHandlerMessage中收到音讯后再去履行其他代码)。

而上面main办法中运用runWithScissors却是同步的,先履行音讯中的代码,然后再履行handler.post之后的代码。

runWithScissors完结同步的原理是线程确定,阻塞等候handler履行完结。代码如下:

    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");
        }
        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }
        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }

BlockingRunnable中的Run办法:

    @Override
    public void run() {
        try {
            mTask.run();
        } finally {
            synchronized (this) {
                mDone = true;
                //唤醒下面的wait
                notifyAll();
            }
        }
    }

postAndWait办法代码如下:

    public boolean postAndWait(Handler handler, long timeout) {
        if (!handler.post(this)) {
            //音讯发送失败直接回来false,不进行确定
            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 {
                        //等候,上面履行完结之后会进行notifyAll唤醒
                        wait(delay);
                    } catch (InterruptedException ex) {
                    }
                }
            } else {
                while (!mDone) {
                    try {
                       //等候,上面履行完结之后会进行notifyAll唤醒
                        wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }
        return true;
    }

WMS发动完结之后在SystemServer中持续往下履行,将WMS和AMS绑定。

mActivityManagerService.setWindowManager(wm);

调用WMS中的onInitReady接口。

wm.onInitReady();–> initPolicy()–>UIThread.getHandler.runWithScissors()

持续往下,调用displayReady办法,初始化显现尺度信息。

    try {
        wm.displayReady();
    } catch (Throwable e) {
        reportWtf("making display ready", e);
    }

持续往下:调用wms中的systemReady办法。

try {
    wm.systemReady();
} catch (Throwable e) {
    reportWtf("making Window Manager Service ready", e);
}

WMS流程总结

以上便是wms的发动流程,总结一下流程:

  • SystemServer.main()
  • SystemServer.startOtherService()
  • WindowManagerService–>main() DisplayThread线程创立
  • WindowManagerService–>initPolicy() UI线程进行初始化战略,和用户看到的界面显现相关,所以运用UI线程。
  • WindowManagerService–>displayReady()
  • WindowManagerService–>systemReady()

WMS的发动涉及三个线程:SystemServer线程、DisplayThread线程,UIThread。

其间创立WMS的线程是在DisplayThread线程中进行的。由于SystemServer担任的办理、发动的服务许多,而wms是办理一切窗口、担任显现相关的服务,也是用户能够明显感知到的,所以不太适合放在systemServer线程当中去初始化,因此才从运用DisplayThread线程去进行创立WMS。

WMS发动之后和Activity的相关。

WMS发动之后是怎么和Activity相关起来的,咱们持续看源码

想要弄清楚他们是怎么相关起来的,咱们应该看activity的发动流程,前面的文章已经做了整理,说以能够直接找到Activity创立和绑定的代码方位:

  • ActivityThread–> handleLaunchActivity()
  • ActivityThread–> performLaunchActivity()
  • Instrumentation –> newActivity()
  • Activity –> attach()

在attach办法中,做了如下事情:

//个Activity中创立一个PhoneWindow目标
mWindow = new PhoneWindow(this, window, activityConfigCallback);
//给刚刚创立的PhoneWindow目标设置WM;获取WindowManager接口类,WindowManagerImpl是它的完结类。
mWindow.setWindowManager(  (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
        mToken, mComponent.flattenToString(),
        (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
  • Window –> setWindowManager();
  • WindowManagerImpl –> createLocalWindowManager(); 创立一个WindowManagerImpl目标。
  • WindowManagerGlobal –> getInstance();

addView() 流程

和Activity相关之后,咱们最终再看一下AddView流程,咱们的setContentView最终便是走的addView流程。

  • Actiivty –>setVisible –> makeVisible();activity显现的时分调用。

  • WindowManagerImpl –> addView();

  • WindowManagerGlobal –> addView();

  • ViewRootImpl –> setView(); 在此办法中,调用了WindowSession中的addToDisplayAsUser办法。

  • IWindowSession –> addToDisplayAsUser(); 此类是aidl接口,在Seesion中完结了此接口。

  • Seesion –> addToDisplayAsUser();

  • WindowManagerService –> addWindow();

    //addWindow办法中要害代码:
    //创立DisplayContent
    final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
      //创立WindowState
      final WindowState win = new WindowState(this, session, client, token, parentWindow,
              appOp[0], seq, attrs, viewVisibility, session.mUid, userId,
              session.mCanAddInternalSystemWindow);
      win.attach();
    
  • WindowState –> attach();

  • Session –> windowAddedLocked();

  • SurfaceSession –> SurfaceSession() –> nativeCreate();

  • android_view_SurfaceSession.cpp –> nativeCreate();

      static jlong nativeCreate(JNIEnv* env, jclass clazz) {
          SurfaceComposerClient* client = new SurfaceComposerClient();
          client->incStrong((void*)nativeCreate);
          return reinterpret_cast<jlong>(client);
      }
    

最终

这里做了WMS几个重要的流程,包括wms发动、和activity相关、addView。wms中还有其他许多重要的东西没有总结,后边有时刻补充。

本文是自己的学习记录,如有过错,感谢指出。
  • 参阅学习文章:/post/715206…