NotePublic/Software/Development/System/Android/Android_开发简明实用技术.md

241 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Android 开发简明实用技术
## 1.常用命令
### 1.1.Build 命令
```bash
make -j<n> | tee mout.log
# 快速生成镜像
make bootimage
make systemimage
make vendor
# 更新 API
make update-api
# 生成可发布的 SDK
make sdk
# 重新生成 system 镜像
make snod
# 重新生成 vendor 镜像
make vnod
# 重新生成 product 镜像
make pnod
# 清除 out 目录下对应板文件夹中的内容
make installclean
```
### 1.2.ADB 命令
```bash
adb root
# 关闭在调试环境下的 dm-verity 检查,允许对调试系统执行 adb remount 操作,重启后生效
adb disable-verity
adb remount
adb shell
adb kill-server
```
### 1.3.Display 信息
```bash
dumpsys display
```
### 1.4.Input 信息
```bash
dumpsys input
```
## 2.Bootargs
```ini
# 设置 SELinux 为强制模式,代表 SELinux 运作中,且会执行实际的限制
androidboot.selinux=enforcing
# 设置 SELinux 为宽容模式,代表 SELinux 运作中,但只会记录警告讯息并,不执行实际的限制
androidboot.selinux=permissive
# 设置 SELinux 为关闭模式,代表 SELinux 不会实际运作
androidboot.selinux=disabled
```
## 3.自动运行服务
首先在该程序的目录下创建并编写 demo init rc 文件,参考模板如下:
```rc
service <service name> /path/to/demo
class <class>
user <user>
group <group>
```
class指所在的分类主要有 core 等。
user 和 group 指以该 user 和 group 运行程序。
之后在该程序的 Android.mk 文件中增加:
```mk
LOCAL_INIT_RC := <demo init rc file>
```
或在 Android.bp 文件中增加:
```json
init_rc: ["<demo init rc file>"]
```
## 4.SEAndroid
SEAndroid 是在 Android 系统中基于 SELinux 推出的强制访问控制模型,来完善自主访问模型中只要取得 root 权限就可以为所欲为的情况。SEAndroid 有:强制、宽容 和 关闭三种模式。
一般可通过一下命令临时关闭 SEAndroid
```bash
adb root
adb shell setenforce 0
```
或通过修改 Bootargs 从而在系统一启动时就设定好 SELinux 的工作模式,详见 Bootargs 部分。
SEAndroid 工作大致分为两部分:设置 Security Context 和根据 Security Context 做权限控制。如果没有为程序设置 Security Context 该程序将无法自动加载。
### 4.1.Security Context
我们可以通过 ls -Z 来查看文件的 Security Context 或者通过 ps -Z 来查看进程的 Security Context。
Security Context 由四部分组成,每一部分用冒号隔开,来看一个例子:
```bash
u:r:init:s0
u:object_r:rootfs:s0
```
* 第一部分 u 代表用户,在 SeAndroid 中只有一个用户,就是 u
* 第二部分 r 或者 object_r 代表用户的角色,如果角色是 r 代表的是进程,如果角色是 object_r 代表的是文件;
* 第三部分 init 或者 rootfs 等,代表类型或者域,一般管文件的这部分叫类型,管进程的这部分叫域。不同的域拥有不同的权限;
* 第四部分 s0 代表安全等级,我们不用关注。
文件 Security Context 定义在 file_contexts 中:
```bash
# file_contexts
/(vendor|system/vendor)/bin/demo u:object_r:demo_exec:s0
```
### 4.2.根据 Security Context 做权限控制
主要是编写 Policy 文件了,最常见的 Policy 就是 TE 文件TE 文件定义了程序由 init 创建后所处的域,需要的权限及权限转换规则。以下是一个 TE 文件示例:
TE 文件的主要语法格式如下:
```bash
<rule name> <source context> <target context>:<target class> <permission set>
```
其中:
* rule name规则名称主要有 allow、dontaudit、auditallow 和 neverallow
* source context源类型主要作用是用来填写一个域(domain)
* target context目标的类型的安全上下文
* target class类别目标客体是哪种类别主要有 file、dir、socket、SEAndroid 还有 Binder 等在这些基础上又细分出设备字符类型chr_file链接文件lnk_file等。可以通过 ls -l 查看文件类型
* permission set动作集
解读为:为 source context 设置一个规则,该规则是对 target context 的 class 进行 permission set 的操作,如:
```bash
allow demo sysfs:file { create open read write };
```
用中文来表述是:允许 demo 域里的进程或服务对类型为 sysfs 的类别为文件file进行 create、open、read 和 write 操作。
permission set 是与 class 相关联的,常见组合如下:
| Class | Permission |
|------------|------------|
| file | ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton |
| directory | add_name remove_name reparent search rmdir open audit_access execmod |
| socket | ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind |
| filesystem | mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget |
| process | fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap setkeycreate setsockcreate |
| security | compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy |
| capability | chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap |
| tcp_socket | create connect name_connect lock append bind name_bind listen accept recvfrom sendto read write getattr setattr getopt setopt |
| sock_file | open read write |
| chr_file | create open read write map ioctl |
### 4.3.TE 宏
为便于编写 TE 文件,系统提供了一些 TE 宏,这些宏依然是由基本的 TE 语句组成。
常用 TE 宏如下:
* net_domain(domain)Allow a base set of permissions required for network access.
* unix_socket_connect(clientdomain, socket, serverdomain)Allow a local socket connection from clientdomain via socket to serverdomain.
### 4.4.TE 文件编写指导
通常很难知道一个程序需要哪些权限,所以一般根据经验知识先设置一些基本权限。然后通过 dmesg 和 logcat 查看该程序的 avc denied这些 log 会指示出一些重要信息:
```bash
avc: denied { <permission> } ... scontext=<source context> tcontext=<target context> tclass=<target class> ...
```
此时根据上面的信息继续编写 TE 文件即可。
### 4.5.调试指导
为程序编写完 TE 文件后,可在 init 中自动加载该程序或使用如下命令其中程序:
```bash
setprop ctl.start <service name>
```
其中 service name 即为 init rc 文件中的服务名称。
然后可通过:
```bash
ps -A | grep <app name>
```
命令查看程序是否已经运行,如果没有运行或运行出现了问题可通过一下命令获取 log
```bash
dmesg | grep <service name>
logcat | grep <service name>
```
### 4.6.TE 文件模板
一下根据程序所需的谋一单一功能提供了一些 TE 文件模板。
### 4.6.1.Sysfs 访问权限
```bash
type demo, domain;
type demo_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(demo)
allow demo self:capability { sys_admin };
allow demo sysfs:file { create open read write };
allow demo device:dir { create open read write };
```
### 4.6.2.Socket 访问权限
```bash
type demo, domain;
type demo_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(demo)
net_domain(demo)
unix_socket_connect(demo, netd, netd)
allow demo self:capability { net_admin net_raw net_bind_service };
allow demo device:dir { create open read write ioctl };
allow demo self:tcp_socket { create connect name_connect lock append bind name_bind listen accept recvfrom sendto read write getattr setattr getopt setopt };
allow demo port:tcp_socket { create connect name_connect lock append bind name_bind listen accept recvfrom sendto read write getattr setattr getopt setopt };
allow demo fwmarkd_socket:sock_file { write };
```