Java层Binder使用(ServiceManager)
跟上篇Binder使用一样,先通过例子来跟踪Java层Binder机制。本文参考了Binder In java
(http://www.cnblogs.com/angeldevil/p/3328748.html),只作为研究android记忆用
在Init进程的init2阶段,系统启动了ServerThread,在ServerThread中会启动很多用Java实现的系统服务
(frameworks/base/services/java/com/android/server/SystemServer.java)
代码
power = new PowerManagerService();ServiceManager.addService(Context.POWER_SERVICE, power);context = ActivityManagerService.main(factoryTest);Slog.i(TAG, "Display Manager");display = new DisplayManagerService(context, wmHandler, uiHandler);ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
通过ServiceManager的addService注册为binder 的server端。
我们以PowerManagerService为例,
(frameworks/base/services/java/com/android/server/power/)
PowerManagerService继承于IPowerManager.stub,而IPowerManager.stub位于
(frameworks/base/core/java/com/android/os/IPowerManager.aidl)
package android.os;import android.os.WorkSource;/** @hide */interface IPowerManager{ // WARNING: The first two methods must remain the first two methods because their // transaction numbers must not change unless IPowerManager.cpp is also updated. void acquireWakeLock(IBinder lock, int flags, String tag, in WorkSource ws); void releaseWakeLock(IBinder lock, int flags); void updateWakeLockWorkSource(IBinder lock, in WorkSource ws); boolean isWakeLockLevelSupported(int level); void userActivity(long time, int event, int flags); void wakeUp(long time); void goToSleep(long time, int reason); void nap(long time); boolean isScreenOn(); void reboot(boolean confirm, String reason, boolean wait); void shutdown(boolean confirm, boolean wait); void crash(String message); void setStayOnSetting(int val); void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs); // temporarily overrides the screen brightness settings to allow the user to // see the effect of a settings change without applying it immediately void setTemporaryScreenBrightnessSettingOverride(int brightness); void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj); // sets the attention light (used by phone app only) void setAttentionLight(boolean on, int color);}
Aidl是android内部进程通信接口的描述语言,通过编译我们可以编译出
package android.os;/** @hide */public interface IPowerManager extends android.os.IInterface {/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implementsandroid.os.IPowerManager {private static final java.lang.String DESCRIPTOR = "android.os.IPowerManager";/** Construct the stub at attach it to the interface. */public Stub() {this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an android.os.IPowerManager interface, * generating a proxy if needed. */public static android.os.IPowerManager asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof android.os.IPowerManager))) {return ((android.os.IPowerManager) iin);}return new android.os.IPowerManager.Stub.Proxy(obj);}@Overridepublic android.os.IBinder asBinder() {return this;}@Overridepublic boolean onTransact(int code, android.os.Parcel data,android.os.Parcel reply, int flags)throws android.os.RemoteException {switch (code) {case INTERFACE_TRANSACTION: {reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_acquireWakeLock: {data.enforceInterface(DESCRIPTOR);android.os.IBinder _arg0;_arg0 = data.readStrongBinder();int _arg1;_arg1 = data.readInt();java.lang.String _arg2;_arg2 = data.readString();android.os.WorkSource _arg3;if ((0 != data.readInt())) {_arg3 = android.os.WorkSource.CREATOR.createFromParcel(data);} else {_arg3 = null;}this.acquireWakeLock(_arg0, _arg1, _arg2, _arg3);reply.writeNoException();return true;}case TRANSACTION_releaseWakeLock: {data.enforceInterface(DESCRIPTOR);android.os.IBinder _arg0;_arg0 = data.readStrongBinder();int _arg1;_arg1 = data.readInt();this.releaseWakeLock(_arg0, _arg1);reply.writeNoException();return true;}case TRANSACTION_updateWakeLockWorkSource: {data.enforceInterface(DESCRIPTOR);android.os.IBinder _arg0;_arg0 = data.readStrongBinder();android.os.WorkSource _arg1;if ((0 != data.readInt())) {_arg1 = android.os.WorkSource.CREATOR.createFromParcel(data);} else {_arg1 = null;}this.updateWakeLockWorkSource(_arg0, _arg1);reply.writeNoException();return true;}case TRANSACTION_isWakeLockLevelSupported: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();boolean _result = this.isWakeLockLevelSupported(_arg0);reply.writeNoException();reply.writeInt(((_result) ? (1) : (0)));return true;}case TRANSACTION_userActivity: {data.enforceInterface(DESCRIPTOR);long _arg0;_arg0 = data.readLong();int _arg1;_arg1 = data.readInt();int _arg2;_arg2 = data.readInt();this.userActivity(_arg0, _arg1, _arg2);reply.writeNoException();return true;}case TRANSACTION_wakeUp: {data.enforceInterface(DESCRIPTOR);long _arg0;_arg0 = data.readLong();this.wakeUp(_arg0);reply.writeNoException();return true;}case TRANSACTION_goToSleep: {data.enforceInterface(DESCRIPTOR);long _arg0;_arg0 = data.readLong();int _arg1;_arg1 = data.readInt();this.goToSleep(_arg0, _arg1);reply.writeNoException();return true;}case TRANSACTION_nap: {data.enforceInterface(DESCRIPTOR);long _arg0;_arg0 = data.readLong();this.nap(_arg0);reply.writeNoException();return true;}case TRANSACTION_isScreenOn: {data.enforceInterface(DESCRIPTOR);boolean _result = this.isScreenOn();reply.writeNoException();reply.writeInt(((_result) ? (1) : (0)));return true;}case TRANSACTION_reboot: {data.enforceInterface(DESCRIPTOR);boolean _arg0;_arg0 = (0 != data.readInt());java.lang.String _arg1;_arg1 = data.readString();boolean _arg2;_arg2 = (0 != data.readInt());this.reboot(_arg0, _arg1, _arg2);reply.writeNoException();return true;}case TRANSACTION_shutdown: {data.enforceInterface(DESCRIPTOR);boolean _arg0;_arg0 = (0 != data.readInt());boolean _arg1;_arg1 = (0 != data.readInt());this.shutdown(_arg0, _arg1);reply.writeNoException();return true;}case TRANSACTION_crash: {data.enforceInterface(DESCRIPTOR);java.lang.String _arg0;_arg0 = data.readString();this.crash(_arg0);reply.writeNoException();return true;}case TRANSACTION_setStayOnSetting: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();this.setStayOnSetting(_arg0);reply.writeNoException();return true;}case TRANSACTION_setMaximumScreenOffTimeoutFromDeviceAdmin: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();this.setMaximumScreenOffTimeoutFromDeviceAdmin(_arg0);reply.writeNoException();return true;}case TRANSACTION_setTemporaryScreenBrightnessSettingOverride: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();this.setTemporaryScreenBrightnessSettingOverride(_arg0);reply.writeNoException();return true;}case TRANSACTION_setTemporaryScreenAutoBrightnessAdjustmentSettingOverride: {data.enforceInterface(DESCRIPTOR);float _arg0;_arg0 = data.readFloat();this.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(_arg0);reply.writeNoException();return true;}case TRANSACTION_setAttentionLight: {data.enforceInterface(DESCRIPTOR);boolean _arg0;_arg0 = (0 != data.readInt());int _arg1;_arg1 = data.readInt();this.setAttentionLight(_arg0, _arg1);reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements android.os.IPowerManager {private android.os.IBinder mRemote;Proxy(android.os.IBinder remote) {mRemote = remote;}@Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}// WARNING: The first two methods must remain the first two methods// because their// transaction numbers must not change unless IPowerManager.cpp is// also updated.@Overridepublic void acquireWakeLock(android.os.IBinder lock, int flags,java.lang.String tag, android.os.WorkSource ws)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeStrongBinder(lock);_data.writeInt(flags);_data.writeString(tag);if ((ws != null)) {_data.writeInt(1);ws.writeToParcel(_data, 0);} else {_data.writeInt(0);}mRemote.transact(Stub.TRANSACTION_acquireWakeLock, _data,_reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void releaseWakeLock(android.os.IBinder lock, int flags)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeStrongBinder(lock);_data.writeInt(flags);mRemote.transact(Stub.TRANSACTION_releaseWakeLock, _data,_reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void updateWakeLockWorkSource(android.os.IBinder lock,android.os.WorkSource ws) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeStrongBinder(lock);if ((ws != null)) {_data.writeInt(1);ws.writeToParcel(_data, 0);} else {_data.writeInt(0);}mRemote.transact(Stub.TRANSACTION_updateWakeLockWorkSource,_data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic boolean isWakeLockLevelSupported(int level)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();boolean _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(level);mRemote.transact(Stub.TRANSACTION_isWakeLockLevelSupported,_data, _reply, 0);_reply.readException();_result = (0 != _reply.readInt());} finally {_reply.recycle();_data.recycle();}return _result;}@Overridepublic void userActivity(long time, int event, int flags)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeLong(time);_data.writeInt(event);_data.writeInt(flags);mRemote.transact(Stub.TRANSACTION_userActivity, _data,_reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void wakeUp(long time) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeLong(time);mRemote.transact(Stub.TRANSACTION_wakeUp, _data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void goToSleep(long time, int reason)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeLong(time);_data.writeInt(reason);mRemote.transact(Stub.TRANSACTION_goToSleep, _data, _reply,0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void nap(long time) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeLong(time);mRemote.transact(Stub.TRANSACTION_nap, _data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic boolean isScreenOn() throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();boolean _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_isScreenOn, _data,_reply, 0);_reply.readException();_result = (0 != _reply.readInt());} finally {_reply.recycle();_data.recycle();}return _result;}@Overridepublic void reboot(boolean confirm, java.lang.String reason,boolean wait) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(((confirm) ? (1) : (0)));_data.writeString(reason);_data.writeInt(((wait) ? (1) : (0)));mRemote.transact(Stub.TRANSACTION_reboot, _data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void shutdown(boolean confirm, boolean wait)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(((confirm) ? (1) : (0)));_data.writeInt(((wait) ? (1) : (0)));mRemote.transact(Stub.TRANSACTION_shutdown, _data, _reply,0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void crash(java.lang.String message)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeString(message);mRemote.transact(Stub.TRANSACTION_crash, _data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void setStayOnSetting(int val)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(val);mRemote.transact(Stub.TRANSACTION_setStayOnSetting, _data,_reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(timeMs);mRemote.transact(Stub.TRANSACTION_setMaximumScreenOffTimeoutFromDeviceAdmin,_data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}// temporarily overrides the screen brightness settings to allow the// user to// see the effect of a settings change without applying it// immediately@Overridepublic void setTemporaryScreenBrightnessSettingOverride(int brightness) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(brightness);mRemote.transact(Stub.TRANSACTION_setTemporaryScreenBrightnessSettingOverride,_data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}@Overridepublic void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeFloat(adj);mRemote.transact(Stub.TRANSACTION_setTemporaryScreenAutoBrightnessAdjustmentSettingOverride,_data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}// sets the attention light (used by phone app only)@Overridepublic void setAttentionLight(boolean on, int color)throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(((on) ? (1) : (0)));_data.writeInt(color);mRemote.transact(Stub.TRANSACTION_setAttentionLight, _data,_reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}}static final int TRANSACTION_acquireWakeLock = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_releaseWakeLock = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);static final int TRANSACTION_updateWakeLockWorkSource = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);static final int TRANSACTION_isWakeLockLevelSupported = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);static final int TRANSACTION_userActivity = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);static final int TRANSACTION_wakeUp = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);static final int TRANSACTION_goToSleep = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);static final int TRANSACTION_nap = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);static final int TRANSACTION_isScreenOn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);static final int TRANSACTION_reboot = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);static final int TRANSACTION_shutdown = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);static final int TRANSACTION_crash = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);static final int TRANSACTION_setStayOnSetting = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12);static final int TRANSACTION_setMaximumScreenOffTimeoutFromDeviceAdmin = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13);static final int TRANSACTION_setTemporaryScreenBrightnessSettingOverride = (android.os.IBinder.FIRST_CALL_TRANSACTION + 14);static final int TRANSACTION_setTemporaryScreenAutoBrightnessAdjustmentSettingOverride = (android.os.IBinder.FIRST_CALL_TRANSACTION + 15);static final int TRANSACTION_setAttentionLight = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16);}// WARNING: The first two methods must remain the first two methods because// their// transaction numbers must not change unless IPowerManager.cpp is also// updated.public void acquireWakeLock(android.os.IBinder lock, int flags,java.lang.String tag, android.os.WorkSource ws)throws android.os.RemoteException;public void releaseWakeLock(android.os.IBinder lock, int flags)throws android.os.RemoteException;public void updateWakeLockWorkSource(android.os.IBinder lock,android.os.WorkSource ws) throws android.os.RemoteException;public boolean isWakeLockLevelSupported(int level)throws android.os.RemoteException;public void userActivity(long time, int event, int flags)throws android.os.RemoteException;public void wakeUp(long time) throws android.os.RemoteException;public void goToSleep(long time, int reason)throws android.os.RemoteException;public void nap(long time) throws android.os.RemoteException;public boolean isScreenOn() throws android.os.RemoteException;public void reboot(boolean confirm, java.lang.String reason, boolean wait)throws android.os.RemoteException;public void shutdown(boolean confirm, boolean wait)throws android.os.RemoteException;public void crash(java.lang.String message)throws android.os.RemoteException;public void setStayOnSetting(int val) throws android.os.RemoteException;public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs)throws android.os.RemoteException;// temporarily overrides the screen brightness settings to allow the user to// see the effect of a settings change without applying it immediatelypublic void setTemporaryScreenBrightnessSettingOverride(int brightness)throws android.os.RemoteException;public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) throws android.os.RemoteException;// sets the attention light (used by phone app only)public void setAttentionLight(boolean on, int color)throws android.os.RemoteException;}
我们可以从代码中看到Stub是一个抽象类,里面还有个proxy类
Stub提供asInterface, asBinder, onTransact,
PowerManagerService
其实这个是不是看起来很熟悉呢,我们回忆下MediaplayerService,MediaplayerService 继承于BnMediaPlayerService,而BnMediaPlayerService刚好跟这个Stub很类似,
然后我们再看看proxy类是不是跟BpMediaPlayerService类似,而IPowerManager则跟IMediaPlayerService类似,而PowerManagerServic则跟MediaplayerService一样实现功能。
并Stub继承于Binder,而在Binder构造函数中调用native的init
(framework\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->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);}
可以看出创建了一个JavaBBinderHolder,然后把值强制转int,返回给java层Binder类的
private int mObject;
在AndroidRuntine::startReg中会调用register_android_os_Binder,register_android_os_Binder会调用int_register_android_os_Binder等函数建立Java层Binder、BinderProxy、BinderInternal、Log等与Native层的映射关系
Native层对java层的反射
static int int_register_android_os_Binder(JNIEnv* env){ jclass clazz; clazz = env->FindClass(kBinderPathName); LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder"); gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gBinderOffsets.mExecTransact = env->GetMethodID(clazz, "execTransact", "(IIII)Z"); assert(gBinderOffsets.mExecTransact); gBinderOffsets.mObject = env->GetFieldID(clazz, "mObject", "I"); assert(gBinderOffsets.mObject); return AndroidRuntime::registerNativeMethods( env, kBinderPathName, gBinderMethods, NELEM(gBinderMethods));}
那JavaBBinderHolder是什么呢?
在android_os_Binder_init中new了一个JavaBBinderHolder,JavaBBinderHolder 的get()函数new了一个JavaBBinder保存到了自己的成员sp
有了这些我们可以猜测IPowerManager.aidl编译出来的文件就是binder机制中Server端
现在既然知道了PowerManagerService是binder的server端,那他怎么在java层向binder注册呢,还有client端怎么在java层获取Service呢
首先,按着binder的机制,ServiceManager.addService(Context.POWER_SERVICE, power);
我们查看ServiceManager类
(frameworks/base/core/java/android/os/ServiceManager.java)
public static void addService(String name, IBinder service, boolean allowIsolated) { try { getIServiceManager().addService(name, service, allowIsolated); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager;}
从代码可以看出addService是调用了ServiceManagerNative,而asInterface则是传入一个IBinder对象,并创建出ServiceManagerProxy,是不是跟Mediaplayer Server获取binder smgr有点类似?
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(); }
我们在看看BinderInternal.getContextObject(),他是一个native函数,我们到native层看看是不是跟Mediaplayer Server一样通过new Bpbinder(0),获取到Binder smgr。
(framework\base\core\jni\android_util_Binder.cpp)
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz){ sp b = ProcessState::self()->getContextObject(NULL); return javaObjectForIBinder(env, b);}
jobject javaObjectForIBinder(JNIEnv* env, const sp& val){ if (val == NULL) return NULL; if (val->checkSubclass(&gBinderOffsets)) {// BpBinder没重写,返回false // One of our own! jobject object = static_cast(val.get())->object(); LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object); return object; } // For the rest of the function we will hold this lock, to serialize // looking/creation of Java proxies for native Binder proxies. AutoMutex _l(mProxyLock); // Someone else's... do we know about it?// BpBinder没有带proxy过来 jobject object = (jobject)val->findObject(&gBinderProxyOffsets); if (object != NULL) { jobject res = jniGetReferent(env, object); if (res != NULL) { ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res); return res; } LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); android_atomic_dec(&gNumProxyRefs); val->detachObject(&gBinderProxyOffsets); env->DeleteGlobalRef(object); } // 因为proxy,创建一个proxy // const char* const kBinderProxyPathName = "android/os/BinderProxy"; object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); if (object != NULL) { LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object); // The proxy holds a reference to the native object. env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get()); // 把BpBinder(0)赋值给BinderProxy 的mObject val->incStrong((void*)javaObjectForIBinder); // The native object needs to hold a weak reference back to the // proxy, so we can retrieve the same proxy if it is still active. jobject refObject = env->NewGlobalRef( env->GetObjectField(object, gBinderProxyOffsets.mSelf)); val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup); // Also remember the death recipients registered on this proxy sp drl = new DeathRecipientList; drl->incStrong((void*)javaObjectForIBinder); env->SetIntField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast(drl.get())); // Note that a new object reference has been created. android_atomic_inc(&gNumProxyRefs); incRefsCreated(env); } return object;}
可以看出返回了android.os.BinderProxy
也就是说ServiceManagerProxy的mRemote带的BinderProxy
frameworks/base/core/java/com/android/os/Binder.java)
而里面的Transact是调用native层的android_os_BinderProxy_transact
frameworks/base/core/jni/android/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->GetIntField(obj, gBinderProxyOffsets.mObject); //此时的mObject为BpBinder(0); 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 %d\n", target, obj, code); // Only log the binder call duration for things on the Java-level main thread. // But if we don't const bool time_binder_calls = should_time_binder_calls(); int64_t start_millis; 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 (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*/); return JNI_FALSE;}
看出status_t err = target->transact(code, *data, reply, flags);
是调用了BinderProxy里面mObject(Bpbinder(0))的transact来传输数据
可以看到跟Mediaplayer Server一样 获取了smgr binder,并通过他通讯给smgr binder
那我们可以归结出ServiceManagerProxy 为BpServicemanager,并带入了smgr binder,跟binder通讯
其次,我们在java层获取Service是通过
Context.getSystemService(Context.POWER_SERVICE);
getSystemService位于ContextImpl中
(frameworks/base/core/java/com/android/app/ContextImpl.java)
@Override public Object getSystemService(String name) { ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name); return fetcher == null ? null : fetcher.getService(this);}
Static{.... registerService(POWER_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(POWER_SERVICE); IPowerManager service = IPowerManager.Stub.asInterface(b); return new PowerManager(ctx.getOuterContext(), service, ctx.mMainThread.getHandler()); }});....};
static class ServiceFetcher { int mContextCacheIndex = -1; /** * Main entrypoint; only override if you don't need caching. */ public Object getService(ContextImpl ctx) { ArrayList
从代码里面看出,要是从cache中获取不到service,那么
Static{.... registerService(POWER_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(POWER_SERVICE); IPowerManager service = IPowerManager.Stub.asInterface(b); return new PowerManager(ctx.getOuterContext(), service, ctx.mMainThread.getHandler()); }});....};
通过ServiceManager获取到PowerService,并通过Stub转化成IPowerManager,并创建了PowerManager返回给客户端调用。
而getService函数就跟addService一样,先获取smgr,然后用ServiceManagerProxy 的getService获取到binder,然后通过stub的asInterface转化为IPowerManager(实际是让其带Service的Binder)
public static android.os.IPowerManager asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof android.os.IPowerManager))) {return ((android.os.IPowerManager) iin);}return new android.os.IPowerManager.Stub.Proxy(obj);}
Proxy(android.os.IBinder remote) {mRemote = remote;}
更多相关文章
- 【转】高通平台android 环境配置编译及开发经验总结
- Android工程直接调用monkey源码进行压力测试
- Android(安卓)GPS应用:动态获取位置信息
- Android(安卓)Service BroadcastReceiver
- 一个常见Android崩溃问题的分析
- 全面了解Activity
- 4.0.x Launcher启动过程
- Android开发工具——ADB(Android(安卓)Debug Bridge) HOST端
- Android(安卓)Intent原理分析