diff options
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 11 | ||||
-rw-r--r-- | core/java/android/os/ISchedulingPolicyService.aidl | 34 | ||||
-rw-r--r-- | core/java/android/os/Process.java | 33 | ||||
-rw-r--r-- | core/java/android/os/SchedulingPolicyService.java | 65 | ||||
-rw-r--r-- | core/jni/android_util_Process.cpp | 12 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 5 |
7 files changed, 159 insertions, 2 deletions
@@ -132,6 +132,7 @@ LOCAL_SRC_FILES += \ core/java/android/os/IPermissionController.aidl \ core/java/android/os/IPowerManager.aidl \ core/java/android/os/IRemoteCallback.aidl \ + core/java/android/os/ISchedulingPolicyService.aidl \ core/java/android/os/IUpdateLock.aidl \ core/java/android/os/IVibratorService.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 36638f9..381daa3 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1928,6 +1928,17 @@ public abstract class Context { public static final String INPUT_SERVICE = "input"; /** + * Use with {@link #getSystemService} to retrieve a + * {@link android.os.SchedulingPolicyService} for managing scheduling policy. + * + * @see #getSystemService + * @see android.os.SchedulingPolicyService + * + * @hide + */ + public static final String SCHEDULING_POLICY_SERVICE = "scheduling_policy"; + + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. * diff --git a/core/java/android/os/ISchedulingPolicyService.aidl b/core/java/android/os/ISchedulingPolicyService.aidl new file mode 100644 index 0000000..1273c83 --- /dev/null +++ b/core/java/android/os/ISchedulingPolicyService.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012 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; + +/** + * Initially only provides requestPriority() below, but in longer term + * other scheduling policy related services will be collected here. + * + * @hide + */ +interface ISchedulingPolicyService { + + /** + * Move thread tid into appropriate cgroup and assign it priority prio. + * The thread group leader of tid must be pid. + * There may be restrictions on who can call this. + */ + int requestPriority(int pid, int tid, int prio); + +} diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 8e041bb..0ba7b88 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -299,6 +299,24 @@ public class Process { **/ private static final int THREAD_GROUP_FOREGROUND = 1; + /** + * System thread group. + * @hide + **/ + public static final int THREAD_GROUP_SYSTEM = 2; + + /** + * Application audio thread group. + * @hide + **/ + public static final int THREAD_GROUP_AUDIO_APP = 3; + + /** + * System audio thread group. + * @hide + **/ + public static final int THREAD_GROUP_AUDIO_SYS = 4; + public static final int SIGNAL_QUIT = 3; public static final int SIGNAL_KILL = 9; public static final int SIGNAL_USR1 = 10; @@ -658,6 +676,21 @@ public class Process { } /** + * Returns the thread group leader id for a currently running thread. + * @param tid the thread id + * @return the thread group leader id of the thread, or -1 if the thread is not running. + * This is same as what getpid(2) would return if called by tid. + * @hide + */ + public static final int getThreadGroupLeader(int tid) { + String[] procStatusLabels = { "Tgid:" }; + long[] procStatusValues = new long[1]; + procStatusValues[0] = -1; + Process.readProcLines("/proc/" + tid + "/status", procStatusLabels, procStatusValues); + return (int) procStatusValues[0]; + } + + /** * Set the priority of a thread, based on Linux priorities. * * @param tid The identifier of the thread/process to change. diff --git a/core/java/android/os/SchedulingPolicyService.java b/core/java/android/os/SchedulingPolicyService.java new file mode 100644 index 0000000..94f907b --- /dev/null +++ b/core/java/android/os/SchedulingPolicyService.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 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.Context; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.Process; +import android.util.Log; + +/** + * The implementation of the scheduling policy service interface. + * + * @hide + */ +public class SchedulingPolicyService extends ISchedulingPolicyService.Stub { + + private static final String TAG = "SchedulingPolicyService"; + + // Minimum and maximum values allowed for requestPriority parameter prio + private static final int PRIORITY_MIN = 1; + private static final int PRIORITY_MAX = 2; + + public SchedulingPolicyService() { + } + + public int requestPriority(int pid, int tid, int prio) { + //Log.i(TAG, "requestPriority(pid=" + pid + ", tid=" + tid + ", prio=" + prio + ")"); + + // Verify that caller is mediaserver, priority is in range, and that the + // callback thread specified by app belongs to the app that called mediaserver. + // Once we've verified that the caller is mediaserver, we can trust the pid but + // we can't trust the tid. No need to explicitly check for pid == 0 || tid == 0, + // since if not the case then the getThreadGroupLeader() test will also fail. + if (Binder.getCallingUid() != Process.MEDIA_UID || prio < PRIORITY_MIN || + prio > PRIORITY_MAX || Process.getThreadGroupLeader(tid) != pid) { + return PackageManager.PERMISSION_DENIED; + } + try { + // make good use of our CAP_SYS_NICE capability + Process.setThreadGroup(tid, Binder.getCallingPid() == pid ? + Process.THREAD_GROUP_AUDIO_SYS : Process.THREAD_GROUP_AUDIO_APP); + // must be in this order or it fails the schedulability constraint + Process.setThreadScheduler(tid, Process.SCHED_FIFO, prio); + } catch (RuntimeException e) { + return PackageManager.PERMISSION_DENIED; + } + return PackageManager.PERMISSION_GRANTED; + } + +} diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 93be342..d20cc9e 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -242,9 +242,17 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin continue; } - if (isDefault) { - t_pri = getpriority(PRIO_PROCESS, t_pid); + t_pri = getpriority(PRIO_PROCESS, t_pid); + + if (t_pri <= ANDROID_PRIORITY_AUDIO) { + int scheduler = sched_getscheduler(t_pid); + if ((scheduler == SCHED_FIFO) || (scheduler == SCHED_RR)) { + // This task wants to stay in it's current audio group so it can keep it's budget + continue; + } + } + if (isDefault) { if (t_pri >= ANDROID_PRIORITY_BACKGROUND) { // This task wants to stay at background continue; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index d68a1ef..849281d 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -30,6 +30,7 @@ import android.media.AudioService; import android.net.wifi.p2p.WifiP2pService; import android.os.Looper; import android.os.RemoteException; +import android.os.SchedulingPolicyService; import android.os.ServiceManager; import android.os.StrictMode; import android.os.SystemClock; @@ -155,6 +156,10 @@ class ServerThread extends Thread { Slog.i(TAG, "Telephony Registry"); ServiceManager.addService("telephony.registry", new TelephonyRegistry(context)); + Slog.i(TAG, "Scheduling Policy"); + ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE, + new SchedulingPolicyService()); + AttributeCache.init(context); Slog.i(TAG, "Package Manager"); |