power: Handle launch and interaction hints for perf HAL platforms
* MP-CTL does not handle POWER_HINT_INTERACTION and POWER_HINT_LAUNCH
directly. Requests for processing are sent by Qualcomm BoostFramework
(QPerformance) at the framework service level. Since we do not have
BoostFramework, process POWER_HINT_INTERACTION and POWER_HINT_LAUNCH
in PowerHAL to ensure a sufficient level of performance.
* For proper operation, perfboostsconfig.xml file is required.
Change-Id: I4c67d886c9dd74ae07094d32bdffc8ef403e04e7
diff --git a/performance.h b/performance.h
index 970d42e..461ae31 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_FIRST_LAUNCH_BOOST 0x00001081
+#define VENDOR_HINT_SCROLL_BOOST 0x00001080
+
+enum LAUNCH_BOOST_TYPE {
+ LAUNCH_BOOST_V1 = 1,
+ LAUNCH_BOOST_V2 = 2,
+ LAUNCH_BOOST_V3 = 3
+};
+
+enum SCROLL_BOOST_TYPE {
+ SCROLL_VERTICAL = 1,
+ SCROLL_HORIZONTAL = 2,
+ SCROLL_PANEL_VIEW = 3,
+ SCROLL_PREFILING = 4
+};
+
enum SCREEN_DISPLAY_TYPE {
DISPLAY_OFF = 0x00FF,
};
diff --git a/power-660.c b/power-660.c
index 0bec132..0a297e2 100644
--- a/power-660.c
+++ b/power-660.c
@@ -31,6 +31,7 @@
#define LOG_NIDEBUG 0
#include <errno.h>
+#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -51,6 +52,10 @@
#define MIN_VAL(X,Y) ((X>Y)?(Y):(X))
+const int kMaxInteractiveDuration = 5000; /* ms */
+const int kMinInteractiveDuration = 500; /* ms */
+const int kMinFlingDuration = 1500; /* ms */
+
static int video_encode_hint_sent;
static int current_power_profile = PROFILE_BALANCED;
@@ -244,6 +249,45 @@
}
}
+static void process_activity_launch_hint(void *UNUSED(data))
+{
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+}
+
+static void process_interaction_hint(void *data)
+{
+ static struct timespec s_previous_boost_timespec;
+ static int s_previous_duration = 0;
+
+ 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 previous hint's duration covers this hint's duration
+ if ((s_previous_duration * 1000) > (elapsed_time + duration * 1000)) {
+ return;
+ }
+ s_previous_boost_timespec = cur_boost_timespec;
+ s_previous_duration = duration;
+
+ if (duration >= kMinFlingDuration) {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, -1, SCROLL_PREFILING);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL);
+ }
+}
+
int power_hint_override(power_hint_t hint, void *data)
{
if (hint == POWER_HINT_SET_PROFILE) {
@@ -264,6 +308,12 @@
case POWER_HINT_VIDEO_ENCODE:
process_video_encode_hint(data);
return HINT_HANDLED;
+ case POWER_HINT_INTERACTION:
+ process_interaction_hint(data);
+ return HINT_HANDLED;
+ case POWER_HINT_LAUNCH:
+ process_activity_launch_hint(data);
+ return HINT_HANDLED;
default:
break;
}
diff --git a/power-845.c b/power-845.c
index dce15a5..235ab81 100644
--- a/power-845.c
+++ b/power-845.c
@@ -31,6 +31,7 @@
#define LOG_NIDEBUG 0
#include <errno.h>
+#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -54,6 +55,10 @@
#define SYS_DISPLAY_PWR "/sys/kernel/hbtp/display_pwr"
+const int kMaxInteractiveDuration = 5000; /* ms */
+const int kMinInteractiveDuration = 100; /* ms */
+const int kMinFlingDuration = 1500; /* ms */
+
static int display_fd;
typedef enum {
@@ -187,6 +192,56 @@
return HINT_NONE;
}
+static int process_activity_launch_hint(void *UNUSED(data))
+{
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+ }
+ return HINT_HANDLED;
+}
+
+static int process_interaction_hint(void *data)
+{
+ static struct timespec s_previous_boost_timespec;
+ static int s_previous_duration = 0;
+
+ struct timespec cur_boost_timespec;
+ long long elapsed_time;
+ int duration = kMinInteractiveDuration;
+
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ return HINT_HANDLED;
+ }
+
+ 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 previous hint's duration covers this hint's duration
+ if ((s_previous_duration * 1000) > (elapsed_time + duration * 1000)) {
+ return HINT_HANDLED;
+ }
+ s_previous_boost_timespec = cur_boost_timespec;
+ s_previous_duration = duration;
+
+ if (duration >= kMinFlingDuration) {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, -1, SCROLL_PREFILING);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL);
+ }
+ return HINT_HANDLED;
+}
+
int power_hint_override(power_hint_t hint, void *data)
{
int ret_val = HINT_NONE;
@@ -201,14 +256,10 @@
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;
- }
+ ret_val = process_interaction_hint(data);
+ break;
+ case POWER_HINT_LAUNCH:
+ ret_val = process_activity_launch_hint(data);
break;
default:
break;
diff --git a/power-8937.c b/power-8937.c
index 5b1b542..abf0f8e 100644
--- a/power-8937.c
+++ b/power-8937.c
@@ -31,6 +31,7 @@
#define LOG_NIDEBUG 0
#include <errno.h>
+#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -49,6 +50,10 @@
#include "performance.h"
#include "power-common.h"
+const int kMaxInteractiveDuration = 5000; /* ms */
+const int kMinInteractiveDuration = 500; /* ms */
+const int kMinFlingDuration = 1500; /* ms */
+
static int video_encode_hint_sent;
static int current_power_profile = PROFILE_BALANCED;
@@ -191,6 +196,46 @@
}
}
+static void process_activity_launch_hint(void *UNUSED(data))
+{
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+}
+
+static void process_interaction_hint(void *data)
+{
+ static struct timespec s_previous_boost_timespec;
+ static int s_previous_duration = 0;
+
+ 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 previous hint's duration covers this hint's duration
+ if ((s_previous_duration * 1000) > (elapsed_time + duration * 1000)) {
+ return;
+ }
+ s_previous_boost_timespec = cur_boost_timespec;
+ s_previous_duration = duration;
+
+ if (duration >= kMinFlingDuration) {
+ // Use launch boost resources for fling boost
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL);
+ }
+}
+
int power_hint_override(power_hint_t hint, void *data)
{
if (hint == POWER_HINT_SET_PROFILE) {
@@ -209,6 +254,12 @@
case POWER_HINT_VIDEO_ENCODE:
process_video_encode_hint(data);
return HINT_HANDLED;
+ case POWER_HINT_INTERACTION:
+ process_interaction_hint(data);
+ return HINT_HANDLED;
+ case POWER_HINT_LAUNCH:
+ process_activity_launch_hint(data);
+ return HINT_HANDLED;
default:
break;
}
diff --git a/power-8953.c b/power-8953.c
index 78ee3df..5dacc03 100644
--- a/power-8953.c
+++ b/power-8953.c
@@ -31,6 +31,7 @@
#define LOG_NIDEBUG 0
#include <errno.h>
+#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -52,6 +53,10 @@
#define CHECK_HANDLE(x) ((x)>0)
#define NUM_PERF_MODES 3
+const int kMaxInteractiveDuration = 5000; /* ms */
+const int kMinInteractiveDuration = 500; /* ms */
+const int kMinFlingDuration = 1500; /* ms */
+
static int current_power_profile = PROFILE_BALANCED;
static int profile_high_performance[] = {
@@ -274,6 +279,58 @@
return HINT_NONE;
}
+static int process_activity_launch_hint(void *UNUSED(data))
+{
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+ }
+ return HINT_HANDLED;
+}
+
+static int process_interaction_hint(void *data)
+{
+ static struct timespec s_previous_boost_timespec;
+ static int s_previous_duration = 0;
+
+ struct timespec cur_boost_timespec;
+ long long elapsed_time;
+ int duration = kMinInteractiveDuration;
+
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ return HINT_HANDLED;
+ }
+
+ 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 previous hint's duration covers this hint's duration
+ if ((s_previous_duration * 1000) > (elapsed_time + duration * 1000)) {
+ return HINT_HANDLED;
+ }
+ s_previous_boost_timespec = cur_boost_timespec;
+ s_previous_duration = duration;
+
+ if (duration >= kMinFlingDuration) {
+ // Use launch boost resources for fling boost
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL);
+ }
+
+ return HINT_HANDLED;
+}
+
int power_hint_override(power_hint_t hint, void *data)
{
int ret_val = HINT_NONE;
@@ -302,6 +359,12 @@
case POWER_HINT_VR_MODE:
ret_val = process_perf_hint(data, VR_MODE);
break;
+ case POWER_HINT_INTERACTION:
+ ret_val = process_interaction_hint(data);
+ break;
+ case POWER_HINT_LAUNCH:
+ ret_val = process_activity_launch_hint(data);
+ break;
default:
break;
}
diff --git a/power-8996.c b/power-8996.c
index f782299..c3acab8 100644
--- a/power-8996.c
+++ b/power-8996.c
@@ -31,6 +31,7 @@
#define LOG_NIDEBUG 0
#include <errno.h>
+#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -52,6 +53,10 @@
#define CHECK_HANDLE(x) ((x)>0)
#define NUM_PERF_MODES 3
+const int kMaxInteractiveDuration = 5000; /* ms */
+const int kMinInteractiveDuration = 500; /* ms */
+const int kMinFlingDuration = 1500; /* ms */
+
static int current_power_profile = PROFILE_BALANCED;
static int profile_high_performance[] = {
@@ -265,6 +270,58 @@
return HINT_NONE;
}
+static int process_activity_launch_hint(void *UNUSED(data))
+{
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+ }
+ return HINT_HANDLED;
+}
+
+static int process_interaction_hint(void *data)
+{
+ static struct timespec s_previous_boost_timespec;
+ static int s_previous_duration = 0;
+
+ struct timespec cur_boost_timespec;
+ long long elapsed_time;
+ int duration = kMinInteractiveDuration;
+
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ return HINT_HANDLED;
+ }
+
+ 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 previous hint's duration covers this hint's duration
+ if ((s_previous_duration * 1000) > (elapsed_time + duration * 1000)) {
+ return HINT_HANDLED;
+ }
+ s_previous_boost_timespec = cur_boost_timespec;
+ s_previous_duration = duration;
+
+ if (duration >= kMinFlingDuration) {
+ // Use launch boost resources for fling boost
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL);
+ }
+
+ return HINT_HANDLED;
+}
+
int power_hint_override(power_hint_t hint, void *data)
{
int ret_val = HINT_NONE;
@@ -291,6 +348,12 @@
case POWER_HINT_VR_MODE:
ret_val = process_perf_hint(data, VR_MODE);
break;
+ case POWER_HINT_INTERACTION:
+ ret_val = process_interaction_hint(data);
+ break;
+ case POWER_HINT_LAUNCH:
+ ret_val = process_activity_launch_hint(data);
+ break;
default:
break;
}
diff --git a/power-8998.c b/power-8998.c
index af14e67..20804ab 100644
--- a/power-8998.c
+++ b/power-8998.c
@@ -31,6 +31,7 @@
#define LOG_NIDEBUG 0
#include <errno.h>
+#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -53,6 +54,10 @@
#define CHECK_HANDLE(x) ((x)>0)
#define NUM_PERF_MODES 3
+const int kMaxInteractiveDuration = 5000; /* ms */
+const int kMinInteractiveDuration = 500; /* ms */
+const int kMinFlingDuration = 1500; /* ms */
+
static int current_power_profile = PROFILE_BALANCED;
static int profile_high_performance[] = {
@@ -261,6 +266,57 @@
return HINT_NONE;
}
+static int process_activity_launch_hint(void *UNUSED(data))
+{
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_FIRST_LAUNCH_BOOST, -1, LAUNCH_BOOST_V1);
+ }
+ return HINT_HANDLED;
+}
+
+static int process_interaction_hint(void *data)
+{
+ static struct timespec s_previous_boost_timespec;
+ static int s_previous_duration = 0;
+
+ struct timespec cur_boost_timespec;
+ long long elapsed_time;
+ int duration = kMinInteractiveDuration;
+
+ if (current_mode != NORMAL_MODE) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ return HINT_HANDLED;
+ }
+
+ 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 previous hint's duration covers this hint's duration
+ if ((s_previous_duration * 1000) > (elapsed_time + duration * 1000)) {
+ return HINT_HANDLED;
+ }
+ s_previous_boost_timespec = cur_boost_timespec;
+ s_previous_duration = duration;
+
+ if (duration >= kMinFlingDuration) {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, -1, SCROLL_PREFILING);
+ } else {
+ perf_hint_enable_with_type(VENDOR_HINT_SCROLL_BOOST, duration, SCROLL_VERTICAL);
+ }
+
+ return HINT_HANDLED;
+}
+
int power_hint_override(power_hint_t hint, void *data)
{
int ret_val = HINT_NONE;
@@ -288,9 +344,10 @@
ret_val = process_perf_hint(data, VR_MODE);
break;
case POWER_HINT_INTERACTION:
- if (current_mode != NORMAL_MODE) {
- ret_val = HINT_HANDLED;
- }
+ ret_val = process_interaction_hint(data);
+ break;
+ case POWER_HINT_LAUNCH:
+ ret_val = process_activity_launch_hint(data);
break;
default:
break;
diff --git a/utils.c b/utils.c
index ffa3e34..d86ffd8 100644
--- a/utils.c
+++ b/utils.c
@@ -273,6 +273,21 @@
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)
diff --git a/utils.h b/utils.h
index 79ebd33..6975b41 100644
--- a/utils.h
+++ b/utils.h
@@ -42,6 +42,7 @@
void release_request(int lock_handle);
void interaction(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);