143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor/*
243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * Copyright (C) 2010 The Android Open Source Project
343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor *
443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * Licensed under the Apache License, Version 2.0 (the "License");
543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * you may not use this file except in compliance with the License.
643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * You may obtain a copy of the License at
743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor *
843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor *      http://www.apache.org/licenses/LICENSE-2.0
943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor *
1043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * Unless required by applicable law or agreed to in writing, software
1143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * distributed under the License is distributed on an "AS IS" BASIS,
1243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * See the License for the specific language governing permissions and
1443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * limitations under the License.
1543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor */
1643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
1743fe81bc2c186e49b25762450003276a7ed0002dDan Egnorpackage android.os;
1843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
1943fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport android.content.ComponentName;
2043fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport android.content.Context;
2143fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport android.content.Intent;
2243fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport android.content.ServiceConnection;
2343fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport android.test.AndroidTestCase;
2443fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport android.test.suitebuilder.annotation.MediumTest;
2543fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport android.util.Log;
2643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
2743fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport java.io.File;
2843fe81bc2c186e49b25762450003276a7ed0002dDan Egnorimport java.io.IOException;
2943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
3043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor/**
3143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor * Test whether Binder calls inherit thread priorities correctly.
3243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor */
3343fe81bc2c186e49b25762450003276a7ed0002dDan Egnorpublic class BinderThreadPriorityTest extends AndroidTestCase {
3443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    private static final String TAG = "BinderThreadPriorityTest";
3543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    private IBinderThreadPriorityService mService;
3643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    private int mSavedPriority;
3743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
3843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    private ServiceConnection mConnection = new ServiceConnection() {
3943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        public void onServiceConnected(ComponentName name, IBinder service) {
4043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            synchronized (BinderThreadPriorityTest.this) {
4143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                mService = IBinderThreadPriorityService.Stub.asInterface(service);
4243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                BinderThreadPriorityTest.this.notifyAll();
4343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            }
4443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        }
4543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
4643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        public void onServiceDisconnected(ComponentName name) {
4743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            mService = null;
4843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        }
4943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    };
5043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
5143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    private static class ServiceStub extends IBinderThreadPriorityService.Stub {
5243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        public int getThreadPriority() { fail(); return -999; }
5343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        public String getThreadSchedulerGroup() { fail(); return null; }
5443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        public void setPriorityAndCallBack(int p, IBinderThreadPriorityService cb) { fail(); }
5543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        public void callBack(IBinderThreadPriorityService cb) { fail(); }
5643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        private static void fail() { throw new RuntimeException("unimplemented"); }
5743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    }
5843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
5943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    @Override
6043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    protected void setUp() throws Exception {
6143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        super.setUp();
6243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
6343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        getContext().bindService(
6443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                new Intent(getContext(), BinderThreadPriorityService.class),
6543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                mConnection, Context.BIND_AUTO_CREATE);
6643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
6743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        synchronized (this) {
6843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            if (mService == null) {
6943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                try {
7043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                    wait(30000);
7143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                } catch (InterruptedException e) {
7243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                    throw new RuntimeException(e);
7343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                }
7443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                assertNotNull("Gave up waiting for BinderThreadPriorityService", mService);
7543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            }
7643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        }
7743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
7843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        mSavedPriority = Process.getThreadPriority(Process.myTid());
7943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        Process.setThreadPriority(mSavedPriority);  // To realign priority & cgroup, if needed
8043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        assertEquals(expectedSchedulerGroup(mSavedPriority), getSchedulerGroup());
8143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        Log.i(TAG, "Saved priority: " + mSavedPriority);
8243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    }
8343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
8443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    @Override
8543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    protected void tearDown() throws Exception {
8643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        // HACK -- see bug 2665914 -- setThreadPriority() doesn't always set the
8743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        // scheduler group reliably unless we start out with background priority.
8843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
8943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        Process.setThreadPriority(mSavedPriority);
9043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        assertEquals(mSavedPriority, Process.getThreadPriority(Process.myTid()));
9143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        assertEquals(expectedSchedulerGroup(mSavedPriority), getSchedulerGroup());
9243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
9343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        getContext().unbindService(mConnection);
9443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        super.tearDown();
9543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    }
9643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
9743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    public static String getSchedulerGroup() {
9843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        String fn = "/proc/" + Process.myPid() + "/task/" + Process.myTid() + "/cgroup";
9943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        try {
10043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            String cgroup = FileUtils.readTextFile(new File(fn), 1024, null);
10143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            for (String line : cgroup.split("\n")) {
10243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                String fields[] = line.trim().split(":");
10343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                    if (fields.length == 3 && fields[1].equals("cpu")) return fields[2];
10443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            }
10543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        } catch (IOException e) {
10643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            Log.e(TAG, "Can't read: " + fn, e);
10743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        }
10843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        return null;  // Unknown
10943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    }
11043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
11143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    public static String expectedSchedulerGroup(int prio) {
11243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        return prio < Process.THREAD_PRIORITY_BACKGROUND ? "/" : "/bg_non_interactive";
11343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    }
11443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
11543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    public void testPassPriorityToService() throws Exception {
11643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        for (int prio = 19; prio >= -20; prio--) {
11743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            Process.setThreadPriority(prio);
11843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
11943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            // Local
12043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            assertEquals(prio, Process.getThreadPriority(Process.myTid()));
12143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            assertEquals(expectedSchedulerGroup(prio), getSchedulerGroup());
12243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
12343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            // Remote
12443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            assertEquals(prio, mService.getThreadPriority());
12543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            assertEquals(expectedSchedulerGroup(prio), mService.getThreadSchedulerGroup());
12643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        }
12743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    }
12843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
12943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    public void testCallBackFromServiceWithPriority() throws Exception {
13043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        for (int prio = -20; prio <= 19; prio++) {
13143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            final int expected = prio;
13243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            mService.setPriorityAndCallBack(prio, new ServiceStub() {
13343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                public void callBack(IBinderThreadPriorityService cb) {
13443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                    assertEquals(expected, Process.getThreadPriority(Process.myTid()));
13543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                    assertEquals(expectedSchedulerGroup(expected), getSchedulerGroup());
13643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor                }
13743fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            });
13843fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
13943fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            assertEquals(mSavedPriority, Process.getThreadPriority(Process.myTid()));
14043fe81bc2c186e49b25762450003276a7ed0002dDan Egnor
14143fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            // BROKEN -- see bug 2665954 -- scheduler group doesn't get reset
14243fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            // properly after a back-call with a different priority.
14343fe81bc2c186e49b25762450003276a7ed0002dDan Egnor            // assertEquals(expectedSchedulerGroup(mSavedPriority), getSchedulerGroup());
14443fe81bc2c186e49b25762450003276a7ed0002dDan Egnor        }
14543fe81bc2c186e49b25762450003276a7ed0002dDan Egnor    }
14643fe81bc2c186e49b25762450003276a7ed0002dDan Egnor}
147