diff --git a/Android.mk b/Android.mk index 739b75c..4724c65 100644 --- a/Android.mk +++ b/Android.mk @@ -59,10 +59,6 @@ ifeq ($(call is-board-platform-in-list,sdm845), true) LOCAL_SRC_FILES += power-845.c endif -ifeq ($(call is-board-platform-in-list,msmnile), true) -LOCAL_SRC_FILES += power-msmnile.c -endif - endif # End of board specific list ifneq ($(TARGET_POWERHAL_MODE_EXT),) diff --git a/Power.cpp b/Power.cpp index cb16c92..1c677bc 100644 --- a/Power.cpp +++ b/Power.cpp @@ -84,7 +84,6 @@ ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) { case Mode::DOUBLE_TAP_TO_WAKE: #endif case Mode::LOW_POWER: - case Mode::LAUNCH: case Mode::DEVICE_IDLE: case Mode::DISPLAY_INACTIVE: case Mode::AUDIO_STREAMING_LOW_LATENCY: @@ -98,9 +97,11 @@ ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) { case Mode::EXPENSIVE_RENDERING: set_expensive_rendering(enabled); break; + case Mode::LAUNCH: + power_hint(POWER_HINT_LAUNCH, enabled ? &enabled : NULL); + break; case Mode::INTERACTIVE: setInteractive(enabled); - power_hint(POWER_HINT_INTERACTION, NULL); break; case Mode::SUSTAINED_PERFORMANCE: case Mode::FIXED_PERFORMANCE: @@ -131,6 +132,7 @@ ndk::ScopedAStatus Power::isModeSupported(Mode type, bool* _aidl_return) { #ifdef TAP_TO_WAKE_NODE case Mode::DOUBLE_TAP_TO_WAKE: #endif + case Mode::LAUNCH: case Mode::INTERACTIVE: case Mode::SUSTAINED_PERFORMANCE: case Mode::FIXED_PERFORMANCE: @@ -146,14 +148,30 @@ ndk::ScopedAStatus Power::isModeSupported(Mode type, bool* _aidl_return) { ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) { LOG(VERBOSE) << "Power setBoost: " << static_cast(type) << ", duration: " << durationMs; + switch (type) { + case Boost::INTERACTION: + power_hint(POWER_HINT_INTERACTION, &durationMs); + break; + default: + LOG(INFO) << "Boost " << static_cast(type) << "Not Supported"; + break; + } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) { LOG(INFO) << "Power isBoostSupported: " << static_cast(type); - *_aidl_return = false; + switch (type) { + case Boost::INTERACTION: + *_aidl_return = true; + break; + default: + *_aidl_return = false; + break; + } return ndk::ScopedAStatus::ok(); } + ndk::ScopedAStatus Power::createHintSession(int32_t tgid, int32_t uid, const std::vector& threadIds, int64_t durationNanos, diff --git a/performance.h b/performance.h index 7b40331..1a8fad6 100644 --- a/performance.h +++ b/performance.h @@ -42,6 +42,22 @@ extern "C" { #define VENDOR_HINT_DISPLAY_OFF 0x00001040 #define VENDOR_HINT_DISPLAY_ON 0x00001041 +#define VENDOR_HINT_SCROLL_BOOST 0x00001080 +#define VENDOR_HINT_FIRST_LAUNCH_BOOST 0x00001081 + +enum SCROLL_BOOST_TYPE { + SCROLL_VERTICAL = 1, + SCROLL_HORIZONTAL = 2, + SCROLL_PANEL_VIEW = 3, + SCROLL_PREFILING = 4, +}; + +enum LAUNCH_BOOST_TYPE { + LAUNCH_BOOST_V1 = 1, + LAUNCH_BOOST_V2 = 2, + LAUNCH_BOOST_V3 = 3, +}; + enum SCREEN_DISPLAY_TYPE { DISPLAY_OFF = 0x00FF, }; diff --git a/power-845.c b/power-845.c index 0044bf6..becee95 100644 --- a/power-845.c +++ b/power-845.c @@ -49,7 +49,6 @@ #include "power-common.h" #include "utils.h" -#define CHECK_HANDLE(x) ((x) > 0) #define NUM_PERF_MODES 3 typedef enum { @@ -189,12 +188,6 @@ int power_hint_override(power_hint_t hint, void* data) { case POWER_HINT_VR_MODE: ret_val = process_perf_hint(data, VR_MODE); break; - case POWER_HINT_INTERACTION: { - int resources[] = {MIN_FREQ_LITTLE_CORE_0, 0x514}; - int duration = 100; - interaction(duration, ARRAY_SIZE(resources), resources); - ret_val = HINT_HANDLED; - } break; default: break; } diff --git a/power-8996.c b/power-8996.c index 8202942..48d9048 100644 --- a/power-8996.c +++ b/power-8996.c @@ -47,7 +47,6 @@ #include "power-common.h" #include "utils.h" -#define CHECK_HANDLE(x) ((x) > 0) #define NUM_PERF_MODES 3 static int video_encode_hint_sent; diff --git a/power-8998.c b/power-8998.c index 0b03aef..3e4b7b9 100644 --- a/power-8998.c +++ b/power-8998.c @@ -48,7 +48,6 @@ #include "power-common.h" #include "utils.h" -#define CHECK_HANDLE(x) ((x) > 0) #define NUM_PERF_MODES 3 typedef enum { @@ -188,11 +187,6 @@ int power_hint_override(power_hint_t hint, void* data) { case POWER_HINT_VR_MODE: ret_val = process_perf_hint(data, VR_MODE); break; - case POWER_HINT_INTERACTION: - if (current_mode != NORMAL_MODE) { - ret_val = HINT_HANDLED; - } - break; default: break; } diff --git a/power-common.c b/power-common.c index 9665068..16bf084 100644 --- a/power-common.c +++ b/power-common.c @@ -51,6 +51,10 @@ static struct hint_handles handles[NUM_HINTS]; static int handleER = 0; +const int kMaxLaunchDuration = 5000; /* ms */ +const int kMaxInteractiveDuration = 5000; /* ms */ +const int kMinInteractiveDuration = 500; /* ms */ + void power_init() { ALOGI("Initing"); @@ -60,6 +64,69 @@ void power_init() { } } +void process_interaction_hint(void* data) { + static struct timespec s_previous_boost_timespec; + static int s_previous_duration = 0; + static int prev_interaction_handle = -1; + + struct timespec cur_boost_timespec; + long long elapsed_time; + int duration = kMinInteractiveDuration; + + if (data) { + int input_duration = *((int*)data); + if (input_duration > duration) { + duration = (input_duration > kMaxInteractiveDuration) ? kMaxInteractiveDuration + : input_duration; + } + } + + clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); + + elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); + // don't hint if it's been less than 250ms since last boost + // also detect if we're doing anything resembling a fling + // support additional boosting in case of flings + if (elapsed_time < 250000 && duration <= 750) { + return; + } + s_previous_boost_timespec = cur_boost_timespec; + s_previous_duration = duration; + + int interaction_handle = + perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL); + + if (CHECK_HANDLE(prev_interaction_handle)) { + release_request(prev_interaction_handle); + } + prev_interaction_handle = interaction_handle; +} + +void process_activity_launch_hint(void* data) { + static int launch_handle = -1; + static int launch_mode = 0; + + // release lock early if launch has finished + if (!data) { + if (CHECK_HANDLE(launch_handle)) { + release_request(launch_handle); + launch_handle = -1; + } + launch_mode = 0; + return; + } + + if (!launch_mode) { + launch_handle = perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, + kMaxLaunchDuration, LAUNCH_BOOST_V1); + if (!CHECK_HANDLE(launch_handle)) { + ALOGE("Failed to perform launch boost"); + return; + } + launch_mode = 1; + } +} + int __attribute__((weak)) power_hint_override(power_hint_t hint, void* data) { return HINT_NONE; } @@ -74,12 +141,6 @@ void power_hint(power_hint_t hint, void* data) { case POWER_HINT_VR_MODE: ALOGI("VR mode power hint not handled in power_hint_override"); break; - case POWER_HINT_INTERACTION: { - int resources[] = {0x702, 0x20F, 0x30F}; - int duration = 3000; - - interaction(duration, sizeof(resources) / sizeof(resources[0]), resources); - } break; // fall through below, hints will fail if not defined in powerhint.xml case POWER_HINT_SUSTAINED_PERFORMANCE: case POWER_HINT_VIDEO_ENCODE: @@ -99,6 +160,12 @@ void power_hint(power_hint_t hint, void* data) { } } break; + case POWER_HINT_INTERACTION: + process_interaction_hint(data); + break; + case POWER_HINT_LAUNCH: + process_activity_launch_hint(data); + break; default: break; } diff --git a/power-common.h b/power-common.h index 16ba0db..02fd557 100644 --- a/power-common.h +++ b/power-common.h @@ -52,6 +52,7 @@ void set_expensive_rendering(bool enabled); void set_interactive(int on); #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) +#define CHECK_HANDLE(x) ((x) > 0) #ifdef __cplusplus } diff --git a/power-msmnile.c b/power-msmnile.c deleted file mode 100644 index d92a5ff..0000000 --- a/power-msmnile.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define LOG_NIDEBUG 0 - -#include -#include -#include -#include -#include -#include -#include - -#define LOG_TAG "QTI PowerHAL" -#include -#include -#include - -#include "performance.h" -#include "power-common.h" -#include "utils.h" - -int power_hint_override(power_hint_t hint, void* data) { - int ret_val = HINT_NONE; - switch (hint) { - case POWER_HINT_INTERACTION: { - int resources[] = {MIN_FREQ_LITTLE_CORE_0, 0x514}; - int duration = 100; - interaction(duration, ARRAY_SIZE(resources), resources); - ret_val = HINT_HANDLED; - } - default: - break; - } - return ret_val; -} diff --git a/utils.c b/utils.c index 06c1efd..f6b4a5e 100644 --- a/utils.c +++ b/utils.c @@ -43,6 +43,9 @@ #define LOG_TAG "QTI PowerHAL" #include +#define USINSEC 1000000L +#define NSINUS 1000L + #define SOC_ID_0 "/sys/devices/soc0/soc_id" #define SOC_ID_1 "/sys/devices/system/soc/soc0/id" @@ -258,6 +261,20 @@ int perf_hint_enable(int hint_id, int duration) { return lock_handle; } +// Same as perf_hint_enable, but with the ability to +// choose the type +int perf_hint_enable_with_type(int hint_id, int duration, int type) { + int lock_handle = 0; + + if (qcopt_handle) { + if (perf_hint) { + lock_handle = perf_hint(hint_id, NULL, duration, type); + if (lock_handle == -1) ALOGE("Failed to acquire lock."); + } + } + return lock_handle; +} + void release_request(int lock_handle) { if (qcopt_handle && perf_lock_rel) perf_lock_rel(lock_handle); } @@ -364,3 +381,10 @@ int get_soc_id(void) { close(fd); return soc_id; } + +long long calc_timespan_us(struct timespec start, struct timespec end) { + long long diff_in_us = 0; + diff_in_us += (end.tv_sec - start.tv_sec) * USINSEC; + diff_in_us += (end.tv_nsec - start.tv_nsec) / NSINUS; + return diff_in_us; +} diff --git a/utils.h b/utils.h index abc7c79..2feb4c3 100644 --- a/utils.h +++ b/utils.h @@ -47,7 +47,9 @@ void release_request(int lock_handle); void interaction(int duration, int num_args, int opt_list[]); int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]); int perf_hint_enable(int hint_id, int duration); +int perf_hint_enable_with_type(int hint_id, int duration, int type); +long long calc_timespan_us(struct timespec start, struct timespec end); int get_soc_id(void); PropVal perf_get_property(const char* prop, const char* def_val);