samsung: hidl: import Pixel libperfmgr Power HAL

hardware/google/pixel/power-libperfmgr from android-10.0.0_r39

Change-Id: I969f76219e6507627d3689b3c2dc025983bcfde4
Signed-off-by: Jesse Chan <jc@lineageos.org>
tirimbino
Jesse Chan 5 years ago
parent ccd5c4c52b
commit 87f97d145b
  1. 47
      hidl/power-libperfmgr/Android.bp
  2. 30
      hidl/power-libperfmgr/AudioStreaming.h
  3. 30
      hidl/power-libperfmgr/CameraMode.h
  4. 251
      hidl/power-libperfmgr/InteractionHandler.cpp
  5. 74
      hidl/power-libperfmgr/InteractionHandler.h
  6. 390
      hidl/power-libperfmgr/Power.cpp
  7. 88
      hidl/power-libperfmgr/Power.h
  8. 26
      hidl/power-libperfmgr/android.hardware.power@1.3-service.pixel-libperfmgr.rc
  9. 11
      hidl/power-libperfmgr/android.hardware.power@1.3-service.pixel.xml
  10. 74
      hidl/power-libperfmgr/display-helper.cpp
  11. 28
      hidl/power-libperfmgr/display-helper.h
  12. 59
      hidl/power-libperfmgr/service.cpp

@ -0,0 +1,47 @@
//
// 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_library_headers {
name: "pixel_power_headers",
vendor_available: true,
export_include_dirs: ["."],
}
cc_binary {
name: "android.hardware.power@1.3-service.pixel-libperfmgr",
relative_install_path: "hw",
vintf_fragments: ["android.hardware.power@1.3-service.pixel.xml"],
init_rc: ["android.hardware.power@1.3-service.pixel-libperfmgr.rc"],
srcs: ["service.cpp", "Power.cpp", "InteractionHandler.cpp",
"display-helper.cpp"],
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",
"android.hardware.power@1.3",
"libperfmgr",
],
proprietary: true,
}

@ -0,0 +1,30 @@
/*
* Copyright (C) 2019 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_AUDIOSTREAMING_H_
#define POWER_LIBPERFMGR_AUDIOSTREAMING_H_
enum AUDIO_STREAMING_HINT {
AUDIO_STREAMING_OFF = 0,
AUDIO_STREAMING_ON = 1,
TPU_BOOST_OFF = 1000,
TPU_BOOST_SHORT = 1001,
TPU_BOOST_LONG = 1002
};
enum TPU_HINT_DURATION_MS { SHORT = 200, LONG = 2000 };
#endif // POWER_LIBPERFMGR_AUDIOSTREAMING_H_

@ -0,0 +1,30 @@
/*
* 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_CAMERAMODE_H_
#define POWER_LIBPERFMGR_CAMERAMODE_H_
enum CameraStreamingMode {
CAMERA_STREAMING_OFF = 0,
CAMERA_STREAMING,
CAMERA_STREAMING_1080P,
CAMERA_STREAMING_60FPS,
CAMERA_STREAMING_4K,
CAMERA_STREAMING_SECURE,
CAMERA_STREAMING_MAX
};
#endif // POWER_LIBPERFMGR_CAMERAMODE_H_

@ -0,0 +1,251 @@
/*
* 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.pixel-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;
int fd = fb_idle_open();
if (fd < 0)
return false;
mIdleFd = fd;
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);
}
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;
}
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();
}
}

@ -0,0 +1,74 @@
/*
* 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_

@ -0,0 +1,390 @@
/*
* 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.pixel-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 "AudioStreaming.h"
#include "Power.h"
#include "display-helper.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;
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 kPowerHalConfigPath[] = "/vendor/etc/powerhint.json";
static const std::map<enum CameraStreamingMode, std::string> kCamStreamingHint = {
{CAMERA_STREAMING_OFF, "CAMERA_STREAMING_OFF"},
{CAMERA_STREAMING, "CAMERA_STREAMING"},
{CAMERA_STREAMING_1080P, "CAMERA_STREAMING_1080P"},
{CAMERA_STREAMING_60FPS, "CAMERA_STREAMING_60FPS"},
{CAMERA_STREAMING_4K, "CAMERA_STREAMING_4K"},
{CAMERA_STREAMING_SECURE, "CAMERA_STREAMING_SECURE"}};
Power::Power()
: mHintManager(nullptr),
mInteractionHandler(nullptr),
mVRModeOn(false),
mSustainedPerfModeOn(false),
mCameraStreamingMode(CAMERA_STREAMING_OFF),
mReady(false) {
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 = CAMERA_STREAMING;
} else if (state == "CAMERA_STREAMING_1080P") {
ALOGI("Initialize CAMERA_STREAMING_1080P on");
mHintManager->DoHint("CAMERA_STREAMING_1080P");
mCameraStreamingMode = CAMERA_STREAMING_1080P;
} else if (state == "CAMERA_STREAMING_60FPS") {
ALOGI("Initialize CAMERA_STREAMING_60FPS on");
mHintManager->DoHint("CAMERA_STREAMING_60FPS");
mCameraStreamingMode = CAMERA_STREAMING_60FPS;
} else if (state == "CAMERA_STREAMING_4K") {
ALOGI("Initialize with CAMERA_STREAMING_4K on");
mHintManager->DoHint("CAMERA_STREAMING_4K");
mCameraStreamingMode = CAMERA_STREAMING_4K;
} else if (state == "CAMERA_STREAMING_SECURE") {
ALOGI("Initialize with CAMERA_STREAMING_SECURE on");
mHintManager->DoHint("CAMERA_STREAMING_SECURE");
mCameraStreamingMode = CAMERA_STREAMING_SECURE;
} 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");
}
// Now start to take powerhint
mReady.store(true);
ALOGI("PowerHAL ready to process hints");
});
mInitThread.detach();
}
// 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 (!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:
if (data) {
// Device in battery saver mode, enable display low power mode
set_display_lpm(true);
} else {
// Device exiting battery saver mode, disable display low power mode
set_display_lpm(false);
}
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) {
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 == static_cast<int32_t>(AUDIO_STREAMING_HINT::AUDIO_STREAMING_ON)) {
mHintManager->DoHint("AUDIO_STREAMING");
} else if (data ==
static_cast<int32_t>(AUDIO_STREAMING_HINT::AUDIO_STREAMING_OFF)) {
mHintManager->EndHint("AUDIO_STREAMING");
} else if (data == static_cast<int32_t>(AUDIO_STREAMING_HINT::TPU_BOOST_SHORT)) {
mHintManager->DoHint("TPU_BOOST",
std::chrono::milliseconds(TPU_HINT_DURATION_MS::SHORT));
} else if (data == static_cast<int32_t>(AUDIO_STREAMING_HINT::TPU_BOOST_LONG)) {
mHintManager->DoHint("TPU_BOOST",
std::chrono::milliseconds(TPU_HINT_DURATION_MS::LONG));
} else if (data == static_cast<int32_t>(AUDIO_STREAMING_HINT::TPU_BOOST_OFF)) {
mHintManager->EndHint("TPU_BOOST");
} else {
ALOGE("AUDIO STREAMING INVALID DATA: %d", data);
}
}
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: {
const enum CameraStreamingMode mode = static_cast<enum CameraStreamingMode>(data);
if (mode < CAMERA_STREAMING_OFF || mode >= CAMERA_STREAMING_MAX) {
ALOGE("CAMERA STREAMING INVALID Mode: %d", mode);
break;
}
if (mCameraStreamingMode == mode)
break;
// turn it off first if any previous hint.
if ((mCameraStreamingMode != CAMERA_STREAMING_OFF)) {
const auto modeValue = kCamStreamingHint.at(mCameraStreamingMode);
mHintManager->EndHint(modeValue);
if ((mCameraStreamingMode != CAMERA_STREAMING_SECURE)) {
// Boost 1s for tear down if not secure streaming use case
mHintManager->DoHint("CAMERA_LAUNCH", std::chrono::seconds(1));
}
}
if (mode != CAMERA_STREAMING_OFF) {
const auto hintValue = kCamStreamingHint.at(mode);
mHintManager->DoHint(hintValue);
}
mCameraStreamingMode = mode;
const auto prop = (mCameraStreamingMode == CAMERA_STREAMING_OFF)
? ""
: kCamStreamingHint.at(mode).c_str();
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();
}
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();
}
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),
kCamStreamingHint.at(mCameraStreamingMode).c_str(),
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

@ -0,0 +1,88 @@
/*
* 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 "CameraMode.h"
#include "InteractionHandler.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;
class Power : public IPower {
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 ::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<enum CameraStreamingMode> mCameraStreamingMode;
std::atomic<bool> mReady;
std::thread mInitThread;
};
} // namespace implementation
} // namespace V1_3
} // namespace power
} // namespace hardware
} // namespace android
#endif // POWER_LIBPERFMGR_POWER_H_

@ -0,0 +1,26 @@
service vendor.power-hal-1-3 /vendor/bin/hw/android.hardware.power@1.3-service.pixel-libperfmgr
class hal
user root
group system
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
# restart powerHAL when cameraHAL died
on property:init.svc.vendor.camera-provider-2-4=restarting && property:vendor.powerhal.state=CAMERA_STREAMING
setprop vendor.powerhal.state ""
restart vendor.power-hal-1-3
# restart powerHAL when audioHAL died
on property:init.svc.vendor.audio-hal-2-0=restarting && property:vendor.powerhal.audio=AUDIO_LOW_LATENCY
setprop vendor.powerhal.audio ""
restart vendor.power-hal-1-3

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

@ -0,0 +1,74 @@
/*
* 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_NIDEBUG 0
#define LOG_TAG "android.hardware.power@1.3-service.pixel-libperfmgr"
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <cutils/sockets.h>
#include <log/log.h>
#include "display-helper.h"
#define DAEMON_SOCKET "pps"
static int daemon_socket = -1;
static int connectPPDaemon() {
// Setup socket connection, if not already done.
if (daemon_socket < 0)
daemon_socket =
socket_local_client(DAEMON_SOCKET, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
if (daemon_socket < 0) {
ALOGE("Connecting to socket failed: %s", strerror(errno));
return -1;
}
return 0;
}
static int ppdComm(const char *cmd) {
int ret = -1;
ret = connectPPDaemon();
if (ret < 0)
return ret;
ret = write(daemon_socket, cmd, strlen(cmd));
if (ret < 0) {
ALOGE("Failed to send data over socket, %s", strerror(errno));
return ret;
}
return 0;
}
void set_display_lpm(int enable) {
ALOGI("set_display_lpm state: %d", enable);
if (enable) {
ppdComm("foss:on");
} else {
ppdComm("foss:off");
}
}

@ -0,0 +1,28 @@
/*
* 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_DISPLAY_HELPER_H_
#define POWER_LIBPERFMGR_DISPLAY_HELPER_H_
enum display_lpm_state {
DISPLAY_LPM_OFF = 0,
DISPLAY_LPM_ON,
DISPLAY_LPM_UNKNOWN,
};
void set_display_lpm(int enable);
#endif // POWER_LIBPERFMGR_DISPLAY_HELPER_H_

@ -0,0 +1,59 @@
/*
* 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.pixel-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 Pixel 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;
}
Loading…
Cancel
Save