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

Commit a326a116 authored by Tim Murray's avatar Tim Murray
Browse files

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
parent fd538001
Loading
Loading
Loading
Loading
+36 −0
Original line number Original line Diff line number Diff line
@@ -400,6 +400,17 @@ public final class ActivityManagerService extends ActivityManagerNative
    private static final int PERSISTENT_MASK =
    private static final int PERSISTENT_MASK =
            ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
            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 */
    /** All system services */
    SystemServiceManager mSystemServiceManager;
    SystemServiceManager mSystemServiceManager;
@@ -1356,6 +1367,7 @@ public final class ActivityManagerService extends ActivityManagerNative
    static final int REPORT_TIME_TRACKER_MSG = 55;
    static final int REPORT_TIME_TRACKER_MSG = 55;
    static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56;
    static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56;
    static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57;
    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_ACTIVITY_STACK_MSG = 100;
    static final int FIRST_BROADCAST_QUEUE_MSG = 200;
    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.
                // it is finished we make sure it is reset to its default.
                mUserIsMonkey = false;
                mUserIsMonkey = false;
            } break;
            } 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 = 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:
        // We don't have to do anything more if:
        // (1) There is an existing application record; and
        // (1) There is an existing application record; and
        // (2) The caller doesn't think it is dead, OR there is no thread
        // (2) The caller doesn't think it is dead, OR there is no thread
+7 −0
Original line number Original line Diff line number Diff line
@@ -4,9 +4,16 @@ LOCAL_REL_DIR := core/jni


LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
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_SRC_FILES += \
    $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
    $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
    $(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.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_AssetAtlasService.cpp \
    $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
    $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
    $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
    $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
+151 −0
Original line number Original line Diff line number Diff line
/*
 * 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));
    }

}
+3 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@
#include "utils/misc.h"
#include "utils/misc.h"


namespace android {
namespace android {
int register_android_server_ActivityManagerService(JNIEnv* env);
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_AssetAtlasService(JNIEnv* env);
int register_android_server_AssetAtlasService(JNIEnv* env);
int register_android_server_BatteryStatsService(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!");
    ALOG_ASSERT(env, "Could not retrieve the env!");


    register_android_server_ActivityManagerService(env);
    register_android_server_PowerManagerService(env);
    register_android_server_PowerManagerService(env);
    register_android_server_SerialService(env);
    register_android_server_SerialService(env);
    register_android_server_InputApplicationHandle(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_PersistentDataBlockService(env);
    register_android_server_Watchdog(env);
    register_android_server_Watchdog(env);



    return JNI_VERSION_1_4;
    return JNI_VERSION_1_4;
}
}