Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c94c841 authored by Olivier Gaillard's avatar Olivier Gaillard Committed by Android (Google) Code Review
Browse files

Merge "Tests for binder work source propagation"

parents ce871128 1d724581
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -400,6 +400,9 @@ public class Binder implements IBinder {
     * }
     * }
     * </pre>
     * </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.
     * @param workSource The original UID responsible for the binder call.
     * @return token to restore original work source.
     * @return token to restore original work source.
     * @hide
     * @hide
@@ -423,6 +426,9 @@ public class Binder implements IBinder {
    /**
    /**
     * Clears the work source on this thread.
     * 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.
     * @return token to restore original work source.
     * @hide
     * @hide
     **/
     **/
@@ -442,6 +448,9 @@ public class Binder implements IBinder {
     *   Binder.restoreCallingWorkSource(token);
     *   Binder.restoreCallingWorkSource(token);
     * }
     * }
     * </pre>
     * </pre>
     *
     * <p>The work source will be propagated for future outgoing binder transactions
     * executed on this thread.
     * @hide
     * @hide
     **/
     **/
    @CriticalNative
    @CriticalNative
+6 −0
Original line number Original line Diff line number Diff line
@@ -1316,6 +1316,12 @@
        <service android:name="android.os.BinderThreadPriorityService"
        <service android:name="android.os.BinderThreadPriorityService"
                android:process=":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 -->
        <!-- Application components used for search manager tests -->


        <activity android:name="android.app.activity.SearchableActivity"
        <activity android:name="android.app.activity.SearchableActivity"
+91 −0
Original line number Original line Diff line number Diff line
/*
 * 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;
    }
}
+36 −0
Original line number Original line Diff line number Diff line
/*
 * 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;
    }
}
+166 −0
Original line number Original line Diff line number Diff line
/*
 * 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());
    }
}
Loading