diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 9c4a36f1c9658..2fa75f16a5464 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -913,6 +913,18 @@ public class Binder implements IBinder { resultReceiver.send(0, null); } + /** @hide */ + @Override + public final native @Nullable IBinder getExtension(); + + /** + * Set the binder extension. + * This should be called immediately when the object is created. + * + * @hide + */ + public final native void setExtension(@Nullable IBinder extension); + /** * Default implementation rewinds the parcels and calls onTransact. On * the remote side, transact calls into the binder to do the IPC. diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index c35b05f104986..a26bd39eed9d3 100644 --- a/core/java/android/os/BinderProxy.java +++ b/core/java/android/os/BinderProxy.java @@ -454,6 +454,10 @@ public final class BinderProxy implements IBinder { return null; } + /** @hide */ + @Override + public native @Nullable IBinder getExtension() throws RemoteException; + /** * Perform a binder transaction on a proxy. * diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index d9ed32799ea53..c43644dbd9605 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -243,6 +243,18 @@ public interface IBinder { @NonNull String[] args, @Nullable ShellCallback shellCallback, @NonNull ResultReceiver resultReceiver) throws RemoteException; + /** + * Get the binder extension of this binder interface. + * This allows one to customize an interface without having to modify the original interface. + * + * @return null if don't have binder extension + * @throws RemoteException + * @hide + */ + public default @Nullable IBinder getExtension() throws RemoteException { + throw new IllegalStateException("Method is not implemented"); + } + /** * Perform a generic operation with the object. * diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index a236f3143f845..079c2652cb178 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -463,6 +463,9 @@ public: if (mVintf) { ::android::internal::Stability::markVintf(b.get()); } + if (mExtension != nullptr) { + b.get()->setExtension(mExtension); + } mBinder = b; ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n", b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount()); @@ -481,6 +484,24 @@ public: mVintf = true; } + sp getExtension() { + AutoMutex _l(mLock); + sp b = mBinder.promote(); + if (b != nullptr) { + return b.get()->getExtension(); + } + return mExtension; + } + + void setExtension(const sp& extension) { + AutoMutex _l(mLock); + mExtension = extension; + sp b = mBinder.promote(); + if (b != nullptr) { + b.get()->setExtension(mExtension); + } + } + private: Mutex mLock; wp mBinder; @@ -489,6 +510,8 @@ private: // is too much binder state here, we can think about making JavaBBinder an // sp here (avoid recreating it) bool mVintf = false; + + sp mExtension; }; // ---------------------------------------------------------------------------- @@ -1033,6 +1056,17 @@ static jobject android_os_Binder_waitForService( return javaObjectForIBinder(env, service); } +static jobject android_os_Binder_getExtension(JNIEnv* env, jobject obj) { + JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject); + return javaObjectForIBinder(env, jbh->getExtension()); +} + +static void android_os_Binder_setExtension(JNIEnv* env, jobject obj, jobject extensionObject) { + JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject); + sp extension = ibinderForJavaObject(env, extensionObject); + jbh->setExtension(extension); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gBinderMethods[] = { @@ -1062,7 +1096,9 @@ static const JNINativeMethod gBinderMethods[] = { { "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder }, { "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer }, { "blockUntilThreadAvailable", "()V", (void*)android_os_Binder_blockUntilThreadAvailable }, - { "waitForService", "(Ljava/lang/String;)Landroid/os/IBinder;", (void*)android_os_Binder_waitForService } + { "waitForService", "(Ljava/lang/String;)Landroid/os/IBinder;", (void*)android_os_Binder_waitForService }, + { "getExtension", "()Landroid/os/IBinder;", (void*)android_os_Binder_getExtension }, + { "setExtension", "(Landroid/os/IBinder;)V", (void*)android_os_Binder_setExtension }, }; const char* const kBinderPathName = "android/os/Binder"; @@ -1502,6 +1538,21 @@ JNIEXPORT jlong JNICALL android_os_BinderProxy_getNativeFinalizer(JNIEnv*, jclas return (jlong) BinderProxy_destroy; } +static jobject android_os_BinderProxy_getExtension(JNIEnv* env, jobject obj) { + IBinder* binder = getBPNativeData(env, obj)->mObject.get(); + if (binder == nullptr) { + jniThrowException(env, "java/lang/IllegalStateException", "Native IBinder is null"); + return nullptr; + } + sp extension; + status_t err = binder->getExtension(&extension); + if (err != OK) { + signalExceptionForError(env, obj, err, true /* canThrowRemoteException */); + return nullptr; + } + return javaObjectForIBinder(env, extension); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gBinderProxyMethods[] = { @@ -1513,6 +1564,7 @@ static const JNINativeMethod gBinderProxyMethods[] = { {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, {"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer}, + {"getExtension", "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension}, }; const char* const kBinderProxyPathName = "android/os/BinderProxy"; diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 9955c512686ad..a9e0a770c1441 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -1340,6 +1340,10 @@ + + +