power-libperfmgr: add aidl extension server

Bug: 151896829
Test: boot flame
Change-Id: Ie951008cabe2a5680fbc546a21bdc9a428864ef9
diff --git a/aidl/power-libperfmgr/Android.mk b/aidl/power-libperfmgr/Android.mk
index 4afc5ad..1ef2ddd 100644
--- a/aidl/power-libperfmgr/Android.mk
+++ b/aidl/power-libperfmgr/Android.mk
@@ -28,12 +28,14 @@
     libdl \
     liblog \
     libperfmgr \
-    libutils
+    libutils \
+    pixel-power-ext-ndk_platform
 
 LOCAL_SRC_FILES := \
     service.cpp \
     InteractionHandler.cpp \
-    Power.cpp
+    Power.cpp \
+    PowerExt.cpp
 
 LOCAL_CFLAGS := -Wno-unused-parameter -Wno-unused-variable
 
diff --git a/aidl/power-libperfmgr/Power.cpp b/aidl/power-libperfmgr/Power.cpp
index fadf0a1..69d9cd4 100644
--- a/aidl/power-libperfmgr/Power.cpp
+++ b/aidl/power-libperfmgr/Power.cpp
@@ -39,63 +39,45 @@
 
 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";
 
-Power::Power()
-    : mHintManager(nullptr),
-      mInteractionHandler(nullptr),
-      mVRModeOn(false),
-      mSustainedPerfModeOn(false),
-      mReady(false) {
-    // Parse config but do not start the looper
-    mHintManager = HintManager::GetFromJSON(kPowerHalConfigPath, false);
-    if (!mHintManager) {
-        LOG(FATAL) << "Invalid config: " << kPowerHalConfigPath;
+void Power::setReady() {
+    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");
     }
 
-    std::thread initThread([this]() {
-        ::android::base::WaitForProperty(kPowerHalInitProp, "1");
-        mHintManager->Start();
-        mInteractionHandler = std::make_unique<InteractionHandler>(mHintManager);
-        mInteractionHandler->Init();
+    state = ::android::base::GetProperty(kPowerHalAudioProp, "");
+    if (state == "AUDIO_STREAMING_LOW_LATENCY") {
+        ALOGI("Initialize with AUDIO_LOW_LATENCY on");
+        mHintManager->DoHint(state);
+    }
 
-        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(kPowerHalRenderingProp, "");
+    if (state == "EXPENSIVE_RENDERING") {
+        ALOGI("Initialize with EXPENSIVE_RENDERING on");
+        mHintManager->DoHint("EXPENSIVE_RENDERING");
+    }
 
-        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
-        mReady.store(true);
-        ALOGI("PowerHAL ready to process hints");
-    });
-    initThread.detach();
+    // Now start to take powerhint
+    mReady.store(true);
+    ALOGI("PowerHAL ready to process hints");
 }
 
 ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
@@ -229,7 +211,7 @@
 
 ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool *_aidl_return) {
     bool supported = mHintManager->IsHintSupported(toString(type));
-    LOG(INFO) << "Power mode " << toString(type) << " isBoostSupported: " << supported;
+    LOG(INFO) << "Power boost " << toString(type) << " isBoostSupported: " << supported;
     *_aidl_return = supported;
     return ndk::ScopedAStatus::ok();
 }
diff --git a/aidl/power-libperfmgr/Power.h b/aidl/power-libperfmgr/Power.h
index bc69bdc..170f40f 100644
--- a/aidl/power-libperfmgr/Power.h
+++ b/aidl/power-libperfmgr/Power.h
@@ -37,12 +37,19 @@
 
 class Power : public BnPower {
   public:
-    Power();
+    Power(std::shared_ptr<HintManager> hm)
+        : mHintManager(hm),
+          mInteractionHandler(nullptr),
+          mVRModeOn(false),
+          mSustainedPerfModeOn(false),
+          mReady(false) {}
+
     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;
+    void setReady();
 
   private:
     std::shared_ptr<HintManager> mHintManager;
diff --git a/aidl/power-libperfmgr/PowerExt.cpp b/aidl/power-libperfmgr/PowerExt.cpp
new file mode 100644
index 0000000..06232fd
--- /dev/null
+++ b/aidl/power-libperfmgr/PowerExt.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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.xiaomi.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 android {
+namespace hardware {
+namespace pixel {
+namespace extension {
+namespace power {
+namespace impl {
+
+void PowerExt::setReady() {
+    // Now start to take powerhint
+    mReady.store(true);
+    ALOGI("PowerHAL extension ready to process hints");
+}
+
+ndk::ScopedAStatus PowerExt::setMode(const std::string &mode, bool enabled) {
+    if (!mReady) {
+        return ndk::ScopedAStatus::ok();
+    }
+    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) {
+    if (!mReady) {
+        return ndk::ScopedAStatus::ok();
+    }
+    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 impl
+}  // namespace power
+}  // namespace extension
+}  // namespace pixel
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/aidl/power-libperfmgr/PowerExt.h b/aidl/power-libperfmgr/PowerExt.h
new file mode 100644
index 0000000..b9fc95d
--- /dev/null
+++ b/aidl/power-libperfmgr/PowerExt.h
@@ -0,0 +1,57 @@
+/*
+ * 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/pixel/extension/power/BnPowerExt.h>
+#include <perfmgr/HintManager.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace pixel {
+namespace extension {
+namespace power {
+namespace impl {
+
+using ::android::perfmgr::HintManager;
+
+class PowerExt : public BnPowerExt {
+  public:
+    PowerExt(std::shared_ptr<HintManager> hm) : mHintManager(hm), mReady(false) {}
+
+    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;
+    void setReady();
+
+  private:
+    std::shared_ptr<HintManager> mHintManager;
+    std::atomic<bool> mReady;
+};
+
+}  // namespace impl
+}  // namespace power
+}  // namespace extension
+}  // namespace pixel
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/aidl/power-libperfmgr/service.cpp b/aidl/power-libperfmgr/service.cpp
index 2a8ef5b..fc509d7 100644
--- a/aidl/power-libperfmgr/service.cpp
+++ b/aidl/power-libperfmgr/service.cpp
@@ -16,23 +16,57 @@
 
 #define LOG_TAG "android.hardware.power-service.mediatek-libperfmgr"
 
-#include "Power.h"
+#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"
+
+using aidl::android::hardware::pixel::extension::power::impl::PowerExt;
 using aidl::android::hardware::power::impl::pixel::Power;
+using ::android::perfmgr::HintManager;
+
+constexpr char kPowerHalConfigPath[] = "/vendor/etc/powerhint.json";
+constexpr char kPowerHalInitProp[] = "vendor.powerhal.init";
 
 int main() {
     LOG(INFO) << "Xiaomi Power HAL AIDL Service 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;
+    }
+
+    // single thread
     ABinderProcess_setThreadPoolMaxThreadCount(0);
-    std::shared_ptr<Power> pw = ndk::SharedRefBase::make<Power>();
+
+    // power hal core service
+    std::shared_ptr<Power> pw = ndk::SharedRefBase::make<Power>(hm);
+    ndk::SpAIBinder pwBinder = pw->asBinder();
+
+    // making the extension service
+    std::shared_ptr<PowerExt> pwExt = ndk::SharedRefBase::make<PowerExt>(hm);
+
+    // need to 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) << "Xiaomi Power HAL AIDL Service is started.";
+    LOG(INFO) << "Xiaomi Power HAL AIDL Service with Extension is started.";
+
+    std::thread initThread([&]() {
+        ::android::base::WaitForProperty(kPowerHalInitProp, "1");
+        hm->Start();
+        pw->setReady();
+        pwExt->setReady();
+    });
+    initThread.detach();
 
     ABinderProcess_joinThreadPool();
     LOG(ERROR) << "Xiaomi Power HAL AIDL Service died.";