软重启功能调研

软重启作用

软重启即用户空间中进程的运行时重启。

  1. 用于应用需要重启的更新(例如,对APEX包的更新),会重启用户空间。
  2. 可以清除临时错误,而无需删除任何数据或设置。如,冻结、性能缓慢和其他软件相关问题。

启用软重启功能

设置系统属性init.userspace_reboot.is_supported=1

判断系统是否支持软重启

  1. adb shell getprop | grep init.userspace_reboot.is_supported判断系统属性值;

  2. 调用API:PowerManager.isRebootingUserspace(),最终也是判断系统属性值。

请求软重启

  1. 调用PowerManager.reboot(PowerManager.REBOOT_USERSPACE)

  2. adb shell svc power reboot userspace

  3. adb reboot userspace

判断软重启是否成功

软重启失败会回退到硬重启。硬重启成功会亮屏且听到一声通知提示音;软重启成功仅听到一声通知提示音,不会自动亮屏。

重启时长

以输入命令按下Enter或点击“重新启动”作为开始,以听到通知提示音为结束,计算时长。

该数据在M2381设备测得,仅作参考。

  1. adb shell svc power reboot userspace,软重启,约13秒;
  2. adb reboot userspace,软重启,约20秒;
  3. 长按电源键,点击“重新启动”,硬重启,约22秒。

软重启流程

adb shell svc power reboot userspace为例。

  • init.cpp#SecondStageMain中的死循环监听关机命令 ->

  • reboot.cpp#HandlePowerctlMessage() ->

  • reboot.cpp#HandleUserspaceReboot()

    1. 根据init.userspace_reboot.is_supported判断系统是否支持软重启

    2. 触发userspace-reboot-requested事件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      on userspace-reboot-requested
      setprop sys.boot_completed ""
      setprop dev.bootcomplete ""
      setprop sys.init.updatable_crashing ""
      setprop sys.init.updatable_crashing_process_name ""
      setprop sys.user.0.ce_available ""
      setprop sys.shutdown.requested ""
      setprop service.bootanim.exit ""
      setprop service.bootanim.progress ""
    3. reboot.cpp#DoUserspaceReboot()

      设置属性sys.init.userspace_reboot.in_progress为true,设置失败则软重启失败;

      重置属性sys.powerctl为””,重置失败则软重启失败;

      记录enabled状态的服务,重启时需要手动enable;

      终止上一步记录的服务,超时则软重启失败;

      卸载zram支持设备,卸载失败则软重启失败;

      执行/system/bin/vdc volume reset命令,执行失败则软重启失败;

      卸载apex包,否则它们可能阻止/data的彻底卸载,卸载失败则软重启失败;

      切换到bootstrap命名空间,切换失败则软重启失败;

      移除apex中定义的服务;

      重新enable服务;

      触发userspace-reboot-resume(见备注1)

备注1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
on userspace-reboot-resume
# 启动vold进程,卸载/data镜像目录,播放动画
# 见备注2
trigger userspace-reboot-fs-remount

# 挂载/data,创建/data下的目录,启动bootchart、tombstoned、apexd、logd、logd-reinit、odsign
# 执行derive_sdk、derive_classpath、apexd-snapshotde
# 见备注3
trigger post-fs-data

# 执行update_verifier_nonencrypted,启动statsd、netd、zygote、zygote_secondary
# 见备注4
trigger zygote-start

# 见备注5
trigger early-boot

# 对网络、内存管理、文件系统进行设置,启动class为hal和core的服务
# 见备注6
trigger boot

备注2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
on userspace-reboot-fs-remount
# vold是一个守护进程,用来管理Android中存储类的热插拔事件,其中包括设备开关机过程中存储设备各分区的挂卸载
# 预防重启过程中,vold因为一些原因没有正常运行
start vold
exec - system system -- /system/bin/vdc checkpoint resetCheckpoint
exec - system system -- /system/bin/vdc checkpoint markBootAttempt
# 卸载/data镜像目录
umount /data_mirror/data_ce/null/0
umount /data_mirror/data_ce/null
umount /data_mirror/data_de/null
umount /data_mirror/cur_profiles
umount /data_mirror/ref_profiles
umount /data_mirror
remount_userdata
# 播放动画
start bootanim

备注3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
on post-fs-data

mark_post_data

# Start checkpoint before we touch data
exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint

# We chown/chmod /data again so because mount is run as root + defaults
chown system system /data
chmod 0771 /data
# 恢复/data的安全上下文
restorecon /data

# 创建DE密钥
installkey /data

# 启动bootchart,bootchart是系统启动过程性能分析的工具
mkdir /data/bootchart 0755 shell shell encryption=Require
bootchart start

# /dev/urandom是随机数设备。避免可预测的熵池,继承上次启动的熵
copy /data/system/entropy.dat /dev/urandom

mkdir /data/vendor 0771 root root encryption=Require
mkdir /data/vendor_ce 0771 root root encryption=None
mkdir /data/vendor_de 0771 root root encryption=None
mkdir /data/vendor/hardware 0771 root root

# 启动tombstoned
mkdir /data/anr 0775 system system encryption=Require
mkdir /data/tombstones 0771 system system encryption=Require
mkdir /data/vendor/tombstones 0771 root root
mkdir /data/vendor/tombstones/wifi 0771 wifi wifi
start tombstoned

# 设置默认的mount namespace
enter_default_mount_ns

# 创建密钥库目录结构,为启动apexd做准备
mkdir /data/misc 01771 system misc encryption=Require
mkdir /data/misc/keystore 0700 keystore keystore
# work around b/183668221
restorecon /data/misc /data/misc/keystore

# 设置odsign签名密钥的启动级别为MAX_BOOT_LEVEL=30
setprop keystore.boot_level 30

# 现在/data已挂载并且我们已经创建了/data/misc/keystore
# 可以通知keystore停止允许使用early-boot密钥
# 并首次访问其数据库以支持MAX_BOOT_LEVEL密钥的创建和使用。
exec - system system -- /system/bin/vdc keymaster earlyBootEnded

# 在启动apexd前加载持久属性
load_persist_props
start logd
start logd-reinit

trigger load_persist_props_action

# 启动apexd,激活APEXes.
mkdir /data/apex 0755 root system encryption=None
mkdir /data/apex/active 0755 root system
mkdir /data/apex/backup 0700 root system
mkdir /data/apex/decompressed 0755 root system encryption=Require
mkdir /data/apex/hashtree 0700 root system
mkdir /data/apex/sessions 0700 root system
mkdir /data/app-staging 0751 system system encryption=DeleteIfNecessary
mkdir /data/apex/ota_reserved 0700 root system encryption=Require
setprop apexd.status ""
restart apexd

# 创建/data下剩余的目录
...

exec_start derive_sdk

# 创建CE密钥
init_user0

# 在升级或策略更新时设置 SELinux 安全上下文。
restorecon --recursive --skip-ce /data

# 定义并导出*CLASSPATH变量。odsign依赖*CLASSPATH变量
exec_start derive_classpath
load_exports /data/system/environ/classpath

# on-device signing守护程序,在需要时生成ART工件
start odsign

# 等待odsign使用完密钥
wait_for_prop odsign.key.done 1

# fs-verity用于文件身份验证,锁定fs-verity密钥环,使无法添加更多密钥
exec -- /system/bin/fsverity_init --lock

# 将启动级别提升至1000000000;这会阻止进一步的on-device签名,用于关闭侦听进一步更新的线程。
setprop keystore.boot_level 1000000000

# 允许apexd在回滚时快照并恢复设备加密的apex数据。这应该在加载DE_user数据密钥后立即完成。在完成此操作并且 apexd.status变为“就绪”之前,APEX不应访问此数据。
exec_start apexd-snapshotde

# 检查/data中的时区数据是否比时区数据模块中的副本新,如果不是则删除
exec - system system -- /system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo

# sys.memfd_use默认设置为false,这会使其保持禁用状态,直到确认应用程序和供应商进程不再对ashmem fds进行 IOCTL
setprop sys.use_memfd false

chown root system /dev/fscklogs/log
chmod 0770 /dev/fscklogs/log
...

on post-fs-data中触发了load_persist_props_action

1
2
3
$/system/logging/logcat/logcatd.rc
on load_persist_props_action
setprop logd.logpersistd.enable true
1
2
3
4
5
6
$/system/server_configurable_flags/disaster_recovery/flags_health_check.rc
on load_persist_props_action
# check server configurable flags(which is based on persistent properties) related
# disaster recovery
mkdir /data/server_configurable_flags 0775 system system encryption=Require
exec - system system -- /system/bin/flags_health_check BOOT_FAILURE

备注4:

1
2
3
4
5
6
7
8
on zygote-start && property:ro.crypto.state=...
wait_for_prop odsign.verification.done 1
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start statsd
start netd
start zygote
start zygote_secondary

备注5:

1
2
3
4
5
6
7
$/frameworks/native/cmds/installd/installd.rc
on early-boot
mkdir /config/sdcardfs/extensions/1055
mkdir /config/sdcardfs/extensions/1056
mkdir /config/sdcardfs/extensions/1057
...
# 在1055、1056、1057文件夹下又创建了一些文件夹

/device/linaro/dragonboard/init.common.rc中也监听了early-boot,但是没有触发。

备注6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
on boot
# 初始化网络
# 启用lo回环网卡
ifup lo
hostname localhost
domainname localdomain

# IPsec SA默认expiration长度
write /proc/sys/net/core/xfrm_acq_expires 3600

# 设置内存管理的参数
write /proc/sys/vm/overcommit_memory 1
write /proc/sys/vm/min_free_order_shift 4

# System server管理zram writeback
# writeback功能,可以将zram中申请的物理页回写到真实的磁盘中,进一步释放内存
chown root system /sys/block/zram0/idle
chmod 0664 /sys/block/zram0/idle
chown root system /sys/block/zram0/writeback
chmod 0664 /sys/block/zram0/writeback

# to access F2FS sysfs on dm-<num> directly
mkdir /dev/sys/fs/by-name 0755 system system
symlink /sys/fs/f2fs/${dev.mnt.dev.data} /dev/sys/fs/by-name/userdata

# dev.mnt.dev.data=dm-N, dev.mnt.blk.data=sdaN/mmcblk0pN, dev.mnt.rootdisk.data=sda/mmcblk0, or
# dev.mnt.dev.data=sdaN/mmcblk0pN, dev.mnt.blk.data=sdaN/mmcblk0pN, dev.mnt.rootdisk.data=sda/mmcblk0
mkdir /dev/sys/block/by-name 0755 system system
symlink /sys/class/block/${dev.mnt.dev.data} /dev/sys/block/by-name/userdata
symlink /sys/class/block/${dev.mnt.rootdisk.data} /dev/sys/block/by-name/rootdisk

# F2FS tuning. Set cp_interval larger than dirty_expire_centisecs, 30 secs,
# to avoid power consumption when system becomes mostly idle. Be careful
# to make it too large, since it may bring userdata loss, if they
# are not aware of using fsync()/sync() to prepare sudden power-cut.
write /dev/sys/fs/by-name/userdata/cp_interval 200
write /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time 50
write /dev/sys/fs/by-name/userdata/iostat_enable 1

# 为POSIX_FADV_SEQUENTIAL文件设置预读乘数readahead multiplier
# 预读乘数会影响读性能,它控制在一个读请求之后,有多少连续数据块被保存到缓存里
write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 16

# 将丢弃大小限制为128MB,以避免调整文件系统(dm或sda)时出现较长的IO延迟。
# 这需要在供应商端启用sda/mmcblk0selinux 条目
write /dev/sys/block/by-name/userdata/queue/discard_max_bytes 134217728
write /dev/sys/block/by-name/rootdisk/queue/discard_max_bytes 134217728

# 设置System Serverdaemons.
chown system system /sys/power/autosleep

chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate
chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_slack
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_slack
chown system system /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
chown system system /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
chown system system /sys/devices/system/cpu/cpufreq/interactive/target_loads
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/target_loads
chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
chown system system /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay
chown system system /sys/devices/system/cpu/cpufreq/interactive/boost
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boost
chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse
chown system system /sys/devices/system/cpu/cpufreq/interactive/input_boost
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/input_boost
chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration
chown system system /sys/devices/system/cpu/cpufreq/interactive/io_is_busy
chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/io_is_busy

# 假设SMP对所有CPU使用共享cpufreq策略
chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

chown system system /sys/class/leds/vibrator/trigger
chown system system /sys/class/leds/vibrator/activate
chown system system /sys/class/leds/vibrator/brightness
chown system system /sys/class/leds/vibrator/duration
chown system system /sys/class/leds/vibrator/state
chown system system /sys/class/timed_output/vibrator/enable
chown system system /sys/class/leds/keyboard-backlight/brightness
chown system system /sys/class/leds/lcd-backlight/brightness
chown system system /sys/class/leds/button-backlight/brightness
chown system system /sys/class/leds/jogball-backlight/brightness
chown system system /sys/class/leds/red/brightness
chown system system /sys/class/leds/green/brightness
chown system system /sys/class/leds/blue/brightness
chown system system /sys/class/leds/red/device/grpfreq
chown system system /sys/class/leds/red/device/grppwm
chown system system /sys/class/leds/red/device/blink
chown system system /sys/module/sco/parameters/disable_esco
chown system system /sys/kernel/ipv4/tcp_wmem_min
chown system system /sys/kernel/ipv4/tcp_wmem_def
chown system system /sys/kernel/ipv4/tcp_wmem_max
chown system system /sys/kernel/ipv4/tcp_rmem_min
chown system system /sys/kernel/ipv4/tcp_rmem_def
chown system system /sys/kernel/ipv4/tcp_rmem_max
chown root radio /proc/cmdline

# 以段为单位定义默认初始接收窗口大小。
setprop net.tcp_def_init_rwnd 60

#FLYME|dzh@meizu.com|lmk-opt: disable rescue party temporarily
setprop persist.sys.disable_rescue true

# 更新dm-verity状态并设置partition.*.verified属性
verity_update_state

# 启动class为hal的服务
class_start hal

# 启动class为core的服务
class_start core

class为hal的服务有:healthd、hidl_memory、vendor.contexthub-default、confirmationui-1-0、vendor.gatekeeper-1-0。

class为core的服务有:artd、audioserver、bootanim、shutdownanim、servicemanager、vndservicemanager、gpu、surfaceflinger、bufferhubd、performanced、virtual_touchpad、ueventd、console、adbd、apexd、lmkd、credstore、odsign、vold等。
车辆服务:carbugreportd、cartelemetryd_service、carwatchdogd、com.android.car.procfsinspector。


软重启功能调研
https://citrus-maxima.github.io/2024/03/09/软重启功能调研/
作者
柚子树
发布于
2024年3月9日
许可协议