Ö÷Òª½á¹¹
AndroidÓ¦ÓóÌÐòʹÓÃJavaÓïÑÔ¿ª·¢£¬Binder¿ò¼Ü×ÔȻҲÉÙ²»ÁËÔÚJava²ãÌṩ½Ó¿Ú¡£
ǰÎÄÖÐÎÒÃÇ¿´µ½£¬Binder»úÖÆÔÚC++²ãÒѾÓÐÁËÍêÕûµÄʵÏÖ¡£Òò´ËJava²ãÍêÈ«²»ÓÃÖØ¸´ÊµÏÖ£¬¶øÊÇͨ¹ýJNIÏνÓÁËC++²ãÒÔ¸´ÓÃÆäʵÏÖ¡£
ÏÂͼÃèÊöÁËBinder Framework Java²ãµ½C++²ãµÄÏνӹØÏµ¡£

ÕâÀï¶ÔͼÖÐJava²ãºÍJNI²ãµÄ¼¸¸öÀà×öÒ»ÏÂ˵Ã÷( ¹ØÓÚC++²ãµÄ½²½âÇë¿´ÕâÀï )£º

ÕâÀïµÄIInterface£¬IBinderºÍC++²ãµÄÁ½¸öÀàÊÇͬÃûµÄ¡£Õâ¸öͬÃû²¢²»ÊÇÇɺϣºËüÃDz»½ö½öͬÃû£¬ËüÃÇËùÆðµÄ×÷Óã¬ÒÔ¼°ÆäÖаüº¬µÄ½Ó¿Ú¶¼ÊǼ¸ºõÒ»ÑùµÄ£¬Çø±ð½ö½öÔÚÓÚÒ»¸öÊÇC++²ã£¬Ò»¸öÊÇJava²ã¶øÒÑ¡£
³ýÁËIInterface£¬IBinderÖ®Í⣬ÕâÀïBinderÓëBinderProxyÀàÒ²ÊÇÓëC++µÄÀà¶ÔÓ¦µÄ£¬ÏÂÃæÁгöÁËJava²ãºÍC++²ãÀàµÄ¶ÔÓ¦¹ØÏµ£º

JNIµÄÏνÓ
JNIÈ«³ÆÊÇJava Native Interface£¬Õâ¸öÊÇÓÉJavaÐéÄâ»úÌṩµÄ»úÖÆ¡£Õâ¸ö»úÖÆÊ¹µÃnative´úÂë¿ÉÒÔºÍJava´úÂ뻥ÏàͨѶ¡£¼òµ¥À´Ëµ¾ÍÊÇ£ºÎÒÃÇ¿ÉÒÔÔÚC/C++¶Ëµ÷ÓÃJava´úÂ룬Ҳ¿ÉÒÔÔÚJava¶Ëµ÷ÓÃC/C++´úÂë¡£
¹ØÓÚJNIµÄÏêϸ˵Ã÷£¬¿ÉÒԲμûOracleµÄ¹Ù·½Îĵµ£ºJava Native Interface £¬ÕâÀï²»¶à˵Ã÷¡£
ʵ¼ÊÉÏ£¬ÔÚAndroidÖкܶàµÄ·þÎñ»òÕß»úÖÆ¶¼ÊÇÔÚC/C++²ãʵÏֵģ¬ÏëÒª½«ÕâЩʵÏÖ¸´Óõ½Java²ã£¬¾Í±ØÐëͨ¹ýJNI½øÐÐÏνӡ£AOSPÔ´ÂëÖУ¬/frameworks/base/core/jni/
Ŀ¼ÏµÄÔ´Âë¾ÍÊÇרÃÅÓÃÀ´¶Ô½ÓFramework²ãµÄJNIʵÏֵġ£
¿´Ò»ÏÂBinder.javaµÄʵÏ־ͻᷢÏÖ£¬ÕâÀïÃæÓв»Éٵķ½·¨¶¼ÊÇÓÃnative¹Ø¼ü×ÖÐÞÊε쬲¢ÇÒûÓз½·¨ÊµÏÖÌ壬ÕâЩ·½·¨Æäʵ¶¼ÊÇÔÚC++ÖÐʵÏֵģº
public static final native int getCallingPid();
public static final native int getCallingUid();
public static final native long clearCallingIdentity();
public static final native void restoreCallingIdentity(long
token);
public static final native void setThreadStrictModePolicy(int
policyMask);
public static final native int getThreadStrictModePolicy();
public static final native void flushPendingCommands();
public static final native void joinThreadPool();
|
ÔÚandroid_util_Binder.cppÎļþÖеÄÏÂÃæÕâ¶Î´úÂ룬É趨ÁËJava·½·¨ÓëC++·½·¨µÄ¶ÔÓ¦¹ØÏµ£º
static const JNINativeMethod gBinderMethods[] = { { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, { "init", "()V", (void*)android_os_Binder_init }, { "destroy", "()V", (void*)android_os_Binder_destroy }, { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable } };
|
ÕâÖÖ¶ÔÓ¦¹ØÏµÒâζ×Å£ºµ±Binder.javaÖеÄgetCallingPid·½·¨±»µ÷ÓõÄʱºò£¬ÕæÕýµÄʵÏÖÆäʵÊÇandroid_os_Binder_getCallingPid£¬µ±getCallingUid·½·¨±»µ÷ÓõÄʱºò£¬ÕæÕýµÄʵÏÖÆäʵÊÇandroid_os_Binder_getCallingUid£¬ÆäËûÀàͬ¡£
È»ºóÎÒÃÇÔÙ¿´Ò»ÏÂandroid_os_Binder_getCallingPid·½·¨µÄʵÏ־ͻᷢÏÖ£¬ÕâÀïÆäʵ¾ÍÊǶԽӵ½ÁËlibbinderÖÐÁË£º
static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz) { return IPCThreadState::self()->getCallingPid(); }
|
ÕâÀï¿´µ½ÁËJava¶ËµÄ´úÂëÊÇÈçºÎµ÷ÓõÄlibbinderÖеÄC++·½·¨µÄ¡£ÄÇô£¬Ïà·´µÄ·½ÏòÊÇÈçºÎµ÷ÓõÄÄØ£¿×î¹Ø¼üµÄ£¬libbinderÖеÄBBinder::onTransactÊÇÈçºÎÄܹ»µ÷Óõ½JavaÖеÄBinder::onTransactµÄÄØ£¿
Õâ¶ÎÂß¼¾ÍÊÇandroid_util_Binder.cppÖÐJavaBBinder::onTransactÖд¦ÀíµÄÁË¡£JavaBBinderÊÇBBinder×ÓÀ࣬ÆäÀà½á¹¹ÈçÏ£º

JavaBBinder::onTransact¹Ø¼ü´úÂëÈçÏ£º
virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { JNIEnv* env = javavm_to_jnienv(mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int32_t strict_policy_before = thread_state->getStrictModePolicy();
jboolean res = env->CallBooleanMethod(mObject,
gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data),
reinterpret_cast<jlong>(reply), flags);
...
} |
Çë×¢ÒâÕâ¶Î´úÂëÖеÄÕâÒ»ÐУº
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
|
ÕâÒ»ÐдúÂëÆäʵÊÇÔÚµ÷ÓÃmObjectÉÏoffsetΪmExecTransactµÄ·½·¨¡£ÕâÀïµÄ¼¸¸ö²ÎÊý˵Ã÷ÈçÏ£º
1.mObject Ö¸ÏòÁËJava¶ËµÄBinder¶ÔÏó
2.gBinderOffsets.mExecTransact Ö¸ÏòÁËBinderÀàµÄexecTransact·½·¨
3.data µ÷ÓÃexecTransact·½·¨µÄ²ÎÊý
4.code, data, reply, flags¶¼ÊÇ´«µÝ¸øµ÷Ó÷½·¨execTransactµÄ²ÎÊý
¶øJNIEnv.CallBooleanMethodÕâ¸ö·½·¨ÊÇÓÉÐéÄâ»úʵÏֵġ£¼´£ºÐéÄâ»ú»áÌṩnative·½·¨À´µ÷ÓÃÒ»¸öJava
ObjectÉϵķ½·¨£¨¹ØÓÚAndroidÉϵÄJavaÐéÄâ»ú£¬½ñºóÎÒÃÇ»áרÃŽ²½â£©¡£
ÕâÑù£¬¾ÍÔÚC++²ãµÄJavaBBinder::onTransactÖе÷ÓÃÁËJava²ãBinder::execTransact·½·¨¡£¶øÔÚBinder::execTransact·½·¨ÖУ¬ÓÖµ÷ÓÃÁË×ÔÉíµÄonTransact·½·¨£¬Óɴ˱£Ö¤Õû¸ö¹ý³Ì´®ÁªÁËÆðÀ´£º
private boolean execTransact(int code, long dataObj, long replyObj, int flags) { Parcel data = Parcel.obtain(dataObj); Parcel reply = Parcel.obtain(replyObj); boolean res; try { res = onTransact(code, data, reply, flags); } catch (RemoteException|RuntimeException e) { if (LOG_RUNTIME_EXCEPTION) { Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e); } if ((flags & FLAG_ONEWAY) != 0) { if (e instanceof RemoteException) { Log.w(TAG, "Binder call failed.", e); } else { Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e); } } else { reply.setDataPosition(0); reply.writeException(e); } res = true; } catch (OutOfMemoryError e) { RuntimeException re = new RuntimeException("Out of memory", e); reply.setDataPosition(0); reply.writeException(re); res = true; } checkParcel(this, code, reply, "Unreasonably large binder reply buffer"); reply.recycle(); data.recycle();
StrictMode.clearGatheredViolations();
return res;
|
Java Binder·þÎñ¾ÙÀý
ºÍC++²ãÒ»Ñù£¬ÕâÀïÎÒÃÇ»¹ÊÇͨ¹ýÒ»¸ö¾ßÌåµÄʵÀýÀ´¿´Ò»ÏÂJava²ãµÄBinder·þÎñÊÇÈçºÎʵÏֵġ£
ÏÂͼÊÇActivityManagerʵÏÖµÄÀàͼ:

ÏÂÃæÊÇÉÏͼÖм¸¸öÀàµÄ˵Ã÷£º

¿´¹ýBinder C++²ãʵÏÖÖ®ºó£¬¶ÔÓÚÕâ¸ö½á¹¹Ó¦¸ÃÒ²ÊǺÜÈÝÒ×Àí½âµÄ£¬×éÖ¯½á¹¹ºÍC++²ã·þÎñµÄʵÏÖÊÇһģһÑùµÄ¡£
¶ÔÓÚAndroidÓ¦ÓóÌÐòµÄ¿ª·¢ÕßÀ´Ëµ£¬ÎÒÃDz»»áÖ±½Ó½Ó´¥µ½ÉÏͼÖеöÀ࣬¶øÊÇʹÓÃandroid.app.ActivityManagerÖеĽӿڡ£
ÕâÀïÎÒÃǾÍÀ´¿´Ò»Ï£¬android.app.ActivityManagerÖеĽӿÚÓëÉÏͼµÄʵÏÖÊÇʲô¹ØÏµ¡£ÎÒÃÇѡȡÆäÖеÄÒ»¸ö·½·¨À´¿´Ò»Ï£º
public void getMemoryInfo(MemoryInfo outInfo) { try { ActivityManagerNative.getDefault().getMemoryInfo(outInfo); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
|
Õâ¸ö·½·¨µÄʵÏÖµ÷ÓÃÁËActivityManagerNative.getDefault()Öеķ½·¨£¬Òò´ËÎÒÃÇÔÚÀ´¿´Ò»ÏÂActivityManagerNative.getDefault()·µ»Øµ½µ½µ×ÊÇʲô¡£
static public IActivityManager getDefault() { return gDefault.get(); }
private static final Singleton<IActivityManager>
gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default
service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default
service = " + am);
}
return am;
}
}; |
Õâ¶Î´úÂëÖÐÎÒÃÇ¿´µ½£¬ÕâÀïÆäʵÊÇÏÈͨ¹ýIBinder b = ServiceManager.getService("activity");
»ñÈ¡ActivityManagerµÄBinder¶ÔÏ󣨡°activity¡±ÊÇActivityManagerServiceµÄBinder·þÎñ±êʶ£©£¬½Ó×ÅÎÒÃÇÔÙÀ´¿´Ò»ÏÂasInterface(b)µÄʵÏÖ£º
static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; }
return new ActivityManagerProxy(obj);
} |
ÕâÀïÓ¦¸ÃÊDZȽÏÃ÷°×ÁË£ºÊ×ÏÈͨ¹ýqueryLocalInterfaceÈ·¶¨ÓÐûÓб¾µØBinder£¬Èç¹ûÓеϰֱ½Ó·µ»Ø£¬·ñÔò´´½¨Ò»¸öActivityManagerProxy¶ÔÏ󡣺ÜÏÔÈ»£¬¼ÙÉèÔÚActivityManagerServiceËùÔڵĽø³Ìµ÷ÓÃÕâ¸ö·½·¨£¬ÄÇôqueryLocalInterface½«Ö±½Ó·µ»Ø±¾µØBinder£¬¶ø¼ÙÉèÔÚÆäËû½ø³ÌÖе÷Óã¬Õâ¸ö·½·¨½«·µ»Ø¿Õ£¬Óɴ˵¼ÖÂÆäËûµ÷ÓûñÈ¡µ½µÄ¶ÔÏóÆäʵ¾ÍÊÇActivityManagerProxy¡£¶øÔÚÄõ½ActivityManagerProxy¶ÔÏóÖ®ºóÔÚµ÷ÓÃÆä·½·¨Ëù×ߵķÏßÎÒÏë¶ÁÕßÓ¦¸ÃÒ²ÄÜÃ÷°×ÁË£ºÄǾÍÊÇͨ¹ýBinderÇý¶¯¿ç½ø³Ìµ÷ÓÃActivityManagerServiceÖеķ½·¨¡£
ÕâÀïµÄasInterface·½·¨µÄʵÏÖ»áÈÃÎÒÃǾõµÃËÆÔøÏàʶ¡£Êǵģ¬ÒòΪÕâÀïµÄʵÏÖ·½Ê½ºÍC++²ãµÄʵÏÖÊÇÒ»ÑùµÄģʽ¡£
Java²ãµÄServiceManager
Ô´Âë·¾¶£º
frameworks/base/core/java/android/os/IServiceManager.java frameworks/base/core/java/android/os/ServiceManager.java frameworks/base/core/java/android/os/ServiceManagerNative.java frameworks/base/core/java/com/android/internal/os/BinderInternal.java frameworks/base/core/jni/android_util_Binder.cpp
|
ÓÐJava¶ËµÄBinder·þÎñ£¬×ÔȻҲÉÙ²»ÁËJava¶ËµÄServiceManager¡£ÎÒÃÇÏÈ¿´Ò»ÏÂJava¶ËµÄServiceManagerµÄ½á¹¹£º

ͨ¹ýÕâ¸öÀàͼÎÒÃÇ¿´µ½£¬Java²ãµÄServiceManagerºÍC++²ãµÄ½Ó¿ÚÊÇÒ»ÑùµÄ¡£
È»ºóÎÒÃÇÔÙѡȡaddService·½·¨¿´Ò»ÏÂʵÏÖ£º
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;
} |
ºÜÏÔÈ»£¬Õâ¶Î´úÂëÖУ¬×î¹Ø¼ü¾ÍÊÇÏÂÃæÕâ¸öµ÷Óãº
ServiceManagerNative.asInterface(BinderInternal.getContextObject());
|
È»ºóÎÒÃÇÐèÒªÔÙ¿´Ò»ÏÂBinderInternal.getContextObject()ºÍServiceManagerNative.asInterfaceÁ½¸ö·½·¨¡£
BinderInternal.getContextObject()ÊÇÒ»¸öJNI·½·¨£¬ÆäʵÏÖ´úÂëÔÚandroid_util_Binder.cppÖУº
<table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" class="content"> <tr > <td width="694" height="25" bgcolor="#f5f5f5"> <pre style="text-indent: 0em;">Hello World!</pre> </td> </tr> </table>
|
¶øServiceManagerNative.asInterfaceµÄʵÏÖºÍÆäËûµÄBinder·þÎñÊÇÒ»ÑùµÄÌ×·£º
static public IServiceManager asInterface(IBinder obj) { if (obj == null) { return null; } IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; }
return new ServiceManagerProxy(obj);
} |
ÏÈͨ¹ýqueryLocalInterface²é¿´Äܲ»ÄÜ»ñµÃ±¾µØBinder£¬Èç¹ûÎÞ·¨»ñÈ¡£¬Ôò´´½¨²¢·µ»ØServiceManagerProxy¶ÔÏó¡£
¶øServiceManagerProxy×ÔȻҲÊÇºÍÆäËûBinder ProxyÒ»ÑùµÄʵÏÖÌ×·£º
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(); }
|
ÓÐÁËÉÏÎĵĽ²½â£¬Õâ¶Î´úÂëÓ¦¸Ã¶¼ÊDZȽÏÈÝÒ×Àí½âµÄÁË¡£
¹ØÓÚAIDL
×÷ΪBinder»úÖÆµÄ×îºóÒ»¸ö²¿·ÖÄÚÈÝ£¬ÎÒÃÇÀ´½²½âһϿª·¢Õß¾³£Ê¹ÓõÄAIDL»úÖÆÊÇÔõô»ØÊ¡£
AIDLÈ«³ÆÊÇAndroid Interface Definition Language£¬ËüÊÇAndroid
SDKÌṩµÄÒ»ÖÖ»úÖÆ¡£½èÖúÕâ¸ö»úÖÆ£¬Ó¦ÓÿÉÒÔÌṩ¿ç½ø³ÌµÄ·þÎñ¹©ÆäËûÓ¦ÓÃʹÓá£AIDLµÄÏêϸ˵Ã÷¿ÉÒԲμû¹Ù·½¿ª·¢Îĵµ£ºhttps://developer.android.com/guide/components/aidl.html
¡£
ÕâÀÎÒÃǾÍÒÔ¹Ù·½ÎĵµÉϵÄÀý×Ó¿´À´Ò»ÏÂAIDLÓëBinder¿ò¼ÜµÄ¹ØÏµ¡£
¿ª·¢Ò»¸ö»ùÓÚAIDLµÄServiceÐèÒªÈý¸ö²½Ö裺
1.¶¨ÒåÒ»¸ö.aidlÎļþ
2.ʵÏÖ½Ó¿Ú
3.±©Â¶½Ó¿Ú¸ø¿Í»§¶ËʹÓÃ
aidlÎļþʹÓÃJavaÓïÑÔµÄÓï·¨À´¶¨Ò壬ÿ¸ö.aidlÎļþÖ»Äܰüº¬Ò»¸öinterface£¬²¢ÇÒÒª°üº¬interfaceµÄËùÓз½·¨ÉùÃ÷¡£
ĬÈÏÇé¿öÏ£¬AIDLÖ§³ÖµÄÊý¾ÝÀàÐͰüÀ¨£º
»ù±¾Êý¾ÝÀàÐÍ£¨¼´int£¬long£¬char£¬booleanµÈ£©
String
CharSequence
List£¨ListµÄÔªËØÀàÐͱØÐëÊÇAIDLÖ§³ÖµÄ£©
Map£¨MapÖеÄÔªËØ±ØÐëÊÇAIDLÖ§³ÖµÄ£©
¶ÔÓÚAIDLÖеĽӿڣ¬¿ÉÒÔ°üº¬0¸ö»ò¶à¸ö²ÎÊý£¬¿ÉÒÔ·µ»Øvoid»òÒ»¸öÖµ¡£ËùÓзǻù±¾ÀàÐ͵IJÎÊý±ØÐë°üº¬Ò»¸öÃèÊöÊÇÊý¾ÝÁ÷ÏòµÄ±êÇ©£¬¿ÉÄܵÄȡֵÊÇ£ºin£¬out»òÕßinout¡£
ÏÂÃæÊÇÒ»¸öaidlÎļþµÄʾÀý£º
//
IRemoteService.aidl
package com.example.android;
// Declare any non-default types here with import
statements
/** Example service interface */
interface IRemoteService {
/** Request the process ID of this service, to
do evil things with it. */
int getPid();
/** Demonstrates some basic types that you can
use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean
aBoolean, float aFloat,
double aDouble, String aString);
} |
Õâ¸öÎļþÖаüº¬ÁËÁ½¸ö½Ó¿Ú £º
getPid Ò»¸öÎ޲εĽӿڣ¬·µ»ØÖµÀàÐÍΪint
basicTypes£¬°üº¬Á˼¸¸ö»ù±¾ÀàÐÍ×÷Ϊ²ÎÊýµÄ½Ó¿Ú£¬ÎÞ·µ»ØÖµ
¶ÔÓÚ°üº¬.aidlÎļþµÄ¹¤³Ì£¬Android IDE£¨ÒÔǰÊÇEclipse£¬ÏÖÔÚÊÇAndroid Studio£©ÔÚ±àÒëÏîÄ¿µÄʱºò£¬»áΪaidlÎļþÉú³É¶ÔÓ¦µÄJavaÎļþ¡£
Õë¶ÔÉÏÃæÕâ¸öaidlÎļþÉú³ÉµÄjavaÎļþÖаüº¬µÄ½á¹¹ÈçÏÂͼËùʾ£º

ÔÚÕâ¸öÉú³ÉµÄJavaÎļþÖУ¬°üÀ¨ÁË£º
Ò»¸öÃû³ÆÎªIRemoteServiceµÄinterface£¬¸Ãinterface¼Ì³Ð×Ôandroid.os.IInterface²¢ÇÒ°üº¬ÁËÎÒÃÇÔÚaidlÎļþÖÐÉùÃ÷µÄ½Ó¿Ú·½·¨
IRemoteServiceÖаüº¬ÁËÒ»¸öÃû³ÆÎªStubµÄ¾²Ì¬ÄÚ²¿À࣬Õâ¸öÀàÊÇÒ»¸ö³éÏóÀ࣬Ëü¼Ì³Ð×Ôandroid.os.Binder²¢ÇÒʵÏÖÁËIRemoteService½Ó¿Ú¡£Õâ¸öÀàÖаüº¬ÁËÒ»¸öonTransact·½·¨
StubÄÚ²¿ÓÖ°üº¬ÁËÒ»¸öÃû³ÆÎªProxyµÄ¾²Ì¬ÄÚ²¿À࣬ProxyÀàͬÑùʵÏÖÁËIRemoteService½Ó¿Ú
×Ðϸ¿´Ò»ÏÂStubÀàºÍProxyÁ½¸öÖаüº¬µÄ·½·¨£¬ÊDz»ÊǾõµÃºÜÊìϤ£¿Êǵģ¬ÕâÀïºÍÇ°Ãæ½éÉܵķþÎñʵÏÖÊÇÒ»ÑùµÄģʽ¡£ÕâÀïÎÒÃÇÁÐһϸ÷²ãÀàµÄ¶ÔÓ¦¹ØÏµ£º
ΪÁËÕû¸ö½á¹¹µÄÍêÕûÐÔ£¬×îºóÎÒÃÇ»¹ÊÇÀ´¿´Ò»ÏÂÉú³ÉµÄStubºÍProxyÀàÖеÄʵÏÖÂß¼¡£
StubÊÇÌṩ¸ø¿ª·¢ÕßʵÏÖÒµÎñµÄ¸¸À࣬¶øProxyµÄʵÏÖÁ˶ÔÍâÌṩµÄ½Ó¿Ú¡£StubºÍProxyÁ½¸öÀà¶¼ÓÐÒ»¸öasBinderµÄ·½·¨¡£
StubÀàÖеÄasBinderʵÏÖ¾ÍÊÇ·µ»Ø×ÔÉí¶ÔÏó£º
@Override public android.os.IBinder asBinder() { return this; }
|
¶øProxyÖÐasBinderµÄʵÏÖÊÇ·µ»Ø¹¹Ô캯ÊýÖлñÈ¡µÄmRemote¶ÔÏó£¬Ïà¹Ø´úÂëÈçÏ£º
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
|
¶øÕâÀïµÄmRemote¶ÔÏóÆäʵ¾ÍÊÇÔ¶³Ì·þÎñÔÚµ±Ç°½ø³ÌµÄ±êʶ¡£
ÉÏÎÄÎÒÃÇ˵ÁË£¬StubÀàÊÇÓÃÀ´Ìṩ¸ø¿ª·¢ÕßʵÏÖÒµÎñÂß¼µÄ¸¸À࣬¿ª·¢ÕßÕ߼̳Ð×ÔStubÈ»ºóÍê³É×Ô¼ºµÄÒµÎñÂ߼ʵÏÖ£¬ÀýÈçÕâÑù£º
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { public int getPid(){ return Process.myPid(); } public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) { // Does something } };
|
¶øÕâ¸öProxyÀ࣬¾ÍÊÇÓÃÀ´¸øµ÷ÓÃÕßʹÓõĶÔÍâ½Ó¿Ú¡£ÎÒÃÇ¿ÉÒÔ¿´Ò»ÏÂProxyÖеĽӿڵ½µ×ÊÇÈçºÎʵÏֵģº
ProxyÖÐgetPid·½·¨ÊµÏÖÈçÏÂËùʾ£º
@Override public int getPid() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; }
|
ÕâÀï¾ÍÊÇͨ¹ýParcel¶ÔÏóÒÔ¼°transactµ÷ÓöÔÓ¦Ô¶³Ì·þÎñµÄ½Ó¿Ú¡£¶øÔÚStubÀàÖУ¬Éú³ÉµÄonTransact·½·¨¶ÔÓ¦µÄ´¦ÀíÁËÕâÀïµÄÇëÇó£º
@Override public 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_getPid: { data.enforceInterface(DESCRIPTOR); int _result = this.getPid(); reply.writeNoException(); reply.writeInt(_result); return true; } case TRANSACTION_basicTypes: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); long _arg1; _arg1 = data.readLong(); boolean _arg2; _arg2 = (0 != data.readInt()); float _arg3; _arg3 = data.readFloat(); double _arg4; _arg4 = data.readDouble(); java.lang.String _arg5; _arg5 = data.readString(); this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); }
|
onTransactËùÒª×öµÄ¾ÍÊÇ£º
1.¸ù¾ÝcodeÇø·ÖÇëÇóµÄÊÇÄĸö½Ó¿Ú
2.ͨ¹ýdataÀ´»ñÈ¡ÇëÇóµÄ²ÎÊý
3.µ÷ÓÃÓÉ×ÓÀàʵÏֵijéÏó·½·¨
|