From e4ff397f0859dd707b7e1ad40176d84f05f689a5 Mon Sep 17 00:00:00 2001 From: Olivier Gaillard Date: Thu, 16 Aug 2018 14:01:58 +0100 Subject: [PATCH] Add WorkSource support to Binder.java. Test: unit test Change-Id: I6f3507b51a89c35943cc34299d7e364aab337e98 --- core/java/android/os/Binder.java | 50 +++++++++++++++++++ core/jni/android_util_Binder.cpp | 21 ++++++++ .../coretests/src/android/os/BinderTest.java | 37 ++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 core/tests/coretests/src/android/os/BinderTest.java 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()); + } +}