diff --git a/api/current.txt b/api/current.txt index 99d4b95463819..f0b331042f375 100644 --- a/api/current.txt +++ b/api/current.txt @@ -33707,6 +33707,7 @@ package android.os { method public static final void flushPendingCommands(); method public static final int getCallingPid(); method public static final int getCallingUid(); + method public static final int getCallingUidOrThrow(); method public static final android.os.UserHandle getCallingUserHandle(); method public java.lang.String getInterfaceDescriptor(); method public boolean isBinderAlive(); diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 9939a3c8f36de..1ebb551df9618 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -272,6 +272,30 @@ public class Binder implements IBinder { @CriticalNative public static final native int getCallingUid(); + /** + * Returns {@code true} if the current thread is currently executing an + * incoming transaction. + * + * @hide + */ + @CriticalNative + public static final native boolean isHandlingTransaction(); + + /** + * Return the Linux uid assigned to the process that sent the transaction + * currently being processed. + * + * @throws IllegalStateException if the current thread is not currently + * executing an incoming transaction. + */ + public static final int getCallingUidOrThrow() { + if (!isHandlingTransaction()) { + throw new IllegalStateException( + "Thread is not in a binder transcation"); + } + return getCallingUid(); + } + /** * Return the UserHandle assigned to the process that sent you the * current transaction that is being processed. This is the user diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 3329e2047085f..f201ceb40ff48 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -875,6 +875,11 @@ static jint android_os_Binder_getCallingUid() return IPCThreadState::self()->getCallingUid(); } +static jboolean android_os_Binder_isHandlingTransaction() +{ + return IPCThreadState::self()->isServingCall(); +} + static jlong android_os_Binder_clearCallingIdentity() { return IPCThreadState::self()->clearCallingIdentity(); @@ -960,6 +965,8 @@ static const JNINativeMethod gBinderMethods[] = { // @CriticalNative { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, // @CriticalNative + { "isHandlingTransaction", "()Z", (void*)android_os_Binder_isHandlingTransaction }, + // @CriticalNative { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, // @CriticalNative diff --git a/core/tests/coretests/src/android/os/BinderTest.java b/core/tests/coretests/src/android/os/BinderTest.java index 534c5cdec259a..6c9c3c111ff82 100644 --- a/core/tests/coretests/src/android/os/BinderTest.java +++ b/core/tests/coretests/src/android/os/BinderTest.java @@ -43,4 +43,13 @@ public class BinderTest extends TestCase { Binder.restoreCallingWorkSource(token); assertEquals(UID, Binder.getCallingWorkSourceUid()); } + + @SmallTest + public void testGetCallingUidOrThrow() throws Exception { + try { + Binder.getCallingUidOrThrow(); + throw new AssertionError("IllegalStateException expected"); + } catch (IllegalStateException expected) { + } + } }