大道废

一切有为法,如梦幻泡影,如露亦如电,当作如是观.

0%

大恕家麦芽糖串串

豆袋下面

哥伦比亚水洗Supremo

卡杜拉种,麦德林,海拔1550-1700,中烘

可能尝到的味道:麦芽糖、蜜饯、杏子

Read more »

大恕家船长与赞美诗

豆袋正面

新几内亚水洗AA

帝皮卡种,谷地,海拔1600-1800,重烘

可能尝到的味道:香草、豆蔻、苹果酒

Read more »

android并没有提供一个一致性的统一的修改某个程序缺省字体的地方,于是网络上的方法:

  1. 在某个activity上得到所有要修改字体的控件,然后一个个的去修改。
  2. 自己实现所有要修改字体的控件的基础类,在这个类上去指定字体。
  3. 实现一个枚举方法,把activity上所有的控件列出,然后自动设置它们的字体。

这三个方法第一个实在太不体现智能了。而第二个是基本是在做死。第三个不错,我一开始也是使用这个方法的。但在实际使用中遇到了如果动态生成的控件,比如listview中由adapter生成的控件是无法在一开始就被枚举到,于是也就无法修改字体。如果放到onDraw里,是很不现实的会严重影响性能。如果放到adapter中的话,就与第一种或第二种没什么不同了,总不能每一个adapter都给个这个函数吧?如果自己生成一个BaseAdapter的话,那不其它类型的adapter就不能用了。

Read more »

Android本身有提供checkPermission(String, String)这一系列的函数来检查某个程序是否有某个权限。但这系列数实际上是在检查AndroidManifest里那user-permission里是否写上了某个权限。大家都知道,这根本行不通,因为安装时那些权限根本没地方让用户部分接受。用户要么全接受一个普通的程序居然有定位读通讯录删除短信这种权限,要么就完全的不能装这个程序了。在一些android机子上,比如华为,会有权限管理这一项。里面可以将程序的一些权限关掉,比如定位、读通讯录、相机还有录音之类的。这个设置就无法通过checkPermission(String, String)这一系列的函数来得到正确的结果了。

Read more »

类别 名称 重量
MSR 1.7升锅 304
MSR 2.5升锅 430
火枫 集热锅 205
铝水壶 147
1升铝锅 53
1.5升 铝锅 82
2升 铝锅 101
3升 铝锅 152
小煎盘 69
大煎盘 115
钛锅把 24
铝锅把 38
锡箔锅盖 5
铝锅把(亮面) 44
炉头 MSR 炉头 177
火枫 大黄蜂 48
长罐转换头 30
火枫 光芒分体锅头 280
三头酒精炉 70
树哥双层柴火炉
树哥双层酒精炉加炉架
钛柴火炉 123
钛柴火炉酒精棉球支架(两根) 16
Tiji钛双层柴火炉 147
FOX 折叠锯子 161
金属棉球酒精垫 5
树哥皇冠酒精棉球炉 11
气罐架 20
木棉球酒精垫 13
小姜手作酒精炉 14.2
bushbuddy柴火炉 181
水具 MSR4升水袋 166
膳魔师FEK800 355
虎牌 480 193
鸭嘴兽1升水袋(奶头盖子) 35
鸭嘴兽1升水袋(普通盖子) 25
鸭嘴兽2升水袋 35
红酒水袋 50
鸭嘴兽水袋管 77
FlodACup 折叠水杯 50
睡觉的家伙 HW LCW300 睡袋 512
田野热核 充绒650 睡袋 872
冰焰 充绒500 睡袋 815
TAR XLITE 充气垫 353
TAR 银搓 215
山之泉蛋槽 189
迪卡侬瑜珈垫 88
SEATTOSUMMIT Nano 蚊帐 95
AR气泵 84
NodWand气泵 58
酱铺2人cuben金字塔 581
懒猫五方塔 566
AMK 救生毯 82
AMK Bivvy 101
钛地钉(长) 15
迪卡侬方钉 11
酱铺发泡垫 224
钛空心地丁 8.8
背包 花岗岩 烈火 1350
花岗岩 晴朗 1030
ULA EPIC 1052
SEATOSUMMIT 35升大河防水袋 237
SEATOSUMMIT 60升大河防水袋 316
多特水壶腰包 174
收线夹 7
胸扣 9
MOLLE扣 7
翔野MOLLE小腰带包 99
翔野MOLLE大腰带包 174
翔野MOLLE水壶包 113
强氧魔怪 105
强氧色包MINI 251
酱铺三明治(含两个腰包一个肩包) 1010
电器 米勒 ML102 33
米勒 ML202 60
18650电池 47
长天 M1200E 27
长天 M241A 40
MOTO DEFY 导航用 114
华为荣耀3C 137
品胜电霸1000 300
曼福图三角架 162
索尼Alpha5000 414
小米两万毫安充电宝 321
伏来阳太阳能板 207
NOKIA 1210 黑白机 76
小米双头充电器 61
garmin forunner 935 50
华为充电5V1A 28
短苹果线 8
iPhone11 211
紫米Type-C充电线+Lightning转接头 30
Apple Watch充电器 24
衣服 cloudveil 防风抓绒 341
迪卡侬羊毛T恤 163
迪卡侬普通T性 127
迪卡侬绒里长袖 263
迪卡侬速干长袖 186
迪卡侬49抓绒 293
迪卡侬速干短裤 229
迪卡侬速干长裤 322
迪卡侬七分裤 134
迪卡侬紧身绒裤 195
迪卡侬抓绒裤 165
迪卡侬防风手套 82
迪卡侬空顶帽 41
IB羊毛袜子 73
outdome羊毛袜子 60
羊毛帽子 78
buff windstopper头巾 79
始祖鸟帽 64
带帽檐头巾 59
smartwood 袜子 68
始祖鸟冲锋衣 400
黑冰羽绒脚套 155
暖宝宝手套 36
HW羽绒短袖 230
天石羽绒裤 258
HW羽绒服 335
迪卡侬皮肤风衣 99
buff太阳帽 30
老鼠神衣 272
三峰裙子 72
冲锋裤 268
鞋子 510 914
杂项 救生哨加打火棒 33
手表加指南针 46
MSR 毛巾 41
PATAGONIA 腰带 132
安全头盔 330
折叠碗 49
HW小椅子 368
汽灯 151
HWB膑骨加压带 54
超轻毛巾 6
便便铲 16
防沙套 40
防水&收纳袋 TPU中号防水袋 34
TPU大号防水袋 67
花岗岩粗苯防水袋18升 24
酱铺粗苯收纳袋 9
SEATOSUMMIT EVENT防水袋 89
HW防水袋 47
蜂鸟6升防水袋 44
三峰收纳袋(中号) 27
三峰收纳袋(小号) 16
三峰收纳袋(大号) 36
三峰网袋(小号) 8
三峰网袋(中号) 13
三峰网袋(大号) 17

食物名称 口感 重量
科尔沁风干牛肉(原味) 口感不错,香脆。但有点过咸,当路粮吃可以,当配菜不行。当路粮吃时会有大量饮水的问题
宝矿力水特冲剂 口感不错,与成品水一样,很清爽
NUUN可乐味 真是难喝到奇皅
H5ZERO柚子味 真是不错,可以再喝
牛肉泡馍 酱包放一半味道非常好,吃不太饱,要配其它主食 178
糊辣汤 一小包可以泡一升这种子,可以吃饱的感觉。可加紫菜豆腐 90
士力架 天冷时很好吃
羊肉泡馍 酱包放一半 192
千石谷熟化米 真的是非常难吃的东西,以后不要买了 124
各种意大利面 分量很足,但太费火了,不合适重装户外,一两日吃吃可以
维维嚼益嚼(苹果味) 味道不错,有苹果的味道,口感与果条很像
维维嚼益嚼(芒果椰子) 有很浓的芒果味道,椰子味道没吃出来
维维嚼益嚼(红枣) 枣味非常浓,很像月饼
维维嚼益嚼(葡萄干) 味道不好吃,相对其它口味来说味道有点惨
维维嚼益嚼(山楂) 味道好像红枣
KOKA 原味鸡汤面 味道很清爽,鸡汤味很好,吃过不会口干
7COIN 泰式冬荫功风味 很浓的柠檬酸味,口味有点重,一点点的辣
喜达(sedoop)捞面原味 原味就是一种冬荫功的感觉,不过捞面看着美好,户外做起来要准备两个碗也是麻烦了点。
尾西 来自日本,于是很合适中国人的口味,比较清淡,就是份量不太足

Table of Contents

类别 名称 重量
  1.5升 铝锅 82
  钛锅把 24
  锡箔锅盖 5
  树哥皇冠酒精棉球炉 11
  木棉球酒精垫 13
  膳魔师FEK800 355
  鸭嘴兽1升水袋(奶头盖子) 35
  鸭嘴兽2升水袋 35
  冰焰 充绒500 睡袋 815
  TAR 银搓 215
  迪卡侬瑜珈垫 88
  懒猫五方塔 566
  救生毯 82
  钛地钉(长) 90
  ULA EPIC 1052
  SEATOSUMMIT 60升大河防水袋 316
  强氧魔怪 105
电器 米勒 ML102 34
  18650电池 188
  长天 M1200E 27
  索尼Alpha5000 414
  NOKIA 1210 黑白机 76
衣服 cloudveil 防风抓绒 341
  迪卡侬速干短裤 229
  迪卡侬防风手套 82
  outdome羊毛袜子 60
  羊毛帽子 78
  smartwood 袜子 68
  始祖鸟冲锋衣 400
  黑冰羽绒脚套 155
  天石羽绒裤 258
  HW羽绒服 335
杂项 救生哨加打火棒 33
  手表加指南针 46
  MSR 毛巾 41
  花岗岩粗苯防水袋18升 48
  酱铺粗苯收纳袋 9
  三峰网袋(中号) 13
  三峰网袋(大号) 17
6841 6841 6841

Table of Contents

类别 名称 重量
MSR 1.7升锅 304
炉头 MSR 炉头 177
水具 膳魔师FEK800 355
  鸭嘴兽1升水袋(奶头盖子) 35
  鸭嘴兽2升水袋 35
睡袋的家伙 冰焰 充绒500 睡袋 815
  TAR 银搓 215
  迪卡侬瑜珈垫 88
  懒猫五方塔 566
  救生毯 82
  钛地钉(长)\* 6 90
背包 ULA EPIC 1052
  SEATOSUMMIT 60升大河防水袋 316
  强氧魔怪 105
电器 米勒 ML102 34
  18650电池 \* 4 188
  NOKIA短USB线 10
  MOTO DEFY 114
  华为荣耀3C 137
  索尼Alpha5000 414
衣服 cloudveil 防风抓绒 341
  迪卡侬羊毛T恤 163
  迪卡侬绒里长袖 263
  迪卡侬速干长裤 320
  迪卡侬紧身绒裤 195
  迪卡侬防风手套 82
  outdome羊毛袜子 60
  羊毛帽子 78
  smartwood 袜子 68
  始祖鸟冲锋衣 340
  stoic冲锋裤 229
  黑冰羽绒脚套 155
  天石羽绒裤 258
  HW羽绒服 335
鞋子 510 914
杂项 救生哨加打火棒 33
  手表加指南针 46
  带帽檐头巾 59
  MSR 毛巾 41
  折叠碗 49
防水袋 花岗岩粗苯防水袋18升 \* 2 48
  酱铺粗苯收纳袋 9
  三峰网袋(大号) 17
    9235

Table of Contents

  1. Android 设计与实现 学习笔记
    1. JNI
      1. JNI方法全名规则
      2. JNI引用类型与JAVA引用类型的转化关系
      3. JNI方法签名规则
      4. JNI操作域与方法的函数
      5. JNI引用
      6. JNI异常处理
    2. 启动
      1. 启动流程
      2. 内核引导阶段
      3. 内核启动阶段
      4. init进程执行过程
      5. init.rc文件
      6. 执行Action,Service与属性服务
      7. 进入Java世界
    3. Binder
    4. 消息通信篇
    5. Package Manager
      1. 结构
      2. 启动
      3. APK安装过程
    6. Activity Manager
      1. 机制与实现
      2. 应用程序Activity的启动和调度
      3. Activity Manager进程管理

Android 设计与实现 学习笔记

JNI

JNI方法全名规则

java方法:public static native boolean isLoggable(String tag, int level)
JNI方法:static jboolean androidutilLogisLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)

JNI引用类型与JAVA引用类型的转化关系

Java类型 JNI类型
java.lang.Class jclass
java.lang.String jstring
java.lang.Throwable jthrowable
object[] jobjectArray
boolean[] jbooleanArray
byte[] jbyteArray
char[] jcharArray
short[] jshortArray
int[] jintArray
long[] jlongArray
float[] jfloatArray
double[] jdoubleArray

JNI方法签名规则

Java类型 类型签名
boolean Z
byte B
chat C
long J
float F
double D
short S
int I
L全限定类名;
数组 [元素类型签名

JNI操作域与方法的函数

访问对象域 调用实例方法 访问静态域 调用静态方法
GetFieldID GetMethodID GetStaticFieldID GetStaticMethodID
GetField CallMethod GetStaticField CallStaticMethod
SetField CallNonvirtualMethod SetStaticField  

JNI引用

引用类型 是否增加引用计数 作用范围 生命周期
局部引用 可以增加引用计数 本线程 一次Native调用,只在创建它的Native方法的线程中有效,并且只在Native方法的一次调用中有效,在方法返回后,被回收
全局引用 可以增加引用计数 多线程 多个Native方法,生命周期到显式释放。通过引用JNI函数NewGlobalRef创建,通过DeleteGlobalRef释放
弱全局引用 不能增加引用计数 多线程 生命周期到显式释放。通过NewWeakGlobalRef创建,通过DeleteWeakGlobalRef释放,通过IsSameObject判断是否被回收

if (env->isSameObject(weakref, NULL) == JNITRUE) 那么引用被释放

全局引用,默认不能超过2000个。如果超过,在logcat中会看到”GREF overflow”

JNI异常处理

检查异常的方法有:

  • 检查上一次JNI函数调用的返回值是否为NULL
  • 通过调用JNI函数ExceptionOccurred()来判断是否发生异常

检查到异常后必须予以处理:

  • 立即返回,异常会在Java代码中抛出
  • 调用ExceptionClear()来清除异常
JNI异常处理函数 功能描述
Throw 抛出现有异常
ThrowNew 抛出新的异常
ExceptionOccurred 判断是否发生异常,并获得异常的引用
ExceptionCheck 判断是否发生异常
ExceptionDescribe 异常堆栈信息
ExceptionClear 清除一个未处理的异常
FatalError 严重错误,退出

启动

启动流程

  1. 执行bootloader
  2. 调用startkernel进入内核启动阶段,最终启动用户空间的init程序
  3. init解析init.rc配置文件,开启zygote与ServiceManager两个守护进程。zygote为Android启动的第一个Dalvik虚拟机,ServiceManager是Binder通信的基础。
  4. zygote定义socket,用于接收ActivityManagerService启动应用程序的请求
  5. zygote虚拟机启动systemserver子进程
  6. systemserver进程的init1与init2阶段分别启动Native System Service和Java System Service
  7. 在systemserver中开启Android核心服务,并添加入ServiceManager中。设置系统为systemReady状态。
  8. ActivityManagerService与zygote中的Socket通信,通过zygote启动Home应用,进入系统桌面。
  9. zygote收到ActivityManagerService连接请求,执行runSelectLoopMode
  10. zygote处理请求通过forkAndSpecialize启动新的应用进程,并最终启动HOME

内核引导阶段

  • kernel/arch/arm/kernel/head.S
  • kernel/arch/arm/kernel/head-common.S

内核启动阶段

  1. kernel/init/main.c -> startkernel函数
  2. restinit -> kernelinit与kthreadd进程
    kernelinit -> initpost -> /init 程序,或:/sbin/init, /etc/init, /bin/init, /bin/sh -> runinitprocess

init进程执行过程

  • 创建 /proc, /sys, tmpfs, /dev/pts, /dev/socket, devpts, proc, sysfs 这些目录
  • 解析init.rc初始化文件
  • 触发build in的Action -> queuebuiltinaction, 这些action并没有在init.rc或者init..rc中配置
  • 重新启动异常退出的Service
  • 监听来自属性服务property service
  • 监控signal,接收子进程异常退出后抛出的SIGCHLD信号,回收子进程资源或者重启子进程
  • 监听来自keychord设备的事件

init.rc文件

  • 基本概念:Section, Action, Service, Trigger, Command, Option
  • 基本关键字:on, service
  • on -> Action
  • service -> Service,Option指定何时,如何启动Service程序。Service由服务名,服务对应命令路径,命令参数组成
  • Command -> Linux命令或者方法
  • Trigger -> 自定义的触发条件
  • Action -> on声明,Trigger触发的Command序列
Trigger关键字 描述
boot /init.conf被加载后的第一个trigger
property:= 属性值改变为指定值时
device-added- 添加设备时触发
device-removed- 移除设备时触发
service-exited- 指定服务存在时
Command关键字 描述
exec [\*] 执行路径为的程序,参数列表为\*
export 设置系统全局环境变量
ifup 使用ifup启动名为的网络接口
import 解析导入的init配置文件,扩展当前的配置
hostname 设置主机名
chdir 切换工作目录
chmod 修改文件访问权限
chown 修改文件所有者和组
chroot 改变程序执行所参考的根目录
classstart 启动指定类别的所有服务
classstop 停止指定类别的所有服务
domainname 设置域名
insmod 加载路径为的内核模块
mkdir [mode] [owner] [group] 创建路径为的目录
mount [\*] 挂载设备
setkey 暂时不可用
setprop 设置系统属性
setrlimit 设置资源限制,resource是当前要限制的资源,cur是软限制,max是硬限制
start 启动指定服务
stop 停止指定服务
symlink 创建指向的软连接
sysclktz westofgmt> 设置系统时钟基准
trigger 触发一个事件
write [\*] 打开路径为的一个文件,并写入一个或多个字符串
Option关键字 描述
critial 核心服务,在一定时间内退出多次,将导致系统重启到recovery mode
disabled 开机时禁用此服务,即开机时不会自动启动此服务,但是可以手动启动
setenv 为服务设置环境变量
socket [ []] 创建一个名为/dev/socket/的socket,然后把它的文件描述符传给启动程序。
  类型type的值为dgram或stream。perm表示该socket的访问权限;
  user和group表示该socket所属的用户各组,这两个参数默认为0
user 执行服务前切换到用户,此选项默认是root
group [\*] 执行服务前切换到组, 默认是root
oneshot 服务只启动一次,一旦关闭就不能再启动
class 为服务指定一个类别,默认为default, 同一类别的服务必须一起启动和停止
onrestart 当服务重启时,执行一个Command

执行Action,Service与属性服务

  • init.c中的executeonecommand, servicestart

  • init.c -> main -> actionforeachtrigger -> builtins.c中的doclassstart -> servicestartifnotdisabled

  • init.c -> main -> propertyinit() 属性服务内存共享区分配 -> propertyloadbootdefaults加载/default.prop文件中的属性 -> propertyserviceinit -> queuepropertytriggers

    1. propertyserviceinitaction -> startpropertyservice 加载属性文件,创建Socket接收客户端请求
    2. queuepropertytriggersaction 触发所有以property: 开头的Action
    3. 通过SOCKET实现属性,通讯接口为propertyset, propertyget

进入Java世界

  1. 启动zygote虚拟机,通过属性系统获取虚拟机配置信息,调用JNICreateJavaVM方法创建虚拟机

  2. 注册JNI方法,registerjniprocs

  3. AndroidRuntime:start -> CallStaticVoidMethod -> ZygoteInit的main 进入Java环境

    1. 注册zygote的Socket, ZygoteInit -> registerZygoteSocket
    2. 预加载Class资源和Resource资源, preload -> preLoadClass, preLoadResources
      1. preLoadClass 加载 preloaded-classes 文件中指定的类
      2. preLoadResources 加载 drawable与color资源,定义在framework/base/core/res/res/values/arrays.xml
    3. ZygoteInit -> startSystemServer 启动systemserve进程
      1. 通过forkSystemServer -> systemserver子进程
      2. systemserver子进程 -> handleSystemServerProcess -> RuntimeInit.zygoteInit
        1. redirectLogStream
        2. commonInit 设置时区,Log配置,HTTP User-Agent,模拟器上的trace调试
        3. nativeZygoteInit 开启Binder通信
        4. invodeStaticMain -> com.android.server.SystemServer.main -> throw new ZygoteInit.MethodAndArgsCaller
    4. ZygoteInit.main -> catch(ZygoteInit.MethodAndArgsCaller) -> 执行MethodAndArgsCaller的run方法
      1. init1 -> 启动Native System Service
        • SurfaceFlinger, SensorService
        • AndroidRuntime -> SystemServer.init2
        • 初始化Binder通信
      2. init2 -> Java System Service
        • Looper.prepare()
        • EntropyService, PowerManagerService, ActivityManagerService, TelephonyRegistry, PackageManagerService, WindowManagerService
        • startSystemUi
        • Watchdog
    5. 执行runSelectLoopMode方法,通过Socket监听客户端请求。用runOnce处理请求
  4. 处理Home启动请求

    ActivityManagerService.systemReady -> ActivityStack.resumeTopActivityLocked -> ActivityManagerService.startHomeActivityLocked -> ActivityStack.startActivityLocked -> ActivityStack.startActivityUncheckedLocked -> other startActivityLocked -> other resumeTopActivityLocked -> startSpecificActivityLocked -> startProcessLocked -> Process.start(“android.app.ActivityThread”) -> startViaZygote -> zygoteSendArgsAndGetResult -> Socket -> zygote -> runOnce -> handleChildProc -> android.app.ActivityThread.main

Binder

  1. 初始化Binder通信

  2. 将自身注册为Context管理者

  3. 循环处理IPC请求

  4. Server启动

    1. 创建ProcessState对象
    2. 获取servicemanager代理对象
      • Binder通信接口: IBinder, BBinder(Server对应的Binder对象), BpBinder(Client访问BBinder的代理对象)
      • Binder服务接口:Server端提供的服务,由IServiceManager提供
      • Proxy:BpInterface继承自BpRefBase,BpRefBase.mRemote指向Client的BpBinder对象。BpServiceManager实现服务接口中声明的方法
      • Stub:BnInterface,BnServerManager
    3. 注册Service
    4. Server进程开启线程池
  5. Binder在Native中的实现

  6. Binder在Java层中的实现

  7. Java系统服务注册过程

    BinderInternal.getContextObject -> IBinder -> ServiceManagerNative.asInteface -> sServiceManager -> addService

    1. BinderInternal.getContextObject
    2. ServiceManagerNative.asInterface
    3. ServiceManagerProxy.addService
      1. Java的Service对象写入Parcel中
      2. 使用transact方法进行ipc通信
  8. Client获取服务代理

    1. 获取服务的Proxy
    2. Proxy.Stub.asInterface
    3. new SomeServer(SomeServerInterface, Thread)
  9. Client调用Java系统服务的方法

  10. AIDL

消息通信篇

  1. Handler.post(Runnable r) -> Handler.sendMessageDelayed(getPostMessage(r), 0) -> Message m.callback = r
  2. Handler.dispatchMessage -> msg.callback != null -> callback
    -> msg.handleMessage != null -> callback.handleMessage
    -> handleMessage
  3. MessageQueue.IdleHandler
  4. Message.recycle
  5. AsyncTask.execute -> executeOnExecutor(SerialExecutor, params) -> SerialExecutor.execute(mFuture)
    • 会通过一个ThreadPoolExecutor来执行线程

Package Manager

  • Permission, Permission Group信息的增加,删除,查询和检查
  • 扫描并安装和卸载APK包,查询包的UID,GID,包名,系统默认程序
  • 比较两个包的签名
  • 查询Activity,Provider、Receiver、Service信息
  • 查询Application、Package、Resouce、Shared、Library、Feature信息
  • Intent匹配

结构

  • adb push -> adb install -r -l -s -> adb uninstall

  • Google Market、PackageInstaller.apk、第三方安装界面

  • PackageManager及其子类、adb与pm命令 -> binder通信 -> PackageManagerService方法

  • PackageManagerService及其相关类 Setting、Installer、FileObserver、DefaultContainerService

启动

  1. SystemServer.Init2() -> ServerThread.run() -> PackageManagerService.main()
  2. PackageManagerService pms = new PackageManagerService(context, factoryTest, onlyCore)
  3. 创建并初始化Setting对象
  4. 获取系统默认设置
  5. 启动PackageHandler
  6. 创建data目录并初始化UserManager
  7. 解析data/system目录下的package.xml、packages-backup.xml
  8. dexopt优化
  9. 启动FileObserver监控APK文件的目录
  10. 调用scanDirLI扫描并安装APK
  11. writeLPr更新package.xml, packages-backup.xml

uid >= FIRSTAPPLICATIONUID 或者 uid < FIRSTAPPLICATIONUID,FISTAPPLICATIONUID < 10000为系统程序UID。

    • 用于为指定的组ID分配权限
    • <assignpermission>用于为指定的用户ID分配指定的权限
    • 指定的系统扩展库
    • Hardware feature 指定当前设备支持的硬件特性:Audio、Bluetooth、Camera、Location、Microphone、NFC、Sensors、Screen、Telephony、Touchscreen、USB、WIFI。
    • Software feature SIP VOIP

    PackageManager的hasSystemFeature, getSystemAvailableFeatures

  1. FileObserver监控

    • system/framework
    • system/app
    • vendor/app
    • data/app
    • data/app-private
  2. scanDirLI

    • system/framework/
    • system/app/
    • vendor/app/
    • data/app
    • data/app-private

APK安装过程

  • 读取目录
  • 解析AndroidManifest.xml

Activity Manager

机制与实现

  • 启动、杀死应用程序
  • 启动并调度Activity生命周期
  • 启动并调度应用程序Service生命周期
  • 注册Broadcast Receiver,并接收和分发Broadcast
  • 启动并发布Content Provider
  • 调度Task
  • 检查、授予、收回访问URI权限
  • 处理crash
  • 调整进程调度优先级及策略
  • 查询当前系统运行状态

ActivityThread:管理应用程序所在进程的主线程的执行调度和运行Activities,broadcast

Instrumentation:应用程序测量工具基类,用于监控系统与应用程序间的交互

ContextImpl:context的通用实现类

Context2: 可以获取应用程序运行环境中的一些全局信息的接口

Application:一个可以维护全局的应用程序状态的基类

  1. 初始化一个单例的Context对象,使其与Resource、LoadApk、ActivityThread、ApplicationContentResolver关联
  2. 创建Application对象,并与Context关联
  3. 创建ActivityStack类,管理Activity栈并维护其状态
  4. startRunning
  5. ActivityManagerService.setSystemProcess
  6. installSystemProviders
  7. 查询、安装Content Provider -> publishContentProvider
  8. systemReady
    1. 发送ACTIONPREBOOTCOMPLETED广播:CalendarProvider、ContactsProvider、MediaProvider
    2. 清理预启动的非persistent进程
    3. 读取Settings配置: alwaysfinishactivities
    4. Runnable回调接口:SystemUIService、BatteryService、NetworkManagementService、Watchdog
    5. 启动persistent应用和Home
    6. 发送ACTIONBOOTCOMPLETED广播

应用程序Activity的启动和调度

Launcher.onClick -> Launcher.startActivitySafely -> Launcher.startActivity -> Launch.parent.startActivity -> Activity.startActivityForResult(requestCode = -1) -> Instrumentation.execStartActivity -> ActivityManagerProxy.startActivity -> BinderProxy.transact(STARTACTIVITYTRANSACTION)

ActivityManagerService.startActivityMayWait -> ActivityStack.startActivityLock -> ActivityStack.startActivityUncheckedLocked -> ActivityStack.startActivityLocked -> ActivityStack.resumeTopActivity

ActivityManagerService.startActivityMayWait

int index = indexOfTokenLocked -> resultCode = mHistory.get(index) -> sendActivityResultLocked

FLAGACTIVITYNEWTASK

  • sourceRecord == null (由Launch或者adb start)
  • sourceRecord 启动模式为singleInstance
  • 要启动的目标为singleInstance或者singleTask

用户行为导致Activity切换 -> 回调Activity.onUserLeaveHint

可利用Task:

  • 目标非singleInstance:
    1. ActivityRecord.affinity == Activity.affinity
    2. ActivityRecord.Task.Intent.Component == Activity.Component
    3. ActivityRecord.Task.affinityIntent.Component == Activity.Component
  • 目标为singleInstance,ActivityRecord.Task.Intent.Component == Activity.Component

启动Activity的第二个阶段为Pause

  1. ActivityStack.startPausingLocked
  2. schedulePauseActivity
  3. handlePauseActivity
  4. performPauseActivity
  5. activityPaused
  6. completedPauseLocked

启动应用程序进程

  • 会根据新的Activity是否占满屏来决定前一个Activity是否可见
  • 如果systemReady 没有设为true,则先启动的应用程序都加入mProcessesOnHold列表中等待

加载应用程序Activity

  • ActivityThread.main创建出程序主线程
  • ActivityThread.attch将应用程序加入到ActivityManagerService中
  • ActivityManagerService.attachApplication
  • ApplicationThread.bindApplication
  • ActivityThread.handleBindApplication
    1. 设置进程名
    2. 低内存设备禁用硬件加速
    3. 创建应用程序对应的Application
    4. 安装ContentProvider
    5. Instrumentation的onCreate方法
    6. Application的onCreate方法

显示Activity

  1. ActivityStack.realStartActivityLocked:加载Activity,onCreate,onStart,onResume。会通过WindowManagerService冻结屏幕并设置Activity可见。

  2. handleLaunchActivity -> performLaunchActivity -> newActivity -> makeApplication -> init -> attach -> callActivityOnCreate -> performCreate -> onCreate -> performStart -> callActivityOnStart -> onStart -> callActivityOnPostCreate -> onPostCreate

  3. handleResumeActivity -> performResumeActivity -> onResume 控制可见性,如果在onResume时,又启动另一个Activity则窗口变不可见,黑屏可能由此来。onResume之前可能会有onNewIntent与onActivityResult调用

  4. 如果当前Activity处于stop状态,onRestart -> onStart -> onResume -》onPostResme

  5. Activity.finish只是标志一下Activity处于完成的状态,会在IdleHandle线程中销毁

停止源Activity,在目标Activity的onCreate、onStart、onResume、activityIdleInternal执行后,开始停止源Activity。

  1. FLAGACTIVITYNOHISTORY启动标记的Activity是不会被放入栈中的
  2. onSaveInstanceState -》 onStop
  3. StopInfo通知ActivityManagerService停止Activity的操作完成

Activity Manager进程管理

非隐藏进程:

  • 有可见但非前台的activity
  • 有可见activity,该进程未被完全覆盖的Activity
  • 处于Pausing和Paused状态的activity
  • 处于STOPPING状态的Activity
  • AMS.setProcessForeground
  • HOME进程
  • 运行在内核空间中的进程
  • 当前线程的上一个线程
  • 备份线程

/sys/module/lowmemorykiller/paramerters/adj 优先级数
/sys/module/lowmemorykiller/paramerters/minfree 对应的内存阀值

lowmemshrink:

  • OOM adj越大的进程越容易被杀
  • 相同OOM adj的进程,占用内存越大的越容易被杀
  • 未达到最小内存阈值的最大值时,不会杀