浅析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系统源代码情景分析》罗升阳