背景:
前些天有学员朋友刚好带回来了一道关于binder相关的面试。当时看着其实感觉也没啥问题,并没啥难度,所以在vip群里也有学员朋友积极的进行回答。

面试题目如下:
有如下一个业务调用场景:
app调用wms接口,wms中处理又会调用到sf进程,请问说出在wms,sf中binder方法中getcalluid是谁?这个callinguid又是在哪设置的?


针对这个面试题大家可能都觉得不难,很多同学都可以答对认为是system_server的uid。
在但是也有同学提出做个实验发现就是uid为system_server,但是pid实际上是0.

所以针对这个getCallingPid到底是多少的问题反而成了最大的争议点。
多个版本验证getCallingPid
针对这个问题已经存在了各种争议,马哥也针对这个问题在不同的版本进行了验证,发现还确实是有差异的。
准备环境:
aosp14,aosp16这两个aosp的版本
打印部分添加:
这里以前些天豆包手机截图接口为案例
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
@Override
public void captureDisplay(int displayId, @Nullable ScreenCapture.CaptureArgs captureArgs,
ScreenCapture.ScreenCaptureListener listener) {
//打印callingpid和callinguid
Slog.d(TAG, "captureDisplay " + Binder.getCallingUid() + " pid " + Binder.getCallingPid());
ScreenCapture.LayerCaptureArgs layerCaptureArgs = getCaptureArgs(displayId, captureArgs);
ScreenCapture.captureLayers(layerCaptureArgs, listener);
}
在远端SurfaceFlinger中也进行打印
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
binder::Status SurfaceComposerAIDL::captureLayers(
const LayerCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
ALOGE("SurfaceComposerAIDL::captureLayers pid %d uid %d " ,pid,uid);
mFlinger->captureLayers(args, captureListener);
return binderStatusFromStatusT(NO_ERROR);
}
但是两个aosp版本确实得出不同的结果。
aosp14版本日志:
12-24 11:32:38.648 341 606 E SurfaceFlinger: SurfaceComposerAIDL::captureLayers pid 515 uid 1000
aosp16版本日志:
12-24 11:40:47.893 518 1285 E SurfaceFlinger: SurfaceComposerAIDL::captureLayers pid 0 uid 1000
12-24 11:40:47.893 518 1285 E SurfaceFlinger: validateScreenshotPermissions pid 0 uid 1000
可以看出确实在aosp16版本显示pid是0,但是对应uid是1000也就是system_server
但是真的aosp16版本都是pid为0吗?明显也不是哈,具体也可以看下面截图:
可以看到其实也是有uid为1000但是pid不是0情况.
前置必学binder驱动相关知识:
那么要解决上面这个疑问就必须学习如下这些前置知识
mCallingPid,mCallingUid是在哪里赋值的呢?
frameworks/native/libs/binder/IPCThreadState.cpp
这里可以看出是在IPCThreadState::executeCommand方法中由内核进行返回的。
所以这块要查到根本原因还是要去binder.c中进行进一步排查。
drivers/android/binder.c
trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid);
t_from = binder_get_txn_from(t);
if (t_from) {
struct task_struct *sender = t_from->proc->tsk;
trd->sender_pid =
task_tgid_nr_ns(sender,
task_active_pid_ns(current));
trace_android_vh_sync_txn_recvd(thread->task, t_from->task);
} else {
trd->sender_pid = 0;
}
这块代码确实看到有设置成0和正常pid的,但是这块代码排查后,两个14,16版本都是一样的调用方式。
那么到底差异在哪呢?这部分就留给各位学员去探索一下,按照我上面限定的方法。
学员作业要求:
1、剖析出uid和pid是如何在kernel中被binder驱动进行设置的
2、解释什么场景调用pid就会设置为0
3、解释清楚为啥同样的captureDisplay接口,aosp14和aosp16会有差异。
原文参考:
https://mp.weixin.qq.com/s/gT7AN6sp3A_bcXeM9Ut7yQ
更多framework实战开发干货,请关注下面“千里马学框架”
1644

被折叠的 条评论
为什么被折叠?



