diff options
author | Tim Murray <timmurray@google.com> | 2015-08-25 00:28:37 -0700 |
---|---|---|
committer | Tim Murray <timmurray@google.com> | 2015-08-28 10:43:40 -0700 |
commit | a326a116f7f9fb939fac3d28c80d32542016decc (patch) | |
tree | 5043dd09fde4d9d3974fb7f0fe954f887ea284bd /services/core | |
parent | fd538001f5c7f1fad68a27d8143c839bda82491b (diff) | |
download | frameworks_base-a326a116f7f9fb939fac3d28c80d32542016decc.zip frameworks_base-a326a116f7f9fb939fac3d28c80d32542016decc.tar.gz frameworks_base-a326a116f7f9fb939fac3d28c80d32542016decc.tar.bz2 |
Enable migration to big cores for app launches.
Uses cpusets to move all foreground tasks to the big cores in order
to improve overall app launch latency. Big cores will be used for
three seconds, and then the cpuset assignment is reset, allowing
foreground tasks to fall back to the little cores as appropriate.
Associated system/core and device/* changes in order to enable
the boost cpuset and configure it per-device.
bug 21915482
Change-Id: Id8a0efcb31950c1988f20273ac01c89c8c948eaf
Diffstat (limited to 'services/core')
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 36 | ||||
-rw-r--r-- | services/core/jni/Android.mk | 7 | ||||
-rw-r--r-- | services/core/jni/com_android_server_am_ActivityManagerService.cpp | 151 | ||||
-rw-r--r-- | services/core/jni/onload.cpp | 3 |
4 files changed, 197 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1b0e6a2..244b890 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -400,6 +400,17 @@ public final class ActivityManagerService extends ActivityManagerNative private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT; + + // Delay to disable app launch boost + static final int APP_BOOST_MESSAGE_DELAY = 3000; + // Lower delay than APP_BOOST_MESSAGE_DELAY to disable the boost + static final int APP_BOOST_TIMEOUT = 2500; + + private static native int nativeMigrateToBoost(); + private static native int nativeMigrateFromBoost(); + private boolean mIsBoosted = false; + private long mBoostStartTime = 0; + /** All system services */ SystemServiceManager mSystemServiceManager; @@ -1356,6 +1367,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int REPORT_TIME_TRACKER_MSG = 55; static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56; static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57; + static final int APP_BOOST_DEACTIVATE_MSG = 58; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -2031,6 +2043,20 @@ public final class ActivityManagerService extends ActivityManagerNative // it is finished we make sure it is reset to its default. mUserIsMonkey = false; } break; + case APP_BOOST_DEACTIVATE_MSG : { + synchronized(ActivityManagerService.this) { + if (mIsBoosted) { + if (mBoostStartTime < (SystemClock.uptimeMillis() - APP_BOOST_TIMEOUT)) { + nativeMigrateFromBoost(); + mIsBoosted = false; + mBoostStartTime = 0; + } else { + Message newmsg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG); + mHandler.sendMessageDelayed(newmsg, APP_BOOST_TIMEOUT); + } + } + } + } break; } } }; @@ -3114,6 +3140,16 @@ public final class ActivityManagerService extends ActivityManagerNative app = null; } + // app launch boost for big.little configurations + // use cpusets to migrate freshly launched tasks to big cores + synchronized(ActivityManagerService.this) { + nativeMigrateToBoost(); + mIsBoosted = true; + mBoostStartTime = SystemClock.uptimeMillis(); + Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG); + mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY); + } + // We don't have to do anything more if: // (1) There is an existing application record; and // (2) The caller doesn't think it is dead, OR there is no thread diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index 9556b08..98d8d08 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -4,9 +4,16 @@ LOCAL_REL_DIR := core/jni LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter +ifneq ($(ENABLE_CPUSETS),) +ifneq ($(ENABLE_SCHED_BOOST),) +LOCAL_CFLAGS += -DUSE_SCHED_BOOST +endif +endif + LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \ + $(LOCAL_REL_DIR)/com_android_server_am_ActivityManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \ $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \ $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \ diff --git a/services/core/jni/com_android_server_am_ActivityManagerService.cpp b/services/core/jni/com_android_server_am_ActivityManagerService.cpp new file mode 100644 index 0000000..52217b9 --- /dev/null +++ b/services/core/jni/com_android_server_am_ActivityManagerService.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2015 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. + */ + +#define LOG_TAG "ActivityManagerService" +//#define LOG_NDEBUG 0 + +#include <android_runtime/AndroidRuntime.h> +#include <jni.h> + +#include <ScopedLocalRef.h> +#include <ScopedPrimitiveArray.h> + +#include <cutils/log.h> +#include <utils/misc.h> +#include <utils/Log.h> + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <semaphore.h> +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +namespace android +{ + + // migrate from foreground to foreground_boost + static jint migrateToBoost(JNIEnv *env, jobject _this) + { +#ifdef USE_SCHED_BOOST + // File descriptors open to /dev/cpuset/../tasks, setup by initialize, or -1 on error + FILE* fg_cpuset_file = NULL; + int boost_cpuset_fd = 0; + if (!access("/dev/cpuset/tasks", F_OK)) { + fg_cpuset_file = fopen("/dev/cpuset/foreground/tasks", "r+"); + if (ferror(fg_cpuset_file)) { + return 0; + } + boost_cpuset_fd = open("/dev/cpuset/foreground/boost/tasks", O_WRONLY); + if (boost_cpuset_fd < 0) { + fclose(fg_cpuset_file); + return 0; + } + + } + if (!fg_cpuset_file || !boost_cpuset_fd) { + fclose(fg_cpuset_file); + close(boost_cpuset_fd); + return 0; + } + char buf[17]; + while (fgets(buf, 16, fg_cpuset_file)) { + int i = 0; + for (; i < 16; i++) { + if (buf[i] == '\n') { + buf[i] = 0; + break; + } + } + if (write(boost_cpuset_fd, buf, i) < 0) { + // ignore error + } + if (feof(fg_cpuset_file)) + break; + } + fclose(fg_cpuset_file); + close(boost_cpuset_fd); +#endif + return 0; + } + + // migrate from foreground_boost to foreground + static jint migrateFromBoost(JNIEnv *env, jobject _this) + { +#ifdef USE_SCHED_BOOST + // File descriptors open to /dev/cpuset/../tasks, setup by initialize, or -1 on error + int fg_cpuset_fd = 0; + FILE* boost_cpuset_file = NULL; + if (!access("/dev/cpuset/tasks", F_OK)) { + boost_cpuset_file = fopen("/dev/cpuset/foreground/boost/tasks", "r+"); + if (ferror(boost_cpuset_file)) { + return 0; + } + fg_cpuset_fd = open("/dev/cpuset/foreground/tasks", O_WRONLY); + if (fg_cpuset_fd < 0) { + fclose(boost_cpuset_file); + return 0; + } + + } + if (!boost_cpuset_file || !fg_cpuset_fd) { + fclose(boost_cpuset_file); + close(fg_cpuset_fd); + return 0; + } + char buf[17]; + char *curBuf = buf; + while (fgets(buf, 16, boost_cpuset_file)) { + //ALOGE("Appending FD %s to fg", buf); + int i = 0; + for (; i < 16; i++) { + if (buf[i] == '\n') { + buf[i] = 0; + break; + } + } + if (write(fg_cpuset_fd, buf, i) < 0) { + //ALOGE("Appending FD %s to fg ERROR", buf); + // handle error? + } + if (feof(boost_cpuset_file)) + break; + } + + close(fg_cpuset_fd); + fclose(boost_cpuset_file); + +#endif + return 0; + + } + + + static JNINativeMethod method_table[] = { + { "nativeMigrateToBoost", "()I", (void*)migrateToBoost }, + { "nativeMigrateFromBoost", "()I", (void*)migrateFromBoost }, + }; + + int register_android_server_ActivityManagerService(JNIEnv *env) + { + return jniRegisterNativeMethods(env, "com/android/server/am/ActivityManagerService", + method_table, NELEM(method_table)); + } + +} diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 67872da..1f3fde6 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -20,6 +20,7 @@ #include "utils/misc.h" namespace android { +int register_android_server_ActivityManagerService(JNIEnv* env); int register_android_server_AlarmManagerService(JNIEnv* env); int register_android_server_AssetAtlasService(JNIEnv* env); int register_android_server_BatteryStatsService(JNIEnv* env); @@ -57,6 +58,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) } ALOG_ASSERT(env, "Could not retrieve the env!"); + register_android_server_ActivityManagerService(env); register_android_server_PowerManagerService(env); register_android_server_SerialService(env); register_android_server_InputApplicationHandle(env); @@ -80,5 +82,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_PersistentDataBlockService(env); register_android_server_Watchdog(env); + return JNI_VERSION_1_4; } |