libqservice: Add a client interface.

Add a client interface which interfaces with hwc.
qservice upon receiving IPC, provides a callback notification to the qclient
which does appropriate stuff in hwc.

In future, qservice can safely be even made a separate process with no changes
to exisiting code. This was not true earlier owing to the hwc pointer held by
qservice forcing it to be in the same process that hwc is in.

CRs-fixed: 452977
Change-Id: I05838c213f5d4606a6573693de1bacbc5876107e
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index a9ada35..1618ef5 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -8,7 +8,7 @@
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libEGL liboverlay libgenlock \
                                  libexternal libqdutils libhardware_legacy \
-                                 libdl libmemalloc libqservice libsync
+                                 libdl libmemalloc libqservice libsync libbinder
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := hwc.cpp          \
@@ -18,6 +18,7 @@
                                  hwc_vsync.cpp    \
                                  hwc_fbupdate.cpp \
                                  hwc_mdpcomp.cpp  \
-                                 hwc_copybit.cpp
+                                 hwc_copybit.cpp  \
+                                 hwc_qclient.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
new file mode 100644
index 0000000..32dc451
--- /dev/null
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -0,0 +1,83 @@
+/*
+ *  Copyright (c) 2013, The Linux Foundation. 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 CLIENTS; 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.
+ */
+
+#include <hwc_qclient.h>
+#include <IQService.h>
+#include <hwc_utils.h>
+
+#define QCLIENT_DEBUG 0
+
+using namespace android;
+using namespace qService;
+
+namespace qClient {
+
+// ----------------------------------------------------------------------------
+QClient::QClient(hwc_context_t *ctx) : mHwcContext(ctx)
+{
+    ALOGD_IF(QCLIENT_DEBUG, "QClient Constructor invoked");
+}
+
+QClient::~QClient()
+{
+    ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
+}
+
+void QClient::notifyCallback(uint32_t msg, uint32_t value) {
+    switch(msg) {
+        case IQService::SECURING:
+            securing(value);
+            break;
+        case IQService::UNSECURING:
+            unsecuring(value);
+            break;
+        default:
+            return;
+    }
+}
+
+void QClient::securing(uint32_t startEnd) {
+    mHwcContext->mSecuring = startEnd;
+    //We're done securing
+    if(startEnd == IQService::END)
+        mHwcContext->mSecureMode = true;
+    if(mHwcContext->proc)
+        mHwcContext->proc->invalidate(mHwcContext->proc);
+}
+
+void QClient::unsecuring(uint32_t startEnd) {
+    mHwcContext->mSecuring = startEnd;
+    //We're done unsecuring
+    if(startEnd == IQService::END)
+        mHwcContext->mSecureMode = false;
+    if(mHwcContext->proc)
+        mHwcContext->proc->invalidate(mHwcContext->proc);
+}
+
+}
diff --git a/libhwcomposer/hwc_qclient.h b/libhwcomposer/hwc_qclient.h
new file mode 100644
index 0000000..1f3944f
--- /dev/null
+++ b/libhwcomposer/hwc_qclient.h
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2013, The Linux Foundation. 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 CLIENTS; 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 ANDROID_QCLIENT_H
+#define ANDROID_QCLIENT_H
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <binder/IServiceManager.h>
+#include <IQClient.h>
+
+struct hwc_context_t;
+
+namespace qClient {
+// ----------------------------------------------------------------------------
+
+class QClient : public BnQClient {
+public:
+    QClient(hwc_context_t *ctx);
+    virtual ~QClient();
+    virtual void notifyCallback(uint32_t msg, uint32_t value);
+private:
+    void securing(uint32_t startEnd);
+    void unsecuring(uint32_t startEnd);
+    hwc_context_t *mHwcContext;
+};
+}; // namespace qClient
+#endif // ANDROID_QCLIENT_H
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 093c0b3..0c26bda 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -19,6 +19,7 @@
  */
 #define HWC_UTILS_DEBUG 0
 #include <sys/ioctl.h>
+#include <binder/IServiceManager.h>
 #include <EGL/egl.h>
 #include <cutils/properties.h>
 #include <gralloc_priv.h>
@@ -30,8 +31,14 @@
 #include "mdp_version.h"
 #include "hwc_copybit.h"
 #include "external.h"
+#include "hwc_qclient.h"
 #include "QService.h"
 #include "comptype.h"
+
+using namespace qClient;
+using namespace qService;
+using namespace android;
+
 namespace qhwc {
 
 // Opens Framebuffer device
@@ -60,7 +67,6 @@
     openFramebufferDevice(ctx);
     overlay::Overlay::initOverlay();
     ctx->mOverlay = overlay::Overlay::getInstance();
-    ctx->mQService = qService::QService::getInstance(ctx);
     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
@@ -93,6 +99,15 @@
     pthread_cond_init(&(ctx->vstate.cond), NULL);
     ctx->vstate.enable = false;
     ctx->mExtDispConfiguring = false;
+
+    //Right now hwc starts the service but anybody could do it, or it could be
+    //independent process as well.
+    QService::init();
+    sp<IQClient> client = new QClient(ctx);
+    interface_cast<IQService>(
+            defaultServiceManager()->getService(
+            String16("display.qservice")))->connect(client);
+
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index c66f7ff..525fd75 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -40,10 +40,6 @@
 struct hwc_context_t;
 struct framebuffer_device_t;
 
-namespace qService {
-class QService;
-}
-
 namespace overlay {
 class Overlay;
 }
@@ -229,8 +225,6 @@
 
     //Overlay object - NULL for non overlay devices
     overlay::Overlay *mOverlay;
-    //QService object
-    qService::QService *mQService;
 
     //Primary and external FB updater
     qhwc::IFBUpdate *mFBUpdate[HWC_NUM_DISPLAY_TYPES];
diff --git a/libqservice/Android.mk b/libqservice/Android.mk
index 8e82f42..e1585e4 100644
--- a/libqservice/Android.mk
+++ b/libqservice/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdqservice\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := QService.cpp \
-                                 IQService.cpp
+                                 IQService.cpp \
+                                 IQClient.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libqservice/IQClient.cpp b/libqservice/IQClient.cpp
new file mode 100644
index 0000000..4ff67dc
--- /dev/null
+++ b/libqservice/IQClient.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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 <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <utils/Errors.h>
+#include <IQClient.h>
+
+using namespace android;
+
+// ---------------------------------------------------------------------------
+
+namespace qClient {
+
+enum {
+    NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpQClient : public BpInterface<IQClient>
+{
+public:
+    BpQClient(const sp<IBinder>& impl)
+        : BpInterface<IQClient>(impl) {}
+
+    virtual void notifyCallback(uint32_t msg, uint32_t value) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IQClient::getInterfaceDescriptor());
+        data.writeInt32(msg);
+        data.writeInt32(value);
+        remote()->transact(NOTIFY_CALLBACK, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(QClient, "android.display.IQClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnQClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case NOTIFY_CALLBACK: {
+            CHECK_INTERFACE(IQClient, data, reply);
+            uint32_t msg = data.readInt32();
+            uint32_t value = data.readInt32();
+            notifyCallback(msg, value);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace qClient
diff --git a/libqservice/IQClient.h b/libqservice/IQClient.h
new file mode 100644
index 0000000..68d8275
--- /dev/null
+++ b/libqservice/IQClient.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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_IQCLIENT_H
+#define ANDROID_IQCLIENT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+
+namespace qClient {
+// ----------------------------------------------------------------------------
+class IQClient : public android::IInterface
+{
+public:
+    DECLARE_META_INTERFACE(QClient);
+    virtual void notifyCallback(uint32_t msg, uint32_t value) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnQClient : public android::BnInterface<IQClient>
+{
+public:
+    virtual android::status_t onTransact( uint32_t code,
+                                          const android::Parcel& data,
+                                          android::Parcel* reply,
+                                          uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace qClient
+
+#endif // ANDROID_IQCLIENT_H
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index 420d59c..7a88bdf 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -31,6 +31,7 @@
 #include <IQService.h>
 
 using namespace android;
+using namespace qClient;
 
 // ---------------------------------------------------------------------------
 
@@ -55,6 +56,13 @@
         data.writeInt32(startEnd);
         remote()->transact(UNSECURING, data, &reply);
     }
+
+    virtual void connect(const sp<IQClient>& client) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        data.writeStrongBinder(client->asBinder());
+        remote()->transact(CONNECT, data, &reply);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
@@ -100,6 +108,18 @@
             unsecuring(startEnd);
             return NO_ERROR;
         } break;
+        case CONNECT: {
+            CHECK_INTERFACE(IQService, data, reply);
+            if(callerUid != AID_GRAPHICS) {
+                ALOGE("display.qservice CONNECT access denied: pid=%d uid=%d process=%s",
+                      callerPid, callerUid, callingProcName);
+                return PERMISSION_DENIED;
+            }
+            sp<IQClient> client =
+                interface_cast<IQClient>(data.readStrongBinder());
+            connect(client);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 8647efa..70e6c64 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -26,6 +26,8 @@
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <IQClient.h>
 
 namespace qService {
 // ----------------------------------------------------------------------------
@@ -34,8 +36,10 @@
 public:
     DECLARE_META_INTERFACE(QService);
     enum {
-        SECURING = 0, // Hardware securing start/end notification
+        // Hardware securing start/end notification
+        SECURING = android::IBinder::FIRST_CALL_TRANSACTION,
         UNSECURING, // Hardware unsecuring start/end notification
+        CONNECT,
     };
     enum {
         END = 0,
@@ -43,6 +47,7 @@
     };
     virtual void securing(uint32_t startEnd) = 0;
     virtual void unsecuring(uint32_t startEnd) = 0;
+    virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index 1c9f165..8fc7319 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -28,7 +28,6 @@
  */
 
 #include <QService.h>
-#include <hwc_utils.h>
 
 #define QSERVICE_DEBUG 0
 
@@ -38,7 +37,7 @@
 
 QService* QService::sQService = NULL;
 // ----------------------------------------------------------------------------
-QService::QService(hwc_context_t *ctx):mHwcContext(ctx)
+QService::QService()
 {
     ALOGD_IF(QSERVICE_DEBUG, "QService Constructor invoked");
 }
@@ -49,27 +48,25 @@
 }
 
 void QService::securing(uint32_t startEnd) {
-    mHwcContext->mSecuring = startEnd;
-    //We're done securing
-    if(startEnd == END)
-        mHwcContext->mSecureMode = true;
-    if(mHwcContext->proc)
-        mHwcContext->proc->invalidate(mHwcContext->proc);
+    if(mClient.get()) {
+        mClient->notifyCallback(SECURING, startEnd);
+    }
 }
 
 void QService::unsecuring(uint32_t startEnd) {
-    mHwcContext->mSecuring = startEnd;
-    //We're done unsecuring
-    if(startEnd == END)
-        mHwcContext->mSecureMode = false;
-    if(mHwcContext->proc)
-        mHwcContext->proc->invalidate(mHwcContext->proc);
+    if(mClient.get()) {
+        mClient->notifyCallback(UNSECURING, startEnd);
+    }
 }
 
-QService* QService::getInstance(hwc_context_t *ctx)
+void QService::connect(const sp<qClient::IQClient>& client) {
+    mClient = client;
+}
+
+void QService::init()
 {
     if(!sQService) {
-        sQService = new QService(ctx);
+        sQService = new QService();
         sp<IServiceManager> sm = defaultServiceManager();
         sm->addService(String16("display.qservice"), sQService);
         if(sm->checkService(String16("display.qservice")) != NULL)
@@ -77,7 +74,6 @@
         else
             ALOGD_IF(QSERVICE_DEBUG, "adding display.qservice failed");
     }
-    return sQService;
 }
 
 }
diff --git a/libqservice/QService.h b/libqservice/QService.h
index ab458a4..4f7e570 100644
--- a/libqservice/QService.h
+++ b/libqservice/QService.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -35,6 +35,7 @@
 #include <cutils/log.h>
 #include <binder/IServiceManager.h>
 #include <IQService.h>
+#include <IQClient.h>
 
 struct hwc_context_t;
 
@@ -46,11 +47,12 @@
     virtual ~QService();
     virtual void securing(uint32_t startEnd);
     virtual void unsecuring(uint32_t startEnd);
-    static QService* getInstance(hwc_context_t *ctx);
+    virtual void connect(const android::sp<qClient::IQClient>& client);
+    static void init();
 private:
-    QService(hwc_context_t *ctx);
+    QService();
+    android::sp<qClient::IQClient> mClient;
     static QService *sQService;
-    hwc_context_t *mHwcContext;
 };
 }; // namespace qService
 #endif // ANDROID_QSERVICE_H