The Android framework knows a lot about tasks that are running and can help inform scheduler decisions. AOSP uses CPU Cgroup to implement tasks scheduler in framework in android N.
App schedule policy
There are 7 app task schedule policies defined in android N.
typedef enum { SP_DEFAULT = -1, SP_BACKGROUND= 0, SP_FOREGROUND= 1, //Not used in the framework SP_SYSTEM = 2, // can't be used with set_sched_policy() SP_AUDIO_APP = 3, SP_AUDIO_SYS = 4, SP_TOP_APP = 5, SP_CNT, SP_MAX = SP_CNT - 1, SP_SYSTEM_DEFAULT= SP_FOREGROUND, }SchedPolicy;
Thread SP
There are two classification threads in Andorid OS that are Java thread and native thread. Both threads are created by pthread_create in the end.It will set the JAVA thread SP when create .While it does not set the SP for native thread when create it. Framework provides 3 methods to set the thread SP.
Thread::SetNativePriority(int newPriority) { ... if (newNice >= ANDROID_PRIORITY_BACKGROUND){ set_sched_policy(tid, SP_BACKGROUND); }else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND){ set_sched_policy(tid,SP_FOREGROUND); } ... }
int androidSetThreadPriority(pid_t tid, int pri){
... if (pri >= ANDROID_PRIORITY_BACKGROUND) { rc = set_sched_policy(tid, SP_BACKGROUND); }else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND){ rc = set_sched_policy(tid, SP_FOREGROUND); }
....
}
CPU Cgroup
There are 4 cgroups defined cpu, cpuset, cpuboots and cpuschedtune so far in android N.
CPU_CTL
This cgroup uses two different scheduling classes bg_non_interactive and default (foreground). The configuration is that bg_non_interactive is low priority and can maximum utilize ~5% of the cpu (including all background tasks) and foreground ~95%. Forground means either an Activity or a service that is started foreground. At startup Services are running in bg_non_interactive unless they have been elevated to foreground scheduling group using startForeground. All the app tasks which belong to THREAD_GROUP_BG_NONINTERACTIVE BP are put into the bg_non_interactive tasks and other tasks to foreground.
int set_sched_policy(int tid, SchedPolicy policy)
{
…
if (__sys_supports_schedgroups) {
int fd;
switch (policy) {
case SP_BACKGROUND:
fd = bg_cgroup_fd;
break;
case SP_FOREGROUND:
case SP_AUDIO_APP:
case SP_AUDIO_SYS:
fd = fg_cgroup_fd;
break;
default:
fd = -1;
break;
}
if (add_tid_to_cgroup(tid, fd) != 0) {
if (errno != ESRCH && errno != ENOENT)
return -errno;
}
}
…
}
/dev/cpuctl/cpu.shares 1024 /dev/cpuctl/cpu.rt_runtime_us 800000 /dev/cpuctl/cpu.rt_period_us 1000000
/dev/cpuctl/bg_non_interactive/cpu.shares 52 /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000 /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000
CPUSET
Framework use CPUSET implement app tasks run different CPUS according to tasks SP and runtime state in order to get the better UX and power save. There are two scenarios in framework to use CPUSET. One is start app and the other is app runtime.
App start
Framework will migrate all the tasks from foreground group to foreground_boost cgroup when the app start.After 3000ms ,it will migrate back the tasks from foreground_boost cgroup to foreground cgroup.
Note,this feature shall enable the CPUSET and USE_SCHED_BOOST.
App runtime
Framework classifies all the tasks into 4 schedule group according to thread SP. Correspondingly,there are 4 cgroups in CPUSET,the default design as below,
int set_cpuset_policy(int tid, SchedPolicy policy)
{
// in the absence of cpusets, use the old sched policy
#ifndef USE_CPUSETS
return set_sched_policy(tid, policy);
#else
if (tid == 0) {
tid = gettid();
}
policy = _policy(policy);
pthread_once(&the_once, __initialize);
int fd;
switch (policy) {
case SP_BACKGROUND:
fd = bg_cpuset_fd;
break;
case SP_FOREGROUND:
case SP_AUDIO_APP:
case SP_AUDIO_SYS:
fd = fg_cpuset_fd;
break;
default:
fd = -1;
break;
}
if(add_tid_to_cgroup(tid, fd) != 0) {
if (errno != ESRCH && errno != ENOENT)
return -errno;
}
return 0;
#endif
}
//CPUS use to boost /dev/cpuset/foreground/cpus /dev/cpuset/foreground/mems //tasksput into this cgroup /dev/cpuset/foreground/tasks
/dev/cpuset/top-app/cpus /dev/cpuset/top-app/mems //tasks put into this cgroup /dev/cpuset/top-app/tasks
/dev/cpuset/background/cpus /dev/cpuset/background/mems //tasks put into this cgroup /dev/cpuset/background/tasks
/dev/cpuset/system-background/cpus /dev/cpuset/system-background/mems //tasksput into this cgroup /dev/cpuset/system-background/tasks
Cpuschedtune
It is for task "performance boosting". While seems that AOSP has not complete implement it.
/dev/stune/foreground /dev/stune/tasks /dev/stune/foreground/tasks /dev/stune/background /dev/stune/background/tasks /dev/stune/top-app /dev/stune/top-app/tasks /dev/stune/system-background /dev/stune/system-background/tasks
Huawei Mate9 Implement