* from tag android-11.0.0_r18 Signed-off-by: Michael Benedict <michaelbt@live.com> Change-Id: Ic1408f7d68463379514b62ef2f811bd1102467e1tirimbino
parent
004df56ac2
commit
3598031c4d
@ -0,0 +1,17 @@ |
||||
#
|
||||
# Copyright (C) 2019 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.
|
||||
#
|
||||
|
||||
include $(call all-subdir-makefiles) |
@ -0,0 +1,93 @@ |
||||
// |
||||
// 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", |
||||
"hardware/google/interfaces", |
||||
], |
||||
} |
||||
|
||||
cc_library { |
||||
name: "libdisppower-pixel", |
||||
proprietary: true, |
||||
srcs: [ |
||||
"disp-power/DisplayLowPower.cpp", |
||||
"disp-power/InteractionHandler.cpp", |
||||
], |
||||
shared_libs: [ |
||||
"libbase", |
||||
"libcutils", |
||||
"liblog", |
||||
"libperfmgr", |
||||
"libutils", |
||||
], |
||||
} |
||||
|
||||
cc_library_headers { |
||||
name: "pixel_power_headers", |
||||
vendor: true, |
||||
export_include_dirs: ["hidl"], |
||||
} |
||||
|
||||
cc_binary { |
||||
name: "android.hardware.power@1.3-service.pixel-libperfmgr", |
||||
relative_install_path: "hw", |
||||
vintf_fragments: ["hidl/android.hardware.power@1.3-service.pixel.xml"], |
||||
init_rc: ["hidl/android.hardware.power@1.3-service.pixel-libperfmgr.rc"], |
||||
srcs: ["hidl/service.cpp", "hidl/Power.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", |
||||
"libdisppower-pixel", |
||||
"libperfmgr", |
||||
], |
||||
proprietary: true, |
||||
} |
||||
|
||||
cc_binary { |
||||
name: "android.hardware.power-service.pixel-libperfmgr", |
||||
relative_install_path: "hw", |
||||
init_rc: ["aidl/android.hardware.power-service.pixel-libperfmgr.rc"], |
||||
vintf_fragments: ["aidl/android.hardware.power-service.pixel.xml"], |
||||
vendor: true, |
||||
shared_libs: [ |
||||
"android.hardware.power-ndk_platform", |
||||
"libbase", |
||||
"libcutils", |
||||
"liblog", |
||||
"libutils", |
||||
"libbinder_ndk", |
||||
"libdisppower-pixel", |
||||
"libperfmgr", |
||||
"pixel-power-ext-ndk_platform", |
||||
], |
||||
srcs: [ |
||||
"aidl/service.cpp", |
||||
"aidl/Power.cpp", |
||||
"aidl/PowerExt.cpp", |
||||
], |
||||
} |
@ -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@-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,256 @@ |
||||
/*
|
||||
* Copyright (C) 2020 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-service.pixel-libperfmgr" |
||||
|
||||
#include "Power.h" |
||||
|
||||
#include <mutex> |
||||
|
||||
#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 <utils/Log.h> |
||||
#include <utils/Trace.h> |
||||
|
||||
#include "disp-power/DisplayLowPower.h" |
||||
|
||||
namespace aidl { |
||||
namespace google { |
||||
namespace hardware { |
||||
namespace power { |
||||
namespace impl { |
||||
namespace pixel { |
||||
|
||||
constexpr char kPowerHalStateProp[] = "vendor.powerhal.state"; |
||||
constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio"; |
||||
constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering"; |
||||
|
||||
Power::Power(std::shared_ptr<HintManager> hm, std::shared_ptr<DisplayLowPower> dlpw) |
||||
: mHintManager(hm), |
||||
mDisplayLowPower(dlpw), |
||||
mInteractionHandler(nullptr), |
||||
mVRModeOn(false), |
||||
mSustainedPerfModeOn(false) { |
||||
mInteractionHandler = std::make_unique<InteractionHandler>(mHintManager); |
||||
mInteractionHandler->Init(); |
||||
|
||||
std::string state = ::android::base::GetProperty(kPowerHalStateProp, ""); |
||||
if (state == "SUSTAINED_PERFORMANCE") { |
||||
ALOGI("Initialize with SUSTAINED_PERFORMANCE on"); |
||||
mHintManager->DoHint("SUSTAINED_PERFORMANCE"); |
||||
mSustainedPerfModeOn = true; |
||||
} else if (state == "VR") { |
||||
ALOGI("Initialize with VR on"); |
||||
mHintManager->DoHint(state); |
||||
mVRModeOn = true; |
||||
} else if (state == "VR_SUSTAINED_PERFORMANCE") { |
||||
ALOGI("Initialize with SUSTAINED_PERFORMANCE and VR on"); |
||||
mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE"); |
||||
mSustainedPerfModeOn = true; |
||||
mVRModeOn = true; |
||||
} else { |
||||
ALOGI("Initialize PowerHAL"); |
||||
} |
||||
|
||||
state = ::android::base::GetProperty(kPowerHalAudioProp, ""); |
||||
if (state == "AUDIO_STREAMING_LOW_LATENCY") { |
||||
ALOGI("Initialize with AUDIO_LOW_LATENCY on"); |
||||
mHintManager->DoHint(state); |
||||
} |
||||
|
||||
state = ::android::base::GetProperty(kPowerHalRenderingProp, ""); |
||||
if (state == "EXPENSIVE_RENDERING") { |
||||
ALOGI("Initialize with EXPENSIVE_RENDERING on"); |
||||
mHintManager->DoHint("EXPENSIVE_RENDERING"); |
||||
} |
||||
|
||||
// Now start to take powerhint
|
||||
ALOGI("PowerHAL ready to process hints"); |
||||
} |
||||
|
||||
ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) { |
||||
LOG(DEBUG) << "Power setMode: " << toString(type) << " to: " << enabled; |
||||
ATRACE_INT(toString(type).c_str(), enabled); |
||||
switch (type) { |
||||
case Mode::LOW_POWER: |
||||
mDisplayLowPower->SetDisplayLowPower(enabled); |
||||
if (enabled) { |
||||
mHintManager->DoHint(toString(type)); |
||||
} else { |
||||
mHintManager->EndHint(toString(type)); |
||||
} |
||||
break; |
||||
case Mode::SUSTAINED_PERFORMANCE: |
||||
if (enabled && !mSustainedPerfModeOn) { |
||||
if (!mVRModeOn) { // Sustained mode only.
|
||||
mHintManager->DoHint("SUSTAINED_PERFORMANCE"); |
||||
} else { // Sustained + VR mode.
|
||||
mHintManager->EndHint("VR"); |
||||
mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE"); |
||||
} |
||||
mSustainedPerfModeOn = true; |
||||
} else if (!enabled && mSustainedPerfModeOn) { |
||||
mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE"); |
||||
mHintManager->EndHint("SUSTAINED_PERFORMANCE"); |
||||
if (mVRModeOn) { // Switch back to VR Mode.
|
||||
mHintManager->DoHint("VR"); |
||||
} |
||||
mSustainedPerfModeOn = false; |
||||
} |
||||
break; |
||||
case Mode::VR: |
||||
if (enabled && !mVRModeOn) { |
||||
if (!mSustainedPerfModeOn) { // VR mode only.
|
||||
mHintManager->DoHint("VR"); |
||||
} else { // Sustained + VR mode.
|
||||
mHintManager->EndHint("SUSTAINED_PERFORMANCE"); |
||||
mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE"); |
||||
} |
||||
mVRModeOn = true; |
||||
} else if (!enabled && mVRModeOn) { |
||||
mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE"); |
||||
mHintManager->EndHint("VR"); |
||||
if (mSustainedPerfModeOn) { // Switch back to sustained Mode.
|
||||
mHintManager->DoHint("SUSTAINED_PERFORMANCE"); |
||||
} |
||||
mVRModeOn = false; |
||||
} |
||||
break; |
||||
case Mode::LAUNCH: |
||||
if (mVRModeOn || mSustainedPerfModeOn) { |
||||
break; |
||||
} |
||||
[[fallthrough]]; |
||||
case Mode::DOUBLE_TAP_TO_WAKE: |
||||
[[fallthrough]]; |
||||
case Mode::FIXED_PERFORMANCE: |
||||
[[fallthrough]]; |
||||
case Mode::EXPENSIVE_RENDERING: |
||||
[[fallthrough]]; |
||||
case Mode::INTERACTIVE: |
||||
[[fallthrough]]; |
||||
case Mode::DEVICE_IDLE: |
||||
[[fallthrough]]; |
||||
case Mode::DISPLAY_INACTIVE: |
||||
[[fallthrough]]; |
||||
case Mode::AUDIO_STREAMING_LOW_LATENCY: |
||||
[[fallthrough]]; |
||||
case Mode::CAMERA_STREAMING_SECURE: |
||||
[[fallthrough]]; |
||||
case Mode::CAMERA_STREAMING_LOW: |
||||
[[fallthrough]]; |
||||
case Mode::CAMERA_STREAMING_MID: |
||||
[[fallthrough]]; |
||||
case Mode::CAMERA_STREAMING_HIGH: |
||||
[[fallthrough]]; |
||||
default: |
||||
if (enabled) { |
||||
mHintManager->DoHint(toString(type)); |
||||
} else { |
||||
mHintManager->EndHint(toString(type)); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
ndk::ScopedAStatus Power::isModeSupported(Mode type, bool *_aidl_return) { |
||||
bool supported = mHintManager->IsHintSupported(toString(type)); |
||||
// LOW_POWER handled insides PowerHAL specifically
|
||||
if (type == Mode::LOW_POWER) { |
||||
supported = true; |
||||
} |
||||
LOG(INFO) << "Power mode " << toString(type) << " isModeSupported: " << supported; |
||||
*_aidl_return = supported; |
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) { |
||||
LOG(DEBUG) << "Power setBoost: " << toString(type) << " duration: " << durationMs; |
||||
ATRACE_INT(toString(type).c_str(), durationMs); |
||||
switch (type) { |
||||
case Boost::INTERACTION: |
||||
if (mVRModeOn || mSustainedPerfModeOn) { |
||||
break; |
||||
} |
||||
mInteractionHandler->Acquire(durationMs); |
||||
break; |
||||
case Boost::DISPLAY_UPDATE_IMMINENT: |
||||
[[fallthrough]]; |
||||
case Boost::ML_ACC: |
||||
[[fallthrough]]; |
||||
case Boost::AUDIO_LAUNCH: |
||||
[[fallthrough]]; |
||||
case Boost::CAMERA_LAUNCH: |
||||
[[fallthrough]]; |
||||
case Boost::CAMERA_SHOT: |
||||
[[fallthrough]]; |
||||
default: |
||||
if (mVRModeOn || mSustainedPerfModeOn) { |
||||
break; |
||||
} |
||||
if (durationMs > 0) { |
||||
mHintManager->DoHint(toString(type), std::chrono::milliseconds(durationMs)); |
||||
} else if (durationMs == 0) { |
||||
mHintManager->DoHint(toString(type)); |
||||
} else { |
||||
mHintManager->EndHint(toString(type)); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool *_aidl_return) { |
||||
bool supported = mHintManager->IsHintSupported(toString(type)); |
||||
LOG(INFO) << "Power boost " << toString(type) << " isBoostSupported: " << supported; |
||||
*_aidl_return = supported; |
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
constexpr const char *boolToString(bool b) { |
||||
return b ? "true" : "false"; |
||||
} |
||||
|
||||
binder_status_t Power::dump(int fd, const char **, uint32_t) { |
||||
std::string buf(::android::base::StringPrintf( |
||||
"HintManager Running: %s\n" |
||||
"VRMode: %s\n" |
||||
"SustainedPerformanceMode: %s\n", |
||||
boolToString(mHintManager->IsRunning()), boolToString(mVRModeOn), |
||||
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 STATUS_OK; |
||||
} |
||||
|
||||
} // namespace pixel
|
||||
} // namespace impl
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace google
|
||||
} // namespace aidl
|
@ -0,0 +1,63 @@ |
||||
/*
|
||||
* Copyright (C) 2020 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. |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <atomic> |
||||
#include <memory> |
||||
#include <thread> |
||||
|
||||
#include <aidl/android/hardware/power/BnPower.h> |
||||
#include <perfmgr/HintManager.h> |
||||
|
||||
#include "disp-power/DisplayLowPower.h" |
||||
#include "disp-power/InteractionHandler.h" |
||||
|
||||
namespace aidl { |
||||
namespace google { |
||||
namespace hardware { |
||||
namespace power { |
||||
namespace impl { |
||||
namespace pixel { |
||||
|
||||
using ::InteractionHandler; |
||||
using ::aidl::android::hardware::power::Boost; |
||||
using ::aidl::android::hardware::power::Mode; |
||||
using ::android::perfmgr::HintManager; |
||||
|
||||
class Power : public ::aidl::android::hardware::power::BnPower { |
||||
public: |
||||
Power(std::shared_ptr<HintManager> hm, std::shared_ptr<DisplayLowPower> dlpw); |
||||
ndk::ScopedAStatus setMode(Mode type, bool enabled) override; |
||||
ndk::ScopedAStatus isModeSupported(Mode type, bool *_aidl_return) override; |
||||
ndk::ScopedAStatus setBoost(Boost type, int32_t durationMs) override; |
||||
ndk::ScopedAStatus isBoostSupported(Boost type, bool *_aidl_return) override; |
||||
binder_status_t dump(int fd, const char **args, uint32_t numArgs) override; |
||||
|
||||
private: |
||||
std::shared_ptr<HintManager> mHintManager; |
||||
std::shared_ptr<DisplayLowPower> mDisplayLowPower; |
||||
std::unique_ptr<InteractionHandler> mInteractionHandler; |
||||
std::atomic<bool> mVRModeOn; |
||||
std::atomic<bool> mSustainedPerfModeOn; |
||||
}; |
||||
|
||||
} // namespace pixel
|
||||
} // namespace impl
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace google
|
||||
} // namespace aidl
|
@ -0,0 +1,87 @@ |
||||
/*
|
||||
* Copyright (C) 2020 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-service.pixel.ext-libperfmgr" |
||||
|
||||
#include "PowerExt.h" |
||||
|
||||
#include <mutex> |
||||
|
||||
#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 <utils/Log.h> |
||||
#include <utils/Trace.h> |
||||
|
||||
namespace aidl { |
||||
namespace google { |
||||
namespace hardware { |
||||
namespace power { |
||||
namespace impl { |
||||
namespace pixel { |
||||
|
||||
ndk::ScopedAStatus PowerExt::setMode(const std::string &mode, bool enabled) { |
||||
LOG(DEBUG) << "PowerExt setMode: " << mode << " to: " << enabled; |
||||
ATRACE_INT(mode.c_str(), enabled); |
||||
|
||||
if (enabled) { |
||||
mHintManager->DoHint(mode); |
||||
} else { |
||||
mHintManager->EndHint(mode); |
||||
} |
||||
|
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
ndk::ScopedAStatus PowerExt::isModeSupported(const std::string &mode, bool *_aidl_return) { |
||||
bool supported = mHintManager->IsHintSupported(mode); |
||||
LOG(INFO) << "PowerExt mode " << mode << " isModeSupported: " << supported; |
||||
*_aidl_return = supported; |
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
ndk::ScopedAStatus PowerExt::setBoost(const std::string &boost, int32_t durationMs) { |
||||
LOG(DEBUG) << "PowerExt setBoost: " << boost << " duration: " << durationMs; |
||||
ATRACE_INT(boost.c_str(), durationMs); |
||||
|
||||
if (durationMs > 0) { |
||||
mHintManager->DoHint(boost, std::chrono::milliseconds(durationMs)); |
||||
} else if (durationMs == 0) { |
||||
mHintManager->DoHint(boost); |
||||
} else { |
||||
mHintManager->EndHint(boost); |
||||
} |
||||
|
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
ndk::ScopedAStatus PowerExt::isBoostSupported(const std::string &boost, bool *_aidl_return) { |
||||
bool supported = mHintManager->IsHintSupported(boost); |
||||
LOG(INFO) << "PowerExt boost " << boost << " isBoostSupported: " << supported; |
||||
*_aidl_return = supported; |
||||
return ndk::ScopedAStatus::ok(); |
||||
} |
||||
|
||||
} // namespace pixel
|
||||
} // namespace impl
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace google
|
||||
} // namespace aidl
|
@ -0,0 +1,56 @@ |
||||
/*
|
||||
* Copyright (C) 2020 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. |
||||
*/ |
||||
|
||||
#pragma once |
||||
|
||||
#include <atomic> |
||||
#include <memory> |
||||
#include <thread> |
||||
|
||||
#include <aidl/google/hardware/power/extension/pixel/BnPowerExt.h> |
||||
#include <perfmgr/HintManager.h> |
||||
|
||||
#include "disp-power/DisplayLowPower.h" |
||||
|
||||
namespace aidl { |
||||
namespace google { |
||||
namespace hardware { |
||||
namespace power { |
||||
namespace impl { |
||||
namespace pixel { |
||||
|
||||
using ::android::perfmgr::HintManager; |
||||
|
||||
class PowerExt : public ::aidl::google::hardware::power::extension::pixel::BnPowerExt { |
||||
public: |
||||
PowerExt(std::shared_ptr<HintManager> hm, std::shared_ptr<DisplayLowPower> dlpw) |
||||
: mHintManager(hm), mDisplayLowPower(dlpw) {} |
||||
ndk::ScopedAStatus setMode(const std::string &mode, bool enabled) override; |
||||
ndk::ScopedAStatus isModeSupported(const std::string &mode, bool *_aidl_return) override; |
||||
ndk::ScopedAStatus setBoost(const std::string &boost, int32_t durationMs) override; |
||||
ndk::ScopedAStatus isBoostSupported(const std::string &boost, bool *_aidl_return) override; |
||||
|
||||
private: |
||||
std::shared_ptr<HintManager> mHintManager; |
||||
std::shared_ptr<DisplayLowPower> mDisplayLowPower; |
||||
}; |
||||
|
||||
} // namespace pixel
|
||||
} // namespace impl
|
||||
} // namespace power
|
||||
} // namespace hardware
|
||||
} // namespace google
|
||||
} // namespace aidl
|
@ -0,0 +1,29 @@ |
||||
service vendor.power-hal-aidl /vendor/bin/hw/android.hardware.power-service.pixel-libperfmgr |
||||
class hal |
||||
user root |
||||
group system |
||||
priority -20 |
||||
|
||||
on late-fs |
||||
start vendor.power-hal-aidl |
||||
|
||||
# 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-aidl |
||||
|
||||
# restart powerHAL when audioHAL died |
||||
on property:init.svc.vendor.audio-hal-2-0=restarting && property:vendor.powerhal.audio=AUDIO_STREAMING_LOW_LATENCY |
||||
setprop vendor.powerhal.audio "" |
||||
restart vendor.power-hal-aidl |
||||
|
||||
# Clean up after b/163539793 resolved |
||||
on property:vendor.powerhal.dalvik.vm.dex2oat-threads=* |
||||
setprop dalvik.vm.dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads} |
||||
setprop dalvik.vm.restore-dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads} |
||||
|
||||
on property:vendor.powerhal.dalvik.vm.dex2oat-cpu-set=* |
||||
setprop dalvik.vm.dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set} |
||||
setprop dalvik.vm.restore-dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set} |
@ -0,0 +1,6 @@ |
||||
<manifest version="1.0" type="device"> |
||||
<hal format="aidl"> |
||||
<name>android.hardware.power</name> |
||||
<fqname>IPower/default</fqname> |
||||
</hal> |
||||
</manifest> |
@ -0,0 +1,5 @@ |
||||
BOARD_SEPOLICY_DIRS += hardware/google/pixel-sepolicy/power-libperfmgr
|
||||
|
||||
# power HAL
|
||||
PRODUCT_PACKAGES += \
|
||||
android.hardware.power-service.pixel-libperfmgr
|
@ -0,0 +1,78 @@ |
||||
/*
|
||||
* Copyright (C) 2020 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-service.pixel-libperfmgr" |
||||
|
||||
#include <thread> |
||||
|
||||
#include <android-base/logging.h> |
||||
#include <android-base/properties.h> |
||||
#include <android/binder_manager.h> |
||||
#include <android/binder_process.h> |
||||
|
||||
#include "Power.h" |
||||
#include "PowerExt.h" |
||||
#include "disp-power/DisplayLowPower.h" |
||||
|
||||
using aidl::google::hardware::power::impl::pixel::Power; |
||||
using aidl::google::hardware::power::impl::pixel::PowerExt; |
||||
using ::android::perfmgr::HintManager; |
||||
|
||||
constexpr char kPowerHalConfigPath[] = "/vendor/etc/powerhint.json"; |
||||
constexpr char kPowerHalInitProp[] = "vendor.powerhal.init"; |
||||
|
||||
int main() { |
||||
LOG(INFO) << "Pixel Power HAL AIDL Service with Extension is starting."; |
||||
|
||||
// Parse config but do not start the looper
|
||||
std::shared_ptr<HintManager> hm = HintManager::GetFromJSON(kPowerHalConfigPath, false); |
||||
if (!hm) { |
||||
LOG(FATAL) << "Invalid config: " << kPowerHalConfigPath; |
||||
} |
||||
|
||||
std::shared_ptr<DisplayLowPower> dlpw = std::make_shared<DisplayLowPower>(); |
||||
|
||||
// single thread
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0); |
||||
|
||||
// core service
|
||||
std::shared_ptr<Power> pw = ndk::SharedRefBase::make<Power>(hm, dlpw); |
||||
ndk::SpAIBinder pwBinder = pw->asBinder(); |
||||
|
||||
// extension service
|
||||
std::shared_ptr<PowerExt> pwExt = ndk::SharedRefBase::make<PowerExt>(hm, dlpw); |
||||
|
||||
// attach the extension to the same binder we will be registering
|
||||
CHECK(STATUS_OK == AIBinder_setExtension(pwBinder.get(), pwExt->asBinder().get())); |
||||
|
||||
const std::string instance = std::string() + Power::descriptor + "/default"; |
||||
binder_status_t status = AServiceManager_addService(pw->asBinder().get(), instance.c_str()); |
||||
CHECK(status == STATUS_OK); |
||||
LOG(INFO) << "Pixel Power HAL AIDL Service with Extension is started."; |
||||
|
||||
std::thread initThread([&]() { |
||||
::android::base::WaitForProperty(kPowerHalInitProp, "1"); |
||||
hm->Start(); |
||||
dlpw->Init(); |
||||
}); |
||||
initThread.detach(); |
||||
|
||||
ABinderProcess_joinThreadPool(); |
||||
|
||||
// should not reach
|
||||
LOG(ERROR) << "Pixel Power HAL AIDL Service with Extension just died."; |
||||
return EXIT_FAILURE; |
||||
} |
Loading…
Reference in new issue