Camera2: Add thermal adapter

Thermal adapter is a singleton class to abstract a
thermal daemon client. The adapter would notify
camera HAL of thermal events.

Based on thermal threshold and level, we may adjust
camera/camcorder FPS accordingly.

Change-Id: Ib5192243f5b20ea151bd18cdf743a04e926aaab9
diff --git a/QCamera2/HAL/Android.mk b/QCamera2/HAL/Android.mk
index 7d1d968..dce1cc1 100644
--- a/QCamera2/HAL/Android.mk
+++ b/QCamera2/HAL/Android.mk
@@ -14,7 +14,8 @@
         QCameraStream.cpp \
 	QCameraPostProc.cpp \
         QCamera2HWICallbacks.cpp \
-        QCameraParameters.cpp
+        QCameraParameters.cpp \
+        QCameraThermalAdapter.cpp
 
 LOCAL_CFLAGS = -Wall -Werror
 
@@ -31,7 +32,7 @@
 LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/media
 LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 
-LOCAL_SHARED_LIBRARIES := libcamera_client liblog libhardware libutils libcutils
+LOCAL_SHARED_LIBRARIES := libcamera_client liblog libhardware libutils libcutils libdl
 LOCAL_SHARED_LIBRARIES += libmmcamera_interface libmmjpeg_interface libgenlock
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index d2c4c43..4a87d58 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -564,6 +564,7 @@
       mStoreMetaDataInFrame(0),
       m_stateMachine(this),
       m_postprocessor(this),
+      m_thermalAdapter(QCameraThermalAdapter::getInstance()),
       m_bShutterSoundPlayed(false),
       m_bAutoFocusRunning(false),
       m_pHistBuf(NULL)
@@ -574,6 +575,7 @@
     mCameraDevice.ops = &mCameraOps;
     mCameraDevice.priv = this;
 
+
     pthread_mutex_init(&m_lock, NULL);
     pthread_cond_init(&m_cond, NULL);
     memset(&m_apiResult, 0, sizeof(qcamera_api_result_t));
@@ -625,7 +627,7 @@
 
     m_evtNotifyTh.launch(evtNotifyRoutine, this);
     mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
-                                              evtHandle,
+                                              camEvtHandle,
                                               (void *) this);
 
     int32_t rc = m_postprocessor.init(jpegEvtHandle, this);
@@ -647,6 +649,11 @@
         gCamCapability[mCameraId]->padding_info.plane_padding = padding_info.plane_padding;
     }
 
+    rc = m_thermalAdapter.init(this);
+    if (rc != 0) {
+        ALOGE("Init thermal adapter failed");
+    }
+
     mParameters.init(gCamCapability[mCameraId], mCameraHandle);
     mCameraOpened = true;
 
@@ -665,6 +672,8 @@
     m_postprocessor.stop();
     m_postprocessor.deinit();
 
+    m_thermalAdapter.deinit();
+
     // delete all channels if not already deleted
     for (i = 0; i < QCAMERA_CH_TYPE_MAX; i++) {
         if (m_channels[i] != NULL) {
@@ -1340,7 +1349,7 @@
     return m_stateMachine.procEvt(evt, evt_payload);
 }
 
-void QCamera2HardwareInterface::evtHandle(uint32_t /*camera_handle*/,
+void QCamera2HardwareInterface::camEvtHandle(uint32_t /*camera_handle*/,
                                           mm_camera_event_t *evt,
                                           void *user_data)
 {
@@ -1381,6 +1390,14 @@
     }
 }
 
+int QCamera2HardwareInterface::thermalEvtHandle(char *name,
+                                                 int threshold,
+                                                 int level)
+{
+    ALOGI("%s: name: %s, threshold: %d, level: %d", __func__, name, threshold, level);
+    return NO_ERROR;
+}
+
 void *QCamera2HardwareInterface::evtNotifyRoutine(void *data)
 {
     int running = 1;
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index 92b902e..0e7bfca 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -40,6 +40,7 @@
 #include "QCameraStateMachine.h"
 #include "QCameraAllocator.h"
 #include "QCameraPostProc.h"
+#include "QCameraThermalAdapter.h"
 
 extern "C" {
 #include <mm_camera_interface.h>
@@ -81,7 +82,8 @@
 #define QCAMERA_DUMP_FRM_RAW        1<<4
 #define QCAMERA_DUMP_FRM_JPEG       1<<5
 
-class QCamera2HardwareInterface : public QCameraAllocator
+class QCamera2HardwareInterface : public QCameraAllocator,
+                                    public QCameraThermalCallback
 {
 public:
     /* static variable and functions accessed by camera service */
@@ -131,6 +133,10 @@
     virtual QCameraMemory *allocateStreamBuf(cam_stream_type_t stream_type, int size);
     virtual QCameraHeapMemory *allocateStreamInfoBuf(cam_stream_type_t stream_type);
 
+    // Implementation of QCameraThermalCallback
+    virtual int thermalEvtHandle(char *name,
+                              int threshold, int level);
+
     friend class QCameraStateMachine;
     friend class QCameraPostProcessor;
 
@@ -226,7 +232,7 @@
     bool isNoDisplayMode() {return mParameters.isNoDisplayMode();};
     uint8_t numOfSnapshotsExpected() {return mParameters.getNumOfSnapshots();};
 
-    static void evtHandle(uint32_t camera_handle,
+    static void camEvtHandle(uint32_t camera_handle,
                           mm_camera_event_t *evt,
                           void *user_data);
     static void jpegEvtHandle(jpeg_job_status_t status,
@@ -284,6 +290,7 @@
 
     QCameraStateMachine m_stateMachine;   // state machine
     QCameraPostProcessor m_postprocessor; // post processor
+    QCameraThermalAdapter &m_thermalAdapter;
     pthread_mutex_t m_lock;
     pthread_cond_t m_cond;
     qcamera_api_result_t m_apiResult;
diff --git a/QCamera2/HAL/QCameraStateMachine.cpp b/QCamera2/HAL/QCameraStateMachine.cpp
index 82e9514..5773fcd 100644
--- a/QCamera2/HAL/QCameraStateMachine.cpp
+++ b/QCamera2/HAL/QCameraStateMachine.cpp
@@ -508,6 +508,7 @@
     case QCAMERA_SM_EVT_EVT_NOTIFY:
     case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
     case QCAMERA_SM_EVT_SNAPSHOT_DONE:
+    case QCAMERA_SM_EVT_THERMAL_NOTIFY:
     default:
         ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
         break;
@@ -742,6 +743,7 @@
     case QCAMERA_SM_EVT_EVT_NOTIFY:
     case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
     case QCAMERA_SM_EVT_SNAPSHOT_DONE:
+    case QCAMERA_SM_EVT_THERMAL_NOTIFY:
     default:
         ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
         break;
@@ -1028,6 +1030,9 @@
             }
         }
         break;
+    case QCAMERA_SM_EVT_THERMAL_NOTIFY:
+        //TODO: Adjust FPS.
+        break;
     case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
     case QCAMERA_SM_EVT_SNAPSHOT_DONE:
     default:
@@ -1292,6 +1297,7 @@
             m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
         }
         break;
+    case QCAMERA_SM_EVT_THERMAL_NOTIFY:
     default:
         ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
         break;
@@ -1567,6 +1573,9 @@
             }
         }
         break;
+    case QCAMERA_SM_EVT_THERMAL_NOTIFY:
+        //TODO: Adjust FPS
+        break;
     case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
     case QCAMERA_SM_EVT_SNAPSHOT_DONE:
     default:
@@ -1845,6 +1854,9 @@
             m_state = QCAMERA_SM_STATE_RECORDING;
         }
         break;
+    case QCAMERA_SM_EVT_THERMAL_NOTIFY:
+        //TODO: Adjust FPS.
+        break;
     default:
         ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
         break;
@@ -2128,6 +2140,9 @@
             m_state = QCAMERA_SM_STATE_PREVIEWING;
         }
         break;
+    case QCAMERA_SM_EVT_THERMAL_NOTIFY:
+        //TODO: Adjust FPS
+        break;
     default:
         ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
         break;
diff --git a/QCamera2/HAL/QCameraStateMachine.h b/QCamera2/HAL/QCameraStateMachine.h
index 8798b4e..0e7502f 100644
--- a/QCamera2/HAL/QCameraStateMachine.h
+++ b/QCamera2/HAL/QCameraStateMachine.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -82,6 +82,7 @@
     QCAMERA_SM_EVT_EVT_NOTIFY,               // evt notify from server
     QCAMERA_SM_EVT_JPEG_EVT_NOTIFY,          // evt notify from jpeg
     QCAMERA_SM_EVT_SNAPSHOT_DONE,            // internal evt that snapshot is done
+    QCAMERA_SM_EVT_THERMAL_NOTIFY,           // evt notify from thermal daemon
     QCAMERA_SM_EVT_MAX
 } qcamera_sm_evt_enum_t;
 
diff --git a/QCamera2/HAL/QCameraThermalAdapter.cpp b/QCamera2/HAL/QCameraThermalAdapter.cpp
new file mode 100644
index 0000000..e5ae096
--- /dev/null
+++ b/QCamera2/HAL/QCameraThermalAdapter.cpp
@@ -0,0 +1,146 @@
+/* Copyright (c) 2013, The Linux Foundataion. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_TAG "QCameraThermalAdapter"
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include "QCameraThermalAdapter.h"
+
+using namespace android;
+
+namespace qcamera {
+
+
+QCameraThermalAdapter& QCameraThermalAdapter::getInstance()
+{
+    static QCameraThermalAdapter instance;
+    return instance;
+}
+
+QCameraThermalAdapter::QCameraThermalAdapter() :
+                                        mCallback(NULL),
+                                        mHandle(NULL),
+                                        mRegister(NULL),
+                                        mUnregister(NULL)
+{
+}
+
+int QCameraThermalAdapter::init(QCameraThermalCallback *thermalCb)
+{
+    const char *error = NULL;
+    int rc;
+
+    ALOGV("%s E", __func__);
+    mHandle = dlopen("/system/lib/libthermalclient.so", RTLD_NOW);
+    if (!mHandle) {
+        error = dlerror();
+        ALOGE("%s: dlopen failed with error %s",
+                    __func__, error ? error : "");
+        rc = UNKNOWN_ERROR;
+        goto error;
+    }
+    *(void **)&mRegister = dlsym(mHandle, "thermal_register_callback");
+    if (!mRegister) {
+        error = dlerror();
+        ALOGE("%s: dlsym failed with error code %s",
+                    __func__, error ? error: "");
+        rc = UNKNOWN_ERROR;
+        goto error2;
+    }
+    *(void **)&mUnregister = dlsym(mHandle, "thermal_unregister_callback");
+    if (!mUnregister) {
+        error = dlerror();
+        ALOGE("%s: dlsym failed with error code %s",
+                    __func__, error ? error: "");
+        rc = UNKNOWN_ERROR;
+        goto error2;
+    }
+
+    // Register camera and camcorder callbacks
+    rc = mRegister(mStrCamera, thermalCallback, NULL);
+    if (rc < 0) {
+        ALOGE("%s: thermal_register_callback failed %d", __func__, rc);
+        goto error2;
+    }
+    rc = mRegister(mStrCamcorder, thermalCallback, NULL);
+    if (rc < 0) {
+        ALOGE("%s: thermal_register_callback failed %d", __func__, rc);
+        goto error3;
+    }
+
+    mCallback = thermalCb;
+    ALOGV("%s X", __func__);
+    return rc;
+
+error3:
+    mUnregister(mStrCamera);
+error2:
+    dlclose(mHandle);
+error:
+    ALOGV("%s X", __func__);
+    return rc;
+}
+
+void QCameraThermalAdapter::deinit()
+{
+    ALOGV("%s E", __func__);
+    if (mUnregister) {
+        mUnregister(mStrCamera);
+        mUnregister(mStrCamcorder);
+    }
+    if (mHandle)
+        dlclose(mHandle);
+
+    mHandle = NULL;
+    mRegister = NULL;
+    mUnregister = NULL;
+    mCallback = NULL;
+    ALOGV("%s X", __func__);
+}
+
+char QCameraThermalAdapter::mStrCamera[] = "camera";
+char QCameraThermalAdapter::mStrCamcorder[] = "camcorder";
+
+int QCameraThermalAdapter::thermalCallback(char * name,
+                                int threshold, int level)
+{
+    int rc = 0;
+    ALOGV("%s E", __func__);
+    QCameraThermalAdapter& instance = getInstance();
+    if (instance.mCallback)
+        rc = instance.mCallback->thermalEvtHandle(name, threshold, level);
+    ALOGV("%s X", __func__);
+    return rc;
+}
+
+}; //namespace qcamera
diff --git a/QCamera2/HAL/QCameraThermalAdapter.h b/QCamera2/HAL/QCameraThermalAdapter.h
new file mode 100644
index 0000000..ca6f1c5
--- /dev/null
+++ b/QCamera2/HAL/QCameraThermalAdapter.h
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013, The Linux Foundataion. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __QCAMERA_THERMAL_ADAPTER__
+#define __QCAMERA_THERMAL_ADAPTER__
+
+namespace qcamera {
+
+class QCameraThermalCallback
+{
+public:
+    virtual int thermalEvtHandle(char *name, int threshold,
+                                    int level) = 0;
+    virtual ~QCameraThermalCallback() {}
+};
+
+class QCameraThermalAdapter
+{
+public:
+    static QCameraThermalAdapter& getInstance();
+
+    int init(QCameraThermalCallback *thermalCb);
+    void deinit();
+
+private:
+    static char mStrCamera[];
+    static char mStrCamcorder[];
+
+    static int thermalCallback(char *name, int threshold, int level);
+
+    QCameraThermalCallback *mCallback;
+    void *mHandle;
+    int (*mRegister)(char *name, int (*callback)(char *, int, int), void *data);
+    int (*mUnregister)(char *name);
+
+    QCameraThermalAdapter();
+    QCameraThermalAdapter(QCameraThermalAdapter const& copy); // not implemented
+    QCameraThermalAdapter& operator=(QCameraThermalAdapter const& copy); // not implemented
+
+};
+
+}; // namespace qcamera
+
+#endif /* __QCAMERA_THERMAL_ADAPTER__ */