set vsync power hint

Change-Id: I28c2faf9ff584df3e74392712971cbcf75eb9e98
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 8b16456..6f7a7e1 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -10,6 +10,7 @@
     DisplayHardware/DisplayHardware.cpp     \
     DisplayHardware/DisplayHardwareBase.cpp \
     DisplayHardware/HWComposer.cpp          \
+    DisplayHardware/PowerHAL.cpp            \
     GLExtensions.cpp                        \
     MessageQueue.cpp                        \
     SurfaceFlinger.cpp                      \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 48651b6..bb93215 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -358,6 +358,13 @@
     mVSyncHandler = handler;
 }
 
+void DisplayHardware::eventControl(int event, int enabled) {
+    if (event == EVENT_VSYNC) {
+        mPowerHAL.vsyncHint(enabled);
+    }
+    mHwc->eventControl(event, enabled);
+}
+
 void DisplayHardware::onVSyncReceived(int dpy, nsecs_t timestamp) {
     sp<VSyncHandler> handler;
     { // scope for the lock
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index f1dee91..0604031 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -31,6 +31,7 @@
 
 #include "DisplayHardware/DisplayHardwareBase.h"
 #include "HWComposer.h"
+#include "PowerHAL.h"
 
 namespace android {
 
@@ -86,6 +87,12 @@
 
     void setVSyncHandler(const sp<VSyncHandler>& handler);
 
+    enum {
+        EVENT_VSYNC = HWC_EVENT_VSYNC
+    };
+
+    void eventControl(int event, int enabled);
+
 
     uint32_t getPageFlipCount() const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
@@ -129,6 +136,8 @@
 
     // constant once set
     HWComposer*     mHwc;
+    PowerHAL        mPowerHAL;
+
 
     mutable Mutex   mLock;
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index b87e191..65763db 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -125,19 +125,21 @@
     mEventHandler.onVSyncReceived(dpy, timestamp);
 }
 
-status_t HWComposer::eventControl(int event, int enabled) {
+void HWComposer::eventControl(int event, int enabled) {
     status_t err = NO_ERROR;
     if (mHwc && mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
         if (!mDebugForceFakeVSync) {
             err = mHwc->methods->eventControl(mHwc, event, enabled);
+            // error here should not happen -- not sure what we should
+            // do if it does.
+            ALOGE_IF(err, "eventControl(%d, %d) failed %s",
+                    event, enabled, strerror(-err));
         }
     }
 
     if (err == NO_ERROR && mVSyncThread != NULL) {
         mVSyncThread->setEnabled(enabled);
     }
-
-    return err;
 }
 
 void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 76aadf8..aada3cd 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -86,7 +86,7 @@
         EVENT_VSYNC = HWC_EVENT_VSYNC
     };
 
-    status_t eventControl(int event, int enabled);
+    void eventControl(int event, int enabled);
 
     // this class is only used to fake the VSync event on systems that don't
     // have it.
diff --git a/services/surfaceflinger/DisplayHardware/PowerHAL.cpp b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
new file mode 100644
index 0000000..0cb47d5
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+#include <utils/Errors.h>
+
+#include "PowerHAL.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+PowerHAL::PowerHAL() : mPowerModule(0) {
+    int err = hw_get_module(POWER_HARDWARE_MODULE_ID,
+            (const hw_module_t **)&mPowerModule);
+    ALOGW_IF(err, "%s module not found", POWER_HARDWARE_MODULE_ID);
+}
+
+PowerHAL::~PowerHAL() {
+}
+
+status_t PowerHAL::initCheck() const {
+    return mPowerModule ? NO_ERROR : NO_INIT;
+}
+
+status_t PowerHAL::vsyncHint(bool enabled) {
+    if (!mPowerModule) {
+        return NO_INIT;
+    }
+    if (mPowerModule->common.module_api_version >= POWER_MODULE_API_VERSION_0_2) {
+        if (mPowerModule->powerHint) {
+            mPowerModule->powerHint(mPowerModule, POWER_HINT_VSYNC, (void*)enabled);
+        }
+    }
+    return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/surfaceflinger/DisplayHardware/PowerHAL.h b/services/surfaceflinger/DisplayHardware/PowerHAL.h
new file mode 100644
index 0000000..929bc03
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/PowerHAL.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 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 ANDROID_SF_POWER_HAL_H
+#define ANDROID_SF_POWER_HAL_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <hardware/power.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class PowerHAL
+{
+public:
+    PowerHAL();
+    ~PowerHAL();
+
+    status_t initCheck() const;
+    status_t vsyncHint(bool enabled);
+
+private:
+    power_module_t*   mPowerModule;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_POWER_HAL_H
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 21634ee..47fa2f3 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -253,13 +253,13 @@
 void EventThread::enableVSyncLocked() {
     if (!mUseSoftwareVSync) {
         // never enable h/w VSYNC when screen is off
-        mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true);
+        mHw.eventControl(DisplayHardware::EVENT_VSYNC, true);
     }
     mDebugVsyncEnabled = true;
 }
 
 void EventThread::disableVSyncLocked() {
-    mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, false);
+    mHw.eventControl(DisplayHardware::EVENT_VSYNC, false);
     mDebugVsyncEnabled = false;
 }