Android Framework层开发

1.Android Framework基础

Framework
查看源码工具:SourceInsight
在这里插入图片描述
Instrumentation:可以理解为ActivityThread的一个工具类,在ActivityThread中初始化,一个进程只存在一个Instrumentation对象,在每个Activity初始化时,会通过Activity的Attach方法,将该引用传递给Activity。Activity所有生命周期的方法都有该类来执行。

1.1 系统启动流程:

Init进程(pid=1): 启动和守护系统的关键/核心服务(父pid=1,比如start ServiceManager/SurfaceFlinger/Zygote) :杀不死的服务(打电话,发短信,小米商城等卸载不了的,init的子进程(ServiceManager、SurfaceFlinger、Zygote))
Zygote进程(App-process,2377):通过解析init.rc(任务清单)来启动Zygote进程(启动所有App进程;Zygote是native进程-因为入口函数是C语言),Zygote会开启一个serverSocket(c/s,串行)和别的进程通信,为了降低开启App进程效率(打开10个App,开辟内存100->10G); 作用:加载系统资源, 开启App进程;
-Xzygote /system/bin --zygote --start-system-server
SystemServer(1457):Zygote进程fork出SystemServer进程(这是个java进程),并开启(startBootstrapServices)好多服务(AMS,PMS,WMS)

PMS(运行在开机的时候): 包管理相关操作,

  • 1>.遍历包 /data/app文件夹(scanDirLi 遍历并确定是不是Apk -> 获得路径给第二步);
  • 2>.解压apk fun scanPackageTracedLi -> (ParallelPackageParse.java类操作.parsePackage ->loadApkIntoAssertManager -> 获得cookie给第三步)
  • 3.> DOM解析 AndroidManifest.xml (fun openXmlResourceParser(cookie,MANAFEST_NAME)) -> 最终会得到一个Package对象,里面会包含四大组件的ArrayList<ActivityInfo -> bean对象>集合,并将这个Package对象放到缓存中(ArrayMap<String包名,Package>),以便查找 ; => 提供查询结果;

AMS:Activity管理操作(启动和生命周期的管理):

  • 1. AMS的startActivity会从PMS中获得package信息
    • 1.1 AMS的startActivity方法中 -> 创建ActivityStarter.class对象,并调用execute()方法 -> 创建 ActivityStackSupervisor.class 调用resolveIntent(intent, ) 从而返回ResolveInfo;
    • 1.2 resolveIntent方法中具体细节: 通过ams.getPackageManagerInternal -> PackageManagerInternalImpl(PMS的内部类)-> packageManager.resolveIntent -> 获得package后进一步获得ResolveInfo (包含ActivityInfo,serviceInfo…)
    • 1.3 ActivityStarter中处触发mSupervisor.resolveActivity() (把rInfo转activityInfo)
    • 1.4 activityStarter中调用.startActivity( appInfo) -> resource
  • 2. AMS间接触发appThread.scheduleLaunchActivity(ActivityInfo info) (在at.attachApplication的时候,AMS会获得appThread,注意:appThread是activityThread的内部类)
    • 2.1 AT: sendMessage(case: LaunchActivity) -> handleMessage
  • 3. AT: handleLaunchActivity(activityClientRecord, intent) 被触发在handleMessage中,activityClientRecord是来自ams传过来的信息;
    • 3.1 利用反射从r.activityInfo创建activity对象(instrumentation来搞)
    • 3.2 AT: activity.attach(appContext) 再此会new PhoneWindow() 和构建windowManager管理对象;
    • 3.3 AT: instrumentation.callActivityCreate() (然后把activity对象封装成ActivityClientRecord对象(r.activity = activity),并将其添加到缓存。at.activities: ArrayMap<IBinder, ActivityClientRecord这是个activity的包装类>,记录打开过的Activity. )
    • 3.4 Instrumentation: performCreate() -> activity.onCreate()

1.2 APP首次启动过程(二次启动走startActivity)

  1. 点App图标,Launcher进程从ServiceManage里面获得AMS服务,然后触发startActivity.

  2. 如果没有App进程,则Zygote进程fork出App进程, 触发ActivityThread的main函数 -> new ActivityThead() -> at.attach()

  3. App进程中获得AMS本地代理(AT: ActivityManager.getService()),触发amsProxy.attachApplication(创建application,attachBaseContext 和realStartActivity);
    细节别管
    -> AT: amsProxy.attachApplication(appThread) 其中appThread是IApplicationThread.stub. 为了AMS和APP通信。
    -> AMS: appThread.bindApplication(progressName, appinfo,… ) // AMS拿到appInfo给App进程,然后这些信息组装成一个appBindData -> AT: sendMessage(BIND_APPLICATION, appBindData) -> AT: handleMessage(case Bind_Application) -> AT: activityThread.handleBindApplication(appBindData) (创建app: makeApplication -> app.attachBaseContext -> installContentProvider -> 执行Application的生命周期函数:callApplictionOnCreate 就是这后三步耗时) 最终创建出Application 而且走到application的onCreate方法。

  4. AMS间接触发**appThread.scheduleLaunchActivity(ActivityInfo info)**** (在at.attachApplication的时候,AMS会获得appThread,注意:appThread(IApplicationThread.stub)是activityThread的内部类)

  5. AT: handleLaunchActivity(activityClientRecord, customIntent) (具体加AMS那一部分)

上面四部过程中都是黑白屏(fork app进程之前)的状态 -> 解决方案:给appTheme为一张带有app logo的图片(addSplashscreenContent只能是drawable,aos12之后可以是一个动画);在splashActivity显示的时候,黑白屏终止;
@drawable/icon
广告页(splashActivity):预加载数据;

启动优化:
在attachBaseContext中搞事情:加载dex文件(热修复,加固)
在installContentProvider中搞事情:有的第三方leakCanary写了contentProvider;
在app的onCreate中优化:减少第三方SDK 启动,或者异步启动
在这里插入图片描述

在这里插入图片描述

1.4 WMS

在这里插入图片描述
窗口管理,窗口动画,输入系统中转站和Surface 管理. 如窗口创建、绘制、更新、响应事件等
WindowManagerGlobal 就是专门和WMS通信的,类似于appThread和AMS通信。

WMS是管理所有App的PhoneWindow的,例如:addView,removeView, updateViewLayout;
WindowManagerGlobal(单例,一个App中只有一个): 缓存App中所有的DecorView,给wms提供服务,wms也只和WMG联系;
会通过getWindowManagerService 拿到WMS的binder:sWindowManagerService:IWindowManager.Stub.asInterface

1>. 在startActivity中:AT: activity.attach(appContext) 的方法里会构建phoneWindow和windowManagerImpl:
2>. View和window的关联
handleResumeActivity中拿到 PhoneWindow和Decor还有wm:WindowManagerImpl(这个里面会持有Activity的phoneWindow)
然后wm.addView(decor); 而WindowManagerImpl里面有global的单例;
因为global要把这个view丢给WMS, 然后wms调用底层来渲染;
global.addView(xxxz) 只干一件事 就是给view(DecorView)一个ViewRootImpl(处理onMesure、 onLayout、 onDraw )
root.setView(xxx)
mWindowSession.addToDisplay(xxx) // Session类是继承于IWindowSession.Stub;
mService.addWindow(xxxx) // mService = wms , addWindow后面会调用WMS的WindowState操作,最后会交给SurfaceFling进行完成。

3>. 绘制
Root: requestLayout() -> scheduleTraversals() ->
mChoreographer.postCallBack (runnalbe) 监听vSync信号,有信号则触发runnable方法:
runnable里面只搞了一件事: doTraversal() // 这个就是真正绘制
->performTraversals()
-> perfromLayout()这个方法里面会就找到DecorView 然后遍历所有view调用onMesure、onLayout、onDraw; 会调用seesion进行绘制。

注意:root中会拿到session,就是surfaceFlinger的本地代理binder
Global:global.getWindowSession( )返回 IWindowSession.stub 就是SF的本地代理的binder。
IWindowSession.stub里面有个属性是SurfaceSession
, 就是surfaceFlinger的surfaceSession
里面其实是:sWindowSession: wmsProxy.openSession()

在这里插入图片描述

1.3 AMS和PMS的作用:

1.3.1 Hook AMS实现集中式登录

Hook点一般在静态变量处(利用反射搞一搞):
通过Hook(反射的方式)拿到AMS的本地代理Proxy,然后去操作AMS里面流程,让Activity跳到自己想要的页面;

1.3.2 Hook PMS实现插件化

Activity/广播 打包-> Apk -> 利用发射拿到PackageParse.java来解压apk解码xml -> Package -> ArrayList<ActivityInfo/receiversInfo> -> 类加载loadClass(activityName).newInstance; -> 注册即可 -> 然后在宿主工程中就可以用了;

1.4. Launcher3定制

SystemServer会启动Launcher

1.4.1 启动流程

1>.systemServer-> startOtherService -> AMS的systemReady函数中调用aTaskManager.startHomeOnAllDisplay(), 此方法中PMS供过Intent获得activityInfo.

Intent(intentAction = Intent.ACTION_MAIN, category = Intent.CATEGORY_HOME)

2>.AMS调用ams.getActivitystartController().startHomeActivity(homeIntent, aInfo) 去开启launcher.

1.4.1 关键方法

  1. loadAllApps(); // 加载手机中所有的app信息; List
1>. 在launcher的onCreate方法中会创建loadTask, 会获取pmi,进而获取List<ResolveInfo>
mLauncherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
mLauncherApps.getActivityList(packageName=null,xxx)
1>.获取到 PackageManagerInternalPackageManagerInternalImpl,PMS的内部类)
LocalService.getService(PackageManagerInternal.class)
2>.List<ResolveInfo> apps = pmi.queryInterntActivities(intent=null,xxx)
ResolveInfo(包含ActivityInfo,serviceInfo...3>. 在loadTask中有个回调OnUpdateListener, 会调用rebindAdapter对数据进行填充绑定;
4>. 在viewHolder中会创建点击事件,进而调用startAppShortcutOrInforActivity(), 最终触发Activity的startActivity方法;---->AMS开启Activity的流程;

Launcher负责桌面滑动,App拖动和卸载之类的;
DragLayer: 处理拖拽事件;
ShotcutsInfo: 里面存放图标和标题信息;
AppWidgetProvider extends BroadcastReceiver : 小组件(日期)

1.5. SystemUI

1.5.1 SystemUI概述

SystemUI路径:framework/base/package/systemUI/
SystemServer会启动这个SystemUI的服务:

在startOtherServices中会启动SystemUI.
在这里插入图片描述

SystemUIService中的onCreate方法中:
// 这个里面就会添加systemUIServiceComponents
(SystemUIApplication getApplication()).startServicesIfNeeded();

1.5.2 SystemUI包含范围:

(1)StatusBars
(2)Navigation bars (底部导航)
(3)Notification (左上边下拉)
(4)Lockscreen keyguard_bouncer.xml
(5)Quick settings (右上边下拉之后,打开关闭Wifi的页面)
(6)Recents:Overview(recent task switcher)
(7)VolumeUI (音量大小UI)VolumeDialogControllerImpl去操作 AudioManager, IAudioService
(8)PowerUI (长按关机键的时候弹出的UI)
(9)ToastUI
(10)KeyboardUI

这些功能的类都继承SystemUI这个抽象类,并重写start方法;
在这里插入图片描述

1.6. 开机动画(BootAnimation进程)

开机后init进程会做两件事情:

  1. 解析init.rc, 启动关键服务(BootAnimation);
  2. 读取开机动画的解压包,播放帧动画;

1.7 MediaCodic 编解码

编码:摄像头获取的视频(Camera)/录屏视频(MediaProjectionManager) -> 编码成H254;
拍摄出视频的数据格式(采样格式YUV420SP, 陪一个色度) 可细分为:NV21(只有android手机是这样, Y在前VU交叉排列) 、NV12 (Y在前UV交叉排列)

mediaCodec = MediaCodec.createEncoderByType("Video/AVC");  
MediaFormat mediaFormat = MediaFormat.createVideoFormat(type, width, height);  
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);  
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);  
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);  
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);  
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);  
mediaCodec.start(); 

数据输入输出:MediaCodec使用ByteBuffer作为输入输出数据的载体,通过configure()方法配置输入输出格式,然后通过queueInputBuffer()方法将输入数据放入队列中,经过编码后,输出数据会被放入输出队列中,通过dequeueOutputBuffer()方法取出。

硬解码: 指的是系统将flv(举个例子)文件分离成H.264(video/avc)视频数据流和aac音频数据流,然后再将H.264视频数据流转交
给DSP芯片进行处理,DSP将处理好的一帧帧画面转交给GPU/CPU然后显示在屏幕上(surfaceview),这就是视频硬解码的过程。

FFmpeg其中包含了先进的音视频解码库 libavcodec 和音视频格式转换库 libavformat。libavfilter滤镜。

2. C(Java是C的一层封装)

2.1 概述

安装mingw,配置环境变量,即可用 gcc(类似Java的JVM)命令编译c文件;
写C的工具:CodeBlocks
预处理指令:#include <stdio.h> 预处理器会对其处理
条件编译指令: #if #else #elif #endif
宏定义:#define PI 3.14
可视化输入: scanf(“%d”, &a)
C是没有GC的!C的碎片管理是依托于OS的碎片整理机制

2.2 数据类型

在这里插入图片描述

// 变量:直接定义的数据会存放在栈里面
int a = 1// 常量:用const修饰
const int a = 10// 字符串
char *pstr = "hello"; // psre保存的是字符串的首地址
char str[] = "hello"char str[] = {
   'h','o', '\0'}; // 要有结束符号

2.2.1 指针变量(地址不可更改)

指针:变量的地址;
取地址运算符:&
解引用运算符: * ; *p 就表示 指针变量指向的p变量;
指针运算只支持±,且步长是指针变量的步长;

2.2.1.1 指针在数组中的使用
int arr[] = {
   1, 2 , 3 , 4 , 5} // 数组必须初始化, 这个写法int arr[]; 就是错误的
sizeof(arr)/sizeof(arr[0])  // 数组长度


int *p = arr;   // 等价于 int *p = &(arr[0]),  定义的时候 * 表示指针的关键字,使用的时候* 表示取地址中的变量;
那么 arr就是p 都表示第一个元素的地址;p是放地址的,占8个字节,且p只做加减运算;

// 二维数组
typedef char (*PTR_TO_ARR)[30]; // 数组指针
char str[3][30] = {
   
    "http://c.biancheng.net",
    "C语言中文网",
    "C-Language"
};
PTR_TO_ARR parr = str;
取值: *(parr+1)  的值就是"C语言中文网",
2.2.1.2 函数指针

类似于数组的指针,C语言中直接获取函数名,就可以得到这个函数的函数指针。
函数指针就是个指针,指向这个函数的内存;
作用:用函数指针可以调用函数;(函数指针可以作为函数参数 就像回调函数-类似闭包)

void test(int a){
   
}
test;//这就是一个函数指针,它的类型是void(*)(int)

void test1(int a){
   
	printf("测试\n");
}
int main(){
   
    //这里将void(*)(int)类型的函数指针重命名为P
	typedef void(*P)(int);
    //并将void(*)(int)类型的函数指针test1赋值给p(初始化)
	P p = test1;  	<=>  P p1 = &test1;
    //调用函数操作
	p(1);   <=> (*p)(1);
2.2.1.3 指针函数

指针函数,说的就是函数,函数的特征点就是返回值为指针。
无法返回局部变量的地址 (因为函数执行完 这个变量就被释放了),可以给局部变量加static修饰;
作用:可以通过指针函数 访问代码顺序后面定义的 变量;

int* getPpos(int pos, int (*pstu)[4]) //第二形参为一个数组指针
{
   
	int *p;
	p = *(pstu+pos); //由于pstu为面向父数组的指针,为了解决p和pstu类型不匹配,所以进行*取得面向子数组的指针
	return p; //返回一个指向子数组的指针,即地址
}
2.2.1.4 数组指针

指向数组的指针;

int a = {
   6,7,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值