淺析Binder(六)——Java服務啟動

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系統源代碼情景分析》羅升陽

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容