Home - mpgcompile/principle GitHub Wiki

AMS

  • 1、ActivityThread源码
  • ActivityThread的main方法是一个App的真正的入口,MainLooper在main方法创建.
    main方法做了一些looper、和handler的初始化
  • 2、ActivityThread和AMS之间的通信
  • AMS通过attachApplication将ApplicationThread绑定到AMS.ApplicationThread是ActivityThread私有内部类,实现了IBinder接口,用于ActivityThread和AMS进程间的通信。
  • 3、app的启动机制
    A: Launcher的startActivity,通过Binder通信,调用SystemServer进程中的AMS的startActivity方法
    B: SystemServer收到请求之后向zygote发送创建进程的请求.
    C: zygote进程fork出App进程执行ActivityThread的main方法,looper初始化,创建ActivityThread,handler初始化。
    D: App进程中通过Binder向SystemServer发送创建attachApplication。
    E: SystemServer收到请求之后,通过binder向App进程发送handlerBindApplication(初始化application并调用onCreate)和scheduleLaunchActivity请求(创建Activity)。
    F: App进程binder线程收到请求之后,通过hander向主线程发送绑定application和创建activity的消息。
    E: 主线程收到消息之后,创建Application并调用onCreate,创建目标的Activity并调用onCreate。
  • 4、activity启动机制
    A: 通过IPC调用AMS的startActivity,然后在ActivityThread的HandleLanchActivity先初始化window,实际就是phonewindow然后调用onCreate。
    B: setContentView初始化decorView,decoview是phonewindow变量继承自FrameLayout。
    C: decorview是根布局里面有一个ContentViewGroup是加载layout的。
    D: 加载layout之后,透过windowmanager把window添加进去显示到界面上。

PMS

  • 1、PMS的结构
    A: IPackageManager.aidl:接口,定义了服务端和客户端之间通信的函数方法。
    B: PackageManagerService:服务端。继承IPackageManager.Stub,继承Binder。
    C: PackageManager:抽象类
    D: ApplicationPackageManager:客户端。PackageManager实现类,通过内部的mPM变量参与Binder通信。
  • 2、PMS的启动
    A: PMS是在systemServer启动之后,是在startBootstartService启动的
    B: PackageManagerService.main():中才是真正启动PMS的服务,初始化PMS,注册服务
  • 3、APK安装过程
    A: InstallStart→PackageInstallerActivity→InstallInstalling
    B: onCreate()创建安装会话,返回sessionid
    C: 创建安装会话,进一步安装。onResume mInstallingTask.execute
    D: PackageInstaller.Session.commit()发送安装
    E: 通过Handler发送了MSG_COMMIT消息,进程间通信
    F: 通过mPm.installStage进入PMS处理
    G: 通过Handler发送INIT_COPY消息,拷贝APK进一步安装(startCopy()),拷贝安装路径
    H: copyFile,拷贝完成之后执行processPendingInstall,开始真正的安装
    I: installerPackageLI检查包的完整性、SDK版本、签名、共享库、设置权限等等,检查安装环境是否满足等。进一步安装
    J: 最终通过binder进入install进程,安装完成

一 SharedPreference

  • 1、commit相对于apply效率较低,commit直接是向物理介质写入内容,而apply是先同步将内容提交到内存,然后再异步向物理介质写入内容。
    2、apply没有返回值,异步操作,第一部写入内存,第二步写入物理磁盘。commit同步操作,有返回值。

二 HashMap

  • 1、jdk1.7数组+链表(16个元素),jdk1.8数组+链表(8个元素)+红黑树,超过8个元素转化红黑树。
    2、扩容机制,出现hash碰撞且到达0.75因子。
    3、put源码 -new HashMapEntry(),在每个数组元素上都有一个链表结构,当数据被Hash后,得到数组下标,把数据放在对应下标元素的链表上。

三 Binder和Linux进程通讯

  • 1、Binder基于C/S架构:Client、Server、Binder驱动 ServiceMannager。
    2、Binder负责client请求转发到serve中执行,并将server返回数据 →client。
    3、ServiceManager使Binder驱动能够转发给具体的Server。
    4、server向ServiceManager注册,client向sm请求server的binder引用,拿到数据之后 binder驱动→通信 server返回数据。
  • A: Linux进程通讯方式(管道pie 信号量 消息队列 共享内存 socket)
    B: 为什么选用Binder作为Android IPC机制呢?
  • 1、从性能来说,管道、消息队列、Socket对数据都会进行两次拷贝,耗费性能,而Binder只需要一次,对于移动设备来说,性能不得不考虑。
    2、从架构来看,C/S架构,功能分离明确,稳定性好。
    3、最重要的一点,Linux IPC 无法鉴别身份,而Binder 可以鉴别用户进程Uid,给予Android身份机制。
    4、从语言来说,Linux 是基于C语言面向过程,而Binder是基于Java面向对象来实现的。
  • C: Linux进程原理,两次拷贝(用户空间 – 内核空间 – 用户空间),效率低下
  • 1、发送方将数据放在缓存区中,通过调用系统API进入内核中
    2、内核服务程序在内核空间分配内存,将数据从发送方缓存区复制到内核缓存区
    3、接收方读数据也要提供一块缓存区,内核将数据从内核缓存区拷贝到接收方缓存区并唤醒线程。即完成一次数据发送
  • D: Binder采用一种全新策略:由Binder驱动负责管理数据接受缓存,通过实现mmap()创建数据接受的缓存空间
    mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
    mmap()返回值是内存映射在用户空间的地址,这段空间为驱动管理,用户不必直接访问(映射类型为PROT_READ,只读映射)。

四 系统启动流程 (bootloader是厂商烧录到芯片的一段代码)

  • 0、开机上电之后,BootLoader拿到cpu使用权,之后做一些初始化工作 。最后把cpu使用权交给kernel
    1、BootLoader引导Linux Kernel启动、Android启动。
    2、BootLoader将系统的软硬件带到一个合适状态、把系统拉起来。
    3、Linux Kernel启动会初始化环境/驱动,启动init进程。
    3、init进程是一个由内核启动的用户级进程,执行函数→ rc文件解析→启动ServiceManager(管理 binder service)和Zygote进程。
    4、zygote进程启动 → 建立Android运行空间app-process Android Runtime →虚拟机→zygote main方法→System Service启动→startBootStopService
    →ActivityManagerService。ams开启之后,会遍历所有presistent=true的应用,有就通知zygote开启一个进程
    A: 启动加载模式
    Bootloader从目标机的某个固态存储设备上将操作系统加载到RAM中运行。
    目标机上的Bootloader将通过串口或网络等通信手段从开发主机(Host)上下载内核映像和根文件系统映像等到RAM中,然后可再被Bootloader写到目标机上的固态存储媒质中,或者直接进行系统的引导。
    C: 启动过程
    第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现(基本硬件设备初始化,为第二阶段准备RAM空间)。
    第二阶段通常用C语言完成,以便实现更复杂的功能,也使程序有更好的可读性和可移植性。

JVM

  • 1、一套自字节码指令集、一组寄存器、一个栈、一个垃圾回收、堆和一个存储方法域。
    2、内存空间(方法区 堆 方法栈 本地方法栈 PC寄存器)。
    3、内存模型(内存屏障(保证执行顺序和可见性的一条cpu指令) 重排序 主内存(共享区域) 工作内存)。
    4、GC ROOT作用域(栈中的引用 方法区的常量和静态引用 JNI中的引用)。
    A:加载时分为五个部分
    加载 → 验证 → 准备 → 解析 → 初始化
    其中初始化时,遇到多个类循环引用,会创建一个空Object类,去替换掉循环引用的类。
    5、新生代(eden)占堆1/3的空间,如果对象内存占用过大,则直接分配到老年代
    6、JVM运行时的内存 : 新生代、老年代 、 永久代(JDK1.8中,永久代被移除成为元数据,永久代主要存放class和meta)
    7、新生代minor过程: 复制 – 清空 – 互换: 采用复制算法
    eden,servicorFrom复制到servicorTo 年龄+1
    把eden和servicorFrom区域存活的对象复制到servicorTo区域
    如果有对象的年龄达到了老年的标准,则复制到老年代
    8、老年代对象比较稳定,majorGC不会频繁执行。导致空间不够用时,才触发MajorGc采用标记清除算法
    9、被volatile修饰的变量,会加一个lock前缀的汇编指令。若变量被修改后,会立刻将变量由工作内存回写到主存中。
    那么意味了之前的操作已经执行完毕。这就是内存屏障。
    它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;
    即在执行到内存屏障这句指令时,在它前面的操作已经全部完成

六 ArrayList LinkedList

  • 1、ArrayList快速随机访问(RandomAcess)内存地址不连续;LinkedList增删快,查询慢,是由于链表支持顺序访问,内存地址连续。

七 动态字节码 BCEL、Javassist、ASM、CGLib

  • 1、在ASM代码实现里,最主要的就是访问中模式。
    2、classReader是ASM入口:传入一个classvistor,这个vistor实现vistuethod。
    3、Instrument是JVM提供的一个可以修改已加载类文件的类库,tansform方法会在类文件被加载时调用。

八 Synchronized、Lock、ThreadLocal、Volatile

  • A: Synchronized
    1、synchronized底层是通过监视器的enter和exit实现,monitor监视器锁,线程执行monitor enter指令获取权。
    2、作用方式时锁住的是对象的实例(this);作用于静态方式时,锁住的是class实例;作用于对象实例时,锁住的是所有调用改对象的方法块。
    3、waitSet(调用wait被阻塞线程);contentionList(竞争队列);EntryList(有条件成为候选的线程);Ower(获取资源的线程);!Ower(被释放线程)。
  • B:Lock
    1、Lock实现类ReentrantLock,除了完成Synchronized之外提供了请求可响应中断锁、可轮训锁、定时锁等避免死锁的方法。
    2、voidlock;执行此方法,如果锁处于空闲宅状态,当前线程获取别的锁。
  • C: Synchronized和Lock比较
    1、都是重入锁,同一线程可以多次获得同一个锁。都保证了锁的可见性和互斥性。
    2、lock是api级别的,乐观并发,同步非阻塞;synchronized是jvm级别的,悲观并非,同步阻塞。
  • D: Synchronized和ThreadLock比较
    1、synchronized是通过线程等待,牺牲时间来解决访问冲突。
    2、threadlocal是通过每个线程单独一份存储空间,牺牲空间来解决冲突。具有隔离效果,线程内。Loper、ActivityThread、AMS。
  • E: Synchronized和Volatile比较
    1、synchronized保证可见行和原子性;volatile保证可见性,不保证操作的原子性。
    2、可见性:一个线程对共享变量的修改,能够及时被其他线程看到。
    3、原子性:即不可再分了,a=1和return a都是原子性,a+=b不是。
  • F: 阻塞状态
    1、等待阻塞: 运行线程执行o.wait(),jvm会把该线程放入等待队列
    2、同步阻塞: lock-锁池
    3、其它阻塞: 执行sleep或join方法时、或者发生了I/O请求时,jvm会把该线程置为阻塞状态

九 网络七层架构

  • 1、物理层: 定义物理设备标准、网线接口类型、传输速率、比特率
    2、数据链路层: 主要是从物理层接受数据,进行mac地址解析封装
    3、网络层: IP地址封解析、数据包
    4、传输层: 定义传输数据协议和端口号
    5、会话层: 建立传输的会话
    6、表示层: 对数据解析加密
    7、应用层: ftp(文件下载)等

十 TCP三次握手

  • 1、主机A发送位码syn=1,随机产生seq number=12345数据包到服务器,主机B由syn=1知道,A要求建立连接
    2、主机B收到消息后向A发送 ack =number syn=1 ack=1 随机产生seq54321包
    3、主机A收到后检查ack number是否正确,主机A再发送ack=number ,B机确认后连接成功
    A: 断开四次握手
  • 1、tcp半关闭造成的断开需要四次握手,tcp是双全工(数据在两个方向同时传输),所以进行关闭时,每次都得需要单独关闭,单方向就是半关闭。

十一 HTTP原理

  • 1、地址解析、协议名http、主机名、端口号
    2、封装http请求数据包
    3、封装tcp包,并建立连接

十二 HTTPS原理

  • 1、服务器将携带的公钥向数字证书机构申请证书。
    2、数字证书机构用自己的私钥对公钥签名颁发证书,并返回给服务器。
    3、服务器将申请携带公钥的证书分发给客服端。
    4、客户端验证证书,证书机构通过验证,或者用户接受不受信任的证书(非权威机构颁发的证书)。获取到公钥。到这一步,在证书保证下服务器拥有私钥,客户端拥有公钥,可进行非对称性加密。
    5、使用公钥加密报文发送给服务器,其中携带随机串。其中的随机串用户传输数据时进行对称加密
    6、服务器使用私钥解密。获取报文信息及随机串。
    7、解密后服务器发送握手消息给客户端。
    8、客户端接受握手消息,握手结束,双方确定加密算法(使用随机串确定的对称性加密),开始传输。

十三 TCP和UDP

  • 1、udp无需三次握手,头部开销小是有八字节,在传输数据报文时很高效。并把所有接受的消息都放到缓冲区队列中,因此接受数据更方便
    2、tcp粘包指发送方发送的数九到接收方时粘成包了
    3、利用tcp每次发送数据,就于对方连接,然后双方发送完数据后,就关闭连接
    A TCP如何保证可靠性
  • 1、使用序号,对收到的tcp报文段进行排序以及检测重复的数据
    2、使用校验来检测报文段的错误
    3、使用确认和计时器来检测和纠正丢包或延时
    4、tcp头部为20字节

十四 Java泛型

  • 1、类型通配符: 一般使用?代替的类型参数
    2、类型擦除(伪泛型): Java中的泛型都是在编译层次实现的,在生成的Java子字节码中是不包含泛型中的类型信息。
    使用泛型的时候加上类型参数,会被编译器在编译的时候去掉,这个过程就叫类型擦除。
    类型擦除过程,首先是找到用来替换类型参数的具体类,这个类一般是Object。
    3、无限制通配符:<?>
    4、<? extends E> 声明类型的上限,类型可能是指定类型,也有可能是此类型的子类
    5、<? super E> 声明类型的下限,类型可能是指定类型,也有可能是此类型的父类
    十四 Java 装箱和拆箱
  • 1、装箱: 就是把包装器类型转换基本数据类型 如 Integer i = 10;
    2、拆箱: 就是把基本数据类型转换为包装器类型 如 int n = i;

十五 JNI基础

  • 1、jni原理
    A:JavaVM:是java虚拟机在JNI层的代表,jni全局只有一个
    B:JNIEnv: javavm在线程中的代码,每个线程只有一个,jni可能有很多jnienv
    a:调用java函数:jnieny代表了java执行环境,能够使用jnieny调用java代码
    b: 操作java代码: java对象传入jni层就是jobject

十六 Okio

  • 1、以Segment作为存储结构,移动segment引用,不用copy数据(一个缓冲区到另一个缓冲区)。
  • 2、segment能通过split()进行分割,可实现数据共享。
  • 3、Source对应输入流,Sink对应输出流

十七 BroadCast

  • 1、LocalBroadCast是应用内,基于Handler实现的通讯。
  • 2、BroadCast是全局的。基于Binder实现通讯。
  • 3、静态注册会一直存在,动态则是代码注册和注销。

十八 Camera

  • 1、相机模组由镜头(lens),传感器(sensor),图像处理芯片(backend ic) 数字信号处理芯片(DSP),软板(fpc)
  • 2、Camera主体分为四层
    a: 应用层,调用AOSP提供的接口。这些借口通过Binder与Framework层的相机服务进行交互
    b: Framework层,承上启下,上与应用层交互,下与HAL交互
    c: HAL层,硬件抽象层,由vendor自己实现
    d: Driver层,驱动层,数据由硬件到驱动层处理,驱动层接受HAL层数据以及传递Sensor数据到HAL层
  • 3、交互流程
    a: 调用API通知Framework Native Service CameraServer去connect HAL继而打开Camera硬件sensor
    b: openCamera成功之后会回调从CameraServer通知到App,之后startPreview-CameraCaptureSession-ConfigureStream
    c: ConfigureStream,该步就是将控件如GLSurfaceView,ImageRender等中的Surface容器给到CameraServer
    d: CameraServer初始化时,开启一个死循环线程等待来接受request
    e: CameraServer将request交到HAL层处理,得到HAL处理结果后取出该request的result中的buffer交给app中的surface容器
    f: 如果是Capture Request则将收到的buffer交给ImageRender的Surface容器
    g: Surface本质是BufferQueue的使用者和封装者,当CameraServer中的App设置的Surface容器被填满了BufferQueue机制将会通知应用
    Preview控件中的Surface内容将通过View提供到SurfaceFlinger中进行最终的合成显示,即预览;而ImageRender中的Surface被填满了,这就是保存成图片。即拍照

 

⚠️ **GitHub.com Fallback** ⚠️