Android高级调试之surfaceflinger(上)
surfaceflinger介绍
SurfaceFlinger的作用是接受缓冲区并对它们进行合成,然后发送到屏幕,其中缓冲区的数据是WindowManager提供的。
SurfaceFlinger可通过两种方式接受缓冲区:分别是BufferQueue+SurfaceControl和ASurfaceControl。
BufferQueue+SurfaceControl
当应用进入前台时,它会从WindowManager请求缓冲区。然后WindowManager会从SurfaceFlinger请求BufferQueue+SurfaceControl。
SurfaceFlinger创建Surface并将其发送至WindowManager。然后,WindowManager将Surface发送至应用,但会保留 SurfaceControl来操控应用在屏幕上的外观。
ASurfaceControl
ASurfaceControl是安卓10开始引入的。
ASurfaceControl将Surface和SurfaceControl组合到一个包中,该包会被发送至 SurfaceFlinger。ASurfaceControl与Surface相关联,应用可通过 ASurfaceTransactions更新该Surface。然后,应用可通过回调(用于传递包含锁定时间、获取时间等信息的ASurfaceTransactionStats)获取有关 ASurfaceTransactions的信息。
安装Nano Code
Nano Code下载链接:https://www.nanocode.cn/#/download
注:未注册用户,在注册后才可以使用调试功能。
准备调试
a. 连接到远端服务,设置好IP后,点击连接。
```c
tcp:port=portID,server=ipAddress
example: tcp:port=2021,server=192.168.7.200
端口取决于ndstub,默认为2021.
```
b. 选择附加到进程,选择机器和进程后,点击附加。
c. 成功附加到进程。
启动流程概览
可以通过下面的链接下载surfaceflinger的源代码。
https://gedu.oss-cn-beijing.aliyuncs.com/android_gdk850/services.tar.gz
下面的main函数代码是surfaceflinger的起点,通过这个函数我们可以知道surfacefliger是如何一点点进入run函数内的。
int main(int, char**) {
signal(SIGPIPE, SIG_IGN);
hardware::configureRpcThreadpool(1 /* maxThreads */,
false /* callerWillJoin */);
startGraphicsAllocatorService();
// When SF is launched in its own process, limit the number of
// binder threads to 4.
ProcessState::self()->setThreadPoolMaxThreadCount(4);
// start the thread pool
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
set_sched_policy(0, SP_FOREGROUND);
// Put most SurfaceFlinger threads in the system-background cpuset
// Keeps us from unnecessarily using big cores
// Do this after the binder thread pool init
if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
// initialize before clients can connect
flinger->init();
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
startDisplayService(); // dependency on SF getting registered above
if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
}
// run surface flinger in this thread
flinger->run();
return 0;
}
为了观察surfaceflinger的main函数操作,首先需要在surfaceflinger!main处设置断点。
bl
0 e 00000059`683d1048 0001 (0001) 0:|surfaceflinger!main
然后跑起来,当断点命中后,看一下当调试器停在main函数时的栈回溯。
k
Child-SP RetAddr Call Site
0000007f`e81dbf10 00000077`6e8eaa38 surfaceflinger!main+0x4
0000007f`e81dbf10 0000005c`4504d048 libselinux!ResetNativeLoader+0x9f163
libselinux!ResetNativeLoader的作用是当JavaVM销毁时,对相关信息进行清理。
可以看到surfaceflinger!main+0x4多走了一点,这是为了看到栈回溯而做的,避免刚停在某函数时,栈帧没有建立起来,导致看不到栈回溯。
通过~*查看线程,可以看到只有一个主线程存在,其他线程还没起来。
~*
. 0 Id: 720.720 Suspend: 1 Teb: 00000000`00000000 Unfrozen
Start: surfaceflinger!__libc_init (00000059`683cf000)
+000 ti_ta_p:000000000000001E /* Process handle */
+008 ti_user_flags:0x0 /* Unused */
+010 ti_tid:0n933220608 /* Thread ID returned by pthread_create() */
+018 ti_tls:0000000000000000 /* Pointer to thread-local data */
+020 ti_startfunc:0000000000186A00 /* Start function passed to pthread_create() */
+028 ti_stkbase:00000000000AAE60 /* Base of thread's stack */
+030 ti_stksize:0x683cf000 /* Size of thread's stack */
+038 ti_ro_area:0000000000000000 /* Unused */
+040 ti_ro_size:0n0 /* Unused */
+044 ti_state:0n0 /* Thread state */
+048 ti_db_suspended:0n0 /* Nonzero if suspended by debugger */
+04c ti_type:0n0 /* Type of the thread (system vs user thread) */
+050 ti_pc:0n0 /* Unused */
+058 ti_sp:0n0 /* Unused */
+060 ti_flags:0n0 /* Unused */
+064 ti_pri:0n0 /* Thread priority */
+068 ti_lid:0n0 /* Kernel PID for this thread */
+0f0 ti_traceme:0n0 /* Nonzero if event reporting enabled */
+0f1 ti_preemptflag:0n0 /* Unused */
+0f2 ti_pirecflag:0n0 /* Unused */
surfaceflinger首先忽略掉了SIGPPE,这是因为跨进程通信机制可能导致SIGPPE信号的发出,为了避免程序中止,所以使用signal函数抓住这个信号,并忽略掉。
signal函数定义:
void (*signal(int sig, void (*func)(int)))(int)
func这个参数可以使用SIG_DFL(默认的信号处理程序)或SIG_IGN(忽略信号),也可以自定义一个函数,指定收到信号时,程序应该做出的操作。
完成忽略信号的操作后,surfaceflinger就开始建立线程池,在Nano Code内可以通过~*命令查看全部线程,对比最上面的线程可以看到,这个时候surfaceflinger的线程已经完成建立了。
~*
. 0 Id: 9b.9b Suspend: 1 Teb: 00000000`00000000 Unfrozen
Start: surfaceflinger!__libc_init (00000064`4b969000)
&