前面提到 AMS 在启动后会将自身作为Context.ACTIVITY_SERVICE的服务注册到 ServiceManager,同事 ServiceManager 的一大功能就是进行服务的注册。下面就以 AMS 注册到 ServiceManager 为例,探讨注册服务的过程。
//.../frameworks//base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setSystemProcess(){
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
...
}
//.../frameworks/base/core/java/android/os/ServiceManager.java
//主要让我疑惑的是 allowIsolated 这个参数
//@param allowIsolated set to true to allow isolated sandboxed processed to access this service
//乍看是说 ture 表示允许隔离的沙盒进程来访问这个服务,暂时看不懂喔
public static void addService(String name, IBinder service, boolean allowIsolated){
getIServiceManager().addService(name, service, allowIsolated);
}
private static IServiceManager getIServiceManager(){
//采用单例模式
if(sServiceManager != null){
return sServiceManaer;
}
//find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
关键就是 ServiceManagerNative.asInterface(BinderInternal.getContextObject())这个方法了
拆分,先看 BinderInternal.getContextObject()再来看 ServiceManagerNative.asinterface();
//.../frameworks//base/core/java/com/android/internal/os/BinderInternal.java
public static final native IBinder getContextObject();
看到这个方法是 native 实现,
//.../frameworks/base/core/jni/android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
ProcessState 采用了单例,保存了进程的上下文信息
//.../frameworks//native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
ProcessState::ProcessState()
: mDriverFD(open_driver())
, ...
{
...
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
...
//关于打开驱动做了什么,后面有空单独分析
static int open_driver()
{
int fd = open("/dev/binder", O_RDWR);
}
关于 ProcessState::getStrongProxyForHandle(0)在defaultServiceManager()@IServiceManager.cpp中介绍过,得到一个new BpBinder(0)
于是
//...frameworks/base/core/jni/android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
等价于
return javaObjectForIBinder(env, new BpBinder(0));
}
//先看这个方法,是javaObjectForIBinder()的前置
const char* const kBinderPrxyPathName = "android/os/BinderProxy";
static int int_register_android_os_BinderProxy(JNIEnv* env){
...
clazz = FindClassOrDie(env, kBinderProxyPathName);
//代表android.os.BinderProxy 这个类
gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
//代表其构造函数 BinderProxy()
gBinderProxyOffsets.mConstructor = GetMethodIdOrDie(env, clazz, "<init>", "()V");
//字段 long mObject
gBinderProxyOffsets.mObject = GetFieldIdOrDie(env, clazz, "mObject", "J");
//字段 WeakReferenct mSelf
gBinderProxyOffsets.mSelt = GetFieldOrDie(env, clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
...
...
}
//然后看,注意这里的val 是一个 BpBinder,并且此时 handle 是0
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val){
...
//从上可以知道这里实例化了一个android.os.BinderProxy 对象
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
//这里将这个 BpBinder 的句柄保存在这个 BinderProxy 对象的mObject 成员变量中
env->SetLongField(object, gBinderProxyOffets.mObject,(jlong)val.get());
...
//返回的是 BinderProxy 对象
return object;
}
可以看到BinderInternal.getContextObject()得到了一个android.os.BinderProxy 对象,并且其内部持有一个BpBinder(0)的引用(handle 为0代表指向 service manager)。
ServiceManagerNative.asInterface(BinderInternal.getContextObject());
登记于
ServiceManagerNative.asInterface(BinderProxy(持有BpBinder(0)的引用))
//.../frameworks//base/core/java/android/os/ServiceManagerNative.java
static public IServiceManager asInterface(IBinder obj){
if(object == null){
return null;
}
//如果寻找的服务在当前进程,会得到 in,就是本地对象否则返回一个本地代理
IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
if(in !=null){
return in;
}
return new ServiceManagerProxy(obj);
}
//ServiceManagerNative 的内部类,内部就是保存了这个remote 即 BinderProxy 对象
public ServiceManagerProxy(IBinder remote){
mRemote = remote
}
现在来看用的地方
public static void addService(String name, IBinder service, boolean allowIsolated){
getIServiceManager().addService(name, service, allowIsolated);
等价于
addService()@ServiceManagerProxy
}
//涉及到了 Parcel 的知识 不知道的需要去补充
public void addService(String name, IBinder service, boolen allowIsolated){
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
简单说下 Parcel,Parcel 用来打包数据,用链表Parcel 池,在 native 层实例化对象,内部存了一个游标,指向当前指向的数据,因此存储需要对应。
上面用 Parcel 保存了参数,利用 mRemote(BinderProxy) 发送数据远程调用。
//.../frameworks/base/core/java/android/os/Binder.java
final class BinderProxy implements IBinder{
public boolean transact(int code, Parcel data, parcel reply, int flags){
return transactNative(code, data, reply, flags);
}
}
采用 JNI 调用 native 方法,经过 Binder 驱动转发给 service_manager进程,调用者在底层是 IPCThreadState发给驱动(Binder 驱动转发暂时先不讨论,后期再单独写一篇补充)。转发 Binder 请求
在service_manager 说过,内部有一个 loop 接受请求。然后将请求转发给svcmgr_handler方法处理
int svcmgr_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply)
{
...
switch(txn->code){
...
//这里就是添加服务了
case SVG_MGR_ADD_SERVICE:
s = bio_getString(msg, &len);
handle = bio_get_Ref(msg);
allow_isolated = bio_get_unit32(msg)? 1 : 0;
//添加服务的核心代码
if(do_add_service()){
...
}
break;
}
}
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
struct svcinfo *si;
//检查权限
if (!svc_can_register(s, len, spid)) {
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
str8(s, len), handle, uid);
return -1;
}
si = find_svc(s, len);
//服务已经注册过了。就释放相应的服务
if (si) {
if (si->handle) {
ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -1;
}
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
// 保存所有已经注册的服务
si->next = svclist;//svclist
svclist = si;
}
//以 BC_ACQUIRE命令。handle 为目标。通过 icotl 发送给 binder 驱动
binder_acquire(bs, handle);
//以 BC_REQUEST_DEATH_NOTIFICATION 命令的信息,通过 ioctl 发送给 binder 驱动,主要用于清理内存扥收尾工作
binder_link_to_death(bs, handle, &si->death);
return 0;
}
注册服务就是将这个服务本身记录到 service_manager 中,这样其他进程需要这个服务时,用name 请求Binder 驱动去转发这个请求给 service manager 后得到目标服务的handle,然后 Binder 驱动将请求转发给真正的目标服务。
按网上的理论,将 Binder驱动理解为路由器,service manager 理解为 DNS的比喻是最恰当的了。