wahoo: power: switch to libperfmgr for powerhint
Test: boot and do powerhint
Bug: 62041945
Change-Id: I7de1d2bf377fb46162171a084fca3413b1067d3b
diff --git a/device.mk b/device.mk
index e8f48d3..d2913c5 100755
--- a/device.mk
+++ b/device.mk
@@ -169,10 +169,10 @@
# power HAL
PRODUCT_PACKAGES += \
- android.hardware.power@1.2-service.wahoo
+ android.hardware.power@1.2-service.wahoo-libperfmgr
PRODUCT_COPY_FILES += \
- $(LOCAL_PATH)/powerhint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/powerhint.xml
+ $(LOCAL_PATH)/powerhint.json:$(TARGET_COPY_OUT_VENDOR)/etc/powerhint.json
# health HAL
PRODUCT_PACKAGES += \
diff --git a/init.hardware.rc b/init.hardware.rc
index 7486996..571eb08 100644
--- a/init.hardware.rc
+++ b/init.hardware.rc
@@ -385,7 +385,6 @@
# b/62837579 elabel directory
mkdir /data/misc/elabel 0700 system system
-
on early-boot
# wait for devices
wait_for_prop sys.qcom.devup 1
@@ -549,11 +548,20 @@
disabled
on property:sys.post_boot.parsed=1
- start vendor.perfd
+ # Setup permission for powerHAL
+ chown system system /dev/stune/top-app/schedtune.boost
+ chown system system /dev/cpu_dma_latency
+ chown system system /sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/min_freq
+ chown system system /sys/class/kgsl/kgsl-3d0/devfreq/min_freq
+ chown system system /sys/class/kgsl/kgsl-3d0/devfreq/max_freq
+ chown system system /sys/class/devfreq/soc:qcom,gpubw/min_freq
+ chown system system /sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/bw_hwmon/hyst_trigger_count
+ chown system system /sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/bw_hwmon/hist_memory
+ chown system system /sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/bw_hwmon/hyst_length
+ chown system system /sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/min_freq
on property:sys.boot_completed=1
# Enable power setting and set sys.post_boot.parsed to 1
- # to start perfd
start vendor.power_sh
# Enable UFS powersaving
diff --git a/power-libperfmgr/Android.bp b/power-libperfmgr/Android.bp
new file mode 100644
index 0000000..8deca67
--- /dev/null
+++ b/power-libperfmgr/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+cc_binary {
+ name: "android.hardware.power@1.2-service.wahoo-libperfmgr",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.power@1.2-service.wahoo-libperfmgr.rc"],
+ srcs: ["service.cpp", "Power.cpp", "InteractionHandler.cpp", "power-helper.c"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ "libcutils",
+ "android.hardware.power@1.0",
+ "android.hardware.power@1.1",
+ "android.hardware.power@1.2",
+ "libperfmgr",
+ ],
+ proprietary: true,
+}
diff --git a/power-libperfmgr/InteractionHandler.cpp b/power-libperfmgr/InteractionHandler.cpp
new file mode 100644
index 0000000..b8ce3ef
--- /dev/null
+++ b/power-libperfmgr/InteractionHandler.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "android.hardware.power@1.2-service.wahoo-libperfmgr"
+#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
+
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/eventfd.h>
+#include <time.h>
+#include <unistd.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "InteractionHandler.h"
+
+#define FB_IDLE_PATH "/sys/class/graphics/fb0/idle_state"
+#define MAX_LENGTH 64
+
+#define MSINSEC 1000L
+#define USINMS 1000000L
+
+InteractionHandler::InteractionHandler(std::shared_ptr<HintManager> const & hint_manager)
+ : mState(INTERACTION_STATE_UNINITIALIZED),
+ mWaitMs(100),
+ mMinDurationMs(1400),
+ mMaxDurationMs(5650),
+ mDurationMs(0),
+ mHintManager(hint_manager) {
+}
+
+InteractionHandler::~InteractionHandler() {
+ Exit();
+}
+
+bool InteractionHandler::Init() {
+ std::lock_guard<std::mutex> lk(mLock);
+
+ if (mState != INTERACTION_STATE_UNINITIALIZED)
+ return true;
+
+ mIdleFd = open(FB_IDLE_PATH, O_RDONLY);
+ if (mIdleFd < 0) {
+ ALOGE("Unable to open idle state path (%d)", errno);
+ return false;
+ }
+
+ mEventFd = eventfd(0, EFD_NONBLOCK);
+ if (mEventFd < 0) {
+ ALOGE("Unable to create event fd (%d)", errno);
+ close(mIdleFd);
+ return false;
+ }
+
+ mState = INTERACTION_STATE_IDLE;
+ mThread = std::unique_ptr<std::thread>(
+ new std::thread(&InteractionHandler::Routine, this));
+
+ return true;
+}
+
+void InteractionHandler::Exit() {
+ std::unique_lock<std::mutex> lk(mLock);
+ if (mState == INTERACTION_STATE_UNINITIALIZED)
+ return;
+
+ AbortWaitLocked();
+ mState = INTERACTION_STATE_UNINITIALIZED;
+ lk.unlock();
+
+ mCond.notify_all();
+ mThread->join();
+
+ close(mEventFd);
+ close(mIdleFd);
+}
+
+void InteractionHandler::PerfLock() {
+ ALOGV("%s: acquiring perf lock", __func__);
+ if (!mHintManager->DoHint("INTERACTION")) {
+ ALOGE("%s: do hint INTERACTION failed", __func__);
+ }
+ ATRACE_INT("interaction_lock", 1);
+}
+
+void InteractionHandler::PerfRel() {
+ ALOGV("%s: releasing perf lock", __func__);
+ if (!mHintManager->EndHint("INTERACTION")) {
+ ALOGE("%s: end hint INTERACTION failed", __func__);
+ }
+ ATRACE_INT("interaction_lock", 0);
+}
+
+long long InteractionHandler::CalcTimespecDiffMs(struct timespec start,
+ struct timespec end) {
+ long long diff_in_us = 0;
+ diff_in_us += (end.tv_sec - start.tv_sec) * MSINSEC;
+ diff_in_us += (end.tv_nsec - start.tv_nsec) / USINMS;
+ return diff_in_us;
+}
+
+void InteractionHandler::Acquire(int32_t duration) {
+ ATRACE_CALL();
+
+ std::lock_guard<std::mutex> lk(mLock);
+ if (mState == INTERACTION_STATE_UNINITIALIZED) {
+ ALOGW("%s: called while uninitialized", __func__);
+ return;
+ }
+
+ int inputDuration = duration + 650;
+ int finalDuration;
+ if (inputDuration > mMaxDurationMs)
+ finalDuration = mMaxDurationMs;
+ else if (inputDuration > mMinDurationMs)
+ finalDuration = inputDuration;
+ else
+ finalDuration = mMinDurationMs;
+
+ struct timespec cur_timespec;
+ clock_gettime(CLOCK_MONOTONIC, &cur_timespec);
+ if (mState != INTERACTION_STATE_IDLE && finalDuration <= mDurationMs) {
+ long long elapsed_time = CalcTimespecDiffMs(mLastTimespec, cur_timespec);
+ // don't hint if previous hint's duration covers this hint's duration
+ if (elapsed_time <= (mDurationMs - finalDuration)) {
+ ALOGV("%s: Previous duration (%d) cover this (%d) elapsed: %lld",
+ __func__, mDurationMs, finalDuration, elapsed_time);
+ return;
+ }
+ }
+ mLastTimespec = cur_timespec;
+ mDurationMs = finalDuration;
+
+ ALOGV("%s: input: %d final duration: %d", __func__,
+ duration, finalDuration);
+
+ if (mState == INTERACTION_STATE_WAITING)
+ AbortWaitLocked();
+ else if (mState == INTERACTION_STATE_IDLE)
+ PerfLock();
+
+ mState = INTERACTION_STATE_INTERACTION;
+ mCond.notify_one();
+}
+
+void InteractionHandler::Release() {
+ std::lock_guard<std::mutex> lk(mLock);
+ if (mState == INTERACTION_STATE_WAITING) {
+ ATRACE_CALL();
+ PerfRel();
+ mState = INTERACTION_STATE_IDLE;
+ } else {
+ // clear any wait aborts pending in event fd
+ uint64_t val;
+ ssize_t ret = read(mEventFd, &val, sizeof(val));
+
+ ALOGW_IF(ret < 0, "%s: failed to clear eventfd (%zd, %d)",
+ __func__, ret, errno);
+ }
+}
+
+// should be called while locked
+void InteractionHandler::AbortWaitLocked() {
+ uint64_t val = 1;
+ ssize_t ret = write(mEventFd, &val, sizeof(val));
+ if (ret != sizeof(val))
+ ALOGW("Unable to write to event fd (%zd)", ret);
+}
+
+void InteractionHandler::WaitForIdle(int32_t wait_ms, int32_t timeout_ms) {
+ char data[MAX_LENGTH];
+ ssize_t ret;
+ struct pollfd pfd[2];
+
+ ATRACE_CALL();
+
+ ALOGV("%s: wait:%d timeout:%d", __func__, wait_ms, timeout_ms);
+
+ pfd[0].fd = mEventFd;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = mIdleFd;
+ pfd[1].events = POLLPRI | POLLERR;
+
+ ret = poll(pfd, 1, wait_ms);
+ if (ret > 0) {
+ ALOGV("%s: wait aborted", __func__);
+ return;
+ } else if (ret < 0) {
+ ALOGE("%s: error in poll while waiting", __func__);
+ return;
+ }
+
+ ret = pread(mIdleFd, data, sizeof(data), 0);
+ if (!ret) {
+ ALOGE("%s: Unexpected EOF!", __func__);
+ return;
+ }
+
+ if (!strncmp(data, "idle", 4)) {
+ ALOGV("%s: already idle", __func__);
+ return;
+ }
+
+ ret = poll(pfd, 2, timeout_ms);
+ if (ret < 0)
+ ALOGE("%s: Error on waiting for idle (%zd)", __func__, ret);
+ else if (ret == 0)
+ ALOGV("%s: timed out waiting for idle", __func__);
+ else if (pfd[0].revents)
+ ALOGV("%s: wait for idle aborted", __func__);
+ else if (pfd[1].revents)
+ ALOGV("%s: idle detected", __func__);
+}
+
+void InteractionHandler::Routine() {
+ std::unique_lock<std::mutex> lk(mLock, std::defer_lock);
+
+ while (true) {
+ lk.lock();
+ mCond.wait(lk, [&] { return mState != INTERACTION_STATE_IDLE; });
+ if (mState == INTERACTION_STATE_UNINITIALIZED)
+ return;
+ mState = INTERACTION_STATE_WAITING;
+ lk.unlock();
+
+ WaitForIdle(mWaitMs, mDurationMs);
+ Release();
+ }
+}
diff --git a/power-libperfmgr/InteractionHandler.h b/power-libperfmgr/InteractionHandler.h
new file mode 100644
index 0000000..893c72f
--- /dev/null
+++ b/power-libperfmgr/InteractionHandler.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INTERACTIONHANDLER_H
+#define INTERACTIONHANDLER_H
+
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+#include <perfmgr/HintManager.h>
+
+using ::android::perfmgr::HintManager;
+
+enum interaction_state {
+ INTERACTION_STATE_UNINITIALIZED,
+ INTERACTION_STATE_IDLE,
+ INTERACTION_STATE_INTERACTION,
+ INTERACTION_STATE_WAITING,
+};
+
+struct InteractionHandler {
+ InteractionHandler(std::shared_ptr<HintManager> const & hint_manager);
+ ~InteractionHandler();
+ bool Init();
+ void Exit();
+ void Acquire(int32_t duration);
+
+ private:
+ void Release();
+ void WaitForIdle(int32_t wait_ms, int32_t timeout_ms);
+ void AbortWaitLocked();
+ void Routine();
+
+ void PerfLock();
+ void PerfRel();
+
+ long long CalcTimespecDiffMs(struct timespec start, struct timespec end);
+
+ enum interaction_state mState;
+
+ int mIdleFd;
+ int mEventFd;
+
+ int32_t mWaitMs;
+ int32_t mMinDurationMs;
+ int32_t mMaxDurationMs;
+ int32_t mDurationMs;
+
+ struct timespec mLastTimespec;
+
+ std::unique_ptr<std::thread> mThread;
+ std::mutex mLock;
+ std::condition_variable mCond;
+ std::shared_ptr<HintManager> mHintManager;
+};
+
+#endif //INTERACTIONHANDLER_H
diff --git a/power-libperfmgr/Power.cpp b/power-libperfmgr/Power.cpp
new file mode 100644
index 0000000..50608d5
--- /dev/null
+++ b/power-libperfmgr/Power.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.power@1.2-service.wahoo-libperfmgr"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <utils/Log.h>
+
+#include "Power.h"
+
+#include "power-helper.h"
+
+/* RPM runs at 19.2Mhz. Divide by 19200 for msec */
+#define RPM_CLK 19200
+
+extern struct stat_pair rpm_stat_map[];
+
+namespace android {
+namespace hardware {
+namespace power {
+namespace V1_2 {
+namespace implementation {
+
+using ::android::hardware::power::V1_0::Feature;
+using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
+using ::android::hardware::power::V1_0::Status;
+using ::android::hardware::power::V1_1::PowerStateSubsystem;
+using ::android::hardware::power::V1_1::PowerStateSubsystemSleepState;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+Power::Power() :
+ mHintManager(HintManager::GetFromJSON("/vendor/etc/powerhint.json")),
+ mInteractionHandler(mHintManager),
+ mVRModeOn(false),
+ mSustainedPerfModeOn(false),
+ mEncoderModeOn(false) {
+ mInteractionHandler.Init();
+}
+
+// Methods from ::android::hardware::power::V1_0::IPower follow.
+Return<void> Power::setInteractive(bool /* interactive */) {
+ return Void();
+}
+
+Return<void> Power::powerHint(PowerHint_1_0 hint, int32_t data) {
+ if (!isSupportedGovernor()) {
+ return Void();
+ }
+
+ switch(hint) {
+ case PowerHint_1_0::INTERACTION:
+ if (mVRModeOn || mSustainedPerfModeOn) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ } else {
+ mInteractionHandler.Acquire(data);
+ }
+ break;
+ case PowerHint_1_0::VIDEO_ENCODE:
+ if (mVRModeOn || mSustainedPerfModeOn) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ } else {
+ if (data) {
+ // Hint until canceled
+ mHintManager->DoHint("VIDEO_ENCODE");
+ ALOGD("VIDEO_ENCODE ON");
+ mEncoderModeOn = true;
+ } else {
+ mHintManager->EndHint("VIDEO_ENCODE");
+ ALOGD("VIDEO_ENCODE OFF");
+ mEncoderModeOn = false;
+ }
+ }
+ break;
+ case PowerHint_1_0::SUSTAINED_PERFORMANCE:
+ if (data && !mSustainedPerfModeOn) {
+ if (!mVRModeOn) { // Sustained mode only.
+ mHintManager->DoHint("SUSTAINED_PERFORMANCE");
+ } else { // Sustained + VR mode.
+ mHintManager->EndHint("VR_MODE");
+ mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
+ }
+ mSustainedPerfModeOn = true;
+ } else if (!data && mSustainedPerfModeOn) {
+ mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
+ mHintManager->EndHint("SUSTAINED_PERFORMANCE");
+ if (mVRModeOn) { // Switch back to VR Mode.
+ mHintManager->DoHint("VR_MODE");
+ }
+ mSustainedPerfModeOn = false;
+ }
+ break;
+ case PowerHint_1_0::VR_MODE:
+ if (data && !mVRModeOn) {
+ if (!mSustainedPerfModeOn) { // VR mode only.
+ mHintManager->DoHint("VR_MODE");
+ } else { // Sustained + VR mode.
+ mHintManager->EndHint("SUSTAINED_PERFORMANCE");
+ mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
+ }
+ mVRModeOn = true;
+ } else if (!data && mVRModeOn) {
+ mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
+ mHintManager->EndHint("VR_MODE");
+ if (mSustainedPerfModeOn) { // Switch back to sustained Mode.
+ mHintManager->DoHint("SUSTAINED_PERFORMANCE");
+ }
+ mVRModeOn = false;
+ }
+ break;
+ case PowerHint_1_0::LAUNCH:
+ if (mVRModeOn || mSustainedPerfModeOn) {
+ ALOGV("%s: ignoring due to other active perf hints", __func__);
+ } else {
+ if (data) {
+ // Hint until canceled
+ mHintManager->DoHint("LAUNCH");
+ ALOGD("LAUNCH ON");
+ } else {
+ mHintManager->EndHint("LAUNCH");
+ ALOGD("LAUNCH OFF");
+ }
+ }
+ break;
+ default:
+ break;
+
+ }
+ return Void();
+}
+
+Return<void> Power::setFeature(Feature /*feature*/, bool /*activate*/) {
+ //Nothing to do
+ return Void();
+}
+
+Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
+
+ hidl_vec<PowerStatePlatformSleepState> states;
+ uint64_t stats[MAX_PLATFORM_STATS * MAX_RPM_PARAMS] = {0};
+ uint64_t *values;
+ struct PowerStatePlatformSleepState *state;
+ int ret;
+
+ states.resize(PLATFORM_SLEEP_MODES_COUNT);
+
+ ret = extract_platform_stats(stats);
+ if (ret != 0) {
+ states.resize(0);
+ goto done;
+ }
+
+ /* Update statistics for XO_shutdown */
+ state = &states[RPM_MODE_XO];
+ state->name = "XO_shutdown";
+ values = stats + (RPM_MODE_XO * MAX_RPM_PARAMS);
+
+ state->residencyInMsecSinceBoot = values[1];
+ state->totalTransitions = values[0];
+ state->supportedOnlyInSuspend = false;
+ state->voters.resize(XO_VOTERS);
+ for(size_t i = 0; i < XO_VOTERS; i++) {
+ int voter = static_cast<int>(i + XO_VOTERS_START);
+ state->voters[i].name = rpm_stat_map[voter].label;
+ values = stats + (voter * MAX_RPM_PARAMS);
+ state->voters[i].totalTimeInMsecVotedForSinceBoot = values[0] / RPM_CLK;
+ state->voters[i].totalNumberOfTimesVotedSinceBoot = values[1];
+ }
+
+ /* Update statistics for VMIN state */
+ state = &states[RPM_MODE_VMIN];
+ state->name = "VMIN";
+ values = stats + (RPM_MODE_VMIN * MAX_RPM_PARAMS);
+
+ state->residencyInMsecSinceBoot = values[1];
+ state->totalTransitions = values[0];
+ state->supportedOnlyInSuspend = false;
+ state->voters.resize(VMIN_VOTERS);
+ //Note: No filling of state voters since VMIN_VOTERS = 0
+
+done:
+ _hidl_cb(states, Status::SUCCESS);
+ return Void();
+}
+
+static int get_wlan_low_power_stats(struct PowerStateSubsystem &subsystem) {
+
+ uint64_t stats[WLAN_POWER_PARAMS_COUNT] = {0};
+ struct PowerStateSubsystemSleepState *state;
+ int ret;
+
+ ret = extract_wlan_stats(stats);
+ if (ret)
+ return ret;
+
+ subsystem.name = "wlan";
+ subsystem.states.resize(WLAN_STATES_COUNT);
+
+ /* Update statistics for Active State */
+ state = &subsystem.states[WLAN_STATE_ACTIVE];
+ state->name = "Active";
+ state->residencyInMsecSinceBoot = stats[CUMULATIVE_TOTAL_ON_TIME_MS];
+ state->totalTransitions = stats[DEEP_SLEEP_ENTER_COUNTER];
+ state->lastEntryTimestampMs = 0; //FIXME need a new value from Qcom
+ state->supportedOnlyInSuspend = false;
+
+ /* Update statistics for Deep-Sleep state */
+ state = &subsystem.states[WLAN_STATE_DEEP_SLEEP];
+ state->name = "Deep-Sleep";
+ state->residencyInMsecSinceBoot = stats[CUMULATIVE_SLEEP_TIME_MS];
+ state->totalTransitions = stats[DEEP_SLEEP_ENTER_COUNTER];
+ state->lastEntryTimestampMs = stats[LAST_DEEP_SLEEP_ENTER_TSTAMP_MS];
+ state->supportedOnlyInSuspend = false;
+
+ return 0;
+}
+
+// Methods from ::android::hardware::power::V1_1::IPower follow.
+Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
+
+ hidl_vec<PowerStateSubsystem> subsystems;
+ int ret;
+
+ subsystems.resize(SUBSYSTEM_COUNT);
+
+ //We currently have only one Subsystem for WLAN
+ ret = get_wlan_low_power_stats(subsystems[SUBSYSTEM_WLAN]);
+ if (ret != 0)
+ goto done;
+
+ //Add query for other subsystems here
+
+done:
+ _hidl_cb(subsystems, Status::SUCCESS);
+ return Void();
+}
+
+bool Power::isSupportedGovernor() {
+ std::string buf;
+ if (android::base::ReadFileToString("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", &buf)) {
+ buf = android::base::Trim(buf);
+ }
+ // Only support EAS 1.2, legacy EAS
+ if (buf == "schedutil" || buf == "sched") {
+ return true;
+ } else {
+ LOG(ERROR) << "Governor not supported by powerHAL, skipping";
+ return false;
+ }
+}
+
+Return<void> Power::powerHintAsync(PowerHint_1_0 hint, int32_t data) {
+ // just call the normal power hint in this oneway function
+ return powerHint(hint, data);
+}
+
+// Methods from ::android::hardware::power::V1_2::IPower follow.
+Return<void> Power::powerHintAsync_1_2(PowerHint_1_2 hint, int32_t data) {
+ if (!isSupportedGovernor()) {
+ return Void();
+ }
+
+ switch(hint) {
+ case PowerHint_1_2::AUDIO_LOW_LATENCY:
+ if (data) {
+ // Hint until canceled
+ mHintManager->DoHint("AUDIO_LOW_LATENCY");
+ ALOGD("AUDIO LOW LATENCY ON");
+ } else {
+ mHintManager->EndHint("AUDIO_LOW_LATENCY");
+ ALOGD("AUDIO LOW LATENCY OFF");
+ }
+ break;
+ case PowerHint_1_2::AUDIO_STREAMING:
+ if (data) {
+ // Hint until canceled
+ mHintManager->DoHint("AUDIO_STREAMING");
+ ALOGD("AUDIO LOW LATENCY ON");
+ } else {
+ mHintManager->EndHint("AUDIO_STREAMING");
+ ALOGD("AUDIO LOW LATENCY OFF");
+ }
+ break;
+ case PowerHint_1_2::CAMERA_LAUNCH:
+ if (data > 0) {
+ mHintManager->DoHint("CAMERA_LAUNCH", std::chrono::milliseconds(data));
+ ALOGD("CAMERA LAUNCH ON: %d MS", data);
+ // boosts 2.5s for launching
+ mHintManager->DoHint("LAUNCH", std::chrono::milliseconds(2500));
+ } else if (data == 0) {
+ mHintManager->EndHint("CAMERA_LAUNCH");
+ ALOGD("CAMERA LAUNCH OFF");
+ } else {
+ ALOGE("CAMERA LAUNCH INVALID DATA: %d", data);
+ }
+ break;
+ case PowerHint_1_2::CAMERA_STREAMING:
+ if (data > 0) {
+ mHintManager->DoHint("CAMERA_STREAMING", std::chrono::milliseconds(data));
+ ALOGD("CAMERA STREAMING ON: %d MS", data);
+ } else if (data == 0) {
+ mHintManager->EndHint("CAMERA_STREAMING");
+ ALOGD("CAMERA STREAMING OFF");
+ } else {
+ ALOGE("CAMERA STREAMING INVALID DATA: %d", data);
+ }
+ break;
+ case PowerHint_1_2::CAMERA_SHOT:
+ if (data > 0) {
+ mHintManager->DoHint("CAMERA_SHOT", std::chrono::milliseconds(data));
+ ALOGD("CAMERA SHOT ON: %d MS", data);
+ } else if (data == 0) {
+ mHintManager->EndHint("CAMERA_SHOT");
+ ALOGD("CAMERA SHOT OFF");
+ } else {
+ ALOGE("CAMERA SHOT INVALID DATA: %d", data);
+ }
+ break;
+ default:
+ return powerHint(static_cast<PowerHint_1_0>(hint), data);
+ }
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_2
+} // namespace power
+} // namespace hardware
+} // namespace android
diff --git a/power-libperfmgr/Power.h b/power-libperfmgr/Power.h
new file mode 100644
index 0000000..2d84fa5
--- /dev/null
+++ b/power-libperfmgr/Power.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_POWER_V1_2_POWER_H
+#define ANDROID_HARDWARE_POWER_V1_2_POWER_H
+
+#include <atomic>
+
+#include <android/hardware/power/1.2/IPower.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include "InteractionHandler.h"
+
+namespace android {
+namespace hardware {
+namespace power {
+namespace V1_2 {
+namespace implementation {
+
+using ::android::hardware::power::V1_0::Feature;
+using ::android::hardware::power::V1_2::IPower;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::InteractionHandler;
+using PowerHint_1_0 = ::android::hardware::power::V1_0::PowerHint;
+using PowerHint_1_2 = ::android::hardware::power::V1_2::PowerHint;
+using ::android::perfmgr::HintManager;
+
+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;
+
+ // Methods from ::android::hidl::base::V1_0::IBase follow.
+
+ private:
+ std::shared_ptr<HintManager> mHintManager;
+ InteractionHandler mInteractionHandler;
+ static bool isSupportedGovernor();
+ std::atomic<bool> mVRModeOn;
+ std::atomic<bool> mSustainedPerfModeOn;
+ std::atomic<bool> mEncoderModeOn;
+};
+
+} // namespace implementation
+} // namespace V1_2
+} // namespace power
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_POWER_V1_2_POWER_H
diff --git a/power-libperfmgr/android.hardware.power@1.2-service.wahoo-libperfmgr.rc b/power-libperfmgr/android.hardware.power@1.2-service.wahoo-libperfmgr.rc
new file mode 100644
index 0000000..65c43b6
--- /dev/null
+++ b/power-libperfmgr/android.hardware.power@1.2-service.wahoo-libperfmgr.rc
@@ -0,0 +1,4 @@
+service vendor.power-hal-1-2 /vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr
+ class hal
+ user system
+ group system
diff --git a/power-libperfmgr/power-helper.c b/power-libperfmgr/power-helper.c
new file mode 100644
index 0000000..e355710
--- /dev/null
+++ b/power-libperfmgr/power-helper.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2012-2013, 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
+#define LOG_TAG "android.hardware.power@1.2-service.wahoo-libperfmgr"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include <log/log.h>
+
+#include "power-helper.h"
+
+#ifndef RPM_SYSTEM_STAT
+#define RPM_SYSTEM_STAT "/d/system_stats"
+#endif
+
+#ifndef WLAN_POWER_STAT
+#define WLAN_POWER_STAT "/d/wlan0/power_stats"
+#endif
+
+#define ARRAY_SIZE(x) (sizeof((x))/sizeof((x)[0]))
+#define LINE_SIZE 128
+
+const char *rpm_stat_params[MAX_RPM_PARAMS] = {
+ "count",
+ "actual last sleep(msec)",
+};
+
+const char *master_stat_params[MAX_RPM_PARAMS] = {
+ "Accumulated XO duration",
+ "XO Count",
+};
+
+struct stat_pair rpm_stat_map[] = {
+ { RPM_MODE_XO, "RPM Mode:vlow", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
+ { RPM_MODE_VMIN, "RPM Mode:vmin", rpm_stat_params, ARRAY_SIZE(rpm_stat_params) },
+ { VOTER_APSS, "APSS", master_stat_params, ARRAY_SIZE(master_stat_params) },
+ { VOTER_MPSS, "MPSS", master_stat_params, ARRAY_SIZE(master_stat_params) },
+ { VOTER_ADSP, "ADSP", master_stat_params, ARRAY_SIZE(master_stat_params) },
+ { VOTER_SLPI, "SLPI", master_stat_params, ARRAY_SIZE(master_stat_params) },
+};
+
+
+const char *wlan_power_stat_params[] = {
+ "cumulative_sleep_time_ms",
+ "cumulative_total_on_time_ms",
+ "deep_sleep_enter_counter",
+ "last_deep_sleep_enter_tstamp_ms"
+};
+
+struct stat_pair wlan_stat_map[] = {
+ { WLAN_POWER_DEBUG_STATS, "POWER DEBUG STATS", wlan_power_stat_params, ARRAY_SIZE(wlan_power_stat_params) },
+};
+
+static int parse_stats(const char **params, size_t params_size,
+ uint64_t *list, FILE *fp) {
+ ssize_t nread;
+ size_t len = LINE_SIZE;
+ char *line;
+ size_t params_read = 0;
+ size_t i;
+
+ line = malloc(len);
+ if (!line) {
+ ALOGE("%s: no memory to hold line", __func__);
+ return -ENOMEM;
+ }
+
+ while ((params_read < params_size) &&
+ (nread = getline(&line, &len, fp) > 0)) {
+ char *key = line + strspn(line, " \t");
+ char *value = strchr(key, ':');
+ if (!value || (value > (line + len)))
+ continue;
+ *value++ = '\0';
+
+ for (i = 0; i < params_size; i++) {
+ if (!strcmp(key, params[i])) {
+ list[i] = strtoull(value, NULL, 0);
+ params_read++;
+ break;
+ }
+ }
+ }
+ free(line);
+
+ return 0;
+}
+
+
+static int extract_stats(uint64_t *list, char *file,
+ struct stat_pair *map, size_t map_size) {
+ FILE *fp;
+ ssize_t read;
+ size_t len = LINE_SIZE;
+ char *line;
+ size_t i, stats_read = 0;
+ int ret = 0;
+
+ fp = fopen(file, "re");
+ if (fp == NULL) {
+ ALOGE("%s: failed to open: %s Error = %s", __func__, file, strerror(errno));
+ return -errno;
+ }
+
+ line = malloc(len);
+ if (!line) {
+ ALOGE("%s: no memory to hold line", __func__);
+ fclose(fp);
+ return -ENOMEM;
+ }
+
+ while ((stats_read < map_size) && (read = getline(&line, &len, fp) != -1)) {
+ size_t begin = strspn(line, " \t");
+
+ for (i = 0; i < map_size; i++) {
+ if (!strncmp(line + begin, map[i].label, strlen(map[i].label))) {
+ stats_read++;
+ break;
+ }
+ }
+
+ if (i == map_size)
+ continue;
+
+ ret = parse_stats(map[i].parameters, map[i].num_parameters,
+ &list[map[i].stat * MAX_RPM_PARAMS], fp);
+ if (ret < 0)
+ break;
+ }
+ free(line);
+ fclose(fp);
+
+ return ret;
+}
+
+int extract_platform_stats(uint64_t *list) {
+ return extract_stats(list, RPM_SYSTEM_STAT, rpm_stat_map, ARRAY_SIZE(rpm_stat_map));
+}
+
+int extract_wlan_stats(uint64_t *list) {
+ return extract_stats(list, WLAN_POWER_STAT, wlan_stat_map, ARRAY_SIZE(wlan_stat_map));
+}
diff --git a/power-libperfmgr/power-helper.h b/power-libperfmgr/power-helper.h
new file mode 100644
index 0000000..6064646
--- /dev/null
+++ b/power-libperfmgr/power-helper.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 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
+ * 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 __POWER_HELPER_H__
+#define __POWER_HELPER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum stats_type {
+ //Platform Stats
+ RPM_MODE_XO = 0,
+ RPM_MODE_VMIN,
+ RPM_MODE_MAX,
+ XO_VOTERS_START = RPM_MODE_MAX,
+ VOTER_APSS = XO_VOTERS_START,
+ VOTER_MPSS,
+ VOTER_ADSP,
+ VOTER_SLPI,
+ MAX_PLATFORM_STATS,
+
+ //WLAN Stats
+ WLAN_POWER_DEBUG_STATS = 0,
+ MAX_WLAN_STATS,
+};
+
+enum subsystem_type {
+ SUBSYSTEM_WLAN = 0,
+
+ //Don't add any lines after this line
+ SUBSYSTEM_COUNT
+};
+
+enum wlan_sleep_states {
+ WLAN_STATE_ACTIVE = 0,
+ WLAN_STATE_DEEP_SLEEP,
+
+ //Don't add any lines after this line
+ WLAN_STATES_COUNT
+};
+
+enum wlan_power_params {
+ CUMULATIVE_SLEEP_TIME_MS = 0,
+ CUMULATIVE_TOTAL_ON_TIME_MS,
+ DEEP_SLEEP_ENTER_COUNTER,
+ LAST_DEEP_SLEEP_ENTER_TSTAMP_MS,
+
+ //Don't add any lines after this line
+ WLAN_POWER_PARAMS_COUNT
+};
+
+
+#define PLATFORM_SLEEP_MODES_COUNT RPM_MODE_MAX
+
+#define MAX_RPM_PARAMS 2
+#define XO_VOTERS (MAX_PLATFORM_STATS - XO_VOTERS_START)
+#define VMIN_VOTERS 0
+
+struct stat_pair {
+ enum stats_type stat;
+ const char *label;
+ const char **parameters;
+ size_t num_parameters;
+};
+
+int extract_platform_stats(uint64_t *list);
+int extract_wlan_stats(uint64_t *list);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__POWER_HELPER_H__
diff --git a/power-libperfmgr/service.cpp b/power-libperfmgr/service.cpp
new file mode 100644
index 0000000..77fb139
--- /dev/null
+++ b/power-libperfmgr/service.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.power@1.2-service.wahoo-libperfmgr"
+
+#include <android/log.h>
+#include <hidl/HidlTransportSupport.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 for Wahoo is starting.");
+
+ service = new Power();
+ if (service == nullptr) {
+ ALOGE("Can not create an instance of Power HAL Iface, exiting.");
+
+ goto shutdown;
+ }
+
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+ status = service->registerAsService();
+ if (status != OK) {
+ ALOGE("Could not register service for Power HAL Iface (%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;
+}
diff --git a/powerhint.json b/powerhint.json
new file mode 100755
index 0000000..b641df3
--- /dev/null
+++ b/powerhint.json
@@ -0,0 +1,431 @@
+{
+ "Nodes": [
+ {
+ "Name": "CPULittleClusterMinFreq",
+ "Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq",
+ "Values": [
+ "1900800",
+ "1555200",
+ "1512000",
+ "1478400",
+ "1134000",
+ "384000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPULittleClusterMaxFreq",
+ "Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq",
+ "Values": [
+ "1555200",
+ "1478400",
+ "1248000",
+ "1900800"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBigClusterMinFreq",
+ "Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq",
+ "Values": [
+ "2457600",
+ "1574400",
+ "1420800",
+ "1344000",
+ "1132800",
+ "300000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBigClusterMaxFreq",
+ "Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_max_freq",
+ "Values": [
+ "1132800",
+ "1267200",
+ "1344000",
+ "1574400",
+ "1958400",
+ "2457600"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUMinFreq",
+ "Path": "/sys/class/kgsl/kgsl-3d0/devfreq/min_freq",
+ "Values": [
+ "515000000",
+ "414000000",
+ "257000000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUMaxFreq",
+ "Path": "/sys/class/kgsl/kgsl-3d0/devfreq/max_freq",
+ "Values": [
+ "342000000",
+ "414000000",
+ "515000000",
+ "710000000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUBusMinFreq",
+ "Path": "/sys/class/devfreq/soc:qcom,gpubw/min_freq",
+ "Values": [
+ "11863",
+ "7759",
+ "0"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "TASchedtuneBoost",
+ "Path": "/dev/stune/top-app/schedtune.boost",
+ "Values": [
+ "50",
+ "10"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWHystTriggerCount",
+ "Path": "/sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/bw_hwmon/hyst_trigger_count",
+ "Values": [
+ "0",
+ "3"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWHistMemory",
+ "Path": "/sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/bw_hwmon/hist_memory",
+ "Values": [
+ "0",
+ "20"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWHystLength",
+ "Path": "/sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/bw_hwmon/hyst_length",
+ "Values": [
+ "0",
+ "10"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWMinFreq",
+ "Path": "/sys/devices/soc/soc:qcom,cpubw/devfreq/soc:qcom,cpubw/min_freq",
+ "Values": [
+ "13763",
+ "5195",
+ "1525",
+ "762"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "PMQoSCpuDmaLatency",
+ "Path": "/dev/cpu_dma_latency",
+ "Values": [
+ "44",
+ "100"
+ ],
+ "HoldFd": true
+ }
+ ],
+ "Actions": [
+ {
+ "PowerHint": "VIDEO_ENCODE",
+ "Node": "CPUBigClusterMaxFreq",
+ "ValueIndex": 4,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "CPUBigClusterMaxFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "CPULittleClusterMaxFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "GPUMaxFreq",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_MODE",
+ "Node": "CPUBigClusterMaxFreq",
+ "ValueIndex": 3,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_MODE",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_MODE",
+ "Node": "CPULittleClusterMaxFreq",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_MODE",
+ "Node": "CPULittleClusterMinFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_MODE",
+ "Node": "GPUMaxFreq",
+ "ValueIndex": 2,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_MODE",
+ "Node": "GPUMinFreq",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_MODE",
+ "Node": "GPUBusMinFreq",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_SUSTAINED_PERFORMANCE",
+ "Node": "CPUBigClusterMaxFreq",
+ "ValueIndex": 2,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_SUSTAINED_PERFORMANCE",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 3,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_SUSTAINED_PERFORMANCE",
+ "Node": "CPULittleClusterMaxFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_SUSTAINED_PERFORMANCE",
+ "Node": "CPULittleClusterMinFreq",
+ "ValueIndex": 3,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_SUSTAINED_PERFORMANCE",
+ "Node": "GPUMaxFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_SUSTAINED_PERFORMANCE",
+ "Node": "GPUMaxFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "VR_SUSTAINED_PERFORMANCE",
+ "Node": "GPUBusMinFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 4,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPULittleClusterMinFreq",
+ "ValueIndex": 4,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "TASchedtuneBoost",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWHystTriggerCount",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWHystLength",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWHistMemory",
+ "ValueIndex": 0,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWMinFreq",
+ "ValueIndex": 1,
+ "Duration": 0
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 5000
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPULittleClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 5000
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "PMQoSCpuDmaLatency",
+ "ValueIndex": 0,
+ "Duration": 5000
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWHystTriggerCount",
+ "ValueIndex": 0,
+ "Duration": 5000
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWHystLength",
+ "ValueIndex": 0,
+ "Duration": 5000
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWHistMemory",
+ "ValueIndex": 0,
+ "Duration": 5000
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWMinFreq",
+ "ValueIndex": 0,
+ "Duration": 5000
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPULittleClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "PMQoSCpuDmaLatency",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "CPULittleClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "PMQoSCpuDmaLatency",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPULittleClusterMinFreq",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "PMQoSCpuDmaLatency",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBWHystTriggerCount",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBWHystLength",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBWHistMemory",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBWMinFreq",
+ "ValueIndex": 0,
+ "Duration": 1000
+ },
+ {
+ "PowerHint": "AUDIO_STREAMING",
+ "Node": "CPUBigClusterMinFreq",
+ "ValueIndex": 2,
+ "Duration": 2000
+ },
+ {
+ "PowerHint": "AUDIO_STREAMING",
+ "Node": "PMQoSCpuDmaLatency",
+ "ValueIndex": 0,
+ "Duration": 2000
+ },
+ {
+ "PowerHint": "AUDIO_LOW_LATENCY",
+ "Node": "PMQoSCpuDmaLatency",
+ "ValueIndex": 0,
+ "Duration": 0
+ }
+ ]
+}
diff --git a/sepolicy/vendor/file_contexts b/sepolicy/vendor/file_contexts
index 2af2d30..1183932 100644
--- a/sepolicy/vendor/file_contexts
+++ b/sepolicy/vendor/file_contexts
@@ -169,6 +169,7 @@
/vendor/bin/oemlock-bridge u:object_r:hal_bootctl_default_exec:s0
/vendor/bin/hw/android\.hardware\.usb@1\.1-service.wahoo u:object_r:hal_usb_default_exec:s0
/vendor/bin/hw/android\.hardware\.power@1\.2-service.wahoo u:object_r:hal_power_default_exec:s0
+/vendor/bin/hw/android\.hardware\.power@1\.2-service.wahoo-libperfmgr u:object_r:hal_power_default_exec:s0
/vendor/bin/hw/android\.hardware\.thermal@1\.0-service.wahoo u:object_r:hal_thermal_default_exec:s0
/vendor/bin/chre u:object_r:chre_exec:s0
/vendor/bin/time_daemon u:object_r:time_daemon_exec:s0
diff --git a/sepolicy/vendor/hal_camera.te b/sepolicy/vendor/hal_camera.te
index 38edfc3..587e078 100644
--- a/sepolicy/vendor/hal_camera.te
+++ b/sepolicy/vendor/hal_camera.te
@@ -1,7 +1,7 @@
# communicate with perfd
-allow hal_camera perfd:unix_stream_socket connectto;
-allow hal_camera perfd_socket:sock_file write;
-allow hal_camera perfd_socket:sock_file w_file_perms;
+dontaudit hal_camera perfd:unix_stream_socket connectto;
+dontaudit hal_camera perfd_socket:sock_file write;
+dontaudit hal_camera perfd_socket:sock_file w_file_perms;
allow hal_camera self:capability sys_nice;
diff --git a/sepolicy/vendor/hal_power_default.te b/sepolicy/vendor/hal_power_default.te
index b588634..3794e32 100644
--- a/sepolicy/vendor/hal_power_default.te
+++ b/sepolicy/vendor/hal_power_default.te
@@ -1,6 +1,3 @@
-allow hal_power_default perfd:unix_stream_socket connectto;
-allow hal_power_default perfd_socket:sock_file write;
-
allow hal_power_default sysfs_graphics:dir search;
allow hal_power_default sysfs_graphics:file r_file_perms;
@@ -8,3 +5,9 @@
allow hal_power_default debugfs_wlan:dir r_dir_perms;
allow hal_power_default debugfs_wlan:file r_file_perms;
+
+# To do powerhint on nodes defined in powerhint.json
+allow hal_power_default sysfs_msm_subsys:dir search;
+allow hal_power_default sysfs_msm_subsys:file w_file_perms;
+allow hal_power_default sysfs_devices_system_cpu:file w_file_perms;
+allow hal_power_default latency_device:chr_file w_file_perms;
diff --git a/sepolicy/vendor/perfd.te b/sepolicy/vendor/perfd.te
index fa99d15..950e1d6 100644
--- a/sepolicy/vendor/perfd.te
+++ b/sepolicy/vendor/perfd.te
@@ -2,31 +2,3 @@
type perfd_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(perfd)
-
-r_dir_file(perfd, sysfs_msm_subsys)
-
-# perfd uses kill(pid, 0) to determine if a process exists.
-# Determining if a process exists does not require the kill capability
-# since a permission denied indicates the process exists.
-dontaudit perfd self:capability kill;
-
-allow perfd mediacodec:process signull;
-allow perfd hal_power_default:process signull;
-
-allow perfd cgroup:file r_file_perms;
-allow perfd post_boot_prop:file r_file_perms;
-
-allow perfd proc:file rw_file_perms;
-allow perfd sysfs_clkscale:file r_file_perms;
-allow perfd sysfs_graphics:dir search;
-allow perfd sysfs_graphics:file r_file_perms;
-allow perfd sysfs_soc:dir search;
-allow perfd sysfs_soc:file r_file_perms;
-allow perfd sysfs_graphics:dir search;
-allow perfd sysfs_graphics:file r_file_perms;
-allow perfd sysfs_msm_subsys:file w_file_perms;
-allow perfd sysfs_devices_system_cpu:file w_file_perms;
-
-allow perfd perfd_socket:sock_file write;
-
-allow perfd latency_device:chr_file w_file_perms;