Android开发笔试&&面试经验安卓资源收集

浅析Binder(六)——Java服务启动

2017-01-11  本文已影响346人  NoOneDev

Java服务一般运行在Android系统进程System或者Android应用程序进程中,在启动前同样需要将自己注册到ServiceManager中,定义的服务也是在Android系统进程System中启动。

比如说你自定义一个服务RemoteService.java

public class RemoteService extends IRemoteService.Stub{
    ......
}

那么Android系统进程System在启动时,会创建一个ServiceThread线程来启动系统中的关键服务,RemoteService就是在这个ServiceThread线程中启动的。addService方法将它注册到ServiceManager。

public final class SystemServer {
    ......
    private void run() {
        ......
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

服务的初始化

因为RemoteService继承了IRemote.Stub类,而后者有继承了Binder类,说以初始化的时候会调用Binder类的构造函数。

//framworks/base/core/java/android/os/Binder.java
public class Binder implement IBinder{
    ......
     public Binder() {
        init();

        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Binder> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Binder class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
    }
    ......
    private native final void init();
}

init()方法是一个Jni函数。具体实现如下

//framworks/base/core/jni/android_util_Binder.cpp
static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    if (jbh == NULL) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return;
    }
    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
    jbh->incStrong((void*)android_os_Binder_init);
    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);
}

RemoteService创建过程中在C++层对应一个JavaBinderHolder对象,而这个JavaBBinderHolder对象通过其成员变量mBInder持有一个类型为JavaBBinder的本地对象。而进程间通信就是通过这个本地对象来实现的。

注册服务到ServiceManager中

ServiceManager的Java代理对象的成员函数addService实现如下

//framworks/base/core/java/android/os/ServiceManagerNative.java
public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
    ......
    class ServiceManagerProxy implements IServiceManager {
        public ServiceManagerProxy(IBinder remote) {
            mRemote = remote;
        }
        ......
         public void addService(String name, IBinder service, boolean allowIsolated)
            throws RemoteException {
        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();
    }
    }
    ......
}

成员变量mRemote指向一个句柄只等于0的Java服务代理对象通过transact()方法可以向ServiceManager发送进程间他通信请求。

//framworks/base/core/java/android/os/Binder.java
public class BinderProxy implement IBinder{
    .....
    public native boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
    }
}

这是一个JNI方法,前面有讲过

//framworks/base/core/jni/android_util_Binder.cpp

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    if (dataObj == NULL) {
        jniThrowNullPointerException(env, NULL);
        return JNI_FALSE;
    }

    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }

    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }

    ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
            target, obj, code);


    bool time_binder_calls;
    int64_t start_millis;
    if (kEnableBinderSample) {
        // Only log the binder call duration for things on the Java-level main thread.
        // But if we don't
        time_binder_calls = should_time_binder_calls();

        if (time_binder_calls) {
            start_millis = uptimeMillis();
        }
    }

    //printf("Transact from Java code to %p sending: ", target); data->print();
    status_t err = target->transact(code, *data, reply, flags);
    //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();

    if (kEnableBinderSample) {
        if (time_binder_calls) {
            conditionally_log_binder_call(start_millis, target, code);
        }
    }

    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }

    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
    return JNI_FALSE;
}

至此Java服务启动过程解析完成。

</br>

参考:

《Android系统源代码情景分析》罗升阳

上一篇 下一篇

猜你喜欢

热点阅读