BinderInternal
BinderInternal 是 Java framework 的 Binder 内部控制面,不实现业务 IBinder。它把 Java 代码连接到 native ProcessState/IPCThreadState/BpBinder:获取 context object、加入线程池、修改线程上限、触发 Binder GC、观察 incoming transaction,以及按 UID 统计 BinderProxy。
本文面向已经读过 Binder基类详解、BinderProxy详解 和 ProcessState初始化 的读者。本文按调用者和状态 owner 拆分这些内部能力,不把它们当公开应用 API,也不重复 native 算法。
1. Native控制面
1.1 Context对象
源码文件:frameworks/base/core/java/com/android/internal/os/BinderInternal.java
public static final native IBinder getContextObject();ServiceManager.getIServiceManager() 调用它取得 handle 0 对应 Java Binder,再转换为 IServiceManager。它返回的是 Binder 对象,不是直接返回 ServiceManager Java 单例。
1.2 线程池
public static final native void joinThreadPool();
public static final native void setMaxThreads(int numThreads);
public static final native void disableBackgroundScheduling(
boolean disable);三者分别让当前线程加入 native Binder pool、配置驱动线程上限、改变 background scheduling 行为。它们共享 JNI 文件,但 owner 分别是当前 IPCThreadState 和进程 ProcessState。
1.3 JNI映射
源码文件:frameworks/base/core/jni/android_util_Binder.cpp
static const JNINativeMethod gBinderInternalMethods[] = {
{"getContextObject", "()Landroid/os/IBinder;", ...},
{"joinThreadPool", "()V", ...},
{"disableBackgroundScheduling", "(Z)V", ...},
{"setMaxThreads", "(I)V", ...},
{"handleGc", "()V", ...},
};JNI 只是桥接;例如 joinThreadPool 最终调用 IPCThreadState::self()->joinThreadPool(),并不在 Java 创建线程。
2. GC观察
2.1 GcWatcher
源码文件:frameworks/base/core/java/com/android/internal/os/BinderInternal.java
static WeakReference<GcWatcher> sGcWatcher =
new WeakReference<>(new GcWatcher());
static final class GcWatcher {
@Override
protected void finalize() throws Throwable {
handleGc();
sLastGcTime = SystemClock.uptimeMillis();
synchronized (sGcWatchers) {
sTmpWatchers = sGcWatchers.toArray(sTmpWatchers);
}
for (Runnable watcher : sTmpWatchers) {
if (watcher != null) watcher.run();
}
sGcWatcher = new WeakReference<>(new GcWatcher());
}
}watcher 被 GC/finalize 时调用 native handleGc(),记录 uptime 并通知注册的 Runnable,随后创建下一代 watcher。这个时间是 BinderInternal 观察到的 GC 时间,不是所有 GC 阶段的精确 trace。
2.2 forceGc
public static void forceGc(String reason) {
EventLog.writeEvent(2741, reason);
VMRuntime.getRuntime().requestConcurrentGC();
}forceGc() 记录原因并请求 concurrent GC;请求不等于 GC 已完成。ActivityThread 使用 getLastGcTime() 做节流判断,完成观察由 GcWatcher 更新。
3. 调用观察
3.1 Observer
public interface Observer {
CallSession callStarted(Binder binder, int code,
int workSourceUid);
void callEnded(CallSession session,
int requestSize, int replySize,
int workSourceUid);
void callThrewException(CallSession session,
Exception exception);
}Java Binder.execTransactInternal() 快照全局 observer,在业务 onTransact() 前后调用它;异常回调之后仍会调用 callEnded()。Observer 只覆盖 Java Stub,源码 TODO 明确它不覆盖所有 C++/Rust transaction。
3.2 工作归因
public interface WorkSourceProvider {
int resolveWorkSourceUid(int untrustedWorkSourceUid);
}provider 在 incoming transaction 关键路径执行,源码要求不能发起 Binder 调用。它把 caller 写入 Parcel 的不可信 work source 转换为最终归因 UID,不是权限检查。
3.3 调用统计
该接口接收聚合调用统计和 Binder 线程 native TID,由 BinderCallsStats 等内部组件消费。它不参与单次事务是否成功的返回路径。
4. Proxy计数
4.1 Native接口
源码文件:frameworks/base/core/java/com/android/internal/os/BinderInternal.java
public static native void nSetBinderProxyCountEnabled(
boolean enabled);
public static native SparseIntArray nGetBinderProxyPerUidCounts();
public static native int nGetBinderProxyCount(int uid);
public static native void nSetBinderProxyCountWatermarks(
int high, int low, int warning);这些方法控制 native BpBinder 的按 UID 计数,不是 Java BinderProxy.ProxyMap 的 entry 数。BinderProxy 调试会同时使用两层信息,但 key 和生命周期不同。
4.2 Java回调
public static void binderProxyLimitCallbackFromNative(int uid) {
sBinderProxyCountEventListenerDelegate.notifyLimitReached(uid);
}native 达到 warning/high watermark 后回调静态 Java 方法;delegate 在锁内读取 listener/handler,并通过 Handler post 到指定线程。native callback 线程不直接执行业务 listener。
5. 状态边界
5.1 Context与线程
获得 context object 不会启动线程池;设置 max threads 不会创建线程;join 当前线程也不等于修改最大值。这些 API 必须按各自 native owner 解释。
5.2 GC与Proxy
force GC 可能帮助清理 Java BinderProxy weak values,但不能保证 native proxy 立即降到水位以下;仍被 Java 强引用或 native 逻辑持有的代理不会消失。
5.3 Observer异常
Observer 方法位于 transaction 关键路径,尤其 callThrewException() 不应再抛异常,否则可能覆盖原业务异常。统计逻辑必须快速且不能递归 Binder 调用。
6. 测试边界
6.1 Proxy计数
源码文件:frameworks/base/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
测试服务通过 BinderInternal 启用计数、配置高低/警告水位并注册 Handler callback,验证指定 UID 的 proxy 数量和回调。它证明 Java-native 水位桥接,不证明 GC 何时清理所有 proxy。
6.2 调用统计
frameworks/base/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.javaframeworks/base/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
这些测试构造 CallSession、调用结束与异常输入,验证统计聚合;它们不执行完整 driver transaction 或 BinderInternal JNI 线程池入口。
6.3 可执行阅读
rg -n "joinThreadPool|getContextObject|disableBackgroundScheduling|setMaxThreads|handleGc" \
frameworks/base/core/java/com/android/internal/os/BinderInternal.java \
frameworks/base/core/jni/android_util_Binder.cpp
rg -n "GcWatcher|forceGc|Observer|WorkSourceProvider|CallStatsObserver" \
frameworks/base/core/java/com/android/internal/os/BinderInternal.java
rg -n "nSetBinderProxyCount|binderProxy.*Callback|setBinderProxyCountCallback" \
frameworks/base/core/java/com/android/internal/os/BinderInternal.java \
frameworks/base/core/jni/android_util_Binder.cpp排查 BinderInternal 行为时,先确认问题属于线程池、context object、GC、incoming observer 还是 proxy UID 水位;这些 API 位于同一类中只是内部封装选择,不意味着它们共享同一个状态机或生效时机。
