endif
ifeq ($(BOARD_VENDOR),samsung)
+include $(SAM_ROOT)/aidl/Android.mk
include $(SAM_ROOT)/audio/Android.mk
include $(SAM_ROOT)/doze/Android.mk
include $(SAM_ROOT)/hidl/Android.mk
--- /dev/null
+#
+# 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)
--- /dev/null
+//
+// 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",
+ ],
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+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}
--- /dev/null
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.power</name>
+ <fqname>IPower/default</fqname>
+ </hal>
+</manifest>
--- /dev/null
+BOARD_SEPOLICY_DIRS += hardware/google/pixel-sepolicy/power-libperfmgr
+
+# power HAL
+PRODUCT_PACKAGES += \
+ android.hardware.power-service.pixel-libperfmgr
--- /dev/null
+/*
+ * 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;
+}