hidl: power: Kill legacy and libperfmgr power implementations

Everyone must switch to aidl now.

Change-Id: I9e812bf3f13dcdf40650c23dee3d5f33ad8fc79d
tirimbino
LuK1337 3 years ago committed by Bruno Martins
parent ae574f353d
commit ec9752f6e3
  1. 53
      hidl/power-libperfmgr/Android.bp
  2. 264
      hidl/power-libperfmgr/InteractionHandler.cpp
  3. 74
      hidl/power-libperfmgr/InteractionHandler.h
  4. 455
      hidl/power-libperfmgr/Power.cpp
  5. 114
      hidl/power-libperfmgr/Power.h
  6. 20
      hidl/power-libperfmgr/android.hardware.power@1.3-service.samsung-libperfmgr.rc
  7. 11
      hidl/power-libperfmgr/android.hardware.power@1.3-service.samsung.xml
  8. 448
      hidl/power-libperfmgr/powerhint.json.template
  9. 59
      hidl/power-libperfmgr/service.cpp
  10. 46
      hidl/power/Android.mk
  11. 247
      hidl/power/Power.cpp
  12. 82
      hidl/power/Power.h
  13. 4
      hidl/power/android.hardware.power@1.0-service.exynos.rc
  14. 42
      hidl/power/include/samsung_power.h
  15. 60
      hidl/power/service.cpp

@ -1,53 +0,0 @@
//
// 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.
soong_namespace {
imports: [
"hardware/google/pixel",
],
}
cc_library_headers {
name: "samsung_power_headers",
vendor_available: true,
export_include_dirs: ["."],
}
cc_binary {
name: "android.hardware.power@1.3-service.samsung-libperfmgr",
relative_install_path: "hw",
vintf_fragments: ["android.hardware.power@1.3-service.samsung.xml"],
init_rc: ["android.hardware.power@1.3-service.samsung-libperfmgr.rc"],
srcs: ["service.cpp", "Power.cpp", "InteractionHandler.cpp"],
cflags: [
"-Wall",
"-Werror",
],
shared_libs: [
"libbase",
"libhidlbase",
"liblog",
"libutils",
"libcutils",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
"android.hardware.power@1.2",
"android.hardware.power@1.3",
"libperfmgr",
"vendor.lineage.power@1.0",
],
proprietary: true,
}

@ -1,264 +0,0 @@
/*
* 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.3-service.samsung-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 <memory>
#include "InteractionHandler.h"
#define MAX_LENGTH 64
#define MSINSEC 1000L
#define USINMS 1000000L
static const std::vector<std::string> fb_idle_patch = {"/sys/class/drm/card0/device/idle_state",
"/sys/class/graphics/fb0/idle_state"};
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();
}
static int fb_idle_open(void) {
int fd;
for (auto &path : fb_idle_patch) {
fd = open(path.c_str(), O_RDONLY);
if (fd >= 0)
return fd;
}
ALOGE("Unable to open fb idle state path (%d)", errno);
return -1;
}
bool InteractionHandler::Init() {
std::lock_guard<std::mutex> lk(mLock);
if (mState != INTERACTION_STATE_UNINITIALIZED)
return true;
mIdleFd = fb_idle_open();
mEventFd = eventfd(0, EFD_NONBLOCK);
if (mEventFd < 0) {
ALOGE("Unable to create event fd (%d)", errno);
if (mIdleFd >= 0) {
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);
if (mIdleFd >= 0) {
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);
}
size_t InteractionHandler::CalcTimespecDiffMs(struct timespec start, struct timespec end) {
size_t 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) {
size_t 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__,
static_cast<int>(mDurationMs), static_cast<int>(finalDuration),
static_cast<long long>(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;
}
if (mIdleFd < 0) {
ret = poll(pfd, 1, timeout_ms);
if (ret > 0) {
ALOGV("%s: wait for duration aborted", __func__);
return;
} else if (ret < 0) {
ALOGE("%s: Error on waiting for duration (%zd)", __func__, ret);
return;
}
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();
}
}

@ -1,74 +0,0 @@
/*
* 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 POWER_LIBPERFMGR_INTERACTIONHANDLER_H_
#define POWER_LIBPERFMGR_INTERACTIONHANDLER_H_
#include <condition_variable>
#include <memory>
#include <mutex>
#include <string>
#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,
};
class InteractionHandler {
public:
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();
size_t 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 // POWER_LIBPERFMGR_INTERACTIONHANDLER_H_

@ -1,455 +0,0 @@
/*
* 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 ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#define LOG_TAG "android.hardware.power@1.3-service.samsung-libperfmgr"
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <mutex>
#include <utils/Log.h>
#include <utils/Trace.h>
#include "Power.h"
namespace android {
namespace hardware {
namespace power {
namespace V1_3 {
namespace implementation {
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::power::V1_0::Feature;
using ::android::hardware::power::V1_0::Status;
using namespace std::chrono_literals;
constexpr char kPowerHalStateProp[] = "vendor.powerhal.state";
constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio";
constexpr char kPowerHalInitProp[] = "vendor.powerhal.init";
constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering";
constexpr char kPowerHalProfileNumProp[] = "vendor.powerhal.perf_profiles";
constexpr char kPowerHalProfileProp[] = "vendor.powerhal.perf_profile";
constexpr char kPowerHalConfigPath[] = "/vendor/etc/powerhint.json";
Power::Power()
: mHintManager(nullptr),
mInteractionHandler(nullptr),
mVRModeOn(false),
mSustainedPerfModeOn(false),
mCameraStreamingMode(false),
mReady(false),
mDoubleTapEnabled(false),
mNumPerfProfiles(0),
mCurrentPerfProfile(PowerProfile::BALANCED) {
mInitThread = std::thread([this]() {
android::base::WaitForProperty(kPowerHalInitProp, "1");
mHintManager = HintManager::GetFromJSON(kPowerHalConfigPath);
if (!mHintManager) {
LOG(FATAL) << "Invalid config: " << kPowerHalConfigPath;
}
mInteractionHandler = std::make_unique<InteractionHandler>(mHintManager);
mInteractionHandler->Init();
std::string state = android::base::GetProperty(kPowerHalStateProp, "");
if (state == "CAMERA_STREAMING") {
ALOGI("Initialize with CAMERA_STREAMING on");
mHintManager->DoHint("CAMERA_STREAMING");
mCameraStreamingMode = true;
} else if (state == "SUSTAINED_PERFORMANCE") {
ALOGI("Initialize with SUSTAINED_PERFORMANCE on");
mHintManager->DoHint("SUSTAINED_PERFORMANCE");
mSustainedPerfModeOn = true;
} else if (state == "VR_MODE") {
ALOGI("Initialize with VR_MODE on");
mHintManager->DoHint("VR_MODE");
mVRModeOn = true;
} else if (state == "VR_SUSTAINED_PERFORMANCE") {
ALOGI("Initialize with SUSTAINED_PERFORMANCE and VR_MODE on");
mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
mSustainedPerfModeOn = true;
mVRModeOn = true;
} else {
ALOGI("Initialize PowerHAL");
}
state = android::base::GetProperty(kPowerHalAudioProp, "");
if (state == "AUDIO_LOW_LATENCY") {
ALOGI("Initialize with AUDIO_LOW_LATENCY on");
mHintManager->DoHint("AUDIO_LOW_LATENCY");
}
state = android::base::GetProperty(kPowerHalRenderingProp, "");
if (state == "EXPENSIVE_RENDERING") {
ALOGI("Initialize with EXPENSIVE_RENDERING on");
mHintManager->DoHint("EXPENSIVE_RENDERING");
}
state = android::base::GetProperty(kPowerHalProfileProp, "");
if (state == "POWER_SAVE") {
ALOGI("Initialize with POWER_SAVE profile");
setProfile(PowerProfile::POWER_SAVE);
mCurrentPerfProfile = PowerProfile::POWER_SAVE;
} else if (state == "BIAS_POWER_SAVE") {
ALOGI("Initialize with BIAS_POWER_SAVE profile");
setProfile(PowerProfile::BIAS_POWER_SAVE);
mCurrentPerfProfile = PowerProfile::BIAS_POWER_SAVE;
} else if (state == "BIAS_PERFORMANCE") {
ALOGI("Initialize with BIAS_PERFORMANCE profile");
setProfile(PowerProfile::BIAS_PERFORMANCE);
mCurrentPerfProfile = PowerProfile::BIAS_PERFORMANCE;
} else if (state == "HIGH_PERFORMANCE") {
ALOGI("Initialize with HIGH_PERFORMANCE profile");
setProfile(PowerProfile::HIGH_PERFORMANCE);
mCurrentPerfProfile = PowerProfile::HIGH_PERFORMANCE;
}
// Now start to take powerhint
mReady.store(true);
ALOGI("PowerHAL ready to process hints");
// setFeature() is called before loading powerhint.json
// is finished so update dt2w state here
switchDT2W(mDoubleTapEnabled);
});
mNumPerfProfiles = android::base::GetIntProperty(kPowerHalProfileNumProp, 0);
mInitThread.detach();
}
Return<void> Power::updateHint(const char *hint, bool enable) {
if (!mReady) {
return Void();
}
if (enable) {
mHintManager->DoHint(hint);
} else {
mHintManager->EndHint(hint);
}
return Void();
}
Return<void> Power::setProfile(PowerProfile profile) {
if (mCurrentPerfProfile == profile) {
return Void();
}
// End previous perf profile hints
switch (mCurrentPerfProfile) {
case PowerProfile::POWER_SAVE:
mHintManager->EndHint("PROFILE_POWER_SAVE");
break;
case PowerProfile::BIAS_POWER_SAVE:
mHintManager->EndHint("PROFILE_BIAS_POWER_SAVE");
break;
case PowerProfile::BIAS_PERFORMANCE:
mHintManager->EndHint("PROFILE_BIAS_PERFORMANCE");
break;
case PowerProfile::HIGH_PERFORMANCE:
mHintManager->EndHint("PROFILE_HIGH_PERFORMANCE");
break;
default:
break;
}
// Apply perf profile hints
switch (profile) {
case PowerProfile::POWER_SAVE:
mHintManager->DoHint("PROFILE_POWER_SAVE");
break;
case PowerProfile::BIAS_POWER_SAVE:
mHintManager->DoHint("PROFILE_BIAS_POWER_SAVE");
break;
case PowerProfile::BIAS_PERFORMANCE:
mHintManager->DoHint("PROFILE_BIAS_PERFORMANCE");
break;
case PowerProfile::HIGH_PERFORMANCE:
mHintManager->DoHint("PROFILE_HIGH_PERFORMANCE");
break;
default:
break;
}
return Void();
}
Return<void> Power::switchDT2W(bool dt2w) {
updateHint("DOUBLE_TAP_TO_WAKE", dt2w);
std::this_thread::sleep_for(20ms);
return Void();
}
// Methods from ::android::hardware::power::V1_0::IPower follow.
Return<void> Power::setInteractive(bool interactive) {
updateHint("NOT_INTERACTIVE", !interactive);
return Void();
}
Return<void> Power::powerHint(PowerHint_1_0 hint, int32_t data) {
if (!mReady) {
return Void();
}
ATRACE_INT(android::hardware::power::V1_0::toString(hint).c_str(), data);
ALOGD_IF(hint != PowerHint_1_0::INTERACTION, "%s: %d",
android::hardware::power::V1_0::toString(hint).c_str(), static_cast<int>(data));
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::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");
} else {
mHintManager->EndHint("LAUNCH");
}
}
break;
case PowerHint_1_0::LOW_POWER:
break;
default:
break;
}
return Void();
}
Return<void> Power::setFeature(Feature feature, bool activate) {
switch (feature) {
case Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
mDoubleTapEnabled = activate;
// this is only called when the device is booting up or
// the user changed the dt2w setting so the touchscreen
// should always be on when this is called
switchDT2W(activate);
break;
default:
break;
}
return Void();
}
Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
LOG(ERROR) << "getPlatformLowPowerStats not supported. Use IPowerStats HAL.";
_hidl_cb({}, Status::SUCCESS);
return Void();
}
// Methods from ::android::hardware::power::V1_1::IPower follow.
Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
LOG(ERROR) << "getSubsystemLowPowerStats not supported. Use IPowerStats HAL.";
_hidl_cb({}, Status::SUCCESS);
return Void();
}
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 (!mReady) {
return Void();
}
ATRACE_INT(android::hardware::power::V1_2::toString(hint).c_str(), data);
ALOGD_IF(hint >= PowerHint_1_2::AUDIO_STREAMING, "%s: %d",
android::hardware::power::V1_2::toString(hint).c_str(), static_cast<int>(data));
switch (hint) {
case PowerHint_1_2::AUDIO_LOW_LATENCY:
if (data) {
// Hint until canceled
mHintManager->DoHint("AUDIO_LOW_LATENCY");
} else {
mHintManager->EndHint("AUDIO_LOW_LATENCY");
}
break;
case PowerHint_1_2::AUDIO_STREAMING:
if (mVRModeOn || mSustainedPerfModeOn) {
ALOGV("%s: ignoring due to other active perf hints", __func__);
} else {
if (data) {
mHintManager->DoHint("AUDIO_STREAMING");
} else {
mHintManager->EndHint("AUDIO_STREAMING");
}
}
break;
case PowerHint_1_2::CAMERA_LAUNCH:
if (data > 0) {
mHintManager->DoHint("CAMERA_LAUNCH");
} else if (data == 0) {
mHintManager->EndHint("CAMERA_LAUNCH");
} else {
ALOGE("CAMERA LAUNCH INVALID DATA: %d", data);
}
break;
case PowerHint_1_2::CAMERA_STREAMING: {
if (data > 0) {
mHintManager->DoHint("CAMERA_STREAMING");
mCameraStreamingMode = true;
} else {
mHintManager->EndHint("CAMERA_STREAMING");
mCameraStreamingMode = false;
}
const auto prop = mCameraStreamingMode
? "CAMERA_STREAMING"
: "";
if (!android::base::SetProperty(kPowerHalStateProp, prop)) {
ALOGE("%s: could set powerHAL state %s property", __func__, prop);
}
break;
}
case PowerHint_1_2::CAMERA_SHOT:
if (data > 0) {
mHintManager->DoHint("CAMERA_SHOT", std::chrono::milliseconds(data));
} else if (data == 0) {
mHintManager->EndHint("CAMERA_SHOT");
} else {
ALOGE("CAMERA SHOT INVALID DATA: %d", data);
}
break;
default:
return powerHint(static_cast<PowerHint_1_0>(hint), data);
}
return Void();
}
// Methods from ::android::hardware::power::V1_3::IPower follow.
Return<void> Power::powerHintAsync_1_3(PowerHint_1_3 hint, int32_t data) {
if (!mReady) {
return Void();
}
switch (static_cast<LineagePowerHint>(hint)) {
case LineagePowerHint::SET_PROFILE:
setProfile(static_cast<PowerProfile>(data));
mCurrentPerfProfile = static_cast<PowerProfile>(data);
return Void();
default:
break;
}
if (hint == PowerHint_1_3::EXPENSIVE_RENDERING) {
ATRACE_INT(android::hardware::power::V1_3::toString(hint).c_str(), data);
if (mVRModeOn || mSustainedPerfModeOn) {
ALOGV("%s: ignoring due to other active perf hints", __func__);
} else {
if (data > 0) {
mHintManager->DoHint("EXPENSIVE_RENDERING");
} else {
mHintManager->EndHint("EXPENSIVE_RENDERING");
}
}
} else {
return powerHintAsync_1_2(static_cast<PowerHint_1_2>(hint), data);
}
return Void();
}
// Methods from ::vendor::lineage::power::V1_0::ILineagePower follow.
Return<int32_t> Power::getFeature(LineageFeature feature) {
switch (feature) {
case LineageFeature::SUPPORTED_PROFILES:
return mNumPerfProfiles;
default:
return -1;
}
}
constexpr const char *boolToString(bool b) {
return b ? "true" : "false";
}
Return<void> Power::debug(const hidl_handle &handle, const hidl_vec<hidl_string> &) {
if (handle != nullptr && handle->numFds >= 1 && mReady) {
int fd = handle->data[0];
std::string buf(android::base::StringPrintf(
"HintManager Running: %s\n"
"VRMode: %s\n"
"CameraStreamingMode: %s\n"
"SustainedPerformanceMode: %s\n",
boolToString(mHintManager->IsRunning()), boolToString(mVRModeOn),
boolToString(mCameraStreamingMode),
boolToString(mSustainedPerfModeOn)));
// Dump nodes through libperfmgr
mHintManager->DumpToFd(fd);
if (!android::base::WriteStringToFd(buf, fd)) {
PLOG(ERROR) << "Failed to dump state to fd";
}
fsync(fd);
}
return Void();
}
} // namespace implementation
} // namespace V1_3
} // namespace power
} // namespace hardware
} // namespace android

@ -1,114 +0,0 @@
/*
* 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 POWER_LIBPERFMGR_POWER_H_
#define POWER_LIBPERFMGR_POWER_H_
#include <atomic>
#include <memory>
#include <thread>
#include <android/hardware/power/1.3/IPower.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <perfmgr/HintManager.h>
#include "InteractionHandler.h"
#include <vendor/lineage/power/1.0/ILineagePower.h>
namespace android {
namespace hardware {
namespace power {
namespace V1_3 {
namespace implementation {
using ::InteractionHandler;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::power::V1_0::Feature;
using ::android::hardware::power::V1_3::IPower;
using PowerHint_1_0 = ::android::hardware::power::V1_0::PowerHint;
using PowerHint_1_2 = ::android::hardware::power::V1_2::PowerHint;
using PowerHint_1_3 = ::android::hardware::power::V1_3::PowerHint;
using ::android::perfmgr::HintManager;
using ::vendor::lineage::power::V1_0::ILineagePower;
using ::vendor::lineage::power::V1_0::LineageFeature;
using ::vendor::lineage::power::V1_0::LineagePowerHint;
enum PowerProfile {
POWER_SAVE = 0,
BALANCED,
HIGH_PERFORMANCE,
BIAS_POWER_SAVE,
BIAS_PERFORMANCE,
MAX
};
class Power : public IPower, public ILineagePower {
public:
// 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::hardware::power::V1_3::IPower follow.
Return<void> powerHintAsync_1_3(PowerHint_1_3 hint, int32_t data) override;
// Methods from ::vendor::lineage::power::V1_0::ILineagePower follow.
Return<int32_t> getFeature(LineageFeature feature) override;
// Methods from ::android::hidl::base::V1_0::IBase follow.
Return<void> debug(const hidl_handle &fd, const hidl_vec<hidl_string> &args) override;
private:
std::shared_ptr<HintManager> mHintManager;
std::unique_ptr<InteractionHandler> mInteractionHandler;
std::atomic<bool> mVRModeOn;
std::atomic<bool> mSustainedPerfModeOn;
std::atomic<bool> mCameraStreamingMode;
std::atomic<bool> mReady;
std::thread mInitThread;
std::atomic<bool> mDoubleTapEnabled;
int32_t mNumPerfProfiles;
std::atomic<PowerProfile> mCurrentPerfProfile;
Return<void> updateHint(const char *hint, bool enable);
Return<void> setProfile(PowerProfile profile);
Return<void> switchDT2W(bool dt2w);
};
} // namespace implementation
} // namespace V1_3
} // namespace power
} // namespace hardware
} // namespace android
#endif // POWER_LIBPERFMGR_POWER_H_

@ -1,20 +0,0 @@
service vendor.power-hal-1-3 /vendor/bin/hw/android.hardware.power@1.3-service.samsung-libperfmgr
class hal
user root
group system radio
priority -20
interface android.hardware.power@1.0::IPower default
interface android.hardware.power@1.1::IPower default
interface android.hardware.power@1.2::IPower default
interface android.hardware.power@1.3::IPower default
# restart powerHAL when framework died
on property:init.svc.zygote=restarting && property:vendor.powerhal.state=*
setprop vendor.powerhal.state ""
setprop vendor.powerhal.audio ""
setprop vendor.powerhal.rendering ""
restart vendor.power-hal-1-3
# initialize powerHAL when boot is completed
on property:sys.boot_completed=1
setprop vendor.powerhal.init 1

@ -1,11 +0,0 @@
<manifest version="1.0" type="device">
<hal format="hidl" override="true">
<name>android.hardware.power</name>
<transport>hwbinder</transport>
<version>1.3</version>
<interface>
<name>IPower</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

@ -1,448 +0,0 @@
{
"Nodes": [
{
"Name": "CPULittleClusterMaxFreq",
"Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq",
"Values": [
"9999999",
"1113600"
],
"DefaultIndex": 0,
"ResetOnInit": true
},
{
"Name": "CPULittleClusterMinFreq",
"Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq",
"Values": [
"9999999",
"1113600",
"576000"
],
"ResetOnInit": true
},
{
"Name": "CPUBigClusterMaxFreq",
"Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_max_freq",
"Values": [
"9999999",
"2016000",
"1497600",
"1401600"
],
"DefaultIndex": 0,
"ResetOnInit": true
},
{
"Name": "CPUBigClusterMinFreq",
"Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq",
"Values": [
"9999999",
"1497600",
"1401600",
"1286400",
"0"
],
"ResetOnInit": true
},
{
"Name": "CPUBigPlusClusterMaxFreq",
"Path": "/sys/devices/system/cpu/cpu7/cpufreq/scaling_max_freq",
"Values": [
"9999999",
"2016000",
"1497600",
"1401600"
],
"DefaultIndex": 0,
"ResetOnInit": true
},
{
"Name": "CPUBigPlusClusterMinFreq",
"Path": "/sys/devices/system/cpu/cpu7/cpufreq/scaling_min_freq",
"Values": [
"9999999",
"1497600",
"1401600",
"1286400",
"0"
],
"ResetOnInit": true
},
{
"Name": "GPUMaxFreq",
"Path": "/sys/class/kgsl/kgsl-3d0/devfreq/max_freq",
"Values": [
"585000000",
"427000000"
],
"DefaultIndex": 0,
"ResetOnInit": true
},
{
"Name": "GPUMinFreq",
"Path": "/sys/class/kgsl/kgsl-3d0/devfreq/min_freq",
"Values": [
"585000000",
"427000000",
"345000000",
"257000000"
],
"ResetOnInit": true
},
{
"Name": "TASchedtuneBoost",
"Path": "/dev/stune/top-app/schedtune.boost",
"Values": [
"30",
"10"
],
"ResetOnInit": true
},
{
"Name": "PMQoSCpuDmaLatency",
"Path": "/dev/cpu_dma_latency",
"Values": [
"44",
"100"
],
"HoldFd": true
},
{
"Name": "TouchscreenEnable",
"Path": "/sys/class/input/input3/enabled",
"Values": [
"0",
"1"
],
"ResetOnInit": true
},
{
"Name": "DoubleTapToWakeEnable",
"Path": "/sys/class/sec/tsp/cmd",
"Values": [
"aot_enable,0",
"aot_enable,1"
],
"DefaultIndex": 0,
},
{
"Name": "PowerHALMainState",
"Path": "vendor.powerhal.state",
"Values": [
"CAMERA_STREAMING",
"SUSTAINED_PERFORMANCE",
"VR_MODE",
"VR_SUSTAINED_PERFORMANCE",
""
],
"Type": "Property"
},
{
"Name": "PowerHALAudioState",
"Path": "vendor.powerhal.audio",
"Values": [
"AUDIO_LOW_LATENCY",
""
],
"Type": "Property"
},
{
"Name": "PowerHALRenderingState",
"Path": "vendor.powerhal.rendering",
"Values": [
"EXPENSIVE_RENDERING",
""
],
"Type": "Property"
},
{
"Name": "PowerHALPerfProfileState",
"Path": "vendor.powerhal.perf_profile",
"Values": [
"POWER_SAVE",
"BIAS_POWER_SAVE",
"BIAS_PERFORMANCE",
"HIGH_PERFORMANCE"
],
"Type": "Property"
}
],
"Actions": [
{
"PowerHint": "INTERACTION",
"Node": "CPUBigClusterMinFreq",
"Duration": 0,
"Value": "1286400"
},
{
"PowerHint": "INTERACTION",
"Node": "CPUBigPlusClusterMinFreq",
"Duration": 0,
"Value": "1286400"
},
{
"PowerHint": "INTERACTION",
"Node": "CPULittleClusterMinFreq",
"Duration": 0,
"Value": "1113600"
},
{
"PowerHint": "INTERACTION",
"Node": "TASchedtuneBoost",
"Duration": 0,
"Value": "30"
},
{
"PowerHint": "LAUNCH",
"Node": "CPUBigClusterMaxFreq",
"Duration": 5000,
"Value": "9999999"
},
{
"PowerHint": "LAUNCH",
"Node": "CPUBigPlusClusterMaxFreq",
"Duration": 5000,
"Value": "9999999"
},
{
"PowerHint": "LAUNCH",
"Node": "CPUBigClusterMinFreq",
"Duration": 5000,
"Value": "9999999"
},
{
"PowerHint": "LAUNCH",
"Node": "CPUBigPlusClusterMinFreq",
"Duration": 5000,
"Value": "9999999"
},
{
"PowerHint": "LAUNCH",
"Node": "CPULittleClusterMinFreq",
"Duration": 5000,
"Value": "9999999"
},
{
"PowerHint": "LAUNCH",
"Node": "PMQoSCpuDmaLatency",
"Duration": 5000,
"Value": "44"
},
{
"PowerHint": "CAMERA_LAUNCH",
"Node": "CPUBigClusterMaxFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_LAUNCH",
"Node": "CPUBigPlusClusterMaxFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_LAUNCH",
"Node": "CPUBigClusterMinFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_LAUNCH",
"Node": "CPUBigPlusClusterMinFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_LAUNCH",
"Node": "CPULittleClusterMaxFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_LAUNCH",
"Node": "CPULittleClusterMinFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_LAUNCH",
"Node": "PMQoSCpuDmaLatency",
"Duration": 1000,
"Value": "44"
},
{
"PowerHint": "CAMERA_STREAMING",
"Node": "PowerHALMainState",
"Duration": 0,
"Value": "CAMERA_STREAMING"
},
{
"PowerHint": "CAMERA_STREAMING",
"Node": "CPUBigClusterMaxFreq",
"Duration": 0,
"Value": "2016000"
},
{
"PowerHint": "CAMERA_STREAMING",
"Node": "CPUBigPlusClusterMaxFreq",
"Duration": 0,
"Value": "2016000"
},
{
"PowerHint": "CAMERA_SHOT",
"Node": "CPUBigClusterMaxFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_SHOT",
"Node": "CPUBigPlusClusterMaxFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_SHOT",
"Node": "CPUBigClusterMinFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_SHOT",
"Node": "CPUBigPlusClusterMinFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_SHOT",
"Node": "CPULittleClusterMaxFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_SHOT",
"Node": "CPULittleClusterMinFreq",
"Duration": 1000,
"Value": "9999999"
},
{
"PowerHint": "CAMERA_SHOT",
"Node": "PMQoSCpuDmaLatency",
"Duration": 1000,
"Value": "44"
},
{
"PowerHint": "AUDIO_STREAMING",
"Node": "PMQoSCpuDmaLatency",
"Duration": 2000,
"Value": "44"
},
{
"PowerHint": "AUDIO_LOW_LATENCY",
"Node": "PowerHALAudioState",
"Duration": 0,
"Value": "AUDIO_LOW_LATENCY"
},
{
"PowerHint": "AUDIO_LOW_LATENCY",
"Node": "PMQoSCpuDmaLatency",
"Duration": 0,
"Value": "44"
},
{
"PowerHint": "SUSTAINED_PERFORMANCE",
"Node": "PowerHALMainState",
"Duration": 0,
"Value": "SUSTAINED_PERFORMANCE"
},
{
"PowerHint": "SUSTAINED_PERFORMANCE",
"Node": "CPUBigClusterMaxFreq",
"Duration": 0,
"Value": "1401600"
},
{
"PowerHint": "SUSTAINED_PERFORMANCE",
"Node": "CPUBigPlusClusterMaxFreq",
"Duration": 0,
"Value": "1401600"
},
{
"PowerHint": "SUSTAINED_PERFORMANCE",
"Node": "CPULittleClusterMaxFreq",
"Duration": 0,
"Value": "1113600"
},
{
"PowerHint": "SUSTAINED_PERFORMANCE",
"Node": "GPUMaxFreq",
"Duration": 0,
"Value": "427000000"
},
{
"PowerHint": "VR_MODE",
"Node": "PowerHALMainState",
"Duration": 0,
"Value": "VR_MODE"
},
{
"PowerHint": "VR_SUSTAINED_PERFORMANCE",
"Node": "PowerHALMainState",
"Duration": 0,
"Value": "VR_SUSTAINED_PERFORMANCE"
},
{
"PowerHint": "EXPENSIVE_RENDERING",
"Node": "PowerHALRenderingState",
"Duration": 0,
"Value": "EXPENSIVE_RENDERING"
},
{
"PowerHint": "EXPENSIVE_RENDERING",
"Node": "GPUMinFreq",
"Duration": 0,
"Value": "427000000"
},
{
"PowerHint": "EXPENSIVE_RENDERING",
"Node": "GPUMaxFreq",
"Duration": 0,
"Value": "585000000"
},
{
"PowerHint": "NOT_INTERACTIVE",
"Node": "TouchscreenEnable",
"Duration": 0,
"Value": "0"
},
{
"PowerHint": "DOUBLE_TAP_TO_WAKE",
"Node": "DoubleTapToWakeEnable",
"Duration": 0,
"Value": "aot_enable,1"
},
{
"PowerHint": "PROFILE_POWER_SAVE",
"Node": "PowerHALPerfProfileState",
"Duration": 0,
"Value": "POWER_SAVE"
},
{
"PowerHint": "PROFILE_BIAS_POWER_SAVE",
"Node": "PowerHALPerfProfileState",
"Duration": 0,
"Value": "BIAS_POWER_SAVE"
},
{
"PowerHint": "PROFILE_BIAS_PERFORMANCE",
"Node": "PowerHALPerfProfileState",
"Duration": 0,
"Value": "BIAS_PERFORMANCE"
},
{
"PowerHint": "PROFILE_HIGH_PERFORMANCE",
"Node": "PowerHALPerfProfileState",
"Duration": 0,
"Value": "HIGH_PERFORMANCE"
}
]
}

@ -1,59 +0,0 @@
/*
* 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.3-service.samsung-libperfmgr"
#include <android/log.h>
#include <hidl/HidlTransportSupport.h>
#include "Power.h"
using android::OK;
using android::sp;
using android::status_t;
// libhwbinder:
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
// Generated HIDL files
using android::hardware::power::V1_3::IPower;
using android::hardware::power::V1_3::implementation::Power;
int main(int /* argc */, char ** /* argv */) {
ALOGI("Power HAL Service 1.3 for Samsung is starting.");
android::sp<IPower> service = new Power();
if (service == nullptr) {
ALOGE("Can not create an instance of Power HAL Iface, exiting.");
return 1;
}
android::hardware::setMinSchedulerPolicy(service, SCHED_NORMAL, -20);
configureRpcThreadpool(1, true /*callerWillJoin*/);
status_t status = service->registerAsService();
if (status != OK) {
ALOGE("Could not register service for Power HAL Iface (%d), exiting.", status);
return 1;
}
ALOGI("Power Service is ready");
joinRpcThreadpool();
// In normal operation, we don't expect the thread pool to exit
ALOGE("Power Service is shutting down");
return 1;
}

@ -1,46 +0,0 @@
#
# Copyright (C) 2020 The LineageOS 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.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
Power.cpp \
service.cpp
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
hardware/samsung/hidl/light/include
LOCAL_SHARED_LIBRARIES := \
libbase \
libbinder \
libhidlbase \
libutils \
android.hardware.power@1.0 \
vendor.lineage.power@1.0
LOCAL_STATIC_LIBRARIES := libc++fs
LOCAL_MODULE := android.hardware.power@1.0-service.exynos
LOCAL_INIT_RC := android.hardware.power@1.0-service.exynos.rc
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_OWNER := samsung
LOCAL_VENDOR_MODULE := true
include $(BUILD_EXECUTABLE)

@ -1,247 +0,0 @@
/*
* Copyright (C) 2020 The LineageOS 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.0-service.exynos"
#include "Power.h"
#include <android-base/logging.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include "samsung_lights.h"
#include "samsung_power.h"
namespace android {
namespace hardware {
namespace power {
namespace V1_0 {
namespace implementation {
/*
* Write value to path and close file.
*/
template <typename T>
static void set(const std::string& path, const T& value) {
std::ofstream file(path);
file << value << std::endl;
}
template <typename T>
static T get(const std::string& path, const T& def) {
std::ifstream file(path);
T result;
file >> result;
return file.fail() ? def : result;
}
Return<void> Power::setInteractive(bool interactive) {
if (!initialized) {
initialize();
}
if (!interactive) {
int32_t panel_brightness = get(PANEL_BRIGHTNESS_NODE, -1);
if (panel_brightness > 0) {
LOG(VERBOSE) << "Moving to non-interactive state, but screen is still on,"
<< "not disabling input devices";
goto out;
}
}
if (!sec_touchscreen.empty()) {
set(sec_touchscreen, interactive ? "1" : "0");
}
if (!sec_touchkey.empty()) {
if (!interactive) {
int button_state = get(sec_touchkey, -1);
if (button_state < 0) {
LOG(ERROR) << "Failed to read touchkey state";
goto out;
}
/*
* If button_state is 0, the keys have been disabled by another component
* (for example lineagehw), which means we don't want them to be enabled when resuming
* from suspend.
*/
if (button_state == 0) {
touchkeys_blocked = true;
}
}
if (!touchkeys_blocked) {
set(sec_touchkey, interactive ? "1" : "0");
}
}
out:
for (const std::string& interactivePath : cpuInteractivePaths) {
set(interactivePath + "/io_is_busy", interactive ? "1" : "0");
}
return Void();
}
Return<void> Power::powerHint(PowerHint hint, int32_t data) {
if (!initialized) {
initialize();
}
/* Bail out if low-power mode is active */
if (current_profile == PowerProfile::POWER_SAVE && hint != PowerHint::LOW_POWER &&
hint != static_cast<PowerHint>(LineagePowerHint::SET_PROFILE)) {
LOG(VERBOSE) << "PROFILE_POWER_SAVE active, ignoring hint " << static_cast<int32_t>(hint);
return Void();
}
switch (hint) {
case PowerHint::INTERACTION:
case PowerHint::LAUNCH:
sendBoostpulse();
break;
case PowerHint::LOW_POWER:
setProfile(data ? PowerProfile::POWER_SAVE : PowerProfile::BALANCED);
break;
default:
if (hint == static_cast<PowerHint>(LineagePowerHint::SET_PROFILE)) {
setProfile(static_cast<PowerProfile>(data));
} else if (hint == static_cast<PowerHint>(LineagePowerHint::CPU_BOOST)) {
sendBoost(data);
} else {
LOG(INFO) << "Unknown power hint: " << static_cast<int32_t>(hint);
}
break;
}
return Void();
}
Return<void> Power::setFeature(Feature feature __unused, bool activate __unused) {
if (!initialized) {
initialize();
}
#ifdef TAP_TO_WAKE_NODE
if (feature == Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE) {
set(TAP_TO_WAKE_NODE, activate ? "1" : "0");
}
#endif
return Void();
}
Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
_hidl_cb({}, Status::SUCCESS);
return Void();
}
Return<int32_t> Power::getFeature(LineageFeature feature) {
switch (feature) {
case LineageFeature::SUPPORTED_PROFILES:
return static_cast<int32_t>(PowerProfile::MAX);
default:
return -1;
}
}
void Power::initialize() {
findInputNodes();
current_profile = PowerProfile::BALANCED;
for (const std::string& interactivePath : cpuInteractivePaths) {
hispeed_freqs.emplace_back(get<std::string>(interactivePath + "/hispeed_freq", ""));
}
for (const std::string& sysfsPath : cpuSysfsPaths) {
max_freqs.emplace_back(get<std::string>(sysfsPath + "/cpufreq/scaling_max_freq", ""));
}
initialized = true;
}
void Power::findInputNodes() {
std::error_code ec;
for (auto& de : std::filesystem::directory_iterator("/sys/class/input/", ec)) {
/* we are only interested in the input devices that we can access */
if (ec || de.path().string().find("/sys/class/input/input") == std::string::npos) {
continue;
}
for (auto& de2 : std::filesystem::directory_iterator(de.path(), ec)) {
if (!ec && de2.path().string().find("/name") != std::string::npos) {
std::string content = get<std::string>(de2.path(), "");
if (content == "sec_touchkey") {
sec_touchkey = de.path().string().append("/enabled");
LOG(INFO) << "found sec_touchkey: " << sec_touchkey;
} else if (content == "sec_touchscreen") {
sec_touchscreen = de.path().string().append("/enabled");
LOG(INFO) << "found sec_touchscreen: " << sec_touchscreen;
}
}
}
}
}
void Power::setProfile(PowerProfile profile) {
if (current_profile == profile) {
return;
}
switch (profile) {
case PowerProfile::POWER_SAVE:
// Limit to hispeed freq
for (int i = 0; i < cpuSysfsPaths.size(); i++) {
if (hispeed_freqs.size() > i && !hispeed_freqs.at(i).empty()) {
set(cpuSysfsPaths.at(i) + "/cpufreq/scaling_max_freq", hispeed_freqs.at(i));
}
}
break;
case PowerProfile::BALANCED:
case PowerProfile::HIGH_PERFORMANCE:
// Restore normal max freq
for (int i = 0; i < cpuSysfsPaths.size(); i++) {
if (max_freqs.size() > i && !max_freqs.at(i).empty()) {
set(cpuSysfsPaths.at(i) + "/cpufreq/scaling_max_freq", max_freqs.at(i));
}
}
break;
default:
break;
}
}
void Power::sendBoostpulse() {
// the boostpulse node is only valid for the LITTLE cluster
set(cpuInteractivePaths.front() + "/boostpulse", "1");
}
void Power::sendBoost(int duration_us) {
set(cpuInteractivePaths.front() + "/boost", "1");
usleep(duration_us);
set(cpuInteractivePaths.front() + "/boost", "0");
}
} // namespace implementation
} // namespace V1_0
} // namespace power
} // namespace hardware
} // namespace android

@ -1,82 +0,0 @@
/*
* Copyright (C) 2020 The LineageOS 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_0_POWER_H
#define ANDROID_HARDWARE_POWER_V1_0_POWER_H
#include <android/hardware/power/1.0/IPower.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <vendor/lineage/power/1.0/ILineagePower.h>
namespace android {
namespace hardware {
namespace power {
namespace V1_0 {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::vendor::lineage::power::V1_0::ILineagePower;
using ::vendor::lineage::power::V1_0::LineageFeature;
using ::vendor::lineage::power::V1_0::LineagePowerHint;
// clang-format off
enum PowerProfile {
POWER_SAVE = 0,
BALANCED,
HIGH_PERFORMANCE,
MAX
};
// clang-format on
struct Power : public IPower, public ILineagePower {
Return<void> setInteractive(bool interactive) override;
Return<void> powerHint(PowerHint hint, int32_t data) override;
Return<void> setFeature(Feature feature, bool activate) override;
Return<void> getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) override;
Return<int32_t> getFeature(LineageFeature feature) override;
private:
void initialize();
void findInputNodes();
void setProfile(PowerProfile profile);
void sendBoostpulse();
void sendBoost(int duration_us);
bool initialized;
bool touchkeys_blocked;
std::string sec_touchkey;
std::string sec_touchscreen;
PowerProfile current_profile;
std::vector<std::string> hispeed_freqs;
std::vector<std::string> max_freqs;
};
} // namespace implementation
} // namespace V1_0
} // namespace power
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_POWER_V1_0_POWER_H

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

@ -1,42 +0,0 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2020 The LineageOS 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 SAMSUNG_POWER_H
#define SAMSUNG_POWER_H
/*
* Board specific nodes
*
* If your kernel exposes these controls in another place, you can either
* symlink to the locations given here, or override this header in your
* device tree.
*/
static const std::vector<std::string> cpuSysfsPaths = {
"/sys/devices/system/cpu/cpu0",
"/sys/devices/system/cpu/cpu4"
};
static const std::vector<std::string> cpuInteractivePaths = {
"/sys/devices/system/cpu/cpu0/cpufreq/interactive",
"/sys/devices/system/cpu/cpu4/cpufreq/interactive"
};
/* double tap to wake node */
//#define TAP_TO_WAKE_NODE "/sys/class/sec/tsp/dt2w_enable"
#endif // SAMSUNG_POWER_H

@ -1,60 +0,0 @@
/*
* Copyright (C) 2020 The LineageOS 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.0-service.exynos"
#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include <utils/Errors.h>
#include "Power.h"
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::power::V1_0::IPower;
using android::hardware::power::V1_0::implementation::Power;
using android::OK;
using android::sp;
using android::status_t;
int main() {
sp<Power> power = new Power();
status_t status = 0;
configureRpcThreadpool(1, true);
status = power->IPower::registerAsService();
if (status != OK) {
LOG(ERROR) << "Could not register service (IPower) for Power HAL";
goto shutdown;
}
status = power->ILineagePower::registerAsService();
if (status != OK) {
LOG(ERROR) << "Could not register service (ILineagePower) for Power HAL";
goto shutdown;
}
LOG(INFO) << "Power HAL service is Ready.";
joinRpcThreadpool();
shutdown:
// In normal operation, we don't expect the thread pool to shutdown
LOG(ERROR) << "Power HAL failed to join thread pool.";
return 1;
}
Loading…
Cancel
Save