录屏失败问题解决记录

问题背景

前期制作fde宣传视频时发现很多Android录屏软件应用都录屏失败,只有腾讯会议的录屏可以使用。
后面我把SystemUI的控制中心放开,使用控制中心的录屏功能,发现同样录屏失败报错。

对录屏时抓取的日志进行分析,在Android中使用软编码时遇到了下面的错误:

10-23 07:23:11.079 27 27 I hwservicemanager: getTransport: Cannot find entry android.hardware.graphics.allocator@4.0::IAllocator/default in either framework or device manifest. 10-23 07:23:11.079 125 125 W Gralloc4: allocator 3.x is not supported 10-23 07:23:11.080 27 27 I hwservicemanager: getTransport: Cannot find entry android.hardware.graphics.allocator@3.0::IAllocator/default in either framework or device manifest. 10-23 07:23:11.080 125 125 W Gralloc3: allocator 3.x is not supported 10-23 07:23:11.082 125 125 I Gralloc2: Adding additional valid usage bits: 0x0 10-23 07:23:11.119 125 125 E android.hardware.media.omx@1.0-service: libminijail[125]: blocked syscall: uname 10-23 07:23:11.127 50 50 I tombstoned: received crash request for pid 125 --------- beginning of crash 10-23 07:23:11.137 125 125 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 10-23 07:23:11.137 125 125 F DEBUG : LineageOS Version: '18.1-20231020-UNOFFICIAL-fde_arm64' 10-23 07:23:11.137 125 125 F DEBUG : Build fingerprint: 'google/redfin/redfin:11/RQ3A.211001.001/eng.electr.20230318.111310:user/release-keys' 10-23 07:23:11.137 125 125 F DEBUG : Revision: '0' 10-23 07:23:11.137 125 125 F DEBUG : ABI: 'arm' 10-23 07:23:11.137 125 125 F DEBUG : Timestamp: 2023-10-23 07:23:11+0000 10-23 07:23:11.137 125 125 F DEBUG : pid: 125, tid: 125, name: omx@1.0-service >>> media.codec <<< 10-23 07:23:11.137 125 125 F DEBUG : uid: 1046 10-23 07:23:11.137 125 125 F DEBUG : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr -------- 10-23 07:23:11.137 125 125 F DEBUG : r0 00000000 r1 0000007d r2 00000006 r3 fff551c8 10-23 07:23:11.137 125 125 F DEBUG : r4 fff551dc r5 fff551c0 r6 0000007d r7 0000016b 10-23 07:23:11.137 125 125 F DEBUG : r8 fff551c8 r9 fff551d8 r10 fff551f8 r11 fff551e8 10-23 07:23:11.137 125 125 F DEBUG : ip 0000007d sp fff55198 lr f60c2d41 pc f60c2d54 10-23 07:23:11.142 125 125 F DEBUG : 10-23 07:23:11.142 125 125 F DEBUG : backtrace: 10-23 07:23:11.142 125 125 F DEBUG : #00 pc 00062d54 /apex/com.android.runtime/lib/bionic/libc.so (abort+172) (BuildId: 52685d40d057d47bd6973b625ed3d1ae) 10-23 07:23:11.142 125 125 F DEBUG : #01 pc 00013ef1 /apex/com.android.vndk.v30/lib/libminijail.so (do_fatal_log+96) (BuildId: 3dd5c187fd772590b2eabe0afbcd2917) 10-23 07:23:11.142 125 125 F DEBUG : #02 pc 0001213f /apex/com.android.vndk.v30/lib/libminijail.so (log_sigsys_handler+38) (BuildId: 3dd5c187fd772590b2eabe0afbcd2917) 10-23 07:23:11.142 125 125 F DEBUG : #03 pc 0005e0a0 /apex/com.android.runtime/lib/bionic/libc.so (__restore_rt) (BuildId: 52685d40d057d47bd6973b625ed3d1ae) 10-23 07:23:11.142 125 125 F DEBUG : #04 pc 0009ccb0 /apex/com.android.runtime/lib/bionic/libc.so (uname+8) (BuildId: 52685d40d057d47bd6973b625ed3d1ae) 10-23 07:23:11.142 125 125 F DEBUG : #05 pc 009fa1ef /vendor/lib/dri/libgallium_dri.so (BuildId: 13fea5df7a7ec4bd2ffa5c23e21fd51e1be8536c)

排查原因:

Android系统使用seccomp机制限制了mediacodec执行某些系统调用,通过修改/frameworks/av/services/mediacodec/seccomp_policy/mediacodec-arm64.policy将uname设置为允许执行。
编译后在系统中文件位置/system/etc/seccomp_policy/mediacodec.policy

10-24 02:22:07.991 179 179 D GraphicBufferSource: got buffer with new dataSpace #104 10-24 02:22:07.992 176 3718 D ACodec : dataspace changed to 0x10c10000 (R:2(Limited), P:1(BT709_5), M:1(BT709_5), T:3(SMPTE170M)) (R:2(Limited), S:1(BT709), T:3(SMPTE_170M)) 10-24 02:22:07.996 179 3719 E android.hardware.media.omx@1.0-service: libminijail[179]: blocked syscall: sched_getaffinity 10-24 02:22:07.997 50 50 I tombstoned: received crash request for pid 179 --------- beginning of crash 10-24 02:22:07.999 179 3719 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 10-24 02:22:07.999 179 3719 F DEBUG : LineageOS Version: '18.1-20231023-UNOFFICIAL-fde_arm64' 10-24 02:22:07.999 179 3719 F DEBUG : Build fingerprint: 'google/redfin/redfin:11/RQ3A.211001.001/eng.electr.20230318.111310:user/release-keys' 10-24 02:22:07.999 179 3719 F DEBUG : Revision: '0' 10-24 02:22:07.999 179 3719 F DEBUG : ABI: 'arm' 10-24 02:22:08.000 179 3719 F DEBUG : Timestamp: 2023-10-24 02:22:07+0000 10-24 02:22:08.000 179 3719 F DEBUG : pid: 179, tid: 3719, name: omx@1.0-service >>> media.codec <<< 10-24 02:22:08.000 179 3719 F DEBUG : uid: 1046 10-24 02:22:08.000 179 3719 F DEBUG : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr -------- 10-24 02:22:08.000 179 3719 F DEBUG : r0 00000000 r1 00000e87 r2 00000006 r3 f4f05150 10-24 02:22:08.000 179 3719 F DEBUG : r4 f4f05164 r5 f4f05148 r6 000000b3 r7 0000016b 10-24 02:22:08.000 179 3719 F DEBUG : r8 f4f05150 r9 f4f05160 r10 f4f05180 r11 f4f05170 10-24 02:22:08.000 179 3719 F DEBUG : ip 00000e87 sp f4f05120 lr f70c6d41 pc f70c6d54

原因同上,在添加uname执行权限后,报新的如上错误。通过修改/frameworks/av/services/mediacodec/seccomp_policy/mediacodec-arm64.policy将sched_getaffinity设置为允许执行。
编译后在系统中文件位置/system/etc/seccomp_policy/mediacodec.policy

经过上面的两次修复后,控制中心的录屏的功能不再报错,可正常录屏。使用视频播放器测试录屏保存的文件可正常播放且画面正常显示。
测试第三方录屏应用,录屏精灵、一键录屏、迅捷录屏大师、录屏大师等录屏也都不再报错且录屏文件可正常播放。

具体修改如下:

pengtg@phytium:/aosp1/ptg_waydroid/frameworks/av$ git diff diff --git a/services/mediacodec/seccomp_policy/mediacodec-arm64.policy b/services/mediacodec/seccomp_policy/mediacodec-arm64.policy index b4a9ff6..40215f0 100644 --- a/services/mediacodec/seccomp_policy/mediacodec-arm64.policy +++ b/services/mediacodec/seccomp_policy/mediacodec-arm64.policy @@ -57,6 +57,8 @@ fstatat64: 1 ugetrlimit: 1 getdents64: 1 getrandom: 1 +uname: 1 +sched_getaffinity: 1 @include /system/etc/seccomp_policy/crash_dump.arm.policy

补充了解

1. libminijail.so是什么库?

libminijail.so是一个用于创建和管理Linux容器中的最小化沙箱环境的库。它通常与Minijail工具一起使用,Minijail是一个轻量级的工具,用于限制进程的权限和访问,以增强系统安全性。
Minijail库和工具通常用于以下用途:

  • 安全性增强:Minijail可以限制进程的系统权限,如文件访问、网络访问、进程间通信等,以减小潜在的攻击面。

  • 沙箱环境:Minijail可以创建一个受限制的沙箱环境,使进程在其中运行,从而防止它们对主机系统的影响。这对于隔离不受信任的代码或进程非常有用。

  • 容器化:Minijail可以与容器技术(如Docker或Kubernetes)一起使用,以确保容器中运行的应用程序和进程受到限制,以增加容器的安全性。

  • Minijail库提供了一组用于创建和配置沙箱环境的函数,可以在应用程序中使用。通常,Minijail库是与Minijail工具一起使用的,后者用于为具体的应用程序或进程创建和管理沙箱环境。 Minijail工具通过将Minijail库的功能封装成命令行工具,使其更易于使用。

2. uname系统调用功能说明

uname(Unix Name)是一个系统调用,通常用于获取有关当前操作系统的信息。
这个系统调用返回一个结构,包含了各种关于操作系统的信息,例如系统名称、网络节点名称、操作系统版本、发行版、硬件类型等等。
uname 命令通常也可以在命令行终端中使用,它返回相同的信息。

在Linux和类Unix系统中,uname系统调用可以返回以下信息:
1、系统名称(System Name):通常是内核的名称,例如 "Linux"。
2、网络节点名称(Node Name):系统的网络主机名。
3、操作系统版本(Operating System Version):包括操作系统的版本号。
4、发行版(Release):这通常指的是操作系统的发行版名称,例如 "Ubuntu" 或 "CentOS"。
5、硬件类型(Machine):描述了系统硬件的类型,例如 "x86_64" 表示64位的x86架构。

uname命令和系统调用通常用于脚本和程序中,以便根据当前运行的操作系统来执行特定的操作或选择适当的代码路径。这允许开发人员编写跨平台的代码,同时能够根据操作系统的不同进行适当的调整。
相关文件:
/external/llvm-project/libc/src/sys/utsname/linux/uname.cpp

3. sched_getaffinity系统调用功能说明

sched_getaffinity 是一个Linux系统调用,用于获取一个特定进程的CPU亲和性(CPU affinity)设置。
CPU亲和性是一种机制,允许进程或线程绑定到特定的CPU核心,以限制它们在运行时可以使用的CPU核心。
这对于优化性能和控制任务分配到特定的处理器核心非常有用。

sched_getaffinity 系统调用的主要目的是查询一个进程的CPU亲和性,以便了解它可以运行在哪些CPU核心上。该系统调用接受以下参数:

  • pid:要查询的进程的进程ID(PID)。

  • len:用于存储CPU亲和性设置的位掩码的缓冲区的大小。

  • mask:一个指向存储CPU亲和性设置的位掩码的指针

系统调用的功能是将与进程关联的CPU亲和性位掩码存储到 mask 指向的缓冲区中。这个位掩码将指定允许进程在哪些CPU核心上运行。
通常,每个位代表一个CPU核心,位的状态表示进程是否允许在相应的CPU核心上运行。位设置为 1 表示允许,位设置为 0 表示不允许。

通过查询进程的CPU亲和性,您可以了解它当前的调度约束,然后根据需要进行调整,以优化性能或满足特定的需求。如果需要更改CPU亲和性,可以使用 sched_setaffinity 系统调用来设置进程的CPU亲和性设置。

相关文件:
/external/llvm-project/libc/src/sched/linux/sched_getaffinity.cpp
/bionic/libc/bionic/sched_getaffinity.cpp

4.android seccomp机制

Android的Seccomp(Secure Computing)机制是一个用于提高应用程序安全性的内核级安全功能。Seccomp允许应用程序在运行时指定允许的系统调用,从而限制应用程序的权限和减小攻击面。这有助于防止潜在的恶意代码执行和系统漏洞的利用。
Seccomp机制的关键特点包括以下内容:

  • 系统调用过滤: Seccomp允许应用程序定义一个策略,只允许白名单内的系统调用,而阻止所有其他系统调用。这使得应用程序只能执行严格控制的操作,从而减小了攻击面。

  • 细粒度控制: 应用程序可以选择性地允许或阻止特定的系统调用,这使得应用程序可以实现自定义的安全策略。例如,应用程序可以允许文件I/O,但禁止网络访问。

  • BPF过滤: Android的Seccomp使用BPF(Berkeley Packet Filter)来定义过滤规则,这允许更高级的过滤策略。

  • 安全性提高: Seccomp可以用于提高应用程序的安全性,尤其是在处理用户提供的不受信任的数据时。通过限制应用程序的权限,Seccomp有助于减少攻击面,即使应用程序受到漏洞,攻击者的能力也会受到限制。

  • Android的Seccomp通常与其他安全机制和策略一起使用,如SELinux(Security-Enhanced Linux)和应用程序沙箱化,以提供多层次的安全性保护。

补充修复

D2000 PC上录屏失败问题。经分析日志发现是mediacodec中对kcmp和sysinfo这两个系统调用被限制执行了。当时只在小盒子上进行了测试验证,在小盒子上只需增加两个权限允许 uname sched_getaffinity。在D2000 PC上则还需增加另外两个权限允许 kcmp sysinfo。