summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/Binder.java9
-rw-r--r--core/tests/coretests/AndroidManifest.xml6
-rw-r--r--core/tests/coretests/src/android/os/BinderWorkSourceNestedService.java91
-rw-r--r--core/tests/coretests/src/android/os/BinderWorkSourceService.java36
-rw-r--r--core/tests/coretests/src/android/os/BinderWorkSourceTest.java166
-rw-r--r--core/tests/coretests/src/android/os/IBinderWorkSourceNestedService.aidl22
-rw-r--r--core/tests/coretests/src/android/os/IBinderWorkSourceService.aidl21
7 files changed, 351 insertions, 0 deletions
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index c7184c0743ce..1468fe5bfca8 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -400,6 +400,9 @@ public class Binder implements IBinder {
* }
* </pre>
*
+ * <p>The work source will be propagated for future outgoing binder transactions
+ * executed on this thread.
+ *
* @param workSource The original UID responsible for the binder call.
* @return token to restore original work source.
* @hide
@@ -423,6 +426,9 @@ public class Binder implements IBinder {
/**
* Clears the work source on this thread.
*
+ * <p>The work source will be propagated for future outgoing binder transactions
+ * executed on this thread.
+ *
* @return token to restore original work source.
* @hide
**/
@@ -442,6 +448,9 @@ public class Binder implements IBinder {
* Binder.restoreCallingWorkSource(token);
* }
* </pre>
+ *
+ * <p>The work source will be propagated for future outgoing binder transactions
+ * executed on this thread.
* @hide
**/
@CriticalNative
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index f60d8d0adcdd..3b650e5ff777 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1316,6 +1316,12 @@
<service android:name="android.os.BinderThreadPriorityService"
android:process=":BinderThreadPriorityService" />
+ <!-- Used by BinderWorkSourceTest -->
+ <service android:name="android.os.BinderWorkSourceService"
+ android:process=":BinderWorkSourceService" />
+ <service android:name="android.os.BinderWorkSourceNestedService"
+ android:process=":BinderWorkSourceNestedService" />
+
<!-- Application components used for search manager tests -->
<activity android:name="android.app.activity.SearchableActivity"
diff --git a/core/tests/coretests/src/android/os/BinderWorkSourceNestedService.java b/core/tests/coretests/src/android/os/BinderWorkSourceNestedService.java
new file mode 100644
index 000000000000..dddeda3874e3
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderWorkSourceNestedService.java
@@ -0,0 +1,91 @@
+/*
+ * 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.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+* Service used by {@link BinderWorkSourceTest}.
+*/
+public class BinderWorkSourceNestedService extends Service {
+ private final IBinderWorkSourceNestedService.Stub mBinder =
+ new IBinderWorkSourceNestedService.Stub() {
+
+ public int[] nestedCallWithWorkSourceToSet(int uidToBlame) {
+ final int uid = Binder.getCallingWorkSourceUid();
+ if (uidToBlame != ThreadLocalWorkSource.UID_NONE) {
+ Binder.setCallingWorkSourceUid(uidToBlame);
+ }
+ final int nestedUid = callGetIncomingWorkSourceUid();
+ return new int[] {uid, nestedUid};
+ }
+
+ public int[] nestedCall() {
+ final int uid = Binder.getCallingWorkSourceUid();
+ final int nestedUid = callGetIncomingWorkSourceUid();
+ return new int[] {uid, nestedUid};
+ }
+
+ private int callGetIncomingWorkSourceUid() {
+ BlockingQueue<IBinderWorkSourceService> blockingQueue =
+ new LinkedBlockingQueue<>();
+ ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ blockingQueue.add(IBinderWorkSourceService.Stub.asInterface(service));
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ }
+ };
+
+ Context context = getApplicationContext();
+ context.bindService(
+ new Intent(context, BinderWorkSourceService.class),
+ mConnection, Context.BIND_AUTO_CREATE);
+
+ final IBinderWorkSourceService service;
+ try {
+ service = blockingQueue.poll(30, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ if (service == null) {
+ throw new RuntimeException("Gave up waiting for BinderWorkSourceService");
+ }
+
+ try {
+ return service.getIncomingWorkSourceUid();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ } finally {
+ context.unbindService(mConnection);
+ }
+ }
+ };
+
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/core/tests/coretests/src/android/os/BinderWorkSourceService.java b/core/tests/coretests/src/android/os/BinderWorkSourceService.java
new file mode 100644
index 000000000000..ac8d7ab98344
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderWorkSourceService.java
@@ -0,0 +1,36 @@
+/*
+ * 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.app.Service;
+import android.content.Intent;
+
+/**
+ * Service used by {@link BinderWorkSourceTest}.
+ */
+public class BinderWorkSourceService extends Service {
+ private final IBinderWorkSourceService.Stub mBinder =
+ new IBinderWorkSourceService.Stub() {
+ public int getIncomingWorkSourceUid() {
+ return Binder.getCallingWorkSourceUid();
+ }
+ };
+
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/core/tests/coretests/src/android/os/BinderWorkSourceTest.java b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
new file mode 100644
index 000000000000..ec178031cc45
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test whether Binder calls work source is propagated correctly.
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class BinderWorkSourceTest {
+ private static Context sContext;
+ private static final int UID = 100;
+ private static final int SECOND_UID = 200;
+ private static final int UID_NONE = ThreadLocalWorkSource.UID_NONE;
+
+ private IBinderWorkSourceService mService;
+ private IBinderWorkSourceNestedService mNestedService;
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mService = IBinderWorkSourceService.Stub.asInterface(service);
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ mService = null;
+ }
+ };
+
+ private ServiceConnection mNestedConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mNestedService = IBinderWorkSourceNestedService.Stub.asInterface(service);
+ }
+
+ public void onServiceDisconnected(ComponentName name) {
+ mNestedService = null;
+ }
+ };
+
+ @BeforeClass
+ public static void setUpOnce() throws Exception {
+ sContext = InstrumentationRegistry.getContext();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ sContext.bindService(
+ new Intent(sContext, BinderWorkSourceService.class),
+ mConnection, Context.BIND_AUTO_CREATE);
+ sContext.bindService(
+ new Intent(sContext, BinderWorkSourceNestedService.class),
+ mNestedConnection, Context.BIND_AUTO_CREATE);
+
+ final long timeoutMs = System.currentTimeMillis() + 30_000;
+ while ((mService == null || mNestedService == null)
+ && System.currentTimeMillis() < timeoutMs) {
+ Thread.sleep(1_000);
+ }
+ assertNotNull("Gave up waiting for BinderWorkSourceService", mService);
+ assertNotNull("Gave up waiting for BinderWorkSourceNestedService", mNestedService);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ sContext.unbindService(mConnection);
+ sContext.unbindService(mNestedConnection);
+ }
+
+ @Test
+ public void setWorkSource() throws Exception {
+ Binder.setCallingWorkSourceUid(UID);
+ assertEquals(UID, mService.getIncomingWorkSourceUid());
+ assertEquals(UID, Binder.getCallingWorkSourceUid());
+ }
+
+ @Test
+ public void clearWorkSource() throws Exception {
+ Binder.setCallingWorkSourceUid(UID);
+ Binder.clearCallingWorkSource();
+ assertEquals(UID_NONE, mService.getIncomingWorkSourceUid());
+ assertEquals(UID_NONE, Binder.getCallingWorkSourceUid());
+ }
+
+ @Test
+ public void setWorkSource_propagatedForMultipleCalls() throws Exception {
+ Binder.setCallingWorkSourceUid(UID);
+ assertEquals(UID, mService.getIncomingWorkSourceUid());
+ assertEquals(UID, mService.getIncomingWorkSourceUid());
+ assertEquals(UID, mService.getIncomingWorkSourceUid());
+ assertEquals(UID, Binder.getCallingWorkSourceUid());
+ }
+
+ @Test
+ public void restoreWorkSource() throws Exception {
+ Binder.setCallingWorkSourceUid(UID);
+ long token = Binder.clearCallingWorkSource();
+ Binder.restoreCallingWorkSource(token);
+
+ assertEquals(UID, mService.getIncomingWorkSourceUid());
+ assertEquals(UID, Binder.getCallingWorkSourceUid());
+ }
+
+ @Test
+ public void nestedSetWorkSoucePropagated() throws Exception {
+ Binder.setCallingWorkSourceUid(UID);
+
+ int[] workSources = mNestedService.nestedCallWithWorkSourceToSet(SECOND_UID);
+ assertEquals(UID, workSources[0]);
+ // UID set in ested call.
+ assertEquals(SECOND_UID, workSources[1]);
+ // Initial work source restored.
+ assertEquals(UID, Binder.getCallingWorkSourceUid());
+ }
+
+ @Test
+ public void nestedSetWorkSouceDoesNotEnablePropagation() throws Exception {
+ int[] workSources = mNestedService.nestedCallWithWorkSourceToSet(UID);
+ assertEquals(UID_NONE, workSources[0]);
+ // UID set in ested call.
+ assertEquals(UID, workSources[1]);
+ // Initial work source restored.
+ assertEquals(UID_NONE, Binder.getCallingWorkSourceUid());
+ }
+
+ @Test
+ public void nestedSetWorkSouceNotPropagated() throws Exception {
+ Binder.setCallingWorkSourceUid(UID);
+
+ int[] workSources = mNestedService.nestedCall();
+ assertEquals(UID, workSources[0]);
+ // No UID propagated.
+ assertEquals(UID_NONE, workSources[1]);
+ // Initial work source restored.
+ assertEquals(UID, Binder.getCallingWorkSourceUid());
+ }
+}
diff --git a/core/tests/coretests/src/android/os/IBinderWorkSourceNestedService.aidl b/core/tests/coretests/src/android/os/IBinderWorkSourceNestedService.aidl
new file mode 100644
index 000000000000..365aebb803f6
--- /dev/null
+++ b/core/tests/coretests/src/android/os/IBinderWorkSourceNestedService.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2010 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;
+
+interface IBinderWorkSourceNestedService {
+ int[] nestedCallWithWorkSourceToSet(int uidToBlame);
+ int[] nestedCall();
+}
diff --git a/core/tests/coretests/src/android/os/IBinderWorkSourceService.aidl b/core/tests/coretests/src/android/os/IBinderWorkSourceService.aidl
new file mode 100644
index 000000000000..05d4e829be0a
--- /dev/null
+++ b/core/tests/coretests/src/android/os/IBinderWorkSourceService.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2010 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;
+
+interface IBinderWorkSourceService {
+ int getIncomingWorkSourceUid();
+}