power: Handle launch and interaction hints
Co-authored-by: dianlujitao <dianlujitao@lineageos.org>
Co-authored-by: Michael Bestas <mkbestas@lineageos.org>
Co-authored-by: Quallenauge <Hamsi2k@freenet.de>
Co-authored-by: tomascus <arbiter1000@gmail.com>
Co-authored-by: Wei Wang <wvw@google.com>
Change-Id: I472a177e0a13b0c4201cf0b1e5ddee18a785b683
diff --git a/Android.mk b/Android.mk
index 739b75c..4724c65 100644
--- a/Android.mk
+++ b/Android.mk
@@ -59,10 +59,6 @@
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 @@
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 @@
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 @@
#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::setBoost(Boost type, int32_t durationMs) {
LOG(VERBOSE) << "Power setBoost: " << static_cast<int32_t>(type)
<< ", duration: " << durationMs;
+ switch (type) {
+ case Boost::INTERACTION:
+ power_hint(POWER_HINT_INTERACTION, &durationMs);
+ break;
+ default:
+ LOG(INFO) << "Boost " << static_cast<int32_t>(type) << "Not Supported";
+ break;
+ }
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) {
LOG(INFO) << "Power isBoostSupported: " << static_cast<int32_t>(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<int32_t>& 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 @@
#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 @@
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 @@
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 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 @@
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 @@
}
}
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_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 <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#define LOG_TAG "QTI PowerHAL"
-#include <hardware/hardware.h>
-#include <hardware/power.h>
-#include <log/log.h>
-
-#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 <log/log.h>
+#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 @@
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 @@
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 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);