Switch to HIDL service based HAL

Switch to using HIDL service based HAL.
Some cleanup.

Test: GTS tests pass

Change-Id: Icf133fe4ead56336973dc50c4ec2aab18382a8ca
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 9aaf9a7..a13ebaf 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -278,7 +278,7 @@
 
 LOCAL_SHARED_LIBRARIES += \
     libhwui \
-    libdl
+    libdl \
 
 # we need to access the private Bionic header
 # <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 30c4f3b..1262737 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -16,13 +16,6 @@
 
 package com.android.server.location;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.HashMap;
-
 import android.Manifest;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -43,8 +36,11 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.HashMap;
 
 /**
  * @hide
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index b340213..d238215 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -74,6 +74,7 @@
     libhwbinder \
     libutils \
     android.hardware.audio.common@2.0 \
+    android.hardware.contexthub@1.0 \
     android.hardware.gnss@1.0 \
     android.hardware.ir@1.0 \
     android.hardware.light@2.0 \
diff --git a/services/core/jni/com_android_server_location_ContextHubService.cpp b/services/core/jni/com_android_server_location_ContextHubService.cpp
index 762aec8..e25bda8 100644
--- a/services/core/jni/com_android_server_location_ContextHubService.cpp
+++ b/services/core/jni/com_android_server_location_ContextHubService.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include "context_hub.h"
 
 #undef LOG_NDEBUG
 #undef LOG_TAG
@@ -28,50 +27,88 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <android-base/macros.h>
-#include <cutils/log.h>
-
 #include <chrono>
 #include <mutex>
 #include <queue>
 #include <unordered_map>
 
-#include "JNIHelp.h"
+#include <android-base/macros.h>
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <cutils/log.h>
+
 #include "core_jni_helpers.h"
+#include "JNIHelp.h"
 
-static constexpr jint OS_APP_ID = -1;
-static constexpr jint INVALID_APP_ID = -2;
-static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
+using IContexthub = android::hardware::contexthub::V1_0::IContexthub;
 
-static constexpr jint MIN_APP_ID = 1;
-static constexpr jint MAX_APP_ID = 128;
+using Result = android::hardware::contexthub::V1_0::Result;
+using NanoAppBinary = android::hardware::contexthub::V1_0::NanoAppBinary;
+using ContextHubMsg = android::hardware::contexthub::V1_0::ContextHubMsg;
+using IContexthubCallback = android::hardware::contexthub::V1_0::IContexthubCallback;
+using AsyncEventType = android::hardware::contexthub::V1_0::AsyncEventType;
+using TransactionResult = android::hardware::contexthub::V1_0::TransactionResult;
+using ContextHub = android::hardware::contexthub::V1_0::ContextHub;
+using HubAppInfo = android::hardware::contexthub::V1_0::HubAppInfo;
 
-static constexpr size_t MSG_HEADER_SIZE = 4;
-static constexpr size_t HEADER_FIELD_MSG_TYPE = 0;
-static constexpr size_t HEADER_FIELD_MSG_VERSION = 1;
-static constexpr size_t HEADER_FIELD_HUB_HANDLE = 2;
-static constexpr size_t HEADER_FIELD_APP_INSTANCE = 3;
+template<typename T>
+using Return = android::hardware::Return<T>;
 
-static constexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
-static constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
-static constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
-
-// Monotonically increasing clock we use to determine if we can cancel
-// a transaction.
 using std::chrono::steady_clock;
+// If a transaction takes longer than this, we'll allow it to be
+// canceled by a new transaction.  Note we do _not_ automatically
+// cancel a transaction after this much time.  We can have a
+// legal transaction which takes longer than this amount of time,
+// as long as no other new transactions are attempted after this
+// time has expired.
+constexpr auto kMinTransactionCancelTime = std::chrono::seconds(29);
 
 namespace android {
 
-namespace {
+enum HubMessageType {
+    CONTEXT_HUB_APPS_ENABLE  = 1, // Enables loaded nano-app(s)
+    CONTEXT_HUB_APPS_DISABLE = 2, // Disables loaded nano-app(s)
+    CONTEXT_HUB_LOAD_APP     = 3, // Load a supplied app
+    CONTEXT_HUB_UNLOAD_APP   = 4, // Unload a specified app
+    CONTEXT_HUB_QUERY_APPS   = 5, // Query for app(s) info on hub
+    CONTEXT_HUB_QUERY_MEMORY = 6, // Query for memory info
+    CONTEXT_HUB_OS_REBOOT    = 7, // Request to reboot context HUB OS
+};
 
-/*
- * Finds the length of a statically-sized array using template trickery that
- * also prevents it from being applied to the wrong type.
- */
-template <typename T, size_t N>
-constexpr size_t array_length(T (&)[N]) { return N; }
+constexpr jint OS_APP_ID = -1;
+constexpr jint INVALID_APP_ID = -2;
 
-struct jniInfo_s {
+constexpr jint MIN_APP_ID = 1;
+constexpr jint MAX_APP_ID = 128;
+
+constexpr size_t MSG_HEADER_SIZE = 4;
+constexpr size_t HEADER_FIELD_MSG_TYPE = 0;
+constexpr size_t HEADER_FIELD_MSG_VERSION = 1;
+constexpr size_t HEADER_FIELD_HUB_HANDLE = 2;
+constexpr size_t HEADER_FIELD_APP_INSTANCE = 3;
+
+constexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
+constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
+constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
+
+jint getAppInstanceForAppId(uint64_t app_id);
+int onMessageReceipt(const uint32_t *header,
+                     size_t headerLen,
+                     const char *msg,
+                     size_t msgLen);
+void onHubReset(uint32_t hubId);
+void queryHubForApps(uint32_t hubId);
+void passOnOsResponse(uint32_t hubHandle,
+                      uint32_t msgType,
+                      TransactionResult result,
+                      const int8_t *additionalData,
+                      size_t additionalDataLen);
+
+bool closeLoadTxn(bool success, jint *appInstanceHandle);
+void closeUnloadTxn(bool success);
+int handleQueryAppsResponse(const std::vector<HubAppInfo> apps,
+                               uint32_t hubHandle);
+
+struct JniInfo {
     JavaVM *vm;
     jclass contextHubInfoClass;
     jclass contextHubServiceClass;
@@ -102,270 +139,280 @@
     jmethodID contextHubServiceDeleteAppInstance;
 };
 
-struct context_hub_info_s {
-    uint32_t *cookies;
-    int numHubs;
-    const struct context_hub_t *hubs;
-    struct context_hub_module_t *contextHubModule;
-};
-
-struct app_instance_info_s {
-    uint64_t truncName;          // Possibly truncated name for logging
-    uint32_t hubHandle;          // Id of the hub this app is on
-    jint instanceId;             // system wide unique instance id - assigned
-    struct hub_app_info appInfo; // returned from the HAL
-};
 
 
-// If a transaction takes longer than this, we'll allow it to be
-// canceled by a new transaction.  Note we do _not_ automatically
-// cancel a transaction after this much time.  We can have a
-// legal transaction which takes longer than this amount of time,
-// as long as no other new transactions are attempted after this
-// time has expired.
-// TODO(b/31105001): Establish a clean timing approach for all
-// of our HAL interactions.
-constexpr auto kMinTransactionCancelTime = std::chrono::seconds(29);
+class TxnManager {
+public:
+    TxnManager() {
+        mData = nullptr;
+        mIsPending = false;
+    }
 
-/*
- * TODO(ashutoshj): From original code review:
- *
- * So, I feel like we could possible do a better job of organizing this code,
- * and being more C++-y.  Consider something like this:
- * class TxnManager {
- *  public:
- *   TxnManager();
- *   ~TxnManager();
- *   int add(hub_message_e identifier, void *data);
- *   int close();
- *   bool isPending() const;
- *   int fetchData(hub_message_e *identifier, void **data) const;
- *
- *  private:
- *   bool mPending;
- *   mutable std::mutex mLock;
- *   hub_message_e mIdentifier;
- *   void *mData;
- * };
- *
- * And then, for example, we'd have things like:
- * TxnManager::TxnManager() : mPending(false), mLock(), mIdentifier(), mData(nullptr) {}
- * int TxnManager::add(hub_message_e identifier, void *data) {
- *    std::lock_guard<std::mutex> lock(mLock);
- *    mPending = true;
- *    mData = txnData;
- *    mIdentifier = txnIdentifier;
- *    return 0;
- *  }
- * And then calling code would look like:
- *    if (!db.txnManager.add(CONTEXT_HUB_LOAD_APP, txnInfo)) {
- *
- * This would make it clearer the nothing is manipulating any state within TxnManager
- * unsafely and outside of these couple of calls.
- */
-struct txnManager_s {
-    bool txnPending;              // Is a transaction pending
-    std::mutex m;                 // mutex for manager
-    hub_messages_e txnIdentifier; // What are we doing
-    void *txnData;                // Details
-    steady_clock::time_point firstTimeTxnCanBeCanceled;
-};
+    ~TxnManager() {
+        closeTxn();
+    }
 
-struct contextHubServiceDb_s {
-    int initialized;
-    context_hub_info_s hubInfo;
-    jniInfo_s jniInfo;
-    std::queue<jint> freeIds;
-    std::unordered_map<jint, app_instance_info_s> appInstances;
-    txnManager_s txnManager;
-};
+    int addTxn(HubMessageType txnIdentifier, void *txnData) {
+        std::lock_guard<std::mutex>lock(mLock);
+        if (mIsPending) {
+            ALOGW("Transaction already found pending when trying to add a new one.");
+            return -1;
+        }
+        mIsPending = true;
+        mFirstTimeTxnCanBeCanceled = steady_clock::now() + kMinTransactionCancelTime;
+        mData = txnData;
+        mIdentifier = txnIdentifier;
 
-}  // unnamed namespace
+        return 0;
+    }
 
-static contextHubServiceDb_s db;
+    int closeTxn() {
+        std::lock_guard<std::mutex>lock(mLock);
+        closeTxnUnlocked();
+        return 0;
+    }
 
-static bool initTxnManager() {
-    txnManager_s *mgr = &db.txnManager;
+    bool isTxnPending() {
+        std::lock_guard<std::mutex>lock(mLock);
+        return mIsPending;
+    }
 
-    mgr->txnData = nullptr;
-    mgr->txnPending = false;
-    return true;
-}
-
-static int addTxn(hub_messages_e txnIdentifier, void *txnData) {
-    txnManager_s *mgr = &db.txnManager;
-
-    std::lock_guard<std::mutex>lock(mgr->m);
-
-    mgr->txnPending = true;
-    mgr->firstTimeTxnCanBeCanceled = steady_clock::now() +
-        kMinTransactionCancelTime;
-    mgr->txnData = txnData;
-    mgr->txnIdentifier = txnIdentifier;
-
-    return 0;
-}
-
-// Only call this if you hold the db.txnManager.m lock.
-static void closeTxnUnlocked() {
-    txnManager_s *mgr = &db.txnManager;
-    mgr->txnPending = false;
-    free(mgr->txnData);
-    mgr->txnData = nullptr;
-}
-
-static int closeTxn() {
-    std::lock_guard<std::mutex>lock(db.txnManager.m);
-    closeTxnUnlocked();
-    return 0;
-}
-
-// If a transaction has been pending for longer than
-// kMinTransactionCancelTime, this call will "cancel" that
-// transaction and return that there are none pending.
-static bool isTxnPending() {
-    txnManager_s *mgr = &db.txnManager;
-    std::lock_guard<std::mutex>lock(mgr->m);
-    if (mgr->txnPending) {
-        if (steady_clock::now() >= mgr->firstTimeTxnCanBeCanceled) {
-            ALOGW("Transaction canceled");
+    void closeAnyStaleTxns() {
+        std::lock_guard<std::mutex>lock(mLock);
+        if (mIsPending && steady_clock::now() >= mFirstTimeTxnCanBeCanceled) {
+            ALOGW("Stale transaction canceled");
             closeTxnUnlocked();
         }
     }
-    return mgr->txnPending;
-}
 
-static int fetchTxnData(hub_messages_e *id, void **data) {
-    txnManager_s *mgr = &db.txnManager;
+    int fetchTxnData(HubMessageType *id, void **data) {
+        if (id == nullptr || data == nullptr) {
+            ALOGW("Null Params isNull{id, data} {%d, %d}",
+                  id == nullptr ? 1 : 0,
+                  data == nullptr ? 1 : 0);
+            return -1;
+        }
 
-    if (!id || !data) {
-        ALOGW("Null params id %p, data %p", id, data);
-        return -1;
-    }
+        std::lock_guard<std::mutex>lock(mLock);
+        if (!mIsPending) {
+            ALOGW("No Transactions pending");
+            return -1;
+        }
 
-    std::lock_guard<std::mutex>lock(mgr->m);
-    if (!mgr->txnPending) {
-        ALOGW("No Transactions pending");
-        return -1;
-    }
-
-    // else
-    *id = mgr->txnIdentifier;
-    *data = mgr->txnData;
-    return 0;
-}
-
-int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg,
-                         void *cookie);
-
-const context_hub_t *get_hub_info(int hubHandle) {
-    if (hubHandle >= 0 && hubHandle < db.hubInfo.numHubs) {
-        return &db.hubInfo.hubs[hubHandle];
-    }
-    return nullptr;
-}
-
-static int send_msg_to_hub(const hub_message_t *msg, int hubHandle) {
-    const context_hub_t *info = get_hub_info(hubHandle);
-
-    if (info) {
-        return db.hubInfo.contextHubModule->send_message(info->hub_id, msg);
-    } else {
-        ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle);
-        return -1;
-    }
-}
-
-static int set_os_app_as_destination(hub_message_t *msg, int hubHandle) {
-    const context_hub_t *info = get_hub_info(hubHandle);
-
-    if (info) {
-        msg->app_name = info->os_app_name;
+        *id = mIdentifier;
+        *data = mData;
         return 0;
-    } else {
-        ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle);
-        return -1;
     }
-}
 
-static int get_hub_id_for_hub_handle(int hubHandle) {
+ private:
+    bool mIsPending;            // Is a transaction pending
+    std::mutex mLock;           // mutex for manager
+    HubMessageType mIdentifier; // What are we doing
+    void *mData;                // Details
+    steady_clock::time_point mFirstTimeTxnCanBeCanceled;
+
+    // Only call this if you hold the lock.
+    void closeTxnUnlocked() {
+        mIsPending = false;
+        free(mData);
+        mData = nullptr;
+    }
+};
+
+
+struct ContextHubServiceCallback : IContexthubCallback {
+    uint32_t mContextHubId;
+
+    ContextHubServiceCallback(uint32_t hubId) {
+        mContextHubId = hubId;
+    }
+
+    virtual Return<void> handleClientMsg(const ContextHubMsg &msg) {
+        jint appHandle = getAppInstanceForAppId(msg.appName);
+        if (appHandle < 0) {
+            ALOGE("Filtering out message due to invalid App Instance.");
+        } else {
+            uint32_t msgHeader[MSG_HEADER_SIZE] = {};
+            msgHeader[HEADER_FIELD_MSG_TYPE] = msg.msgType;
+            msgHeader[HEADER_FIELD_HUB_HANDLE] = mContextHubId;
+            msgHeader[HEADER_FIELD_APP_INSTANCE] = appHandle;
+            onMessageReceipt(msgHeader,
+                             MSG_HEADER_SIZE,
+                             reinterpret_cast<const char *>(msg.msg.data()),
+                             msg.msg.size());
+        }
+
+        return android::hardware::Void();
+    }
+
+    virtual Return<void> handleHubEvent(AsyncEventType evt) {
+        if (evt == AsyncEventType::RESTARTED) {
+            ALOGW("Context Hub handle %d restarted", mContextHubId);
+            onHubReset(mContextHubId);
+        } else {
+            ALOGW("Cannot handle event %u from hub %d", evt, mContextHubId);
+        }
+
+        return android::hardware::Void();
+    }
+
+    virtual Return<void> handleTxnResult(uint32_t txnId,
+                                         TransactionResult result) {
+        ALOGI("Handle transaction result , hubId %" PRIu32 ", txnId %" PRIu32 ", result %" PRIu32,
+              mContextHubId,
+              txnId,
+              result);
+
+        switch(txnId) {
+            case CONTEXT_HUB_APPS_ENABLE:
+            case CONTEXT_HUB_APPS_DISABLE:
+                passOnOsResponse(mContextHubId, txnId, result, nullptr, 0);
+                break;
+
+            case CONTEXT_HUB_UNLOAD_APP:
+                closeUnloadTxn(result == TransactionResult::SUCCESS);
+                passOnOsResponse(mContextHubId, txnId, result, nullptr, 0);
+                break;
+
+            case CONTEXT_HUB_LOAD_APP:
+                {
+                    jint appInstanceHandle = INVALID_APP_ID;
+                    bool appRunningOnHub = (result == TransactionResult::SUCCESS);
+                    if (!(closeLoadTxn(appRunningOnHub, &appInstanceHandle))) {
+                        if (appRunningOnHub) {
+                            // Now we're in an odd situation.  Our nanoapp
+                            // is up and running on the Context Hub.  However,
+                            // something went wrong in our Service code so that
+                            // we're not able to properly track this nanoapp
+                            // in our Service code.  If we tell the Java layer
+                            // things are good, it's a lie because the handle
+                            // we give them will fail when used with the Service.
+                            // If we tell the Java layer this failed, it's kind
+                            // of a lie as well, since this nanoapp is running.
+                            //
+                            // We leave a more robust fix for later, and for
+                            // now just tell the user things have failed.
+                            //
+                            // TODO(b/30835981): Make this situation better.
+                            result = TransactionResult::FAILURE;
+                        }
+                    }
+
+                    passOnOsResponse(mContextHubId,
+                                     txnId,
+                                     result,
+                                     reinterpret_cast<int8_t *>(&appInstanceHandle),
+                                     sizeof(appInstanceHandle));
+                    break;
+                }
+
+            default:
+                ALOGI("unrecognized transction id %" PRIu32, txnId);
+                break;
+        }
+        return android::hardware::Void();
+    }
+
+    virtual Return<void> handleAppsInfo(
+            const android::hardware::hidl_vec<HubAppInfo>& apps) {
+        handleQueryAppsResponse(apps,mContextHubId);
+        return android::hardware::Void();
+    }
+
+    void setContextHubId(uint32_t id) {
+        mContextHubId = id;
+    }
+
+    uint32_t getContextHubId() {
+        return(mContextHubId);
+    }
+};
+
+struct AppInstanceInfo {
+    HubAppInfo appInfo;          // returned from the HAL
+    uint64_t truncName;          // Possibly truncated name for logging
+    uint32_t hubHandle;          // Id of the hub this app is on
+    jint instanceId;             // system wide unique instance id - assigned
+};
+
+struct ContextHubInfo {
+    int numHubs;
+    Vector<ContextHub> hubs;
+    sp<IContexthub> contextHub;
+};
+
+struct ContextHubServiceDb {
+    int initialized;
+    ContextHubInfo hubInfo;
+    JniInfo jniInfo;
+    std::queue<jint> freeIds;
+    std::unordered_map<jint, AppInstanceInfo> appInstances;
+    TxnManager txnManager;
+    std::vector<ContextHubServiceCallback *> regCallBacks;
+};
+
+ContextHubServiceDb db;
+
+int getHubIdForHubHandle(int hubHandle) {
     if (hubHandle < 0 || hubHandle >= db.hubInfo.numHubs) {
       return -1;
     } else {
-      return db.hubInfo.hubs[hubHandle].hub_id;
+      return db.hubInfo.hubs[hubHandle].hubId;
     }
 }
 
-static int get_hub_handle_for_app_instance(jint id) {
+int getHubHandleForAppInstance(jint id) {
     if (!db.appInstances.count(id)) {
         ALOGD("%s: Cannot find app for app instance %" PRId32,
-              __FUNCTION__, id);
+              __FUNCTION__,
+              id);
         return -1;
     }
 
     return db.appInstances[id].hubHandle;
 }
 
-static int get_hub_id_for_app_instance(jint id) {
-    int hubHandle = get_hub_handle_for_app_instance(id);
+int getHubIdForAppInstance(jint id) {
+    int hubHandle = getHubHandleForAppInstance(id);
 
     if (hubHandle < 0) {
+        ALOGD("Cannot find hub instance for app instance %d", id);
         return -1;
     }
 
-    return db.hubInfo.hubs[hubHandle].hub_id;
+    return db.hubInfo.hubs[hubHandle].hubId;
 }
 
-static jint get_app_instance_for_app_id(uint64_t app_id) {
+jint getAppInstanceForAppId(uint64_t app_id) {
     auto end = db.appInstances.end();
     for (auto current = db.appInstances.begin(); current != end; ++current) {
-        if (current->second.appInfo.app_name.id == app_id) {
+        if (current->second.appInfo.appId == app_id) {
             return current->first;
         }
     }
-    ALOGD("Cannot find app for app instance %" PRIu64 ".", app_id);
+    ALOGD("Cannot find app for app id %" PRIu64 ".", app_id);
     return -1;
 }
 
-static int set_dest_app(hub_message_t *msg, jint id) {
+uint64_t getAppIdForAppInstance(jint id) {
     if (!db.appInstances.count(id)) {
-        ALOGD("%s: Cannot find app for app instance %" PRId32,
-              __FUNCTION__, id);
-        return -1;
+        return INVALID_APP_ID;
     }
-
-    msg->app_name = db.appInstances[id].appInfo.app_name;
-    return 0;
+    return db.appInstances[id].appInfo.appId;
 }
 
-static void query_hub_for_apps(uint32_t hubHandle) {
-    hub_message_t msg;
-    query_apps_request_t queryMsg;
-
-    // TODO(b/30835598): When we're able to tell which request our
-    //     response matches, then we should allow this to be more
-    //     targetted, instead of always being every app in the
-    //     system.
-    queryMsg.app_name.id = ALL_APPS;
-
-    msg.message_type = CONTEXT_HUB_QUERY_APPS;
-    msg.message_len  = sizeof(queryMsg);
-    msg.message = &queryMsg;
-
-    ALOGD("Sending query for apps to hub %" PRIu32, hubHandle);
-    set_os_app_as_destination(&msg, hubHandle);
-    if (send_msg_to_hub(&msg, hubHandle) != 0) {
-        ALOGW("Could not query hub %" PRIu32 " for apps", hubHandle);
-    }
+void queryHubForApps(uint32_t hubId) {
+    Result r = db.hubInfo.contextHub->queryApps(hubId);
+    ALOGD("Sent query for apps to hub %" PRIu32 " with result %" PRIu32, hubId, r);
 }
 
-static void sendQueryForApps() {
+void sendQueryForApps() {
     for (int i = 0; i < db.hubInfo.numHubs; i++ ) {
-        query_hub_for_apps(i);
+        queryHubForApps(db.hubInfo.hubs[i].hubId);
     }
 }
 
-static int return_id(jint id) {
+int returnId(jint id) {
     // Note : This method is not thread safe.
     // id returned is guaranteed to be in use
     if (id >= 0) {
@@ -376,7 +423,7 @@
     return -1;
 }
 
-static jint generate_id() {
+jint generateId() {
     // Note : This method is not thread safe.
     jint retVal = -1;
 
@@ -388,31 +435,28 @@
     return retVal;
 }
 
-
-static jint add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle,
+jint addAppInstance(const HubAppInfo *appInfo, uint32_t hubHandle,
         jint appInstanceHandle, JNIEnv *env) {
     // Not checking if the apps are indeed distinct
-    app_instance_info_s entry;
+    AppInstanceInfo entry;
     assert(appInfo);
 
-    const char *action =
-        (db.appInstances.count(appInstanceHandle) == 0) ? "Added" : "Updated";
 
     entry.appInfo = *appInfo;
 
     entry.instanceId = appInstanceHandle;
-    entry.truncName = appInfo->app_name.id;
+    entry.truncName = appInfo->appId;
     entry.hubHandle = hubHandle;
-
     db.appInstances[appInstanceHandle] = entry;
-
     // Finally - let the service know of this app instance, to populate
     // the Java cache.
     env->CallIntMethod(db.jniInfo.jContextHubService,
                        db.jniInfo.contextHubServiceAddAppInstance,
-                       hubHandle, entry.instanceId, entry.truncName,
+                       hubHandle, entry.instanceId,
+                       entry.truncName,
                        entry.appInfo.version);
 
+    const char *action = (db.appInstances.count(appInstanceHandle) == 0) ? "Added" : "Updated";
     ALOGI("%s App 0x%" PRIx64 " on hub Handle %" PRId32
           " as appInstance %" PRId32, action, entry.truncName,
           entry.hubHandle, appInstanceHandle);
@@ -420,7 +464,7 @@
     return appInstanceHandle;
 }
 
-int delete_app_instance(jint id, JNIEnv *env) {
+int deleteAppInstance(jint id, JNIEnv *env) {
     bool fullyDeleted = true;
 
     if (db.appInstances.count(id)) {
@@ -429,7 +473,7 @@
         ALOGW("Cannot delete App id (%" PRId32 ") from the JNI C++ cache", id);
         fullyDeleted = false;
     }
-    return_id(id);
+    returnId(id);
 
     if ((env == nullptr) ||
         (env->CallIntMethod(db.jniInfo.jContextHubService,
@@ -446,12 +490,12 @@
     return -1;
 }
 
-static int startLoadAppTxn(uint64_t appId, int hubHandle) {
-    app_instance_info_s *txnInfo = (app_instance_info_s *)malloc(sizeof(app_instance_info_s));
-    jint instanceId = generate_id();
+int startLoadAppTxn(uint64_t appId, int hubHandle) {
+    AppInstanceInfo *txnInfo = new AppInstanceInfo();
+    jint instanceId = generateId();
 
     if (!txnInfo || instanceId < 0) {
-        return_id(instanceId);
+        returnId(instanceId);
         free(txnInfo);
         return -1;
     }
@@ -460,12 +504,11 @@
     txnInfo->hubHandle = hubHandle;
     txnInfo->instanceId = instanceId;
 
-    txnInfo->appInfo.app_name.id = appId;
-    txnInfo->appInfo.num_mem_ranges = 0;
+    txnInfo->appInfo.appId = appId;
     txnInfo->appInfo.version = -1; // Awaited
 
-    if (addTxn(CONTEXT_HUB_LOAD_APP, txnInfo) != 0) {
-        return_id(instanceId);
+    if (db.txnManager.addTxn(CONTEXT_HUB_LOAD_APP, txnInfo) != 0) {
+        returnId(instanceId);
         free(txnInfo);
         return -1;
     }
@@ -473,8 +516,8 @@
     return 0;
 }
 
-static int startUnloadAppTxn(jint appInstanceHandle) {
-    jint *txnData = (jint *) malloc(sizeof(jint));
+int startUnloadAppTxn(jint appInstanceHandle) {
+    jint *txnData = new(jint);
     if (!txnData) {
         ALOGW("Cannot allocate memory to start unload transaction");
         return -1;
@@ -482,7 +525,7 @@
 
     *txnData = appInstanceHandle;
 
-    if (addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) {
+    if (db.txnManager.addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) {
         free(txnData);
         ALOGW("Cannot start transaction to unload app");
         return -1;
@@ -491,17 +534,21 @@
     return 0;
 }
 
-static void initContextHubService() {
-    int err = 0;
-    db.hubInfo.hubs = nullptr;
+void getHubsCb(const ::android::hardware::hidl_vec<ContextHub>& hubs)  {
+    for (size_t i = 0; i < hubs.size(); i++) {
+        db.hubInfo.hubs.push_back(hubs[i]);
+    }
+}
+
+void initContextHubService() {
     db.hubInfo.numHubs = 0;
 
-    err = hw_get_module(CONTEXT_HUB_MODULE_ID,
-                        (hw_module_t const**)(&db.hubInfo.contextHubModule));
+    db.hubInfo.contextHub = IContexthub::getService("context_hub_hal");
 
-    if (err) {
-      ALOGE("** Could not load %s module : err %s", CONTEXT_HUB_MODULE_ID,
-            strerror(-err));
+    if (db.hubInfo.contextHub == nullptr) {
+        ALOGE("Could not load context hub hal");
+    } else {
+        ALOGI("Loaded context hub hal");
     }
 
     // Prep for storing app info
@@ -509,39 +556,46 @@
         db.freeIds.push(i);
     }
 
-    initTxnManager();
-    if (db.hubInfo.contextHubModule) {
-        int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
-                                                                 &db.hubInfo.hubs);
+    if (db.hubInfo.contextHub != nullptr) {
+        std::function<void(const ::android::hardware::hidl_vec<ContextHub>& hubs)> f = getHubsCb;
+        if(!db.hubInfo.contextHub->getHubs(f).isOk()) {
+            ALOGW("GetHubs Failed! transport error.");
+            return;
+        };
+
+        int retNumHubs = db.hubInfo.hubs.size();
         ALOGD("ContextHubModule returned %d hubs ", retNumHubs);
         db.hubInfo.numHubs = retNumHubs;
 
-        if (db.hubInfo.numHubs > 0) {
-            db.hubInfo.numHubs = retNumHubs;
-            db.hubInfo.cookies = (uint32_t *)malloc(sizeof(uint32_t) * db.hubInfo.numHubs);
+        for (int i = 0; i < db.hubInfo.numHubs; i++) {
+            ALOGI("Subscribing to hubHandle %d", i);
 
-            if (!db.hubInfo.cookies) {
-                ALOGW("Ran out of memory allocating cookies, bailing");
-                return;
-            }
-
-            for (int i = 0; i < db.hubInfo.numHubs; i++) {
-                db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id;
-                ALOGI("Subscribing to hubHandle %d with OS App name %" PRIu64, i, db.hubInfo.hubs[i].os_app_name.id);
-                if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
-                                                                    context_hub_callback,
-                                                                    &db.hubInfo.cookies[i]) == 0) {
-                }
-            }
+            ContextHubServiceCallback *callBackPtr =
+                new ContextHubServiceCallback(db.hubInfo.hubs[i].hubId);
+            db.hubInfo.contextHub->registerCallback(db.hubInfo.hubs[i].hubId,
+                                                    callBackPtr);
+            db.regCallBacks.push_back(callBackPtr);
         }
 
         sendQueryForApps();
+
     } else {
         ALOGW("No Context Hub Module present");
     }
 }
 
-static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_t msgLen) {
+void onHubReset(uint32_t hubId) {
+    TransactionResult result = TransactionResult::SUCCESS;
+    db.txnManager.closeTxn();
+    // TODO : Expose this through an api
+    passOnOsResponse(hubId, CONTEXT_HUB_OS_REBOOT, result, nullptr, 0);
+    queryHubForApps(hubId);
+}
+
+int onMessageReceipt(const uint32_t *header,
+                     size_t headerLen,
+                     const char *msg,
+                     size_t msgLen) {
     JNIEnv *env;
 
     if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
@@ -560,27 +614,27 @@
         return -1;
     }
 
-    env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
-    env->SetIntArrayRegion(jheader, 0, headerLen, (jint *)header);
+    env->SetByteArrayRegion(jmsg, 0, msgLen, reinterpret_cast<const jbyte *>(msg));
+    env->SetIntArrayRegion(jheader, 0, headerLen, reinterpret_cast<const jint *>(header));
 
     int ret = (env->CallIntMethod(db.jniInfo.jContextHubService,
-                          db.jniInfo.contextHubServiceMsgReceiptCallback,
-                          jheader, jmsg) != 0);
+                                  db.jniInfo.contextHubServiceMsgReceiptCallback,
+                                  jheader,
+                                  jmsg) != 0);
     env->DeleteLocalRef(jmsg);
     env->DeleteLocalRef(jheader);
 
     return ret;
 }
 
-int handle_query_apps_response(const uint8_t *msg, int msgLen,
+int handleQueryAppsResponse(const std::vector<HubAppInfo> apps,
                                uint32_t hubHandle) {
     JNIEnv *env;
     if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
             return -1;
     }
 
-    int numApps = msgLen / sizeof(hub_app_info);
-    const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg;
+    int numApps = apps.size();
 
     // We use this information to sync our JNI and Java caches of nanoapp info.
     // We want to accomplish two things here:
@@ -604,52 +658,50 @@
     // over just the JNI cache.
     auto end = db.appInstances.end();
     for (auto current = db.appInstances.begin(); current != end; ) {
-        app_instance_info_s cache_entry = current->second;
+        AppInstanceInfo cacheEntry = current->second;
         // We perform our iteration here because if we call
         // delete_app_instance() below, it will erase() this entry.
         current++;
         bool entryIsStale = true;
         for (int i = 0; i < numApps; i++) {
-            // We use memcmp since this could be unaligned.
-            if (memcmp(&unalignedInfoAddr[i].app_name.id,
-                       &cache_entry.appInfo.app_name.id,
-                       sizeof(cache_entry.appInfo.app_name.id)) == 0) {
+            if (apps[i].appId == cacheEntry.appInfo.appId) {
                 // We found a match; this entry is current.
                 entryIsStale = false;
                 break;
             }
         }
+
         if (entryIsStale) {
-            delete_app_instance(cache_entry.instanceId, env);
+            deleteAppInstance(cacheEntry.instanceId, env);
         }
     }
 
     // (2).  Update our caches with the latest.
     for (int i = 0; i < numApps; i++) {
-        hub_app_info query_info;
-        memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info));
         // We will only have one instance of the app
         // TODO : Change this logic once we support multiple instances of the same app
-        jint appInstance = get_app_instance_for_app_id(query_info.app_name.id);
+        jint appInstance = getAppInstanceForAppId(apps[i].appId);
         if (appInstance == -1) {
             // This is a previously unknown app, let's allocate an "id" for it.
-            appInstance = generate_id();
+            appInstance = generateId();
         }
-        add_app_instance(&query_info, hubHandle, appInstance, env);
+        addAppInstance(&apps[i], hubHandle, appInstance, env);
     }
-
     return 0;
 }
 
 // TODO(b/30807327): Do not use raw bytes for additional data.  Use the
 //     JNI interfaces for the appropriate types.
-static void passOnOsResponse(uint32_t hubHandle, uint32_t msgType,
-                             status_response_t *rsp, int8_t *additionalData,
-                             size_t additionalDataLen) {
+void passOnOsResponse(uint32_t hubHandle,
+                      uint32_t msgType,
+                      TransactionResult result,
+                      const int8_t *additionalData,
+                      size_t additionalDataLen) {
     JNIEnv *env;
 
     if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
-        ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32, msgType);
+        ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32,
+              msgType);
         return;
     }
 
@@ -679,25 +731,7 @@
     // a naive cast.  Further, we can log when we're losing part of the value.
     // TODO(b/30918279): Don't truncate this result.
     int8_t truncatedResult;
-    bool neededToTruncate;
-    if (rsp->result < INT8_MIN) {
-        neededToTruncate = true;
-        truncatedResult = INT8_MIN;
-    } else if (rsp->result > INT8_MAX) {
-        neededToTruncate = true;
-        truncatedResult = INT8_MAX;
-    } else {
-        neededToTruncate = false;
-        // Since this value fits within an int8_t, this is a safe cast which
-        // won't change the value or sign.
-        truncatedResult = static_cast<int8_t>(rsp->result);
-    }
-    if (neededToTruncate) {
-        ALOGW("Response from Context Hub truncated.  Value was %" PRId32
-              ", but giving Java layer %" PRId8,
-              rsp->result, (int)truncatedResult);
-    }
-
+    truncatedResult = static_cast<int8_t>(result);
     msg[0] = truncatedResult;
 
     if (additionalData) {
@@ -707,16 +741,19 @@
     jbyteArray jmsg = env->NewByteArray(msgLen);
     jintArray jheader = env->NewIntArray(arraysize(header));
 
-    env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
-    env->SetIntArrayRegion(jheader, 0, arraysize(header), (jint *)header);
+    env->SetByteArrayRegion(jmsg, 0, msgLen, reinterpret_cast<jbyte *>(msg));
+    env->SetIntArrayRegion(jheader, 0, arraysize(header), reinterpret_cast<jint *>(header));
 
     ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32,
-          header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE],
+          header[HEADER_FIELD_MSG_TYPE],
+          header[HEADER_FIELD_APP_INSTANCE],
           header[HEADER_FIELD_HUB_HANDLE]);
 
     env->CallIntMethod(db.jniInfo.jContextHubService,
                        db.jniInfo.contextHubServiceMsgReceiptCallback,
-                       jheader, jmsg);
+                       jheader,
+                       jmsg);
+
     env->DeleteLocalRef(jmsg);
     env->DeleteLocalRef(jheader);
 
@@ -725,9 +762,9 @@
 
 void closeUnloadTxn(bool success) {
     void *txnData = nullptr;
-    hub_messages_e txnId;
+    HubMessageType txnId;
 
-    if (success && fetchTxnData(&txnId, &txnData) == 0 &&
+    if (success && db.txnManager.fetchTxnData(&txnId, &txnData) == 0 &&
         txnId == CONTEXT_HUB_UNLOAD_APP) {
         JNIEnv *env;
         if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
@@ -735,31 +772,33 @@
             env = nullptr;
         }
         jint handle = *reinterpret_cast<jint *>(txnData);
-        delete_app_instance(handle, env);
+        deleteAppInstance(handle, env);
     } else {
-        ALOGW("Could not unload the app successfully ! success %d, txnData %p", success, txnData);
+        ALOGW("Could not unload the app successfully ! success %d, txnData %p",
+              success,
+              txnData);
     }
 
-    closeTxn();
+    db.txnManager.closeTxn();
 }
 
-static bool closeLoadTxn(bool success, jint *appInstanceHandle) {
+bool closeLoadTxn(bool success, jint *appInstanceHandle) {
     void *txnData;
-    hub_messages_e txnId;
+    HubMessageType txnId;
 
-    if (success && fetchTxnData(&txnId, &txnData) == 0 &&
+    if (success && db.txnManager.fetchTxnData(&txnId, &txnData) == 0 &&
         txnId == CONTEXT_HUB_LOAD_APP) {
-        app_instance_info_s *info = (app_instance_info_s *)txnData;
+        AppInstanceInfo *info = static_cast<AppInstanceInfo *>(txnData);
         *appInstanceHandle = info->instanceId;
 
         JNIEnv *env;
         if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) == JNI_OK) {
-            add_app_instance(&info->appInfo, info->hubHandle, info->instanceId, env);
+            addAppInstance(&info->appInfo, info->hubHandle, info->instanceId, env);
         } else {
             ALOGW("Could not attach to JVM !");
             success = false;
         }
-        // While we just called add_app_instance above, our info->appInfo was
+        // While we just called addAppInstance above, our info->appInfo was
         // incomplete (for example, the 'version' is hardcoded to -1).  So we
         // trigger an additional query to the CHRE, so we'll be able to get
         // all the app "info", and have our JNI and Java caches with the
@@ -771,162 +810,11 @@
         success = false;
     }
 
-    closeTxn();
+    db.txnManager.closeTxn();
     return success;
 }
 
-static bool isValidOsStatus(const uint8_t *msg, size_t msgLen,
-                            status_response_t *rsp) {
-    // Workaround a bug in some HALs
-    if (msgLen == 1) {
-        rsp->result = msg[0];
-        return true;
-    }
-
-    if (!msg || msgLen != sizeof(*rsp)) {
-        ALOGW("Received invalid response %p of size %zu", msg, msgLen);
-        return false;
-    }
-
-    memcpy(rsp, msg, sizeof(*rsp));
-
-    // No sanity checks on return values
-    return true;
-}
-
-static int handle_os_message(uint32_t msgType, uint32_t hubHandle,
-                             const uint8_t *msg, int msgLen) {
-    int retVal = -1;
-
-    ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
-          hubHandle, msgType, msgLen);
-
-    struct status_response_t rsp;
-
-    switch(msgType) {
-
-      case CONTEXT_HUB_APPS_ENABLE:
-      case CONTEXT_HUB_APPS_DISABLE:
-      case CONTEXT_HUB_LOAD_APP:
-      case CONTEXT_HUB_UNLOAD_APP:
-          if (isValidOsStatus(msg, msgLen, &rsp)) {
-              if (msgType == CONTEXT_HUB_LOAD_APP) {
-                  jint appInstanceHandle = INVALID_APP_ID;
-                  bool appRunningOnHub = (rsp.result == 0);
-                  if (!(closeLoadTxn(appRunningOnHub, &appInstanceHandle))) {
-                      if (appRunningOnHub) {
-                          // Now we're in an odd situation.  Our nanoapp
-                          // is up and running on the Context Hub.  However,
-                          // something went wrong in our Service code so that
-                          // we're not able to properly track this nanoapp
-                          // in our Service code.  If we tell the Java layer
-                          // things are good, it's a lie because the handle
-                          // we give them will fail when used with the Service.
-                          // If we tell the Java layer this failed, it's kind
-                          // of a lie as well, since this nanoapp is running.
-                          //
-                          // We leave a more robust fix for later, and for
-                          // now just tell the user things have failed.
-                          //
-                          // TODO(b/30835981): Make this situation better.
-                          rsp.result = -1;
-                      }
-                  }
-                  passOnOsResponse(hubHandle, msgType, &rsp, (int8_t *)(&appInstanceHandle),
-                                   sizeof(appInstanceHandle));
-              } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
-                  closeUnloadTxn(rsp.result == 0);
-                  passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
-              } else {
-                  passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
-              }
-              retVal = 0;
-          }
-          break;
-
-      case CONTEXT_HUB_QUERY_APPS:
-          rsp.result = 0;
-          retVal = handle_query_apps_response(msg, msgLen, hubHandle);
-          passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
-          break;
-
-      case CONTEXT_HUB_QUERY_MEMORY:
-          // Deferring this use
-          retVal = 0;
-          break;
-
-      case CONTEXT_HUB_OS_REBOOT:
-          if (isValidOsStatus(msg, msgLen, &rsp)) {
-              rsp.result = 0;
-              ALOGW("Context Hub handle %d restarted", hubHandle);
-              closeTxn();
-              passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
-              query_hub_for_apps(hubHandle);
-              retVal = 0;
-          }
-          break;
-
-      default:
-          retVal = -1;
-          break;
-    }
-
-    return retVal;
-}
-
-static bool sanity_check_cookie(void *cookie, uint32_t hub_id) {
-    int *ptr = (int *)cookie;
-
-    if (!ptr || *ptr >= db.hubInfo.numHubs) {
-        return false;
-    }
-
-    if (db.hubInfo.hubs[*ptr].hub_id != hub_id) {
-        return false;
-    } else {
-        return true;
-    }
-}
-
-
-int context_hub_callback(uint32_t hubId,
-                         const struct hub_message_t *msg,
-                         void *cookie) {
-    if (!msg) {
-        ALOGW("NULL message");
-        return -1;
-    }
-    if (!sanity_check_cookie(cookie, hubId)) {
-        ALOGW("Incorrect cookie %" PRId32 " for cookie %p! Bailing",
-              hubId, cookie);
-
-        return -1;
-    }
-
-
-    uint32_t messageType = msg->message_type;
-    uint32_t hubHandle = *(uint32_t*) cookie;
-
-    if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
-        handle_os_message(messageType, hubHandle, (uint8_t*) msg->message, msg->message_len);
-    } else {
-        jint appHandle = get_app_instance_for_app_id(msg->app_name.id);
-        if (appHandle < 0) {
-            ALOGE("Filtering out message due to invalid App Instance.");
-        } else {
-            uint32_t msgHeader[MSG_HEADER_SIZE] = {};
-            msgHeader[HEADER_FIELD_MSG_TYPE] = messageType;
-            msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
-            msgHeader[HEADER_FIELD_APP_INSTANCE] = appHandle;
-            onMessageReceipt(msgHeader, MSG_HEADER_SIZE, (char*) msg->message, msg->message_len);
-        }
-    }
-
-    return 0;
-}
-
-static int init_jni(JNIEnv *env, jobject instance) {
-
+int initJni(JNIEnv *env, jobject instance) {
     if (env->GetJavaVM(&db.jniInfo.vm) != JNI_OK) {
         return -1;
     }
@@ -935,7 +823,6 @@
 
     db.jniInfo.contextHubInfoClass =
             env->FindClass("android/hardware/location/ContextHubInfo");
-
     db.jniInfo.contextHubServiceClass =
             env->FindClass("com/android/server/location/ContextHubService");
 
@@ -947,112 +834,124 @@
     db.jniInfo.contextHubInfoSetId =
             env->GetMethodID(db.jniInfo.contextHubInfoClass, "setId", "(I)V");
     db.jniInfo.contextHubInfoSetName =
-            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName",
-                                "(Ljava/lang/String;)V");
-
+            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName", "(Ljava/lang/String;)V");
     db.jniInfo.contextHubInfoSetVendor =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setVendor", "(Ljava/lang/String;)V");
+                             "setVendor",
+                             "(Ljava/lang/String;)V");
     db.jniInfo.contextHubInfoSetToolchain =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setToolchain", "(Ljava/lang/String;)V");
+                             "setToolchain",
+                             "(Ljava/lang/String;)V");
     db.jniInfo.contextHubInfoSetPlatformVersion =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setPlatformVersion", "(I)V");
+                             "setPlatformVersion",
+                             "(I)V");
     db.jniInfo.contextHubInfoSetStaticSwVersion =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setStaticSwVersion", "(I)V");
+                             "setStaticSwVersion",
+                             "(I)V");
     db.jniInfo.contextHubInfoSetToolchainVersion =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setToolchainVersion", "(I)V");
+                             "setToolchainVersion",
+                             "(I)V");
     db.jniInfo.contextHubInfoSetPeakMips =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setPeakMips", "(F)V");
+                             "setPeakMips",
+                             "(F)V");
     db.jniInfo.contextHubInfoSetStoppedPowerDrawMw =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setStoppedPowerDrawMw", "(F)V");
+                             "setStoppedPowerDrawMw",
+                             "(F)V");
     db.jniInfo.contextHubInfoSetSleepPowerDrawMw =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setSleepPowerDrawMw", "(F)V");
+                             "setSleepPowerDrawMw",
+                             "(F)V");
     db.jniInfo.contextHubInfoSetPeakPowerDrawMw =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setPeakPowerDrawMw", "(F)V");
+                             "setPeakPowerDrawMw",
+                             "(F)V");
     db.jniInfo.contextHubInfoSetSupportedSensors =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setSupportedSensors", "([I)V");
+                             "setSupportedSensors",
+                             "([I)V");
     db.jniInfo.contextHubInfoSetMemoryRegions =
             env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setMemoryRegions", "([Landroid/hardware/location/MemoryRegion;)V");
+                             "setMemoryRegions",
+                             "([Landroid/hardware/location/MemoryRegion;)V");
     db.jniInfo.contextHubInfoSetMaxPacketLenBytes =
              env->GetMethodID(db.jniInfo.contextHubInfoClass,
-                                "setMaxPacketLenBytes", "(I)V");
-
-
+                              "setMaxPacketLenBytes",
+                              "(I)V");
     db.jniInfo.contextHubServiceMsgReceiptCallback =
-            env->GetMethodID(db.jniInfo.contextHubServiceClass, "onMessageReceipt",
-                               "([I[B)I");
+            env->GetMethodID(db.jniInfo.contextHubServiceClass,
+                             "onMessageReceipt",
+                             "([I[B)I");
     db.jniInfo.contextHubInfoSetName =
-            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName",
-            "(Ljava/lang/String;)V");
-
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                             "setName",
+                             "(Ljava/lang/String;)V");
     db.jniInfo.contextHubServiceAddAppInstance =
                  env->GetMethodID(db.jniInfo.contextHubServiceClass,
-                                    "addAppInstance", "(IIJI)I");
-
+                                  "addAppInstance",
+                                  "(IIJI)I");
     db.jniInfo.contextHubServiceDeleteAppInstance =
                  env->GetMethodID(db.jniInfo.contextHubServiceClass,
-                                    "deleteAppInstance", "(I)I");
+                                  "deleteAppInstance",
+                                  "(I)I");
 
     return 0;
 }
 
-static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t *hub) {
+jobject constructJContextHubInfo(JNIEnv *env, const ContextHub &hub) {
     jstring jstrBuf;
     jintArray jintBuf;
     jobjectArray jmemBuf;
 
     jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass,
                                   db.jniInfo.contextHubInfoCtor);
-    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub.hubId);
 
-    jstrBuf = env->NewStringUTF(hub->name);
+    jstrBuf = env->NewStringUTF(hub.name);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetName, jstrBuf);
     env->DeleteLocalRef(jstrBuf);
 
-    jstrBuf = env->NewStringUTF(hub->vendor);
+    jstrBuf = env->NewStringUTF(hub.vendor);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetVendor, jstrBuf);
     env->DeleteLocalRef(jstrBuf);
 
-    jstrBuf = env->NewStringUTF(hub->toolchain);
+    jstrBuf = env->NewStringUTF(hub.toolchain);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchain, jstrBuf);
     env->DeleteLocalRef(jstrBuf);
 
-    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub->platform_version);
-    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub->toolchain_version);
-    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub->peak_mips);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub.platformVersion);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub.toolchainVersion);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub.peakMips);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw,
-                        hub->stopped_power_draw_mw);
+                        hub.stoppedPowerDrawMw);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw,
-                        hub->sleep_power_draw_mw);
+                        hub.sleepPowerDrawMw);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw,
-                        hub->peak_power_draw_mw);
+                        hub.peakPowerDrawMw);
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMaxPacketLenBytes,
-                        hub->max_supported_msg_len);
+                        hub.maxSupportedMsgLen);
 
 
-    jintBuf = env->NewIntArray(hub->num_connected_sensors);
-    int *connectedSensors = new int[hub->num_connected_sensors];
+    jintBuf = env->NewIntArray(hub.connectedSensors.size());
+    int *connectedSensors = new int[hub.connectedSensors.size()];
 
     if (!connectedSensors) {
       ALOGW("Cannot allocate memory! Unexpected");
       assert(false);
     } else {
-      for (unsigned int i = 0; i < hub->num_connected_sensors; i++) {
-        connectedSensors[i] = hub->connected_sensors[i].sensor_id;
+      for (unsigned int i = 0; i < hub.connectedSensors.size(); i++) {
+        // TODO :: Populate connected sensors.
+        //connectedSensors[i] = hub.connectedSensors[i].sensorType;
+        connectedSensors[i] = 0;
       }
     }
 
-    env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
+    env->SetIntArrayRegion(jintBuf, 0, hub.connectedSensors.size(),
                            connectedSensors);
 
     env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
@@ -1069,34 +968,39 @@
     return jHub;
 }
 
-static jobjectArray nativeInitialize(JNIEnv *env, jobject instance)
-{
+jobjectArray nativeInitialize(JNIEnv *env, jobject instance) {
     jobject hub;
     jobjectArray retArray;
 
-    if (init_jni(env, instance) < 0) {
+    if (initJni(env, instance) < 0) {
         return nullptr;
     }
 
     initContextHubService();
 
     if (db.hubInfo.numHubs > 1) {
-      ALOGW("Clamping the number of hubs to 1");
-      db.hubInfo.numHubs = 1;
+        ALOGW("Clamping the number of hubs to 1");
+        db.hubInfo.numHubs = 1;
     }
 
     retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, nullptr);
 
     for(int i = 0; i < db.hubInfo.numHubs; i++) {
-        hub = constructJContextHubInfo(env, &db.hubInfo.hubs[i]);
+        hub = constructJContextHubInfo(env, db.hubInfo.hubs[i]);
         env->SetObjectArrayElement(retArray, i, hub);
     }
 
     return retArray;
 }
 
-static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
-                              jbyteArray data_) {
+jint nativeSendMessage(JNIEnv *env,
+                       jobject instance,
+                       jintArray header_,
+                       jbyteArray data_) {
+    // With the new binderized HAL definition, this function can be made much simpler.
+    // All the magic can be removed. This is not however needed for the default implementation
+    // TODO :: Change the JNI interface to conform to the new HAL interface and clean up this
+    // function
     jint retVal = -1; // Default to failure
 
     jint *header = env->GetIntArrayElements(header_, 0);
@@ -1116,7 +1020,7 @@
     uint64_t appId;
 
     if (msgType == CONTEXT_HUB_UNLOAD_APP) {
-        hubHandle = get_hub_handle_for_app_instance(appInstanceHandle);
+        hubHandle = getHubHandleForAppInstance(appInstanceHandle);
     } else if (msgType == CONTEXT_HUB_LOAD_APP) {
         if (numHeaderElements < MSG_HEADER_SIZE_LOAD_APP) {
             return -1;
@@ -1138,12 +1042,13 @@
     if (msgType == CONTEXT_HUB_LOAD_APP ||
         msgType == CONTEXT_HUB_UNLOAD_APP) {
 
-        if (isTxnPending()) {
+        db.txnManager.closeAnyStaleTxns();
+
+        if (db.txnManager.isTxnPending()) {
+            // TODO : There is a race conditio
             ALOGW("Cannot load or unload app while a transaction is pending !");
             return -1;
-        }
-
-        if (msgType == CONTEXT_HUB_LOAD_APP) {
+        } else if (msgType == CONTEXT_HUB_LOAD_APP) {
             if (startLoadAppTxn(appId, hubHandle) != 0) {
                 ALOGW("Cannot Start Load Transaction");
                 return -1;
@@ -1156,40 +1061,54 @@
         }
     }
 
-    bool setAddressSuccess = false;
-    hub_message_t msg;
-
-    msg.message_type = msgType;
+    Result result;
 
     if (msgType == CONTEXT_HUB_UNLOAD_APP) {
-        msg.message_len = sizeof(db.appInstances[appInstanceHandle].appInfo.app_name);
-        msg.message = &db.appInstances[appInstanceHandle].appInfo.app_name;
-        setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
-        hubId = get_hub_id_for_hub_handle(hubHandle);
+        hubId = getHubIdForHubHandle(hubHandle);
+        ALOGW("Calling UnLoad NanoApp for app %" PRIx64 " on hub %d",
+              db.appInstances[appInstanceHandle].appInfo.appId,
+              hubId);
+        result = db.hubInfo.contextHub->unloadNanoApp(
+                hubId, db.appInstances[appInstanceHandle].appInfo.appId, CONTEXT_HUB_UNLOAD_APP);
     } else {
-        msg.message_len = dataBufferLength;
-        msg.message = data;
-
         if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) {
-            setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
-            hubId = get_hub_id_for_hub_handle(hubHandle);
+            if (msgType == CONTEXT_HUB_LOAD_APP) {
+                std::vector<uint8_t> dataVector(reinterpret_cast<uint8_t *>(data),
+                                                reinterpret_cast<uint8_t *>(data + dataBufferLength));
+                hubId = getHubIdForHubHandle(hubHandle);
+                ALOGW("Calling Load NanoApp on hub %d", hubId);
+                result = db.hubInfo.contextHub->loadNanoApp(hubId,
+                                                            dataVector,
+                                                            CONTEXT_HUB_LOAD_APP);
+            } else {
+                ALOGD("Dropping OS addresses message of type - %" PRIu32, msgType);
+                result = Result::BAD_PARAMS;
+            }
         } else {
-            setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0);
-            hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]);
+
+            appId = getAppIdForAppInstance(header[HEADER_FIELD_APP_INSTANCE]);
+            hubId = getHubIdForAppInstance(header[HEADER_FIELD_APP_INSTANCE]);
+
+            if (appId != static_cast<uint64_t>(INVALID_APP_ID) && hubId >= 0) {
+                ContextHubMsg msg;
+                msg.appName = appId;
+                msg.msgType = msgType;
+                msg.msg.setToExternal((unsigned char *)data, dataBufferLength);
+
+                ALOGW("Sending msg of type %" PRIu32 " len %u to app %" PRIx64 " on hub %d",
+                       msgType,
+                       dataBufferLength,
+                       appId,
+                       hubId);
+                result = db.hubInfo.contextHub->sendMessageToHub(hubId, msg);
+            } else {
+                ALOGD("Cannot find application instance %u", header[HEADER_FIELD_APP_INSTANCE]);
+                result = Result::BAD_PARAMS;
+            }
         }
     }
 
-    if (setAddressSuccess && hubId >= 0) {
-        retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
-    } else {
-      ALOGD("Could not find app instance %" PRId32 " on hubHandle %" PRId32
-            ", setAddress %d",
-            header[HEADER_FIELD_APP_INSTANCE],
-            header[HEADER_FIELD_HUB_HANDLE],
-            (int)setAddressSuccess);
-    }
-
-    if (retVal != 0) {
+    if (result != Result::OK) {
         ALOGD("Send Message failure - %d", retVal);
         if (msgType == CONTEXT_HUB_LOAD_APP) {
             jint ignored;
@@ -1197,6 +1116,8 @@
         } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
             closeUnloadTxn(false);
         }
+    } else {
+        retVal = 0;
     }
 
     env->ReleaseIntArrayElements(header_, header, 0);
@@ -1207,13 +1128,13 @@
 
 //--------------------------------------------------------------------------------------------------
 //
-static const JNINativeMethod gContextHubServiceMethods[] = {
+const JNINativeMethod gContextHubServiceMethods[] = {
     {"nativeInitialize",
-             "()[Landroid/hardware/location/ContextHubInfo;",
-             (void*)nativeInitialize },
+            "()[Landroid/hardware/location/ContextHubInfo;",
+            reinterpret_cast<void*>(nativeInitialize)},
     {"nativeSendMessage",
             "([I[B)I",
-            (void*)nativeSendMessage }
+            reinterpret_cast<void*>(nativeSendMessage)}
 };
 
 int register_android_server_location_ContextHubService(JNIEnv *env)