diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 3d10661062eae..0f3ed19e091c6 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -327,17 +327,29 @@ public class Binder implements IBinder { @CriticalNative public static final native boolean isDirectlyHandlingTransaction(); + /** + * Returns {@code true} if the current thread has had its identity + * set explicitly via {@link #clearCallingIdentity()} + * + * @hide + */ + @CriticalNative + private static native boolean hasExplicitIdentity(); + /** * 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. + * executing an incoming transaction and the calling identity has not been + * explicitly set with {@link #clearCallingIdentity()} */ public static final int getCallingUidOrThrow() { - if (!isDirectlyHandlingTransaction()) { + if (!isDirectlyHandlingTransaction() && !hasExplicitIdentity()) { throw new IllegalStateException( - "Thread is not in a binder transcation"); + "Thread is not in a binder transaction, " + + "and the calling identity has not been " + + "explicitly set with clearCallingIdentity"); } return getCallingUid(); } diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 01837f483f105..a7c7d0ba35bcd 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -983,6 +983,10 @@ static void android_os_Binder_restoreCallingIdentity(jlong token) IPCThreadState::self()->restoreCallingIdentity(token); } +static jboolean android_os_Binder_hasExplicitIdentity() { + return IPCThreadState::self()->hasExplicitIdentity(); +} + static void android_os_Binder_setThreadStrictModePolicy(jint policyMask) { IPCThreadState::self()->setStrictModePolicy(policyMask); @@ -1079,6 +1083,8 @@ static const JNINativeMethod gBinderMethods[] = { // @CriticalNative { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, // @CriticalNative + { "hasExplicitIdentity", "()Z", (void*)android_os_Binder_hasExplicitIdentity }, + // @CriticalNative { "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy }, // @CriticalNative { "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy }, diff --git a/core/tests/coretests/src/android/os/BinderTest.java b/core/tests/coretests/src/android/os/BinderTest.java index 99dbe64456623..02f87901318d0 100644 --- a/core/tests/coretests/src/android/os/BinderTest.java +++ b/core/tests/coretests/src/android/os/BinderTest.java @@ -20,6 +20,8 @@ import androidx.test.filters.SmallTest; import junit.framework.TestCase; +import static org.testng.Assert.assertThrows; + public class BinderTest extends TestCase { private static final int UID = 100; @@ -45,12 +47,8 @@ public class BinderTest extends TestCase { } @SmallTest - public void testGetCallingUidOrThrow() throws Exception { - try { - Binder.getCallingUidOrThrow(); - throw new AssertionError("IllegalStateException expected"); - } catch (IllegalStateException expected) { - } + public void testGetCallingUidOrThrow_throws() throws Exception { + assertThrows(IllegalStateException.class, () -> Binder.getCallingUidOrThrow()); } @SmallTest