diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index f947b5ef9f5be..8b6194c29707b 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -28,6 +28,8 @@ import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.util.FunctionalUtils.ThrowingSupplier; +import dalvik.annotation.optimization.CriticalNative; + import libcore.io.IoUtils; import libcore.util.NativeAllocationRegistry; @@ -372,6 +374,54 @@ public class Binder implements IBinder { */ public static final native int getThreadStrictModePolicy(); + /** + * Sets the work source for this thread. + * + *
All the following binder calls on this thread will use the provided work source. + * + *
The concept of worksource is similar to {@link WorkSource}. However, for performance + * reasons, we only support one UID. This UID represents the original user responsible for the + * binder calls. + * + *
A typical use case would be + *
+ * Binder.setThreadWorkSource(uid);
+ * try {
+ * // Call an API.
+ * } finally {
+ * Binder.clearThreadWorkSource();
+ * }
+ *
+ *
+ * @param workSource The original UID responsible for the binder call.
+ * @return The previously set work source.
+ * @hide
+ **/
+ @CriticalNative
+ public static final native int setThreadWorkSource(int workSource);
+
+ /**
+ * Returns the work source set by the caller.
+ *
+ * Unlike {@link Binder#getCallingUid()}, this result of this method cannot be trusted. The
+ * caller can set the value to whatever he wants. Only use this value if you trust the calling
+ * uid.
+ *
+ * @return The original UID responsible for the binder transaction.
+ * @hide
+ */
+ @CriticalNative
+ public static final native int getThreadWorkSource();
+
+ /**
+ * Clears the work source on this thread.
+ *
+ * @return The previously set work source.
+ * @hide
+ **/
+ @CriticalNative
+ public static final native int clearThreadWorkSource();
+
/**
* Flush any Binder commands pending in the current thread to the kernel
* driver. This can be
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index d023d22473c84..ec980800c410e 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -904,6 +904,21 @@ static jint android_os_Binder_getThreadStrictModePolicy(JNIEnv* env, jobject cla
return IPCThreadState::self()->getStrictModePolicy();
}
+static jint android_os_Binder_setThreadWorkSource(jint workSource)
+{
+ return IPCThreadState::self()->setWorkSource(workSource);
+}
+
+static jint android_os_Binder_getThreadWorkSource()
+{
+ return IPCThreadState::self()->getWorkSource();
+}
+
+static jint android_os_Binder_clearThreadWorkSource()
+{
+ return IPCThreadState::self()->clearWorkSource();
+}
+
static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz)
{
IPCThreadState::self()->flushCommands();
@@ -941,6 +956,12 @@ static const JNINativeMethod gBinderMethods[] = {
{ "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity },
{ "setThreadStrictModePolicy", "(I)V", (void*)android_os_Binder_setThreadStrictModePolicy },
{ "getThreadStrictModePolicy", "()I", (void*)android_os_Binder_getThreadStrictModePolicy },
+ // @CriticalNative
+ { "setThreadWorkSource", "(I)I", (void*)android_os_Binder_setThreadWorkSource },
+ // @CriticalNative
+ { "getThreadWorkSource", "()I", (void*)android_os_Binder_getThreadWorkSource },
+ // @CriticalNative
+ { "clearThreadWorkSource", "()I", (void*)android_os_Binder_clearThreadWorkSource },
{ "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands },
{ "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder },
{ "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer },
diff --git a/core/tests/coretests/src/android/os/BinderTest.java b/core/tests/coretests/src/android/os/BinderTest.java
new file mode 100644
index 0000000000000..1beb598663d1c
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+public class BinderTest extends TestCase {
+
+ @SmallTest
+ public void testSetWorkSource() throws Exception {
+ Binder.setThreadWorkSource(100);
+ assertEquals(100, Binder.getThreadWorkSource());
+ }
+
+ @SmallTest
+ public void testClearWorkSource() throws Exception {
+ Binder.setThreadWorkSource(100);
+ Binder.clearThreadWorkSource();
+ assertEquals(-1, Binder.getThreadWorkSource());
+ }
+}