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

Commit 7d167376 authored by Dan Egnor's avatar Dan Egnor Committed by Android (Google) Code Review
Browse files

Merge "Add unit test for passing thread priority & cgroup through Binder." into froyo

parents fb70ffd9 43fe81bc
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -7,9 +7,9 @@ LOCAL_MODULE_TAGS := tests
# Include all test java files.
LOCAL_SRC_FILES := \
	$(call all-java-files-under, src) \
	$(call all-Iaidl-files-under, src) \
	$(call all-java-files-under, DisabledTestApp/src) \
	$(call all-java-files-under, EnabledTestApp/src) \
	src/android/os/IAidlTest.aidl
	$(call all-java-files-under, EnabledTestApp/src)

LOCAL_STATIC_JAVA_LIBRARIES += android-common

+5 −9
Original line number Diff line number Diff line
@@ -1179,8 +1179,11 @@
        <!-- Application components used for os tests -->

        <service android:name="android.os.MessengerService"
                android:process=":messengerService">
        </service>
                android:process=":messengerService" />

        <!-- Used by BinderThreadPriorityTest -->
        <service android:name="android.os.BinderThreadPriorityService"
                android:process=":BinderThreadPriorityService" />

        <!-- Application components used for search manager tests -->

@@ -1198,13 +1201,6 @@
                android:authorities="android.app.SuggestionProvider">
        </provider>

        <!-- Used to test IPC. -->
        <service android:name="com.android.frameworks.coretests.binder.BinderTestService"
                 android:process="binder.BinderTestService" />
        <service android:name="com.android.frameworks.coretests.binder.BinderPerformanceService"
                 android:process="binder.BinderPerformanceService" />
        <service android:name="com.android.frameworks.coretests.binder.BinderVsMessagingService"
                 android:process="binder.BinderVsMessagingService" />
    </application>

    <instrumentation
+62 −0
Original line number Diff line number Diff line
/*
 * 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;

import android.app.Service;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;

/**
 * Service used by {@link BinderThreadPriorityTest} to verify
 * the conveyance of thread priorities over Binder.
 */
public class BinderThreadPriorityService extends Service {
    private static final String TAG = "BinderThreadPriorityService";

    private final IBinderThreadPriorityService.Stub mBinder =
            new IBinderThreadPriorityService.Stub() {
        public int getThreadPriority() {
            return Process.getThreadPriority(Process.myTid());
        }

        public String getThreadSchedulerGroup() {
            return BinderThreadPriorityTest.getSchedulerGroup();
        }

        public void callBack(IBinderThreadPriorityService recurse) {
            try {
                recurse.callBack(this);
            } catch (RemoteException e) {
                Log.e(TAG, "Binder callback failed", e);
            }
        }

        public void setPriorityAndCallBack(int priority, IBinderThreadPriorityService recurse) {
            Process.setThreadPriority(priority);
            try {
                recurse.callBack(this);
            } catch (RemoteException e) {
                Log.e(TAG, "Binder callback failed", e);
            }
        }
    };

    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}
+146 −0
Original line number Diff line number Diff line
/*
 * 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;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;

import java.io.File;
import java.io.IOException;

/**
 * Test whether Binder calls inherit thread priorities correctly.
 */
public class BinderThreadPriorityTest extends AndroidTestCase {
    private static final String TAG = "BinderThreadPriorityTest";
    private IBinderThreadPriorityService mService;
    private int mSavedPriority;

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName name, IBinder service) {
            synchronized (BinderThreadPriorityTest.this) {
                mService = IBinderThreadPriorityService.Stub.asInterface(service);
                BinderThreadPriorityTest.this.notifyAll();
            }
        }

        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
    };

    private static class ServiceStub extends IBinderThreadPriorityService.Stub {
        public int getThreadPriority() { fail(); return -999; }
        public String getThreadSchedulerGroup() { fail(); return null; }
        public void setPriorityAndCallBack(int p, IBinderThreadPriorityService cb) { fail(); }
        public void callBack(IBinderThreadPriorityService cb) { fail(); }
        private static void fail() { throw new RuntimeException("unimplemented"); }
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        getContext().bindService(
                new Intent(getContext(), BinderThreadPriorityService.class),
                mConnection, Context.BIND_AUTO_CREATE);

        synchronized (this) {
            if (mService == null) {
                try {
                    wait(30000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                assertNotNull("Gave up waiting for BinderThreadPriorityService", mService);
            }
        }

        mSavedPriority = Process.getThreadPriority(Process.myTid());
        Process.setThreadPriority(mSavedPriority);  // To realign priority & cgroup, if needed
        assertEquals(expectedSchedulerGroup(mSavedPriority), getSchedulerGroup());
        Log.i(TAG, "Saved priority: " + mSavedPriority);
    }

    @Override
    protected void tearDown() throws Exception {
        // HACK -- see bug 2665914 -- setThreadPriority() doesn't always set the
        // scheduler group reliably unless we start out with background priority.
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        Process.setThreadPriority(mSavedPriority);
        assertEquals(mSavedPriority, Process.getThreadPriority(Process.myTid()));
        assertEquals(expectedSchedulerGroup(mSavedPriority), getSchedulerGroup());

        getContext().unbindService(mConnection);
        super.tearDown();
    }

    public static String getSchedulerGroup() {
        String fn = "/proc/" + Process.myPid() + "/task/" + Process.myTid() + "/cgroup";
        try {
            String cgroup = FileUtils.readTextFile(new File(fn), 1024, null);
            for (String line : cgroup.split("\n")) {
                String fields[] = line.trim().split(":");
                    if (fields.length == 3 && fields[1].equals("cpu")) return fields[2];
            }
        } catch (IOException e) {
            Log.e(TAG, "Can't read: " + fn, e);
        }
        return null;  // Unknown
    }

    public static String expectedSchedulerGroup(int prio) {
        return prio < Process.THREAD_PRIORITY_BACKGROUND ? "/" : "/bg_non_interactive";
    }

    public void testPassPriorityToService() throws Exception {
        for (int prio = 19; prio >= -20; prio--) {
            Process.setThreadPriority(prio);

            // Local
            assertEquals(prio, Process.getThreadPriority(Process.myTid()));
            assertEquals(expectedSchedulerGroup(prio), getSchedulerGroup());

            // Remote
            assertEquals(prio, mService.getThreadPriority());
            assertEquals(expectedSchedulerGroup(prio), mService.getThreadSchedulerGroup());
        }
    }

    public void testCallBackFromServiceWithPriority() throws Exception {
        for (int prio = -20; prio <= 19; prio++) {
            final int expected = prio;
            mService.setPriorityAndCallBack(prio, new ServiceStub() {
                public void callBack(IBinderThreadPriorityService cb) {
                    assertEquals(expected, Process.getThreadPriority(Process.myTid()));
                    assertEquals(expectedSchedulerGroup(expected), getSchedulerGroup());
                }
            });

            assertEquals(mSavedPriority, Process.getThreadPriority(Process.myTid()));

            // BROKEN -- see bug 2665954 -- scheduler group doesn't get reset
            // properly after a back-call with a different priority.
            // assertEquals(expectedSchedulerGroup(mSavedPriority), getSchedulerGroup());
        }
    }
}
+24 −0
Original line number Diff line number Diff line
/*
 * 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 IBinderThreadPriorityService {
    int getThreadPriority();
    String getThreadSchedulerGroup();
    void callBack(IBinderThreadPriorityService recurse);
    void setPriorityAndCallBack(int priority, IBinderThreadPriorityService recurse);
}