sm8250-common: power: Rebase on LA.UM.8.12.r1-11900-sm8250.0

This commit is contained in:
LuK1337 2020-06-23 14:43:35 +02:00
parent 54b02a5e52
commit e032e7cc78
24 changed files with 800 additions and 1050 deletions

View file

@ -158,7 +158,7 @@ PRODUCT_PACKAGES += \
# Power
PRODUCT_PACKAGES += \
power.qcom:64
android.hardware.power@1.2-service.oneplus_kona
# Ramdisk
PRODUCT_COPY_FILES += \

View file

@ -1,11 +0,0 @@
BasedOnStyle: Google
AccessModifierOffset: -2
AllowShortFunctionsOnASingleLine: Inline
ColumnLimit: 100
CommentPragmas: NOLINT:.*
DerivePointerAlignment: false
IndentWidth: 4
PointerAlignment: Left
TabWidth: 4
UseTab: Never
PenaltyExcessCharacter: 32

View file

@ -2,27 +2,60 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := power.qcom
LOCAL_MODULE_PATH_32 := $(TARGET_OUT_PRODUCT)/vendor_overlay/$(PRODUCT_TARGET_VNDK_VERSION)/lib
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_PRODUCT)/vendor_overlay/$(PRODUCT_TARGET_VNDK_VERSION)/lib64
LOCAL_MODULE := android.hardware.power@1.2-service.oneplus_kona
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/vendor_overlay/$(PRODUCT_TARGET_VNDK_VERSION)/bin
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_STEM := android.hardware.power@1.2-service
LOCAL_CFLAGS += \
-Wno-unused-parameter \
-Wno-unused-variable
LOCAL_C_INCLUDES := \
external/libxml2/include \
external/icu/icu4c/source/common
LOCAL_HEADER_LIBRARIES += \
libhardware_headers \
libutils_headers
LOCAL_SRC_FILES := \
hint-data.c \
list.c \
metadata-parser.c \
power-845.c \
power.c \
power-common.c \
Power.cpp \
powerhintparser.c \
service.cpp \
utils.c
LOCAL_C_INCLUDES := external/libxml2/include \
external/icu/icu4c/source/common
LOCAL_REQUIRED_MODULES := \
android.hardware.power@1.2-service.oneplus_kona.rc
LOCAL_SHARED_LIBRARIES := liblog libcutils libdl libxml2
LOCAL_SHARED_LIBRARIES := \
android.hardware.power@1.2 \
libbase \
libcutils \
libdl \
libhidlbase \
libhidltransport \
liblog \
libutils \
libxml2
LOCAL_CFLAGS += -Werror -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -DINTERACTION_BOOST
include $(BUILD_EXECUTABLE)
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.power@1.2-service.oneplus_kona.rc
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/vendor_overlay/$(PRODUCT_TARGET_VNDK_VERSION)/etc/init
LOCAL_MODULE_STEM := android.hardware.power@1.2-service.rc
LOCAL_SRC_FILES := android.hardware.power@1.2-service.rc
include $(BUILD_PREBUILT)

32
power/NOTICE Normal file
View file

@ -0,0 +1,32 @@
Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the
disclaimer below) 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.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.

111
power/Power.cpp Normal file
View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 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_TAG "QTI PowerHAL"
#include <android-base/file.h>
#include <android/log.h>
#include <utils/Log.h>
#include "Power.h"
#include "power-common.h"
namespace android {
namespace hardware {
namespace power {
namespace V1_2 {
namespace implementation {
using ::android::base::WriteStringToFile;
using ::android::hardware::power::V1_0::Feature;
using ::android::hardware::power::V1_0::PowerHint;
using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
using ::android::hardware::power::V1_0::Status;
using ::android::hardware::power::V1_1::PowerStateSubsystem;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
Power::Power() {
power_init();
}
Return<void> Power::setInteractive(bool interactive) {
set_interactive(interactive ? 1:0);
return Void();
}
Return<void> Power::powerHint(PowerHint_1_0 hint, int32_t data) {
power_hint(static_cast<power_hint_t>(hint), data ? (&data) : NULL);
return Void();
}
Return<void> Power::setFeature(Feature feature, bool activate) {
switch (feature) {
case Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
WriteStringToFile(activate ? "1" : "0", "/proc/touchpanel/double_tap_enable", true);
break;
default:
break;
}
return Void();
}
Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
hidl_vec<PowerStatePlatformSleepState> states;
states.resize(0);
_hidl_cb(states, Status::SUCCESS);
return Void();
}
Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
hidl_vec<PowerStateSubsystem> subsystems;
_hidl_cb(subsystems, Status::SUCCESS);
return Void();
}
Return<void> Power::powerHintAsync(PowerHint_1_0 hint, int32_t data) {
return powerHint(hint, data);
}
Return<void> Power::powerHintAsync_1_2(PowerHint_1_2 hint, int32_t data) {
return powerHint(static_cast<PowerHint_1_0> (hint), data);
}
} // namespace implementation
} // namespace V1_2
} // namespace power
} // namespace hardware
} // namespace android

74
power/Power.h Normal file
View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 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.
*/
#ifndef ANDROID_HARDWARE_POWER_V1_2_POWER_H
#define ANDROID_HARDWARE_POWER_V1_2_POWER_H
#include <android/hardware/power/1.2/IPower.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <hardware/power.h>
namespace android {
namespace hardware {
namespace power {
namespace V1_2 {
namespace implementation {
using ::android::hardware::power::V1_0::Feature;
using PowerHint_1_0 = ::android::hardware::power::V1_0::PowerHint;
using PowerHint_1_2 = ::android::hardware::power::V1_2::PowerHint;
using ::android::hardware::power::V1_2::IPower;
using ::android::hardware::Return;
using ::android::hardware::Void;
struct Power : public IPower {
// Methods from ::android::hardware::power::V1_0::IPower follow.
Power();
Return<void> setInteractive(bool interactive) override;
Return<void> powerHint(PowerHint_1_0 hint, int32_t data) override;
Return<void> setFeature(Feature feature, bool activate) override;
Return<void> getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) override;
// Methods from ::android::hardware::power::V1_1::IPower follow
Return<void> getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) override;
Return<void> powerHintAsync(PowerHint_1_0 hint, int32_t data) override;
// Methods from ::android::hardware::power::V1_2::IPower follow
Return<void> powerHintAsync_1_2(PowerHint_1_2 hint, int32_t data) override;
};
} // namespace implementation
} // namespace V1_2
} // namespace power
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_POWER_V1_2_POWER_H

View file

@ -0,0 +1,4 @@
service vendor.power-hal-1-2 /vendor/bin/hw/android.hardware.power@1.2-service
class hal
user system
group system

View file

@ -27,20 +27,21 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <utils/Log.h>
#include "hint-data.h"
int hint_compare(struct hint_data* first_hint, struct hint_data* other_hint) {
int hint_compare(struct hint_data *first_hint,
struct hint_data *other_hint) {
if (first_hint == other_hint) {
return 0;
} else if ((first_hint && other_hint) && (first_hint->hint_id == other_hint->hint_id)) {
} else if ((first_hint && other_hint) &&
(first_hint->hint_id == other_hint->hint_id)) {
return 0;
} else {
return 1;
}
}
void hint_dump(struct hint_data* hint) {
ALOGI("hint_id: %lu", hint->hint_id);
void hint_dump(struct hint_data *hint)
{
/*ALOGI("hint_id: %lu", hint->hint_id);*/
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, 2015, 2017, The Linux Foundation. All rights reserved.
* Copyright (c) 2012, 2013, 2015, 2017-2018, 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
@ -28,34 +28,42 @@
*/
/* Default use-case hint IDs */
#define DEFAULT_VIDEO_ENCODE_HINT_ID (0x0A00)
#define DEFAULT_VIDEO_DECODE_HINT_ID (0x0B00)
#define DISPLAY_STATE_HINT_ID (0x0C00)
#define DISPLAY_STATE_HINT_ID_2 (0x0D00)
#define CAM_PREVIEW_HINT_ID (0x0E00)
#define SUSTAINED_PERF_HINT_ID (0x0F00)
#define VR_MODE_HINT_ID (0x1000)
#define VR_MODE_SUSTAINED_PERF_HINT_ID (0x1001)
#define INTERACTION_HINT_ID (0x1A00)
#define DEFAULT_VIDEO_ENCODE_HINT_ID (0x0A00)
#define DEFAULT_VIDEO_DECODE_HINT_ID (0x0B00)
#define DISPLAY_STATE_HINT_ID (0x0C00)
#define DISPLAY_STATE_HINT_ID_2 (0x0D00)
#define CAM_PREVIEW_HINT_ID (0x0E00)
#define SUSTAINED_PERF_HINT_ID (0x0F00)
#define VR_MODE_HINT_ID (0x1000)
#define VR_MODE_SUSTAINED_PERF_HINT_ID (0x1001)
#define AOSP_DELTA (0x1200)
#define AOSP_DELTA (0x1200)
#define VSYNC_HINT AOSP_DELTA + POWER_HINT_VSYNC
#define INTERACTION_HINT AOSP_DELTA + POWER_HINT_INTERACTION
#define VIDEO_DECODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_DECODE
#define VIDEO_ENCODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_ENCODE
#define LOW_POWER_HINT AOSP_DELTA + POWER_HINT_LOW_POWER
#define SUSTAINED_PERF_HINT AOSP_DELTA + POWER_HINT_SUSTAINED_PERFORMANCE
#define VR_MODE_HINT AOSP_DELTA + POWER_HINT_VR_MODE
#define LAUNCH_HINT AOSP_DELTA + POWER_HINT_LAUNCH
#define DISABLE_TOUCH_HINT AOSP_DELTA + POWER_HINT_DISABLE_TOUCH
#define VSYNC_HINT AOSP_DELTA + POWER_HINT_VSYNC
#define INTERACTION_HINT AOSP_DELTA + POWER_HINT_INTERACTION
#define VIDEO_DECODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_DECODE
#define VIDEO_ENCODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_ENCODE
#define LOW_POWER_HINT AOSP_DELTA + POWER_HINT_LOW_POWER
#define SUSTAINED_PERF_HINT AOSP_DELTA + POWER_HINT_SUSTAINED_PERFORMANCE
#define VR_MODE_HINT AOSP_DELTA + POWER_HINT_VR_MODE
#define LAUNCH_HINT AOSP_DELTA + POWER_HINT_LAUNCH
#define DISABLE_TOUCH_HINT AOSP_DELTA + POWER_HINT_DISABLE_TOUCH
#define VR_MODE_SUSTAINED_PERF_HINT (0x1301)
//update NUM_HINTS if hints are added to AOSP
#define NUM_HINTS (POWER_HINT_DISABLE_TOUCH +1)
#define VR_MODE_SUSTAINED_PERF_HINT (0x1301)
struct hint_handles{
int handle;
int ref_count;
};
struct hint_data {
unsigned long hint_id; /* This is our key. */
unsigned long perflock_handle;
};
int hint_compare(struct hint_data* first_hint, struct hint_data* other_hint);
void hint_dump(struct hint_data* hint);
int hint_compare(struct hint_data *first_hint,
struct hint_data *other_hint);
void hint_dump(struct hint_data *hint);

View file

@ -31,20 +31,23 @@
#include <stdlib.h>
#include <string.h>
#include <utils/Log.h>
#include "list.h"
#include <utils/Log.h>
int init_list_head(struct list_node* head) {
if (head == NULL) return -1;
int init_list_head(struct list_node *head)
{
if (head == NULL)
return -1;
memset(head, 0, sizeof(*head));
return 0;
}
struct list_node* add_list_node(struct list_node* head, void* data) {
struct list_node *add_list_node(struct list_node *head, void *data)
{
/* Create a new list_node. And put 'data' into it. */
struct list_node* new_node;
struct list_node *new_node;
if (head == NULL) {
return NULL;
@ -63,16 +66,18 @@ struct list_node* add_list_node(struct list_node* head, void* data) {
return new_node;
}
int is_list_empty(struct list_node* head) {
int is_list_empty(struct list_node *head)
{
return (head == NULL || head->next == NULL);
}
/*
* Delink and de-allocate 'node'.
*/
int remove_list_node(struct list_node* head, struct list_node* del_node) {
struct list_node* current_node;
struct list_node* saved_node;
int remove_list_node(struct list_node *head, struct list_node *del_node)
{
struct list_node *current_node;
struct list_node *saved_node;
if (head == NULL || head->next == NULL) {
return -1;
@ -102,12 +107,14 @@ int remove_list_node(struct list_node* head, struct list_node* del_node) {
return 0;
}
void dump_list(struct list_node* head) {
struct list_node* current_node = head;
void dump_list(struct list_node *head)
{
struct list_node *current_node = head;
if (head == NULL) return;
if (head == NULL)
return;
ALOGV("List:\n");
printf("List:\n");
while ((current_node = current_node->next)) {
if (current_node->dump) {
@ -116,14 +123,17 @@ void dump_list(struct list_node* head) {
}
}
struct list_node* find_node(struct list_node* head, void* comparison_data) {
struct list_node* current_node = head;
struct list_node *find_node(struct list_node *head, void *comparison_data)
{
struct list_node *current_node = head;
if (head == NULL) return NULL;
if (head == NULL)
return NULL;
while ((current_node = current_node->next)) {
if (current_node->compare) {
if (current_node->compare(current_node->data, comparison_data) == 0) {
if (current_node->compare(current_node->data,
comparison_data) == 0) {
/* Match found. Return current_node. */
return current_node;
}

View file

@ -28,14 +28,14 @@
*/
struct list_node {
struct list_node* next;
void* data;
int (*compare)(void* data1, void* data2);
void (*dump)(void* data);
struct list_node *next;
void *data;
int (*compare)(void *data1, void *data2);
void (*dump)(void *data);
};
int init_list_head(struct list_node* head);
struct list_node* add_list_node(struct list_node* head, void* data);
int remove_list_node(struct list_node* head, struct list_node* del_node);
void dump_list(struct list_node* head);
struct list_node* find_node(struct list_node* head, void* comparison_data);
int init_list_head(struct list_node *head);
struct list_node * add_list_node(struct list_node *head, void *data);
int remove_list_node(struct list_node *head, struct list_node *del_node);
void dump_list(struct list_node *head);
struct list_node *find_node(struct list_node *head, void *comparison_data);

View file

@ -34,7 +34,7 @@
#define METADATA_PARSING_CONTINUE (0)
#define METADATA_PARSING_DONE (1)
#define MIN(x, y) (((x) > (y)) ? (y) : (x))
#define MIN(x,y) (((x)>(y))?(y):(x))
struct video_encode_metadata_t {
int hint_id;
@ -46,9 +46,9 @@ struct video_decode_metadata_t {
int state;
};
int parse_metadata(char* metadata, char** metadata_saveptr, char* attribute,
unsigned int attribute_size, char* value, unsigned int value_size);
int parse_video_encode_metadata(char* metadata,
struct video_encode_metadata_t* video_encode_metadata);
int parse_video_decode_metadata(char* metadata,
struct video_decode_metadata_t* video_decode_metadata);
int parse_metadata(char *metadata, char **metadata_saveptr,
char *attribute, int attribute_size, char *value, int value_size);
int parse_video_encode_metadata(char *metadata,
struct video_encode_metadata_t *video_encode_metadata);
int parse_video_decode_metadata(char *metadata,
struct video_decode_metadata_t *video_decode_metadata);

View file

@ -28,43 +28,55 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include "metadata-defs.h"
int parse_metadata(char* metadata, char** metadata_saveptr, char* attribute,
unsigned int attribute_size, char* value, unsigned int value_size) {
char* attribute_string;
char* attribute_value_delim;
int parse_metadata(char *metadata, char **metadata_saveptr,
char *attribute, int attribute_size, char *value, int value_size)
{
char *attribute_string;
char *attribute_value_delim;
unsigned int bytes_to_copy;
attribute_string = strtok_r(metadata, ATTRIBUTE_STRING_DELIM, metadata_saveptr);
attribute_string = strtok_r(metadata, ATTRIBUTE_STRING_DELIM,
metadata_saveptr);
if (attribute_string == NULL) return METADATA_PARSING_DONE;
if (attribute_string == NULL)
return METADATA_PARSING_DONE;
attribute[0] = value[0] = '\0';
if ((attribute_value_delim = strchr(attribute_string, ATTRIBUTE_VALUE_DELIM)) != NULL) {
unsigned int attribute_len = (unsigned int)(attribute_value_delim - attribute_string);
/* copy only attribute len + NUL character, or as much as can be fit */
bytes_to_copy = MIN(attribute_len + 1, attribute_size);
if ((attribute_value_delim = strchr(attribute_string,
ATTRIBUTE_VALUE_DELIM)) != NULL) {
bytes_to_copy = MIN((attribute_value_delim - attribute_string),
attribute_size - 1);
/* Replace strncpy with strlcpy
* Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */
strlcpy(attribute, attribute_string,
bytes_to_copy+1);
strlcpy(attribute, attribute_string, bytes_to_copy);
strlcpy(value, attribute_value_delim + 1, value_size);
bytes_to_copy = MIN(strlen(attribute_string) - strlen(attribute) - 1,
value_size - 1);
/* Replace strncpy with strlcpy
* Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */
strlcpy(value, attribute_value_delim + 1,
bytes_to_copy+1);
}
return METADATA_PARSING_CONTINUE;
}
int parse_video_encode_metadata(char* metadata,
struct video_encode_metadata_t* video_encode_metadata) {
int parse_video_encode_metadata(char *metadata,
struct video_encode_metadata_t *video_encode_metadata)
{
char attribute[1024], value[1024], *saveptr;
char* temp_metadata = metadata;
char *temp_metadata = metadata;
int parsing_status;
while ((parsing_status = parse_metadata(temp_metadata, &saveptr, attribute, sizeof(attribute),
value, sizeof(value))) == METADATA_PARSING_CONTINUE) {
while ((parsing_status = parse_metadata(temp_metadata, &saveptr,
attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) {
if (strlen(attribute) == strlen("hint_id") &&
(strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) {
if (strlen(value) > 0) {
@ -82,19 +94,21 @@ int parse_video_encode_metadata(char* metadata,
temp_metadata = NULL;
}
if (parsing_status == METADATA_PARSING_ERR) return -1;
if (parsing_status == METADATA_PARSING_ERR)
return -1;
return 0;
}
int parse_video_decode_metadata(char* metadata,
struct video_decode_metadata_t* video_decode_metadata) {
int parse_video_decode_metadata(char *metadata,
struct video_decode_metadata_t *video_decode_metadata)
{
char attribute[1024], value[1024], *saveptr;
char* temp_metadata = metadata;
char *temp_metadata = metadata;
int parsing_status;
while ((parsing_status = parse_metadata(temp_metadata, &saveptr, attribute, sizeof(attribute),
value, sizeof(value))) == METADATA_PARSING_CONTINUE) {
while ((parsing_status = parse_metadata(temp_metadata, &saveptr,
attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) {
if (strlen(attribute) == strlen("hint_id") &&
(strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) {
if (strlen(value) > 0) {
@ -112,7 +126,8 @@ int parse_video_decode_metadata(char* metadata,
temp_metadata = NULL;
}
if (parsing_status == METADATA_PARSING_ERR) return -1;
if (parsing_status == METADATA_PARSING_ERR)
return -1;
return 0;
}

View file

@ -31,31 +31,15 @@
extern "C" {
#endif
#define FAILED -1
#define SUCCESS 0
#define INDEFINITE_DURATION 0
#define FAILED -1
#define SUCCESS 0
#define INDEFINITE_DURATION 0
/* Hints sent to perf HAL from power HAL
* These have to be kept in sync with Perf HAL side definitions
*/
#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_V1 = 1,
LAUNCH_BOOST_V2 = 2,
LAUNCH_BOOST_V3 = 3
};
enum {
SCROLL_VERTICAL = 1,
SCROLL_HORIZONTAL = 2,
SCROLL_PANEL_VIEW = 3,
SCROLL_PREFILING = 4
};
#define VENDOR_HINT_DISPLAY_OFF 0x00001040
#define VENDOR_HINT_DISPLAY_ON 0x00001041
enum SCREEN_DISPLAY_TYPE {
DISPLAY_OFF = 0x00FF,

View file

@ -1,273 +0,0 @@
/*
* Copyright (c) 2017, 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 <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define LOG_TAG "QTI PowerHAL"
#include <hardware/hardware.h>
#include <hardware/power.h>
#include <utils/Log.h>
#include "hint-data.h"
#include "metadata-defs.h"
#include "performance.h"
#include "power-common.h"
#include "utils.h"
#define CHECK_HANDLE(x) ((x) > 0)
#define NUM_PERF_MODES 3
const int kMaxInteractiveDuration = 5000; /* ms */
const int kMinInteractiveDuration = 100; /* ms */
const int kMinFlingDuration = 1500; /* ms */
typedef enum {
NORMAL_MODE = 0,
SUSTAINED_MODE = 1,
VR_MODE = 2,
VR_SUSTAINED_MODE = (SUSTAINED_MODE | VR_MODE),
INVALID_MODE = 0xFF
} perf_mode_type_t;
typedef struct perf_mode {
perf_mode_type_t type;
int perf_hint_id;
} perf_mode_t;
perf_mode_t perf_modes[NUM_PERF_MODES] = {{SUSTAINED_MODE, SUSTAINED_PERF_HINT},
{VR_MODE, VR_MODE_HINT},
{VR_SUSTAINED_MODE, VR_MODE_SUSTAINED_PERF_HINT}};
static pthread_mutex_t perf_mode_switch_lock = PTHREAD_MUTEX_INITIALIZER;
static int current_mode = NORMAL_MODE;
static inline int get_perfd_hint_id(perf_mode_type_t type) {
int i;
for (i = 0; i < NUM_PERF_MODES; i++) {
if (perf_modes[i].type == type) {
ALOGD("Hint id is 0x%x for mode 0x%x", perf_modes[i].perf_hint_id, type);
return perf_modes[i].perf_hint_id;
}
}
ALOGD("Couldn't find the hint for mode 0x%x", type);
return 0;
}
static int switch_mode(perf_mode_type_t mode) {
int hint_id = 0;
static int perfd_mode_handle = -1;
// release existing mode if any
if (CHECK_HANDLE(perfd_mode_handle)) {
ALOGD("Releasing handle 0x%x", perfd_mode_handle);
release_request(perfd_mode_handle);
perfd_mode_handle = -1;
}
// switch to a perf mode
hint_id = get_perfd_hint_id(mode);
if (hint_id != 0) {
perfd_mode_handle = perf_hint_enable(hint_id, 0);
if (!CHECK_HANDLE(perfd_mode_handle)) {
ALOGE("Failed perf_hint_interaction for mode: 0x%x", mode);
return -1;
}
ALOGD("Acquired handle 0x%x", perfd_mode_handle);
}
return 0;
}
static int process_perf_hint(void* data, perf_mode_type_t mode) {
pthread_mutex_lock(&perf_mode_switch_lock);
// enable
if (data) {
ALOGI("Enable request for mode: 0x%x", mode);
// check if mode is current mode
if (current_mode & mode) {
pthread_mutex_unlock(&perf_mode_switch_lock);
ALOGD("Mode 0x%x already enabled", mode);
return HINT_HANDLED;
}
// enable requested mode
if (0 != switch_mode(current_mode | mode)) {
pthread_mutex_unlock(&perf_mode_switch_lock);
ALOGE("Couldn't enable mode 0x%x", mode);
return HINT_NONE;
}
current_mode |= mode;
ALOGI("Current mode is 0x%x", current_mode);
// disable
} else {
ALOGI("Disable request for mode: 0x%x", mode);
// check if mode is enabled
if (!(current_mode & mode)) {
pthread_mutex_unlock(&perf_mode_switch_lock);
ALOGD("Mode 0x%x already disabled", mode);
return HINT_HANDLED;
}
// disable requested mode
if (0 != switch_mode(current_mode & ~mode)) {
pthread_mutex_unlock(&perf_mode_switch_lock);
ALOGE("Couldn't disable mode 0x%x", mode);
return HINT_NONE;
}
current_mode &= ~mode;
ALOGI("Current mode is 0x%x", current_mode);
}
pthread_mutex_unlock(&perf_mode_switch_lock);
return HINT_HANDLED;
}
static int process_video_encode_hint(void* metadata) {
char governor[80];
struct video_encode_metadata_t video_encode_metadata;
static int video_encode_handle = 0;
if (!metadata) return HINT_NONE;
if (get_scaling_governor(governor, sizeof(governor)) == -1) {
ALOGE("Can't obtain scaling governor.");
return HINT_NONE;
}
/* Initialize encode metadata struct fields */
memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
video_encode_metadata.state = -1;
if (parse_video_encode_metadata((char*)metadata, &video_encode_metadata) == -1) {
ALOGE("Error occurred while parsing metadata.");
return HINT_NONE;
}
if (video_encode_metadata.state == 1) {
if (is_interactive_governor(governor)) {
video_encode_handle = perf_hint_enable(VIDEO_ENCODE_HINT, 0);
ALOGI("Video encode hint start");
return HINT_HANDLED;
}
} else if (video_encode_metadata.state == 0) {
if (is_interactive_governor(governor)) {
release_request(video_encode_handle);
ALOGI("Video Encode hint stop");
return HINT_HANDLED;
}
}
return HINT_NONE;
}
static int process_activity_launch_hint(void* 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(struct power_module* module, power_hint_t hint, void* data) {
int ret_val = HINT_NONE;
switch (hint) {
case POWER_HINT_VIDEO_ENCODE:
ret_val = process_video_encode_hint(data);
break;
case POWER_HINT_SUSTAINED_PERFORMANCE:
ret_val = process_perf_hint(data, SUSTAINED_MODE);
break;
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;
}
return ret_val;
}
int set_interactive_override(struct power_module* module, int on) {
static int set_i_count = 0;
set_i_count++;
ALOGI("Got set_interactive hint on= %d, count= %d\n", on, set_i_count);
return HINT_HANDLED; /* Don't excecute this code path, not in use */
}

135
power/power-common.c Normal file
View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2012-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 <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <unistd.h>
#define LOG_TAG "QTI PowerHAL"
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/power.h>
#include "utils.h"
#include "hint-data.h"
#include "performance.h"
#include "power-common.h"
static struct hint_handles handles[NUM_HINTS];
void power_init()
{
ALOGI("Initing");
for (int i=0; i<NUM_HINTS; i++) {
handles[i].handle = 0;
handles[i].ref_count = 0;
}
}
int __attribute__ ((weak)) power_hint_override(power_hint_t hint,
void *data)
{
return HINT_NONE;
}
/* Declare function before use */
void interaction(int duration, int num_args, int opt_list[]);
void power_hint(power_hint_t hint, void *data)
{
/* Check if this hint has been overridden. */
if (power_hint_override(hint, data) == HINT_HANDLED) {
/* The power_hint has been handled. We can skip the rest. */
return;
}
switch(hint) {
case POWER_HINT_VSYNC:
break;
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:
if (data) {
if (handles[hint].ref_count == 0)
handles[hint].handle = perf_hint_enable((AOSP_DELTA + hint), 0);
if (handles[hint].handle > 0)
handles[hint].ref_count++;
}
else
if (handles[hint].handle > 0)
if (--handles[hint].ref_count == 0) {
release_request(handles[hint].handle);
handles[hint].handle = 0;
}
else
ALOGE("Lock for hint: %X was not acquired, cannot be released", hint);
break;
}
}
int __attribute__ ((weak)) set_interactive_override(int on)
{
return HINT_NONE;
}
void set_interactive(int on)
{
if (!on) {
/* Send Display OFF hint to perf HAL */
perf_hint_enable(VENDOR_HINT_DISPLAY_OFF, 0);
} else {
/* Send Display ON hint to perf HAL */
perf_hint_enable(VENDOR_HINT_DISPLAY_ON, 0);
}
if (set_interactive_override(on) == HINT_HANDLED) {
return;
}
ALOGI("Got set_interactive hint");
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
* Copyright (c) 2013, 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
@ -26,6 +26,13 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __POWER_COMMON_H__
#define __POWER_COMMON_H__
#ifdef __cplusplus
extern "C" {
#endif
#define NODE_MAX (64)
#define SCALING_GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
@ -37,8 +44,26 @@
#define ONDEMAND_GOVERNOR "ondemand"
#define INTERACTIVE_GOVERNOR "interactive"
#define MSMDCVS_GOVERNOR "msm-dcvs"
#define SCHEDUTIL_GOVERNOR "schedutil"
#define HINT_HANDLED (0)
#define HINT_NONE (-1)
enum CPU_GOV_CHECK { CPU0 = 0, CPU1 = 1, CPU2 = 2, CPU3 = 3 };
#include <hardware/power.h>
enum CPU_GOV_CHECK {
CPU0 = 0,
CPU1 = 1,
CPU2 = 2,
CPU3 = 3
};
void power_init(void);
void power_hint(power_hint_t hint, void *data);
void set_interactive(int on);
#ifdef __cplusplus
}
#endif
#endif //__POWER_COMMON_H___

View file

@ -1,506 +0,0 @@
/*
* Copyright (c) 2012-2017, 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 <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define LOG_TAG "QCOM PowerHAL"
#include <hardware/hardware.h>
#include <hardware/power.h>
#include <utils/Log.h>
#include "hint-data.h"
#include "metadata-defs.h"
#include "performance.h"
#include "power-common.h"
#include "utils.h"
static int saved_dcvs_cpu0_slack_max = -1;
static int saved_dcvs_cpu0_slack_min = -1;
static int saved_mpdecision_slack_max = -1;
static int saved_mpdecision_slack_min = -1;
static int saved_interactive_mode = -1;
static int slack_node_rw_failed = 0;
static int display_hint_sent;
int display_boost;
static int power_device_open(const hw_module_t* module, const char* name, hw_device_t** device);
static struct hw_module_methods_t power_module_methods = {
.open = power_device_open,
};
static void power_init(struct power_module* module) {
ALOGI("QCOM power HAL initing.");
int fd;
char buf[10] = {0};
fd = open("/sys/devices/soc0/soc_id", O_RDONLY);
if (fd >= 0) {
if (read(fd, buf, sizeof(buf) - 1) == -1) {
ALOGW("Unable to read soc_id");
} else {
int soc_id = atoi(buf);
if (soc_id == 194 || (soc_id >= 208 && soc_id <= 218) || soc_id == 178) {
display_boost = 1;
}
}
close(fd);
}
}
static void process_video_decode_hint(void* metadata) {
char governor[80];
struct video_decode_metadata_t video_decode_metadata;
if (get_scaling_governor(governor, sizeof(governor)) == -1) {
ALOGE("Can't obtain scaling governor.");
return;
}
if (metadata) {
ALOGI("Processing video decode hint. Metadata: %s", (char*)metadata);
}
/* Initialize encode metadata struct fields. */
memset(&video_decode_metadata, 0, sizeof(struct video_decode_metadata_t));
video_decode_metadata.state = -1;
video_decode_metadata.hint_id = DEFAULT_VIDEO_DECODE_HINT_ID;
if (metadata) {
if (parse_video_decode_metadata((char*)metadata, &video_decode_metadata) == -1) {
ALOGE("Error occurred while parsing metadata.");
return;
}
} else {
return;
}
if (video_decode_metadata.state == 1) {
if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
int resource_values[] = {THREAD_MIGRATION_SYNC_OFF};
perform_hint_action(video_decode_metadata.hint_id, resource_values,
sizeof(resource_values) / sizeof(resource_values[0]));
} else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026,
THREAD_MIGRATION_SYNC_OFF};
perform_hint_action(video_decode_metadata.hint_id, resource_values,
sizeof(resource_values) / sizeof(resource_values[0]));
}
} else if (video_decode_metadata.state == 0) {
if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
} else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
undo_hint_action(video_decode_metadata.hint_id);
}
}
}
static void process_video_encode_hint(void* metadata) {
char governor[80];
struct video_encode_metadata_t video_encode_metadata;
if (get_scaling_governor(governor, sizeof(governor)) == -1) {
ALOGE("Can't obtain scaling governor.");
return;
}
/* Initialize encode metadata struct fields. */
memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
video_encode_metadata.state = -1;
video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
if (metadata) {
if (parse_video_encode_metadata((char*)metadata, &video_encode_metadata) == -1) {
ALOGE("Error occurred while parsing metadata.");
return;
}
} else {
return;
}
if (video_encode_metadata.state == 1) {
if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
int resource_values[] = {IO_BUSY_OFF, SAMPLING_DOWN_FACTOR_1, THREAD_MIGRATION_SYNC_OFF};
perform_hint_action(video_encode_metadata.hint_id, resource_values,
sizeof(resource_values) / sizeof(resource_values[0]));
} else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026,
THREAD_MIGRATION_SYNC_OFF, INTERACTIVE_IO_BUSY_OFF};
perform_hint_action(video_encode_metadata.hint_id, resource_values,
sizeof(resource_values) / sizeof(resource_values[0]));
}
} else if (video_encode_metadata.state == 0) {
if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
undo_hint_action(video_encode_metadata.hint_id);
} else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
undo_hint_action(video_encode_metadata.hint_id);
}
}
}
int __attribute__((weak))
power_hint_override(struct power_module* module, power_hint_t hint, void* data) {
return HINT_NONE;
}
/* Declare function before use */
void interaction(int duration, int num_args, int opt_list[]);
static void power_hint(struct power_module* module, power_hint_t hint, void* data) {
/* Check if this hint has been overridden. */
if (power_hint_override(module, hint, data) == HINT_HANDLED) {
/* The power_hint has been handled. We can skip the rest. */
return;
}
switch (hint) {
case POWER_HINT_VSYNC:
break;
case POWER_HINT_SUSTAINED_PERFORMANCE:
ALOGI("Sustained perf power hint not handled in power_hint_override");
break;
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;
case POWER_HINT_VIDEO_ENCODE:
process_video_encode_hint(data);
break;
case POWER_HINT_VIDEO_DECODE:
process_video_decode_hint(data);
break;
default:
break;
}
}
int __attribute__((weak)) set_interactive_override(struct power_module* module, int on) {
return HINT_NONE;
}
void set_interactive(struct power_module* module, int on) {
char governor[80];
char tmp_str[NODE_MAX];
int rc = 0;
if (!on) {
/* Send Display OFF hint to perf HAL */
perf_hint_enable(VENDOR_HINT_DISPLAY_OFF, 0);
} else {
/* Send Display ON hint to perf HAL */
perf_hint_enable(VENDOR_HINT_DISPLAY_ON, 0);
}
if (set_interactive_override(module, on) == HINT_HANDLED) {
return;
}
ALOGI("Got set_interactive hint");
if (get_scaling_governor(governor, sizeof(governor)) == -1) {
ALOGE("Can't obtain scaling governor.");
return;
}
if (!on) {
/* Display off. */
if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
int resource_values[] = {DISPLAY_OFF, MS_500, THREAD_MIGRATION_SYNC_OFF};
if (!display_hint_sent) {
perform_hint_action(DISPLAY_STATE_HINT_ID, resource_values,
sizeof(resource_values) / sizeof(resource_values[0]));
display_hint_sent = 1;
}
} else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
int resource_values[] = {TR_MS_50, THREAD_MIGRATION_SYNC_OFF};
if (!display_hint_sent) {
perform_hint_action(DISPLAY_STATE_HINT_ID, resource_values,
sizeof(resource_values) / sizeof(resource_values[0]));
display_hint_sent = 1;
}
} else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(MSMDCVS_GOVERNOR))) {
if (saved_interactive_mode == 1) {
/* Display turned off. */
if (sysfs_read(DCVS_CPU0_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) {
if (!slack_node_rw_failed) {
ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MAX_NODE);
}
rc = 1;
} else {
saved_dcvs_cpu0_slack_max = atoi(tmp_str);
}
if (sysfs_read(DCVS_CPU0_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) {
if (!slack_node_rw_failed) {
ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MIN_NODE);
}
rc = 1;
} else {
saved_dcvs_cpu0_slack_min = atoi(tmp_str);
}
if (sysfs_read(MPDECISION_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) {
if (!slack_node_rw_failed) {
ALOGE("Failed to read from %s", MPDECISION_SLACK_MAX_NODE);
}
rc = 1;
} else {
saved_mpdecision_slack_max = atoi(tmp_str);
}
if (sysfs_read(MPDECISION_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) {
if (!slack_node_rw_failed) {
ALOGE("Failed to read from %s", MPDECISION_SLACK_MIN_NODE);
}
rc = 1;
} else {
saved_mpdecision_slack_min = atoi(tmp_str);
}
/* Write new values. */
if (saved_dcvs_cpu0_slack_max != -1) {
snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_max);
if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE);
}
rc = 1;
}
}
if (saved_dcvs_cpu0_slack_min != -1) {
snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_min);
if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE);
}
rc = 1;
}
}
if (saved_mpdecision_slack_max != -1) {
snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_max);
if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE);
}
rc = 1;
}
}
if (saved_mpdecision_slack_min != -1) {
snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_min);
if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE);
}
rc = 1;
}
}
}
slack_node_rw_failed = rc;
}
} else {
/* Display on. */
if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
undo_hint_action(DISPLAY_STATE_HINT_ID);
display_hint_sent = 0;
} else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
undo_hint_action(DISPLAY_STATE_HINT_ID);
display_hint_sent = 0;
} else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) &&
(strlen(governor) == strlen(MSMDCVS_GOVERNOR))) {
if (saved_interactive_mode == -1 || saved_interactive_mode == 0) {
/* Display turned on. Restore if possible. */
if (saved_dcvs_cpu0_slack_max != -1) {
snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_max);
if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE);
}
rc = 1;
}
}
if (saved_dcvs_cpu0_slack_min != -1) {
snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_min);
if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE);
}
rc = 1;
}
}
if (saved_mpdecision_slack_max != -1) {
snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_max);
if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE);
}
rc = 1;
}
}
if (saved_mpdecision_slack_min != -1) {
snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_min);
if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) {
if (!slack_node_rw_failed) {
ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE);
}
rc = 1;
}
}
}
slack_node_rw_failed = rc;
}
}
saved_interactive_mode = !!on;
}
void set_feature(struct power_module* module, feature_t feature, int state) {
switch (feature) {
case POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
sysfs_write("/proc/touchpanel/double_tap_enable", state ? "1" : "0");
break;
default:
break;
}
}
static int power_device_open(const hw_module_t* module, const char* name, hw_device_t** device) {
int status = -EINVAL;
if (module && name && device) {
if (!strcmp(name, POWER_HARDWARE_MODULE_ID)) {
power_module_t* dev = (power_module_t*)malloc(sizeof(*dev));
if (dev) {
memset(dev, 0, sizeof(*dev));
if (dev) {
/* initialize the fields */
dev->common.module_api_version = POWER_MODULE_API_VERSION_0_3;
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->init = power_init;
dev->powerHint = power_hint;
dev->setInteractive = set_interactive;
dev->setFeature = set_feature;
/* At the moment we support 0.3 APIs */
dev->get_number_of_platform_modes = NULL;
dev->get_platform_low_power_stats = NULL;
dev->get_voter_list = NULL;
*device = (hw_device_t*)dev;
status = 0;
} else {
status = -ENOMEM;
}
} else {
status = -ENOMEM;
}
}
}
return status;
}
struct power_module HAL_MODULE_INFO_SYM = {
.common =
{
.tag = HARDWARE_MODULE_TAG,
.module_api_version = POWER_MODULE_API_VERSION_0_3,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = POWER_HARDWARE_MODULE_ID,
.name = "QCOM Power HAL",
.author = "Qualcomm",
.methods = &power_module_methods,
},
.init = power_init,
.powerHint = power_hint,
.setInteractive = set_interactive,
.setFeature = set_feature,
};

View file

@ -26,18 +26,18 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_TAG "QCOM PowerHAL"
#include "powerhintparser.h"
#include <cutils/log.h>
#include <cutils/properties.h>
#include <fcntl.h>
#include <string.h>
#include <cutils/properties.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <string.h>
#include <unistd.h>
#include "powerhintparser.h"
#define LOG_TAG "QTI PowerHAL"
int parsePowerhintXML() {
xmlDocPtr doc;
xmlNodePtr currNode;
const char *opcode_str, *value_str, *type_str;
@ -45,18 +45,18 @@ int parsePowerhintXML() {
int numParams = 0;
static int hintCount;
if (access(POWERHINT_XML, F_OK) < 0) {
if(access(POWERHINT_XML, F_OK) < 0) {
return -1;
}
doc = xmlReadFile(POWERHINT_XML, "UTF-8", XML_PARSE_RECOVER);
if (!doc) {
if(!doc) {
ALOGE("Document not parsed successfully");
return -1;
}
currNode = xmlDocGetRootElement(doc);
if (!currNode) {
if(!currNode) {
ALOGE("Empty document");
xmlFreeDoc(doc);
xmlCleanupParser();
@ -64,7 +64,7 @@ int parsePowerhintXML() {
}
// Confirm the root-element of the tree
if (xmlStrcmp(currNode->name, BAD_CAST "Powerhint")) {
if(xmlStrcmp(currNode->name, BAD_CAST "Powerhint")) {
ALOGE("document of the wrong type, root node != root");
xmlFreeDoc(doc);
xmlCleanupParser();
@ -73,34 +73,39 @@ int parsePowerhintXML() {
currNode = currNode->xmlChildrenNode;
for (; currNode != NULL; currNode = currNode->next) {
if (currNode->type != XML_ELEMENT_NODE) continue;
for(; currNode != NULL; currNode=currNode->next) {
if(currNode->type != XML_ELEMENT_NODE)
continue;
xmlNodePtr node = currNode;
if (hintCount == MAX_HINT) {
ALOGE("Number of hints exceeded the max count of %d\n", MAX_HINT);
if(hintCount == MAX_HINT) {
ALOGE("Number of hints exceeded the max count of %d\n",MAX_HINT);
break;
}
if (!xmlStrcmp(node->name, BAD_CAST "Hint")) {
if (xmlHasProp(node, BAD_CAST "type")) {
type_str = (const char*)xmlGetProp(node, BAD_CAST "type");
if (type_str == NULL) {
ALOGE("xmlGetProp failed on type");
xmlFreeDoc(doc);
xmlCleanupParser();
return -1;
}
type = strtol(type_str, NULL, 16);
if(!xmlStrcmp(node->name, BAD_CAST "Hint")) {
if(xmlHasProp(node, BAD_CAST "type")) {
type_str = (const char*)xmlGetProp(node, BAD_CAST "type");
if (type_str == NULL)
{
ALOGE("xmlGetProp failed on type");
xmlFreeDoc(doc);
xmlCleanupParser();
return -1;
}
type = strtol(type_str, NULL, 16);
}
node = node->children;
while (node != NULL) {
if (!xmlStrcmp(node->name, BAD_CAST "Resource")) {
if (xmlHasProp(node, BAD_CAST "opcode")) {
opcode_str = (const char*)xmlGetProp(node, BAD_CAST "opcode");
if (opcode_str == NULL) {
while(node != NULL) {
if(!xmlStrcmp(node->name, BAD_CAST "Resource")) {
if(xmlHasProp(node, BAD_CAST "opcode")) {
opcode_str = (const char*)xmlGetProp(node, BAD_CAST "opcode");
if (opcode_str == NULL)
{
ALOGE("xmlGetProp failed on opcode");
xmlFreeDoc(doc);
xmlCleanupParser();
@ -108,9 +113,10 @@ int parsePowerhintXML() {
}
opcode = strtol(opcode_str, NULL, 16);
}
if (xmlHasProp(node, BAD_CAST "value")) {
if(xmlHasProp(node, BAD_CAST "value")) {
value_str = (const char*)xmlGetProp(node, BAD_CAST "value");
if (value_str == NULL) {
if (value_str == NULL)
{
ALOGE("xmlGetProp failed on value");
xmlFreeDoc(doc);
xmlCleanupParser();
@ -118,12 +124,12 @@ int parsePowerhintXML() {
}
value = strtol(value_str, NULL, 16);
}
if (opcode > 0) {
if (numParams < (MAX_PARAM - 1)) {
if(opcode > 0) {
if(numParams < (MAX_PARAM-1)) {
powerhint[hintCount].paramList[numParams++] = opcode;
powerhint[hintCount].paramList[numParams++] = value;
} else {
ALOGE("Maximum parameters exceeded for Hint ID %x\n", type);
ALOGE("Maximum parameters exceeded for Hint ID %x\n",type);
opcode = value = 0;
break;
}
@ -145,27 +151,29 @@ int parsePowerhintXML() {
return 0;
}
int* getPowerhint(int hint_id, int* params) {
int* result = NULL;
int* getPowerhint(int hint_id, int *params) {
if (!hint_id) return result;
int *result = NULL;
ALOGI("Powerhal hint received=%x\n", hint_id);
if(!hint_id)
return result;
if (!powerhint[0].numParams) {
parsePowerhintXML();
ALOGI("Powerhal hint received=%x\n",hint_id);
if(!powerhint[0].numParams) {
parsePowerhintXML();
}
for (int i = 0; i < MAX_HINT; i++) {
if (hint_id == powerhint[i].type) {
*params = powerhint[i].numParams;
result = powerhint[i].paramList;
break;
}
for(int i = 0; i < MAX_HINT; i++) {
if(hint_id == powerhint[i].type) {
*params = powerhint[i].numParams;
result = powerhint[i].paramList;
break;
}
}
/*for (int j = 0; j < *params; j++)
ALOGI("Powerhal resource again%x = \n", result[j]);*/
return result;
return result;
}

View file

@ -30,19 +30,19 @@
#ifndef __POWERHINTPARSER__
#define __POWERHINTPARSER__
#define POWERHINT_XML "/vendor/etc/powerhint.xml"
#define POWERHINT_XML "/vendor/etc/powerhint.xml"
#define MAX_HINT 6
#define MAX_PARAM 30
typedef struct perflock_param_t {
int type;
int numParams;
int paramList[MAX_PARAM]; // static limit on number of hints - 15
} perflock_param_t;
int paramList[MAX_PARAM];//static limit on number of hints - 15
}perflock_param_t;
static perflock_param_t powerhint[MAX_HINT];
int parsePowerhintXML();
int* getPowerhint(int, int*);
int *getPowerhint(int, int*);
#endif /* __POWERHINTPARSER__ */

81
power/service.cpp Normal file
View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 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_TAG "android.hardware.power@1.2-service"
#include <android/log.h>
#include <hidl/HidlTransportSupport.h>
#include <hardware/power.h>
#include "Power.h"
using android::sp;
using android::status_t;
using android::OK;
// libhwbinder:
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
using android::hardware::power::V1_2::IPower;
using android::hardware::power::V1_2::implementation::Power;
int main() {
status_t status;
android::sp<IPower> service = nullptr;
ALOGI("Power HAL Service 1.2 is starting.");
service = new Power();
if (service == nullptr) {
ALOGE("Can not create an instance of Power HAL interface.");
goto shutdown;
}
configureRpcThreadpool(1, true /*callerWillJoin*/);
status = service->registerAsService();
if (status != OK) {
ALOGE("Could not register service for Power HAL(%d).", status);
goto shutdown;
}
ALOGI("Power Service is ready");
joinRpcThreadpool();
//Should not pass this line
shutdown:
// In normal operation, we don't expect the thread pool to exit
ALOGE("Power Service is shutting down");
return 1;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2013,2015-2017, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2013,2015-2018, 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
@ -29,48 +29,53 @@
#define LOG_NIDEBUG 0
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "hint-data.h"
#include "list.h"
#include "power-common.h"
#include "utils.h"
#include "list.h"
#include "hint-data.h"
#include "power-common.h"
#define LOG_TAG "QCOM PowerHAL"
#define LOG_TAG "QTI PowerHAL"
#include <utils/Log.h>
#define USINSEC 1000000L
#define NSINUS 1000L
char scaling_gov_path[4][80] = {"sys/devices/system/cpu/cpu0/cpufreq/scaling_governor",
"sys/devices/system/cpu/cpu1/cpufreq/scaling_governor",
"sys/devices/system/cpu/cpu2/cpufreq/scaling_governor",
"sys/devices/system/cpu/cpu3/cpufreq/scaling_governor"};
char scaling_gov_path[4][80] ={
"sys/devices/system/cpu/cpu0/cpufreq/scaling_governor",
"sys/devices/system/cpu/cpu1/cpufreq/scaling_governor",
"sys/devices/system/cpu/cpu2/cpufreq/scaling_governor",
"sys/devices/system/cpu/cpu3/cpufreq/scaling_governor"
};
#define PERF_HAL_PATH "libqti-perfd-client.so"
static void* qcopt_handle;
static int (*perf_lock_acq)(unsigned long handle, int duration, int list[], int numArgs);
static int (*perf_lock_rel)(unsigned long handle);
static int (*perf_hint)(int, char*, int, int);
static void *qcopt_handle;
static int (*perf_lock_acq)(int handle, int duration,
int list[], int numArgs);
static int (*perf_lock_rel)(int handle);
static int (*perf_hint)(int, const char *, int, int);
static struct list_node active_hint_list_head;
const char *pkg = "QTI PowerHAL";
static void* get_qcopt_handle() {
void* handle = NULL;
static void *get_qcopt_handle()
{
void *handle = NULL;
dlerror();
handle = dlopen(PERF_HAL_PATH, RTLD_NOW);
if (!handle) {
ALOGE("Unable to open %s: %s\n", PERF_HAL_PATH, dlerror());
ALOGE("Unable to open %s: %s\n", PERF_HAL_PATH,
dlerror());
}
return handle;
}
static void __attribute__((constructor)) initialize(void) {
static void __attribute__ ((constructor)) initialize(void)
{
qcopt_handle = get_qcopt_handle();
if (!qcopt_handle) {
@ -100,13 +105,16 @@ static void __attribute__((constructor)) initialize(void) {
}
}
static void __attribute__((destructor)) cleanup(void) {
static void __attribute__ ((destructor)) cleanup(void)
{
if (qcopt_handle) {
if (dlclose(qcopt_handle)) ALOGE("Error occurred while closing qc-opt library.");
if (dlclose(qcopt_handle))
ALOGE("Error occurred while closing qc-opt library.");
}
}
int sysfs_read(char* path, char* s, int num_bytes) {
int sysfs_read(char *path, char *s, int num_bytes)
{
char buf[80];
int count;
int ret = 0;
@ -133,7 +141,8 @@ int sysfs_read(char* path, char* s, int num_bytes) {
return ret;
}
int sysfs_write(char* path, char* s) {
int sysfs_write(char *path, char *s)
{
char buf[80];
int len;
int ret = 0;
@ -142,7 +151,7 @@ int sysfs_write(char* path, char* s) {
if (fd < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error opening %s: %s\n", path, buf);
return -1;
return -1 ;
}
len = write(fd, s, strlen(s));
@ -158,8 +167,10 @@ int sysfs_write(char* path, char* s) {
return ret;
}
int get_scaling_governor(char governor[], int size) {
if (sysfs_read(SCALING_GOVERNOR_PATH, governor, size) == -1) {
int get_scaling_governor(char governor[], int size)
{
if (sysfs_read(SCALING_GOVERNOR_PATH, governor,
size) == -1) {
// Can't obtain the scaling governor. Return.
return -1;
} else {
@ -168,14 +179,18 @@ int get_scaling_governor(char governor[], int size) {
len--;
while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r')) governor[len--] = '\0';
while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r'))
governor[len--] = '\0';
}
return 0;
}
int get_scaling_governor_check_cores(char governor[], int size, int core_num) {
if (sysfs_read(scaling_gov_path[core_num], governor, size) == -1) {
int get_scaling_governor_check_cores(char governor[], int size,int core_num)
{
if (sysfs_read(scaling_gov_path[core_num], governor,
size) == -1) {
// Can't obtain the scaling governor. Return.
return -1;
}
@ -183,92 +198,96 @@ int get_scaling_governor_check_cores(char governor[], int size, int core_num) {
// Strip newline at the end.
int len = strlen(governor);
len--;
while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r')) governor[len--] = '\0';
while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r'))
governor[len--] = '\0';
return 0;
}
int is_interactive_governor(char* governor) {
if (strncmp(governor, INTERACTIVE_GOVERNOR, (strlen(INTERACTIVE_GOVERNOR) + 1)) == 0) return 1;
return 0;
if (strncmp(governor, INTERACTIVE_GOVERNOR, (strlen(INTERACTIVE_GOVERNOR)+1)) == 0)
return 1;
return 0;
}
void interaction(int duration, int num_args, int opt_list[]) {
void interaction(int duration, int num_args, int opt_list[])
{
#ifdef INTERACTION_BOOST
static int lock_handle = 0;
if (duration < 0 || num_args < 1 || opt_list[0] == 0) return;
if (duration < 0 || num_args < 1 || opt_list[0] == NULL)
return;
if (qcopt_handle) {
if (perf_lock_acq) {
lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args);
if (lock_handle == -1) ALOGE("Failed to acquire lock.");
if (lock_handle == -1)
ALOGE("Failed to acquire lock.");
}
}
#endif
}
int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]) {
if (duration < 0 || num_args < 1 || opt_list[0] == 0) return 0;
int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[])
{
if (duration < 0 || num_args < 1 || opt_list[0] == NULL)
return 0;
if (qcopt_handle) {
if (perf_lock_acq) {
lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args);
if (lock_handle == -1) ALOGE("Failed to acquire lock.");
if (lock_handle == -1)
ALOGE("Failed to acquire lock.");
}
}
return lock_handle;
}
// this is interaction_with_handle using perf_hint instead of
// perf_lock_acq
int perf_hint_enable(int hint_id, int duration) {
//this is interaction_with_handle using perf_hint instead of
//perf_lock_acq
int perf_hint_enable(int hint_id , int duration)
{
int lock_handle = 0;
if (duration < 0) return 0;
if (duration < 0)
return 0;
if (qcopt_handle) {
if (perf_hint) {
lock_handle = perf_hint(hint_id, NULL, duration, -1);
if (lock_handle == -1) ALOGE("Failed to acquire lock.");
lock_handle = perf_hint(hint_id, pkg, duration, -1);
if (lock_handle == -1)
ALOGE("Failed to acquire lock for hint_id: %X.", hint_id);
}
}
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);
if (qcopt_handle && perf_lock_rel)
perf_lock_rel(lock_handle);
}
void perform_hint_action(int hint_id, int resource_values[], int num_resources) {
void perform_hint_action(int hint_id, int resource_values[], int num_resources)
{
if (qcopt_handle) {
if (perf_lock_acq) {
/* Acquire an indefinite lock for the requested resources. */
int lock_handle = perf_lock_acq(0, 0, resource_values, num_resources);
int lock_handle = perf_lock_acq(0, 0, resource_values,
num_resources);
if (lock_handle == -1) {
ALOGE("Failed to acquire lock.");
} else {
/* Add this handle to our internal hint-list. */
struct hint_data* new_hint = (struct hint_data*)malloc(sizeof(struct hint_data));
struct hint_data *new_hint =
(struct hint_data *)malloc(sizeof(struct hint_data));
if (new_hint) {
if (!active_hint_list_head.compare) {
active_hint_list_head.compare = (int (*)(void*, void*))hint_compare;
active_hint_list_head.dump = (void (*)(void*))hint_dump;
active_hint_list_head.compare =
(int (*)(void *, void *))hint_compare;
active_hint_list_head.dump = (void (*)(void *))hint_dump;
}
new_hint->hint_id = hint_id;
@ -277,13 +296,15 @@ void perform_hint_action(int hint_id, int resource_values[], int num_resources)
if (add_list_node(&active_hint_list_head, new_hint) == NULL) {
free(new_hint);
/* Can't keep track of this lock. Release it. */
if (perf_lock_rel) perf_lock_rel(lock_handle);
if (perf_lock_rel)
perf_lock_rel(lock_handle);
ALOGE("Failed to process hint.");
}
} else {
/* Can't keep track of this lock. Release it. */
if (perf_lock_rel) perf_lock_rel(lock_handle);
if (perf_lock_rel)
perf_lock_rel(lock_handle);
ALOGE("Failed to process hint.");
}
@ -292,18 +313,23 @@ void perform_hint_action(int hint_id, int resource_values[], int num_resources)
}
}
void undo_hint_action(int hint_id) {
void undo_hint_action(int hint_id)
{
if (qcopt_handle) {
if (perf_lock_rel) {
/* Get hint-data associated with this hint-id */
struct list_node* found_node;
struct hint_data temp_hint_data = {.hint_id = hint_id};
struct list_node *found_node;
struct hint_data temp_hint_data = {
.hint_id = hint_id
};
found_node = find_node(&active_hint_list_head, &temp_hint_data);
found_node = find_node(&active_hint_list_head,
&temp_hint_data);
if (found_node) {
/* Release this lock. */
struct hint_data* found_hint_data = (struct hint_data*)(found_node->data);
struct hint_data *found_hint_data =
(struct hint_data *)(found_node->data);
if (found_hint_data) {
if (perf_lock_rel(found_hint_data->perflock_handle) == -1)
@ -327,17 +353,11 @@ void undo_hint_action(int hint_id) {
* Used to release initial lock holding
* two cores online when the display is on
*/
void undo_initial_hint_action() {
void undo_initial_hint_action()
{
if (qcopt_handle) {
if (perf_lock_rel) {
perf_lock_rel(1);
}
}
}
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;
}

View file

@ -29,21 +29,19 @@
#include <cutils/properties.h>
int sysfs_read(char* path, char* s, int num_bytes);
int sysfs_write(char* path, char* s);
int sysfs_read(char *path, char *s, int num_bytes);
int sysfs_write(char *path, char *s);
int get_scaling_governor(char governor[], int size);
int get_scaling_governor_check_cores(char governor[], int size, int core_num);
int get_scaling_governor_check_cores(char governor[], int size,int core_num);
int is_interactive_governor(char*);
void vote_ondemand_io_busy_off();
void unvote_ondemand_io_busy_off();
void vote_ondemand_sdf_low();
void unvote_ondemand_sdf_low();
void perform_hint_action(int hint_id, int resource_values[], int num_resources);
void perform_hint_action(int hint_id, int resource_values[],
int num_resources);
void undo_hint_action(int hint_id);
void release_request(int lock_handle);
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);

View file

@ -11,6 +11,7 @@
# HALs
/(product|system/product)/vendor_overlay/[0-9]+/bin/hw/android\.hardware\.light@2\.0-service u:object_r:hal_light_default_exec:s0
/(product|system/product)/vendor_overlay/[0-9]+/bin/hw/android\.hardware\.power@1\.2-service u:object_r:hal_power_default_exec:s0
/system/bin/hw/lineage\.biometrics\.fingerprint\.inscreen@1.0-service\.oneplus_kona u:object_r:hal_fod_kona_exec:s0
/system/bin/hw/lineage\.livedisplay@2\.0-service\.oneplus_kona u:object_r:hal_livedisplay_kona_exec:s0
/system/bin/hw/lineage\.touch@1\.0-service\.oneplus_kona u:object_r:hal_touch_kona_exec:s0