Add new PowerAdvisor interface for SF to pass hints to the power HAL.

GPU composition is slow with FP16 wide color gamut. In this patch, we try to
mitigate this issue by boosting the GPU to higher frequency when SurfaceFlinger
is going to switch to Display P3 color mode by sending the new
PowerHint::EXPENSIVE_RENDERING to PowerManager.

BUG: 110112323
Test: adb shell cat /sys/class/kgsl/kgsl-3d0/devfreq/cur_freq to verify GPU
      frequency with/without WCG content. GPU frequency should be high with
      WCG content, and should be reset without WCG content.
Change-Id: I3758bcf9940e71d4b6d122d8916b7ad7f10f5397
Merged-In: I3758bcf9940e71d4b6d122d8916b7ad7f10f5397
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
new file mode 100644
index 0000000..0e4ad91
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "PowerAdvisor"
+
+#include <cinttypes>
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+
+#include "PowerAdvisor.h"
+
+namespace android {
+namespace Hwc2 {
+
+PowerAdvisor::~PowerAdvisor() = default;
+
+namespace impl {
+
+namespace V1_0 = android::hardware::power::V1_0;
+using V1_3::PowerHint;
+
+PowerAdvisor::~PowerAdvisor() = default;
+
+PowerAdvisor::PowerAdvisor() = default;
+
+void PowerAdvisor::setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) {
+    if (expected) {
+        mExpensiveDisplays.insert(displayId);
+    } else {
+        mExpensiveDisplays.erase(displayId);
+    }
+
+    const sp<V1_3::IPower> powerHal = getPowerHal();
+    if (powerHal == nullptr) {
+        return;
+    }
+
+    const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
+    if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
+        auto ret = powerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING,
+                                                expectsExpensiveRendering);
+        // If Power HAL 1.3 was available previously but now fails,
+        // it may restart, so attempt to reconnect next time
+        if (!ret.isOk()) {
+            mReconnectPowerHal = true;
+            return;
+        }
+        mNotifiedExpensiveRendering = expectsExpensiveRendering;
+    }
+}
+
+sp<V1_3::IPower> PowerAdvisor::getPowerHal() {
+    static sp<V1_3::IPower> sPowerHal_1_3 = nullptr;
+    static bool sHasPowerHal_1_3 = true;
+
+    if (mReconnectPowerHal) {
+        sPowerHal_1_3 = nullptr;
+        mReconnectPowerHal = false;
+    }
+
+    // Power HAL 1.3 is not guaranteed to be available, thus we need to query
+    // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
+    // Power HAL 1.0 is always available, thus if we fail to query it, it means
+    // Power HAL is not available temporarily and we should retry later. However,
+    // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
+    // it means Power HAL 1.3 is not available at all, so we should stop trying.
+    if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) {
+        sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
+        if (powerHal_1_0 != nullptr) {
+            // Try to cast to Power HAL 1.3
+            sPowerHal_1_3 =  V1_3::IPower::castFrom(powerHal_1_0);
+            if (sPowerHal_1_3 == nullptr) {
+                ALOGW("No Power HAL 1.3 service in system");
+                sHasPowerHal_1_3 = false;
+            } else {
+                ALOGI("Loaded Power HAL 1.3 service");
+            }
+        }
+    }
+    return sPowerHal_1_3;
+}
+
+} // namespace impl
+} // namespace Hwc2
+} // namespace android