Android系统学习小记

时间:2023-03-09 19:46:57
Android系统学习小记

  序言

  Android 应用的启动到一个页面显示出来,这个过程涉及到点击事件的处理,以及如何启动一个Activity,启动一个Activity之后,如何将Activity中我们的设置的ContentView显示出来,显示的时候,如何添加窗口,如何在将View绘制到窗口上等一系列操作。涉及到的关键的三个服务,Ams,Wms还有Pms。分别是用来管理全局的Activity,Window,Package。整个过程中有哪些主要的类在里面起作用。

  Ams,Wms,Pms在SystemServer中都是在一个子线程中运行。

  带着一个主线,我们点击了Launcher中的一个图标,这个应用从未被启动过,那么这个应用从被点击到该应用的界面显示出来的整个过程。

  流程

  输入事件的处理

  查找到指定的Activity

  创建相应的进程然后运行

  启动指定的Activity

  为该Activity创建窗口,然后将视图绘制上去

  接收触摸点击事件

  输入事件处理消息的获取过程,InputReader线程会持续调用输入设备的驱动,读取所有用户输入的消息,该线程和InputDispatcher线程都是在system_process空间中运行,第一种是经过管道派发给客户进程。Wms创建一个InputManager对象的时候,然后启动InputDispatcher线程,Native层有两个重要的对象,一个是InputDispatcher,一个是InputReader,从线程的角度来看,只有两个线程存在,一个是InputDispatcher还有一个是InputReaderTread线程,他们运行在system_process进程中。

  查找指定的ActivityPms使用两个目录下的XML文件保存相关的包管理信息,一个是用来管理permissions,一个是packaegs.xml该文件保存了安装程序的基本包信息,比如包名称,安装包路径,程序使用了那些权限,像是系统的注册表,Pms启动后,会从两个目录解析相关的xml文件,建立一个庞大的包信息树,应用程序可以从这个信息树种查找自己所需要的程序包信息。当进行App的跳转的时候。Pms在初始化的时候,会从AndroidManifest.xml文件中提取值,然后建立一个内部数据结构,以后应用可以通过PackageManager提供query方法查询不同的组件的包信息。

  创建相应的进程然后运行检测对应Activity的进程是否存在 - > 不存在则启动对应的进程 - > 进程启动完成通知AMS - > 调用AMS attachApplication(请求AMS给自己attach一个具体的Activity)- > 继续调用resumeTopActivity - > 进程处理(handleLaunchActivity,handleResumeActivity)应用程序执行的时候,首先执行的是创建一个ActivityThread,然后调用prepareMainLooper为UI线程创建一个消息队列,然后创建一个ActivityThread对象,会创建一个Handler和一个ApplicationThread(Binder对象),其负责接收远程的Ams的IPC调用,UI主线程会调用Looper.Loop进入消息循环体,接收到创建指定Activity的来自AMS的消息后,会创建指定的Activity对象,Activity对象会创建PhoneWindow类,DecorView类,相应的View和ViewGroup,调用WindowManager,创建一个ViewRoot和W类,ViewRoot包含一个W类对象,WindowManager和Wms进行交互并将窗口显示到屏幕上

  启动指定的Activity每一个应用程序对应了一个ActivityThread,其负责启动Activity,构造好Activity之后,会调用Activity的attach方法,顾名思义,就是为Activity添加上一些东西,上下文,创建它的线程,创建窗口对象,在Ams中记录的ActivityRecord引用,然后创建窗口,通过PolicyManager的makeNewWindow来创建,归根结底是创建了一个PhoneWindow对象,将创建的Window对象赋值给内部变量mWindow,并设置Window的Callback接口为当前的Activity对象,将用户消息传递给Activity,Window中包含WindowManager对象,Activity中也包含一个WindowManger和其相同,WindowManager的具体功能实现是在WindowManagerImpl中,配置好之后,给窗口中添加显示元素View或者ViewGroup。调用performLaunchActivity内部的callActivityOnCreate,然后辗转调用Activity的onCreate。调用setContentView,实际是调用了其内部的Window的setContentView。

  为该Activity创建窗口,然后将视图绘制上去PhoneWindow的installDecor方法为Window类安装窗口装饰,然后把内容View装载进来,给Window类设置完其视图后,剩下的就是把创建这个窗口告诉给Wms,Wms把窗口显示到屏幕,Ams进行一系列的条件判断后,最终调用Activity的makeVisible方法,调用WindowManager的addView,LocalWindowManager相比于WindowManagerImpl多了一层包裹,可以用来进行一些窗口参数的配置等。调用了LocalWindowManager的addView之后,又要调用WindowManagerImpl的addView方法,一个应用程序只有一个WindowManagerImpl对象,WindowManagerImpl中持有三个数组,其分别为Views(每一个窗口),ViewRoot(每一个窗口对应的ViewRoot),WindowLayoutParams,每一个窗口对应的LayoutParams。调用了addView之后,检查窗口是否已经被添加,然后创建ViewRoot对象,ViewRoot中创建了一个Surface对象,只是一个空壳Surface,没有为其分配具体的地址,调用ViewRoot的setView,给ViewRoot的变量进行赋值,调用requstLayout,发出界面重绘的消息。调用sWindowSession.add()通知Wms添加窗口, mWinsowsession每一个应用程序对应一个,是一个Binder引用,该引用对应Wms的子类。同时对于Surface对象进行了赋值。当一个应用程序需要创建窗口时,首先在本地创建一个Surface对象,然后调用WindowManager类向Wms服务发起请求,请求参数包含Surface对象,Surface类是一个壳,其初始化的本质是给Surface对象分配一段屏幕缓冲区内存。Wms收到请求,调用Surface类的JNI调用SurfaceFlinger——client驱动,通过该驱动为请求sf进程创建指定的窗口,sf创建一块屏幕缓冲区,并在sf内部记录下该窗口,然后sf会把缓冲区地址传递给Wms,Wms在用这个地址去初始化Surface对象。有了平面,但是我们还是不可以在上面进行绘制,Android使用了一个Skia的绘图驱动库,程序中用Canvas类来表示这个功能对象,surface类包含一个函数lockCanvas,可以返回一个Canvas对象。为Canvas指定了一块内存,绘制的结果是给该块内存地址填充不同的像素值。

  Surface的构造函数首先创建一个Canvas对象,该对象作为对于底层的JNI函数的一个外部引用,然后调用init函数,创建一个真正的surface,首先是获得一个SurfaceComposerClient对象,该类是Native层面上SurfaceFlinger服务的客户端对象,然后调用该对象的createSurface函数,创建一个真正的Surface对象,参数包含了当前进程的pid,请求窗口的宽和高。Drawable类,我们可以给它传递一个Canvas,然后就可以进行绘制。

  Pms的作用

  提供根据Intent匹配具体的Component,根据参数中指定的intent转化成一个具体的程序包名和具体组件名称的信息,方便Java类加载器的转载

  权限检查

  提供安装,删除接口

  Ams的作用

  统一调度应用程序的Activity

  内存管理,对于Activity并不会立即杀死,而是对其进行缓存

  进程管理,提供对于运行进程的相关信息的管理

  创建应用进程

  Ams通过调用Process进程类启动一个新的应用进程,新的应用进程会从ActivityThread的main函数开始执行,目标进程启动后,会报告给Ams,然后Ams通知目标进程启动目标Activity。当启动进程的事情结束了,目标进程会通过IPC调用AMS的attachApplication请求Ams给指定目标Activity去执行。

  attachApplication过程,对app对象内部的变量进行赋值,同时根据指定的Activity加载相应的dex文件,根据Intent中的信息,然后查询ApplicaitonInfo,这个时候就已经执行了Application类,然后根据指定的Activity,去启动目标Activity。此时进程中的文件是Framework中的ActivityThread基类。

  新启动的进程在Ams提供的ApplicationInfo的信息加载具体的Activity,ApplicationInfo可以用来进程间的通信。

  attachApplication过程

  handleBindApplication

  重新设置时区和区域,装载相应的系统资源

  是否存在Instrumentation类

  调用makeApplication创建Application类的对象,调用APK文件中的类对象,

  启动Provider,在Activity之前启动

  调用Application的onCreate方法

  handleLaunchActivity

  应用进程launch指定的Activity

  加载目标Activity类

  创建一个ContextImpl对象,每一个Activity都包含一个ContextImpl对象,是一个轻量类,创建后,调用Activity.attach方法,用ContextImpl来初始化Activity对象,同时将其作为Activity的baseContext。

  然后调用Activity的四个声明周期函数。

  把新建的Activity对象家督到ActivityThread的activity列表中,存放是目标Activity和ActivityRecord的对应

  Activity对象找到自己的DecorView显示到屏幕上