19ff7d2235427b211344fa58b608424805a21aa24Peng Xu/*
29ff7d2235427b211344fa58b608424805a21aa24Peng Xu * Copyright 2016, The Android Open Source Project
39ff7d2235427b211344fa58b608424805a21aa24Peng Xu *
49ff7d2235427b211344fa58b608424805a21aa24Peng Xu * Licensed under the Apache License, Version 2.0 (the "License");
59ff7d2235427b211344fa58b608424805a21aa24Peng Xu * you may not use this file except in compliance with the License.
69ff7d2235427b211344fa58b608424805a21aa24Peng Xu * You may obtain a copy of the License at
79ff7d2235427b211344fa58b608424805a21aa24Peng Xu *
89ff7d2235427b211344fa58b608424805a21aa24Peng Xu *     http://www.apache.org/licenses/LICENSE-2.0
99ff7d2235427b211344fa58b608424805a21aa24Peng Xu *
109ff7d2235427b211344fa58b608424805a21aa24Peng Xu * Unless required by applicable law or agreed to in writing, software
119ff7d2235427b211344fa58b608424805a21aa24Peng Xu * distributed under the License is distributed on an "AS IS" BASIS,
129ff7d2235427b211344fa58b608424805a21aa24Peng Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139ff7d2235427b211344fa58b608424805a21aa24Peng Xu * See the License for the specific language governing permissions and
149ff7d2235427b211344fa58b608424805a21aa24Peng Xu * limitations under the License.
159ff7d2235427b211344fa58b608424805a21aa24Peng Xu */
169ff7d2235427b211344fa58b608424805a21aa24Peng Xu
1785547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi#undef LOG_NDEBUG
1885547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi#undef LOG_TAG
19b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi#define LOG_NDEBUG 0
20b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi#define LOG_TAG "ContextHubService"
21b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
22b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi#include <inttypes.h>
23b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi#include <jni.h>
249ff7d2235427b211344fa58b608424805a21aa24Peng Xu#include <stdint.h>
259ff7d2235427b211344fa58b608424805a21aa24Peng Xu#include <stdio.h>
26b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi#include <stdlib.h>
2785547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi#include <string.h>
286644c4547ce849327197786f02da7a045a860aceBrian Duddie#include <sys/endian.h>
29b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
3085547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi#include <chrono>
3185547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi#include <mutex>
3285547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi#include <queue>
3385547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi#include <unordered_map>
346644c4547ce849327197786f02da7a045a860aceBrian Duddie#include <utility>
3585547d15e06b280e5fedc8a297f516cb414d43a3Ashutosh Joshi
3619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi#include <android-base/macros.h>
3719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi#include <android/hardware/contexthub/1.0/IContexthub.h>
3819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi#include <cutils/log.h>
39b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
4019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi#include "core_jni_helpers.h"
4119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi#include "JNIHelp.h"
4254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
438c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::AsyncEventType;
448c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::ContextHub;
458c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::ContextHubMsg;
468c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::HubAppInfo;
478c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::IContexthub;
488c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::IContexthubCallback;
496644c4547ce849327197786f02da7a045a860aceBrian Duddieusing android::hardware::contexthub::V1_0::NanoAppBinary;
508c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::Result;
518c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::contexthub::V1_0::TransactionResult;
52b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
538c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddieusing android::hardware::Return;
549ff7d2235427b211344fa58b608424805a21aa24Peng Xu
5529e868071d64ebbcf6191bb5b7542875ad6fcef8Greg Kaiserusing std::chrono::steady_clock;
568c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie
5719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi// If a transaction takes longer than this, we'll allow it to be
5819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi// canceled by a new transaction.  Note we do _not_ automatically
5919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi// cancel a transaction after this much time.  We can have a
6019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi// legal transaction which takes longer than this amount of time,
6119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi// as long as no other new transactions are attempted after this
6219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi// time has expired.
6319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr auto kMinTransactionCancelTime = std::chrono::seconds(29);
6429e868071d64ebbcf6191bb5b7542875ad6fcef8Greg Kaiser
659ff7d2235427b211344fa58b608424805a21aa24Peng Xunamespace android {
669ff7d2235427b211344fa58b608424805a21aa24Peng Xu
676644c4547ce849327197786f02da7a045a860aceBrian Duddieconstexpr uint32_t kNanoAppBinaryHeaderVersion = 1;
686644c4547ce849327197786f02da7a045a860aceBrian Duddie
696644c4547ce849327197786f02da7a045a860aceBrian Duddie// Important: this header is explicitly defined as little endian byte order, and
706644c4547ce849327197786f02da7a045a860aceBrian Duddie// therefore may not match host endianness
716644c4547ce849327197786f02da7a045a860aceBrian Duddiestruct NanoAppBinaryHeader {
726644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint32_t headerVersion;        // 0x1 for this version
736644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint32_t magic;                // "NANO" (see NANOAPP_MAGIC in context_hub.h)
746644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint64_t appId;                // App Id, contains vendor id
756644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint32_t appVersion;           // Version of the app
766644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint32_t flags;                // Signed, encrypted
776644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint64_t hwHubType;            // Which hub type is this compiled for
786644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint8_t targetChreApiMajorVersion; // Which CHRE API version this is compiled for
796644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint8_t targetChreApiMinorVersion;
806644c4547ce849327197786f02da7a045a860aceBrian Duddie    uint8_t reserved[6];
816644c4547ce849327197786f02da7a045a860aceBrian Duddie} __attribute__((packed));
826644c4547ce849327197786f02da7a045a860aceBrian Duddie
8319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshienum HubMessageType {
8419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    CONTEXT_HUB_APPS_ENABLE  = 1, // Enables loaded nano-app(s)
8519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    CONTEXT_HUB_APPS_DISABLE = 2, // Disables loaded nano-app(s)
8619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    CONTEXT_HUB_LOAD_APP     = 3, // Load a supplied app
8719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    CONTEXT_HUB_UNLOAD_APP   = 4, // Unload a specified app
8819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    CONTEXT_HUB_QUERY_APPS   = 5, // Query for app(s) info on hub
8919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    CONTEXT_HUB_QUERY_MEMORY = 6, // Query for memory info
9019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    CONTEXT_HUB_OS_REBOOT    = 7, // Request to reboot context HUB OS
9119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi};
929ff7d2235427b211344fa58b608424805a21aa24Peng Xu
9319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr jint OS_APP_ID = -1;
9419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr jint INVALID_APP_ID = -2;
9519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
9619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr jint MIN_APP_ID = 1;
9719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr jint MAX_APP_ID = 128;
9819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
9919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t MSG_HEADER_SIZE = 4;
10019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t HEADER_FIELD_MSG_TYPE = 0;
10119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t HEADER_FIELD_MSG_VERSION = 1;
10219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t HEADER_FIELD_HUB_HANDLE = 2;
10319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t HEADER_FIELD_APP_INSTANCE = 3;
10419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
10519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
10619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
10719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconstexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
10819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
10919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshijint getAppInstanceForAppId(uint64_t app_id);
11019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint onMessageReceipt(const uint32_t *header,
11119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                     size_t headerLen,
11219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                     const char *msg,
11319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                     size_t msgLen);
11419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid onHubReset(uint32_t hubId);
11519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid queryHubForApps(uint32_t hubId);
11619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid passOnOsResponse(uint32_t hubHandle,
11719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      uint32_t msgType,
11819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      TransactionResult result,
11919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      const int8_t *additionalData,
12019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      size_t additionalDataLen);
12119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
12219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshibool closeLoadTxn(bool success, jint *appInstanceHandle);
12319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid closeUnloadTxn(bool success);
12419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint handleQueryAppsResponse(const std::vector<HubAppInfo> apps,
12519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                               uint32_t hubHandle);
12619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
12719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshistruct JniInfo {
1289ff7d2235427b211344fa58b608424805a21aa24Peng Xu    JavaVM *vm;
1299ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jclass contextHubInfoClass;
1309ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jclass contextHubServiceClass;
1319ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jclass memoryRegionsClass;
1329ff7d2235427b211344fa58b608424805a21aa24Peng Xu
1339ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jobject jContextHubService;
1349ff7d2235427b211344fa58b608424805a21aa24Peng Xu
1359ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID msgReceiptCallBack;
1369ff7d2235427b211344fa58b608424805a21aa24Peng Xu
1379ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoCtor;
1389ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetId;
1399ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetName;
1409ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetVendor;
1419ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetToolchain;
1429ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetPlatformVersion;
1439ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetStaticSwVersion;
1449ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetToolchainVersion;
1459ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetPeakMips;
1469ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetStoppedPowerDrawMw;
1479ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetSleepPowerDrawMw;
1489ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetPeakPowerDrawMw;
1499ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetSupportedSensors;
1509ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubInfoSetMemoryRegions;
151b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    jmethodID contextHubInfoSetMaxPacketLenBytes;
1529ff7d2235427b211344fa58b608424805a21aa24Peng Xu
1539ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jmethodID contextHubServiceMsgReceiptCallback;
154b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    jmethodID contextHubServiceAddAppInstance;
15554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    jmethodID contextHubServiceDeleteAppInstance;
1569ff7d2235427b211344fa58b608424805a21aa24Peng Xu};
1579ff7d2235427b211344fa58b608424805a21aa24Peng Xu
1589ff7d2235427b211344fa58b608424805a21aa24Peng Xu
15954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
16019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiclass TxnManager {
16119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshipublic:
16219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    TxnManager() {
16319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mData = nullptr;
16419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mIsPending = false;
16519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
16629e868071d64ebbcf6191bb5b7542875ad6fcef8Greg Kaiser
16719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    ~TxnManager() {
16819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        closeTxn();
16919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
17029e868071d64ebbcf6191bb5b7542875ad6fcef8Greg Kaiser
17119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    int addTxn(HubMessageType txnIdentifier, void *txnData) {
17219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        std::lock_guard<std::mutex>lock(mLock);
17319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (mIsPending) {
17419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGW("Transaction already found pending when trying to add a new one.");
17519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            return -1;
17619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        }
17719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mIsPending = true;
17819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mFirstTimeTxnCanBeCanceled = steady_clock::now() + kMinTransactionCancelTime;
17919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mData = txnData;
18019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mIdentifier = txnIdentifier;
181b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
18219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return 0;
18319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
1849ff7d2235427b211344fa58b608424805a21aa24Peng Xu
18519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    int closeTxn() {
18619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        std::lock_guard<std::mutex>lock(mLock);
18719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        closeTxnUnlocked();
18819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return 0;
18919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
1909ff7d2235427b211344fa58b608424805a21aa24Peng Xu
19119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    bool isTxnPending() {
19219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        std::lock_guard<std::mutex>lock(mLock);
19319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return mIsPending;
19419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
1959ff7d2235427b211344fa58b608424805a21aa24Peng Xu
19619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    void closeAnyStaleTxns() {
19719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        std::lock_guard<std::mutex>lock(mLock);
19819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (mIsPending && steady_clock::now() >= mFirstTimeTxnCanBeCanceled) {
19919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGW("Stale transaction canceled");
20019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            closeTxnUnlocked();
20119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        }
20219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
20354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
20419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    int fetchTxnData(HubMessageType *id, void **data) {
20519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (id == nullptr || data == nullptr) {
20619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGW("Null Params isNull{id, data} {%d, %d}",
20719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                  id == nullptr ? 1 : 0,
20819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                  data == nullptr ? 1 : 0);
20919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            return -1;
21019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        }
21154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
21219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        std::lock_guard<std::mutex>lock(mLock);
21319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (!mIsPending) {
21419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGW("No Transactions pending");
21519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            return -1;
21619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        }
21754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
21819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        *id = mIdentifier;
21919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        *data = mData;
22019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return 0;
22119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
22254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
22319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi private:
22419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    bool mIsPending;            // Is a transaction pending
22519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    std::mutex mLock;           // mutex for manager
22619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    HubMessageType mIdentifier; // What are we doing
22719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    void *mData;                // Details
22819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    steady_clock::time_point mFirstTimeTxnCanBeCanceled;
22919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
23019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    // Only call this if you hold the lock.
23119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    void closeTxnUnlocked() {
23219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mIsPending = false;
23319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        free(mData);
23419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mData = nullptr;
23519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
23619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi};
23754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
23854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
23919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshistruct ContextHubServiceCallback : IContexthubCallback {
24019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    uint32_t mContextHubId;
24154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
24219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    ContextHubServiceCallback(uint32_t hubId) {
24319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mContextHubId = hubId;
24419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
24554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
24619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    virtual Return<void> handleClientMsg(const ContextHubMsg &msg) {
24719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        jint appHandle = getAppInstanceForAppId(msg.appName);
24819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (appHandle < 0) {
24919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGE("Filtering out message due to invalid App Instance.");
25019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        } else {
25119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            uint32_t msgHeader[MSG_HEADER_SIZE] = {};
25219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            msgHeader[HEADER_FIELD_MSG_TYPE] = msg.msgType;
25319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            msgHeader[HEADER_FIELD_HUB_HANDLE] = mContextHubId;
25419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            msgHeader[HEADER_FIELD_APP_INSTANCE] = appHandle;
25519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            onMessageReceipt(msgHeader,
25619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             MSG_HEADER_SIZE,
25719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             reinterpret_cast<const char *>(msg.msg.data()),
25819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             msg.msg.size());
25929e868071d64ebbcf6191bb5b7542875ad6fcef8Greg Kaiser        }
26019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
26119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return android::hardware::Void();
26229e868071d64ebbcf6191bb5b7542875ad6fcef8Greg Kaiser    }
26354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
26419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    virtual Return<void> handleHubEvent(AsyncEventType evt) {
26519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (evt == AsyncEventType::RESTARTED) {
26619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGW("Context Hub handle %d restarted", mContextHubId);
26719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            onHubReset(mContextHubId);
26819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        } else {
26919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGW("Cannot handle event %u from hub %d", evt, mContextHubId);
27019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        }
27154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
27219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return android::hardware::Void();
27354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
27454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
27519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    virtual Return<void> handleTxnResult(uint32_t txnId,
27619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                         TransactionResult result) {
27719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        ALOGI("Handle transaction result , hubId %" PRIu32 ", txnId %" PRIu32 ", result %" PRIu32,
27819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              mContextHubId,
27919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              txnId,
28019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              result);
28119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
28219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        switch(txnId) {
28319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            case CONTEXT_HUB_APPS_ENABLE:
28419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            case CONTEXT_HUB_APPS_DISABLE:
28519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                passOnOsResponse(mContextHubId, txnId, result, nullptr, 0);
28619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                break;
28754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
28819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            case CONTEXT_HUB_UNLOAD_APP:
28919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                closeUnloadTxn(result == TransactionResult::SUCCESS);
29019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                passOnOsResponse(mContextHubId, txnId, result, nullptr, 0);
29119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                break;
29254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
29319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            case CONTEXT_HUB_LOAD_APP:
29419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                {
29519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                    jint appInstanceHandle = INVALID_APP_ID;
29619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                    bool appRunningOnHub = (result == TransactionResult::SUCCESS);
29719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                    if (!(closeLoadTxn(appRunningOnHub, &appInstanceHandle))) {
29819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                        if (appRunningOnHub) {
29919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // Now we're in an odd situation.  Our nanoapp
30019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // is up and running on the Context Hub.  However,
30119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // something went wrong in our Service code so that
30219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // we're not able to properly track this nanoapp
30319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // in our Service code.  If we tell the Java layer
30419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // things are good, it's a lie because the handle
30519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // we give them will fail when used with the Service.
30619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // If we tell the Java layer this failed, it's kind
30719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // of a lie as well, since this nanoapp is running.
30819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            //
30919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // We leave a more robust fix for later, and for
31019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // now just tell the user things have failed.
31119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            //
31219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            // TODO(b/30835981): Make this situation better.
31319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                            result = TransactionResult::FAILURE;
31419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                        }
31519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                    }
31619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
31719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                    passOnOsResponse(mContextHubId,
31819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                     txnId,
31919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                     result,
32019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                     reinterpret_cast<int8_t *>(&appInstanceHandle),
32119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                     sizeof(appInstanceHandle));
32219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                    break;
32319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                }
3249ff7d2235427b211344fa58b608424805a21aa24Peng Xu
32519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            default:
32619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                ALOGI("unrecognized transction id %" PRIu32, txnId);
32719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                break;
32819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        }
32919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return android::hardware::Void();
330b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
331b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
33219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    virtual Return<void> handleAppsInfo(
33319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            const android::hardware::hidl_vec<HubAppInfo>& apps) {
3345c78ae3d1d511a8cccf2165b237b479db4fead9fAshutosh Joshi        TransactionResult result = TransactionResult::SUCCESS;
33519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        handleQueryAppsResponse(apps,mContextHubId);
3365c78ae3d1d511a8cccf2165b237b479db4fead9fAshutosh Joshi        passOnOsResponse(mContextHubId, CONTEXT_HUB_QUERY_APPS, result, nullptr, 0);
33719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return android::hardware::Void();
338b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
339b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
340ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi    virtual Return<void> handleAppAbort(uint64_t appId, uint32_t abortCode) {
341ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi        ALOGI("Handle app aport called from %" PRIx64 " with abort code %" PRIu32,
342ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi            appId,
343ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi            abortCode);
344ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi
345ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi        // TODO: Plumb this to the clients interested in this app
346ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi        return android::hardware::Void();
347ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi    }
348ccb8e675257b729d0322461b09ad20effd3f5dc5Ashutosh Joshi
34919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    void setContextHubId(uint32_t id) {
35019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        mContextHubId = id;
35119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
352b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
35319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    uint32_t getContextHubId() {
35419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return(mContextHubId);
355b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
35619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi};
357b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
35819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshistruct AppInstanceInfo {
35919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    HubAppInfo appInfo;          // returned from the HAL
36019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    uint64_t truncName;          // Possibly truncated name for logging
36119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    uint32_t hubHandle;          // Id of the hub this app is on
36219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    jint instanceId;             // system wide unique instance id - assigned
36319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi};
36419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
36519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshistruct ContextHubInfo {
36619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    int numHubs;
36719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    Vector<ContextHub> hubs;
36819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    sp<IContexthub> contextHub;
36919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi};
37019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
37119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshistruct ContextHubServiceDb {
37219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    int initialized;
37319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    ContextHubInfo hubInfo;
37419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    JniInfo jniInfo;
37519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    std::queue<jint> freeIds;
37619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    std::unordered_map<jint, AppInstanceInfo> appInstances;
37719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    TxnManager txnManager;
37819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    std::vector<ContextHubServiceCallback *> regCallBacks;
37919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi};
38019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
38119753cca3f49db2ca66106393d8302c0555fae79Ashutosh JoshiContextHubServiceDb db;
38219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
3838c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddiebool getHubIdForHubHandle(int hubHandle, uint32_t *hubId) {
3848c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie    if (hubHandle < 0 || hubHandle >= db.hubInfo.numHubs || hubId == nullptr) {
3858c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie        return false;
386cafdee9a72652354c5bde0b13c86dac3d88ac2aeAshutosh Joshi    } else {
3878c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie        *hubId = db.hubInfo.hubs[hubHandle].hubId;
3888c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie        return true;
389cafdee9a72652354c5bde0b13c86dac3d88ac2aeAshutosh Joshi    }
390cafdee9a72652354c5bde0b13c86dac3d88ac2aeAshutosh Joshi}
391cafdee9a72652354c5bde0b13c86dac3d88ac2aeAshutosh Joshi
39219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint getHubHandleForAppInstance(jint id) {
393ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov    if (!db.appInstances.count(id)) {
394f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser        ALOGD("%s: Cannot find app for app instance %" PRId32,
39519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              __FUNCTION__,
39619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              id);
397b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        return -1;
398b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
399b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
40054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    return db.appInstances[id].hubHandle;
40154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi}
40254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
40319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshijint getAppInstanceForAppId(uint64_t app_id) {
4046469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa    auto end = db.appInstances.end();
4056469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa    for (auto current = db.appInstances.begin(); current != end; ++current) {
40619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (current->second.appInfo.appId == app_id) {
4076469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa            return current->first;
4086469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa        }
4096469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa    }
41019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    ALOGD("Cannot find app for app id %" PRIu64 ".", app_id);
4116469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa    return -1;
4126469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa}
4136469c233fb9f7e617a5bc8b5d8348d7241d279c7destradaa
41419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiuint64_t getAppIdForAppInstance(jint id) {
415ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov    if (!db.appInstances.count(id)) {
41619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        return INVALID_APP_ID;
417b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
41819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    return db.appInstances[id].appInfo.appId;
419b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
420b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
42119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid queryHubForApps(uint32_t hubId) {
42219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    Result r = db.hubInfo.contextHub->queryApps(hubId);
42319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    ALOGD("Sent query for apps to hub %" PRIu32 " with result %" PRIu32, hubId, r);
42454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi}
42554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
42619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid sendQueryForApps() {
427b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    for (int i = 0; i < db.hubInfo.numHubs; i++ ) {
42819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        queryHubForApps(db.hubInfo.hubs[i].hubId);
429b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
430b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
431b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
43219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint returnId(jint id) {
433b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    // Note : This method is not thread safe.
43454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    // id returned is guaranteed to be in use
43554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (id >= 0) {
43654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        db.freeIds.push(id);
43754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return 0;
43854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
43954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
44054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    return -1;
441b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
442b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
44319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshijint generateId() {
444b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    // Note : This method is not thread safe.
445f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser    jint retVal = -1;
446b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
447b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    if (!db.freeIds.empty()) {
448b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        retVal = db.freeIds.front();
449b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        db.freeIds.pop();
450b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
451b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
452b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    return retVal;
453b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
454b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
45519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshijint addAppInstance(const HubAppInfo *appInfo, uint32_t hubHandle,
456f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser        jint appInstanceHandle, JNIEnv *env) {
457b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    // Not checking if the apps are indeed distinct
45819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    AppInstanceInfo entry;
459ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov    assert(appInfo);
460b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
461b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
462ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov    entry.appInfo = *appInfo;
46354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
464ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov    entry.instanceId = appInstanceHandle;
46519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    entry.truncName = appInfo->appId;
466ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov    entry.hubHandle = hubHandle;
467b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    db.appInstances[appInstanceHandle] = entry;
468f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // Finally - let the service know of this app instance, to populate
469f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // the Java cache.
470b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    env->CallIntMethod(db.jniInfo.jContextHubService,
471b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi                       db.jniInfo.contextHubServiceAddAppInstance,
47219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       hubHandle, entry.instanceId,
47319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       entry.truncName,
474ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov                       entry.appInfo.version);
475b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
47619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    const char *action = (db.appInstances.count(appInstanceHandle) == 0) ? "Added" : "Updated";
477f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    ALOGI("%s App 0x%" PRIx64 " on hub Handle %" PRId32
478fe6d4f518a34aa620eda9fe36365c2f750e6c67fGreg Kaiser          " as appInstance %" PRId32, action, entry.truncName,
479ab2d44596b749f3095a262ca3dc3188238dd19d1Alexey Polyudov          entry.hubHandle, appInstanceHandle);
480b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
481b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    return appInstanceHandle;
482b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
483b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
48419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint deleteAppInstance(jint id, JNIEnv *env) {
4850d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    bool fullyDeleted = true;
486b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
4870d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    if (db.appInstances.count(id)) {
4880d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        db.appInstances.erase(id);
4890d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    } else {
490f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser        ALOGW("Cannot delete App id (%" PRId32 ") from the JNI C++ cache", id);
4910d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        fullyDeleted = false;
4920d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    }
49319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    returnId(id);
4940d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser
4950d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    if ((env == nullptr) ||
4960d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        (env->CallIntMethod(db.jniInfo.jContextHubService,
49754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi                       db.jniInfo.contextHubServiceDeleteAppInstance,
4980d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser                       id) != 0)) {
499f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser        ALOGW("Cannot delete App id (%" PRId32 ") from Java cache", id);
5000d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        fullyDeleted = false;
50154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
50254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
5030d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    if (fullyDeleted) {
504f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser        ALOGI("Deleted App id : %" PRId32, id);
5050d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        return 0;
5060d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    }
5070d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser    return -1;
50854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi}
50954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
51019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint startLoadAppTxn(uint64_t appId, int hubHandle) {
51119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    AppInstanceInfo *txnInfo = new AppInstanceInfo();
51219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    jint instanceId = generateId();
51354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
51454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (!txnInfo || instanceId < 0) {
51519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        returnId(instanceId);
51654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        free(txnInfo);
51754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return -1;
51854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
51954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
52054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    txnInfo->truncName = appId;
52154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    txnInfo->hubHandle = hubHandle;
52254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    txnInfo->instanceId = instanceId;
52354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
52419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    txnInfo->appInfo.appId = appId;
52554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    txnInfo->appInfo.version = -1; // Awaited
52654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
52719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (db.txnManager.addTxn(CONTEXT_HUB_LOAD_APP, txnInfo) != 0) {
52819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        returnId(instanceId);
52954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        free(txnInfo);
53054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return -1;
53154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
532b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
533b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    return 0;
534b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
535b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
53619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint startUnloadAppTxn(jint appInstanceHandle) {
53719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    jint *txnData = new(jint);
53854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (!txnData) {
53954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        ALOGW("Cannot allocate memory to start unload transaction");
54054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return -1;
54154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
54254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
54354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    *txnData = appInstanceHandle;
54454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
54519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (db.txnManager.addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) {
54654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        free(txnData);
54754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        ALOGW("Cannot start transaction to unload app");
54854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return -1;
54954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
55054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
55154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    return 0;
55254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi}
553b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
55419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid getHubsCb(const ::android::hardware::hidl_vec<ContextHub>& hubs)  {
55519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    for (size_t i = 0; i < hubs.size(); i++) {
55619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        db.hubInfo.hubs.push_back(hubs[i]);
55719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    }
55819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi}
55919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
56019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid initContextHubService() {
5619ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.hubInfo.numHubs = 0;
5629ff7d2235427b211344fa58b608424805a21aa24Peng Xu
563de69003f072c0007679a6ad0c0e5f84fde6150d0Chris Phoenix    db.hubInfo.contextHub = IContexthub::getService();
5649ff7d2235427b211344fa58b608424805a21aa24Peng Xu
56519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (db.hubInfo.contextHub == nullptr) {
56619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        ALOGE("Could not load context hub hal");
56719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    } else {
5684c43591588f69f80f21e5341cdf089cb5363d617Ashutosh Joshi        ALOGI("Loaded context hub hal, isRemote %s", db.hubInfo.contextHub->isRemote() ? "TRUE" : "FALSE");
5699ff7d2235427b211344fa58b608424805a21aa24Peng Xu    }
5709ff7d2235427b211344fa58b608424805a21aa24Peng Xu
571b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    // Prep for storing app info
572f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser    for (jint i = MIN_APP_ID; i <= MAX_APP_ID; i++) {
573b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        db.freeIds.push(i);
574b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
575b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
57619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (db.hubInfo.contextHub != nullptr) {
57719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        std::function<void(const ::android::hardware::hidl_vec<ContextHub>& hubs)> f = getHubsCb;
57819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if(!db.hubInfo.contextHub->getHubs(f).isOk()) {
57919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGW("GetHubs Failed! transport error.");
58019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            return;
58119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        };
58219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
58319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        int retNumHubs = db.hubInfo.hubs.size();
584b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        ALOGD("ContextHubModule returned %d hubs ", retNumHubs);
585b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        db.hubInfo.numHubs = retNumHubs;
586b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
58719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        for (int i = 0; i < db.hubInfo.numHubs; i++) {
58819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ALOGI("Subscribing to hubHandle %d", i);
589b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
59019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            ContextHubServiceCallback *callBackPtr =
59119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                new ContextHubServiceCallback(db.hubInfo.hubs[i].hubId);
59219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            db.hubInfo.contextHub->registerCallback(db.hubInfo.hubs[i].hubId,
59319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                                    callBackPtr);
59419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            db.regCallBacks.push_back(callBackPtr);
5952c697fb4a8b8f8c0a2acf1fb15027f363f74c2dcAshutosh Joshi        }
596b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
597f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        sendQueryForApps();
59819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
599b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    } else {
600b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        ALOGW("No Context Hub Module present");
6019ff7d2235427b211344fa58b608424805a21aa24Peng Xu    }
6029ff7d2235427b211344fa58b608424805a21aa24Peng Xu}
6039ff7d2235427b211344fa58b608424805a21aa24Peng Xu
60419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid onHubReset(uint32_t hubId) {
60519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    TransactionResult result = TransactionResult::SUCCESS;
60619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    db.txnManager.closeTxn();
60719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    // TODO : Expose this through an api
60819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    passOnOsResponse(hubId, CONTEXT_HUB_OS_REBOOT, result, nullptr, 0);
60919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    queryHubForApps(hubId);
61019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi}
61119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
61219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint onMessageReceipt(const uint32_t *header,
61319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                     size_t headerLen,
61419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                     const char *msg,
61519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                     size_t msgLen) {
6169ff7d2235427b211344fa58b608424805a21aa24Peng Xu    JNIEnv *env;
617b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
618b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
6199ff7d2235427b211344fa58b608424805a21aa24Peng Xu      return -1;
6209ff7d2235427b211344fa58b608424805a21aa24Peng Xu    }
6219ff7d2235427b211344fa58b608424805a21aa24Peng Xu
6229ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jbyteArray jmsg = env->NewByteArray(msgLen);
623bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    if (jmsg == nullptr) {
624bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser        ALOGW("Can't allocate %zu byte array", msgLen);
625bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser        return -1;
626bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    }
6279ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jintArray jheader = env->NewIntArray(headerLen);
628bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    if (jheader == nullptr) {
629bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser        env->DeleteLocalRef(jmsg);
630bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser        ALOGW("Can't allocate %zu int array", headerLen);
631bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser        return -1;
632bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    }
6339ff7d2235427b211344fa58b608424805a21aa24Peng Xu
63419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->SetByteArrayRegion(jmsg, 0, msgLen, reinterpret_cast<const jbyte *>(msg));
63519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->SetIntArrayRegion(jheader, 0, headerLen, reinterpret_cast<const jint *>(header));
6369ff7d2235427b211344fa58b608424805a21aa24Peng Xu
637bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    int ret = (env->CallIntMethod(db.jniInfo.jContextHubService,
63819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                  db.jniInfo.contextHubServiceMsgReceiptCallback,
63919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                  jheader,
64019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                  jmsg) != 0);
641bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    env->DeleteLocalRef(jmsg);
642bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    env->DeleteLocalRef(jheader);
643bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser
644bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    return ret;
645b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
646b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
64719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint handleQueryAppsResponse(const std::vector<HubAppInfo> apps,
64854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi                               uint32_t hubHandle) {
649b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    JNIEnv *env;
650b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
651b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi            return -1;
652b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
653b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
65419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    int numApps = apps.size();
655b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
656f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // We use this information to sync our JNI and Java caches of nanoapp info.
657f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // We want to accomplish two things here:
658f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // 1) Remove entries from our caches which are stale, and pertained to
659f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    //    apps no longer running on Context Hub.
660f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // 2) Populate our caches with the latest information of all these apps.
661f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser
662f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // We make a couple of assumptions here:
663f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // A) The JNI and Java caches are in sync with each other (this isn't
664f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    //    necessarily true; any failure of a single call into Java land to
665f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    //    update its cache will leave that cache in a bad state.  For NYC,
666f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    //    we're willing to tolerate this for now).
667f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // B) The total number of apps is relatively small, so horribly inefficent
668f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    //    algorithms aren't too painful.
669f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // C) We're going to call this relatively infrequently, so its inefficency
670f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    //    isn't a big impact.
671f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser
672f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser
673f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // (1).  Looking for stale cache entries.  Yes, this is O(N^2).  See
674f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // assumption (B).  Per assumption (A), it is sufficient to iterate
675f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // over just the JNI cache.
676f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    auto end = db.appInstances.end();
677f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    for (auto current = db.appInstances.begin(); current != end; ) {
67819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        AppInstanceInfo cacheEntry = current->second;
679f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        // We perform our iteration here because if we call
680f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        // delete_app_instance() below, it will erase() this entry.
681f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        current++;
682f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        bool entryIsStale = true;
683f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        for (int i = 0; i < numApps; i++) {
68419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            if (apps[i].appId == cacheEntry.appInfo.appId) {
685f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser                // We found a match; this entry is current.
686f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser                entryIsStale = false;
687f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser                break;
688f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser            }
689f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        }
69019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
691f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        if (entryIsStale) {
69219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            deleteAppInstance(cacheEntry.instanceId, env);
693f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        }
694f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    }
695f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser
696f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    // (2).  Update our caches with the latest.
697f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser    for (int i = 0; i < numApps; i++) {
69854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        // We will only have one instance of the app
69954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        // TODO : Change this logic once we support multiple instances of the same app
70019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        jint appInstance = getAppInstanceForAppId(apps[i].appId);
701f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        if (appInstance == -1) {
702f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser            // This is a previously unknown app, let's allocate an "id" for it.
70319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            appInstance = generateId();
704f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        }
70519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        addAppInstance(&apps[i], hubHandle, appInstance, env);
706b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
707b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    return 0;
708b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi}
709b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
710f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser// TODO(b/30807327): Do not use raw bytes for additional data.  Use the
711f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser//     JNI interfaces for the appropriate types.
71219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshivoid passOnOsResponse(uint32_t hubHandle,
71319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      uint32_t msgType,
71419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      TransactionResult result,
71519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      const int8_t *additionalData,
71619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                      size_t additionalDataLen) {
71754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    JNIEnv *env;
718b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
71954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
72019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32,
72119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              msgType);
72254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return;
72354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
724b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
72554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    uint32_t header[MSG_HEADER_SIZE];
72654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    memset(header, 0, sizeof(header));
7276239cc6fe1d18ce4365c56346a09c7963dfa8f10Ashutosh Joshi
72854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (!additionalData) {
72954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        additionalDataLen = 0; // clamp
73054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
73154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    int msgLen = 1 + additionalDataLen;
732b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
73354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    int8_t *msg = new int8_t[msgLen];
734b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
73554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (!msg) {
73654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        ALOGW("Unexpected : Ran out of memory, cannot send response");
73754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return;
73854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
73954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
74054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    header[HEADER_FIELD_MSG_TYPE] = msgType;
74154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    header[HEADER_FIELD_MSG_VERSION] = 0;
74254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    header[HEADER_FIELD_HUB_HANDLE] = hubHandle;
74354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    header[HEADER_FIELD_APP_INSTANCE] = OS_APP_ID;
74454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
7456d9e7f669a6f03fa73abcae1ae36b529de1f6f3fGreg Kaiser    // Due to API constraints, at the moment we can't change the fact that
7466d9e7f669a6f03fa73abcae1ae36b529de1f6f3fGreg Kaiser    // we're changing our 4-byte response to a 1-byte value.  But we can prevent
7476d9e7f669a6f03fa73abcae1ae36b529de1f6f3fGreg Kaiser    // the possible change in sign (and thus meaning) that would happen from
7486d9e7f669a6f03fa73abcae1ae36b529de1f6f3fGreg Kaiser    // a naive cast.  Further, we can log when we're losing part of the value.
7496d9e7f669a6f03fa73abcae1ae36b529de1f6f3fGreg Kaiser    // TODO(b/30918279): Don't truncate this result.
7506d9e7f669a6f03fa73abcae1ae36b529de1f6f3fGreg Kaiser    int8_t truncatedResult;
75119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    truncatedResult = static_cast<int8_t>(result);
7526d9e7f669a6f03fa73abcae1ae36b529de1f6f3fGreg Kaiser    msg[0] = truncatedResult;
75354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
75454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (additionalData) {
75554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        memcpy(&msg[1], additionalData, additionalDataLen);
75654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
75754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
75854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    jbyteArray jmsg = env->NewByteArray(msgLen);
7592e776ff893ba66fadf2977d51627c97d48d0a87eEvgenii Stepanov    jintArray jheader = env->NewIntArray(arraysize(header));
76054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
76119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->SetByteArrayRegion(jmsg, 0, msgLen, reinterpret_cast<jbyte *>(msg));
76219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->SetIntArrayRegion(jheader, 0, arraysize(header), reinterpret_cast<jint *>(header));
76354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
76454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32,
76519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi          header[HEADER_FIELD_MSG_TYPE],
76619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi          header[HEADER_FIELD_APP_INSTANCE],
76754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi          header[HEADER_FIELD_HUB_HANDLE]);
76854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
76954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    env->CallIntMethod(db.jniInfo.jContextHubService,
77054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi                       db.jniInfo.contextHubServiceMsgReceiptCallback,
77119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       jheader,
77219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       jmsg);
77319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
774c35104535cf60fd0bb42640c4993172a62e83671Andrew Rossignol    env->DeleteLocalRef(jmsg);
775c35104535cf60fd0bb42640c4993172a62e83671Andrew Rossignol    env->DeleteLocalRef(jheader);
77654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
77754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    delete[] msg;
77854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi}
77954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
78054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshivoid closeUnloadTxn(bool success) {
78154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    void *txnData = nullptr;
78219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    HubMessageType txnId;
78354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
78419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (success && db.txnManager.fetchTxnData(&txnId, &txnData) == 0 &&
78554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        txnId == CONTEXT_HUB_UNLOAD_APP) {
7860d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        JNIEnv *env;
7870d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
7880d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser            ALOGW("Could not attach to JVM !");
7890d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser            env = nullptr;
7900d052c95088190b37011f045a8443aaea28cd23bGreg Kaiser        }
791f8210797adeb6527fe44dff6f8902d4744ad9540Greg Kaiser        jint handle = *reinterpret_cast<jint *>(txnData);
79219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        deleteAppInstance(handle, env);
79354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    } else {
79419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        ALOGW("Could not unload the app successfully ! success %d, txnData %p",
79519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              success,
79619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              txnData);
79754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
79854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
79919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    db.txnManager.closeTxn();
80054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi}
80154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
80219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshibool closeLoadTxn(bool success, jint *appInstanceHandle) {
80354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    void *txnData;
80419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    HubMessageType txnId;
80554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
80619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (success && db.txnManager.fetchTxnData(&txnId, &txnData) == 0 &&
80754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        txnId == CONTEXT_HUB_LOAD_APP) {
80819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        AppInstanceInfo *info = static_cast<AppInstanceInfo *>(txnData);
80954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        *appInstanceHandle = info->instanceId;
81054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
81154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        JNIEnv *env;
81254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) == JNI_OK) {
81319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            addAppInstance(&info->appInfo, info->hubHandle, info->instanceId, env);
81454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        } else {
81554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            ALOGW("Could not attach to JVM !");
8169d4d881cc5cd5e225f68c85050d99d60445edbcfGreg Kaiser            success = false;
81754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        }
81819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        // While we just called addAppInstance above, our info->appInfo was
819f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        // incomplete (for example, the 'version' is hardcoded to -1).  So we
820f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        // trigger an additional query to the CHRE, so we'll be able to get
821f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        // all the app "info", and have our JNI and Java caches with the
822f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        // full information.
823f16abd98c7ea8332e413d44a0baa8cb6eaa6669cGreg Kaiser        sendQueryForApps();
82454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    } else {
82554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        ALOGW("Could not load the app successfully ! Unexpected failure");
8269d4d881cc5cd5e225f68c85050d99d60445edbcfGreg Kaiser        *appInstanceHandle = INVALID_APP_ID;
8279d4d881cc5cd5e225f68c85050d99d60445edbcfGreg Kaiser        success = false;
82854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
82954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
83019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    db.txnManager.closeTxn();
8319d4d881cc5cd5e225f68c85050d99d60445edbcfGreg Kaiser    return success;
83254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi}
83354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
83419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiint initJni(JNIEnv *env, jobject instance) {
8359ff7d2235427b211344fa58b608424805a21aa24Peng Xu    if (env->GetJavaVM(&db.jniInfo.vm) != JNI_OK) {
836b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        return -1;
8379ff7d2235427b211344fa58b608424805a21aa24Peng Xu    }
8389ff7d2235427b211344fa58b608424805a21aa24Peng Xu
8399ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.jContextHubService = env->NewGlobalRef(instance);
8409ff7d2235427b211344fa58b608424805a21aa24Peng Xu
8419ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoClass =
8429ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->FindClass("android/hardware/location/ContextHubInfo");
8439ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubServiceClass =
844420e45e9cb004ea6c6e11f69adcdbf3dac5fc800Ashutosh Joshi            env->FindClass("com/android/server/location/ContextHubService");
8459ff7d2235427b211344fa58b608424805a21aa24Peng Xu
8469ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.memoryRegionsClass =
8479ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->FindClass("android/hardware/location/MemoryRegion");
8489ff7d2235427b211344fa58b608424805a21aa24Peng Xu
8499ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoCtor =
8509ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass, "<init>", "()V");
8519ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetId =
8529ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setId", "(I)V");
8539ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetName =
85419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName", "(Ljava/lang/String;)V");
8559ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetVendor =
8569ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
85719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setVendor",
85819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(Ljava/lang/String;)V");
8599ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetToolchain =
8609ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
86119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setToolchain",
86219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(Ljava/lang/String;)V");
8639ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetPlatformVersion =
8649ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
86519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setPlatformVersion",
86619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(I)V");
8679ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetStaticSwVersion =
8689ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
86919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setStaticSwVersion",
87019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(I)V");
8719ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetToolchainVersion =
8729ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
87319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setToolchainVersion",
87419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(I)V");
8759ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetPeakMips =
8769ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
87719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setPeakMips",
87819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(F)V");
8799ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetStoppedPowerDrawMw =
8809ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
88119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setStoppedPowerDrawMw",
88219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(F)V");
8839ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetSleepPowerDrawMw =
8849ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
88519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setSleepPowerDrawMw",
88619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(F)V");
8879ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetPeakPowerDrawMw =
8889ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
88919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setPeakPowerDrawMw",
89019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(F)V");
8919ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetSupportedSensors =
8929ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
89319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setSupportedSensors",
89419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "([I)V");
8959ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetMemoryRegions =
8969ff7d2235427b211344fa58b608424805a21aa24Peng Xu            env->GetMethodID(db.jniInfo.contextHubInfoClass,
89719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setMemoryRegions",
89819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "([Landroid/hardware/location/MemoryRegion;)V");
899b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    db.jniInfo.contextHubInfoSetMaxPacketLenBytes =
900b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi             env->GetMethodID(db.jniInfo.contextHubInfoClass,
90119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                              "setMaxPacketLenBytes",
90219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                              "(I)V");
9039ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubServiceMsgReceiptCallback =
90419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            env->GetMethodID(db.jniInfo.contextHubServiceClass,
90519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "onMessageReceipt",
90619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "([I[B)I");
9079ff7d2235427b211344fa58b608424805a21aa24Peng Xu    db.jniInfo.contextHubInfoSetName =
90819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            env->GetMethodID(db.jniInfo.contextHubInfoClass,
90919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "setName",
91019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                             "(Ljava/lang/String;)V");
911b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    db.jniInfo.contextHubServiceAddAppInstance =
912b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi                 env->GetMethodID(db.jniInfo.contextHubServiceClass,
91319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                  "addAppInstance",
91419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                  "(IIJI)I");
91554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    db.jniInfo.contextHubServiceDeleteAppInstance =
91654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi                 env->GetMethodID(db.jniInfo.contextHubServiceClass,
91719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                  "deleteAppInstance",
91819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                                  "(I)I");
9199ff7d2235427b211344fa58b608424805a21aa24Peng Xu
9209ff7d2235427b211344fa58b608424805a21aa24Peng Xu    return 0;
9219ff7d2235427b211344fa58b608424805a21aa24Peng Xu}
9229ff7d2235427b211344fa58b608424805a21aa24Peng Xu
92319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshijobject constructJContextHubInfo(JNIEnv *env, const ContextHub &hub) {
9249ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jstring jstrBuf;
9259ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jintArray jintBuf;
9269ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jobjectArray jmemBuf;
9279ff7d2235427b211344fa58b608424805a21aa24Peng Xu
9289ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass,
9299ff7d2235427b211344fa58b608424805a21aa24Peng Xu                                  db.jniInfo.contextHubInfoCtor);
93019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub.hubId);
9319ff7d2235427b211344fa58b608424805a21aa24Peng Xu
93293945f2c6909289313ac7477b3eda0e71b0efac7Scott Randolph    jstrBuf = env->NewStringUTF(hub.name.c_str());
9339ff7d2235427b211344fa58b608424805a21aa24Peng Xu    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetName, jstrBuf);
934bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    env->DeleteLocalRef(jstrBuf);
9359ff7d2235427b211344fa58b608424805a21aa24Peng Xu
93693945f2c6909289313ac7477b3eda0e71b0efac7Scott Randolph    jstrBuf = env->NewStringUTF(hub.vendor.c_str());
9379ff7d2235427b211344fa58b608424805a21aa24Peng Xu    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetVendor, jstrBuf);
938bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    env->DeleteLocalRef(jstrBuf);
9399ff7d2235427b211344fa58b608424805a21aa24Peng Xu
94093945f2c6909289313ac7477b3eda0e71b0efac7Scott Randolph    jstrBuf = env->NewStringUTF(hub.toolchain.c_str());
9419ff7d2235427b211344fa58b608424805a21aa24Peng Xu    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchain, jstrBuf);
942bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    env->DeleteLocalRef(jstrBuf);
9439ff7d2235427b211344fa58b608424805a21aa24Peng Xu
94419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub.platformVersion);
94519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub.toolchainVersion);
94619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub.peakMips);
947b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw,
94819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                        hub.stoppedPowerDrawMw);
949b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw,
95019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                        hub.sleepPowerDrawMw);
951b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw,
95219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                        hub.peakPowerDrawMw);
953b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMaxPacketLenBytes,
95419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                        hub.maxSupportedMsgLen);
955b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
9569ff7d2235427b211344fa58b608424805a21aa24Peng Xu
95719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    jintBuf = env->NewIntArray(hub.connectedSensors.size());
95819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    int *connectedSensors = new int[hub.connectedSensors.size()];
95954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
96054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (!connectedSensors) {
96154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi      ALOGW("Cannot allocate memory! Unexpected");
96254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi      assert(false);
96354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    } else {
96419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi      for (unsigned int i = 0; i < hub.connectedSensors.size(); i++) {
96519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        // TODO :: Populate connected sensors.
96619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        //connectedSensors[i] = hub.connectedSensors[i].sensorType;
96719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        connectedSensors[i] = 0;
96854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi      }
96954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
97054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
97119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    env->SetIntArrayRegion(jintBuf, 0, hub.connectedSensors.size(),
97254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi                           connectedSensors);
97354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
974b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
975bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    env->DeleteLocalRef(jintBuf);
9769ff7d2235427b211344fa58b608424805a21aa24Peng Xu
9779ff7d2235427b211344fa58b608424805a21aa24Peng Xu    // We are not getting the memory regions from the CH Hal - change this when it is available
978b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, nullptr);
9799ff7d2235427b211344fa58b608424805a21aa24Peng Xu    // Note the zero size above. We do not need to set any elements
9809ff7d2235427b211344fa58b608424805a21aa24Peng Xu    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMemoryRegions, jmemBuf);
981bece5990c7ad14fff494204e68ca251f4c9c626bGreg Kaiser    env->DeleteLocalRef(jmemBuf);
9829ff7d2235427b211344fa58b608424805a21aa24Peng Xu
983b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
98454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    delete[] connectedSensors;
9859ff7d2235427b211344fa58b608424805a21aa24Peng Xu    return jHub;
9869ff7d2235427b211344fa58b608424805a21aa24Peng Xu}
9879ff7d2235427b211344fa58b608424805a21aa24Peng Xu
98819753cca3f49db2ca66106393d8302c0555fae79Ashutosh JoshijobjectArray nativeInitialize(JNIEnv *env, jobject instance) {
9899ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jobject hub;
9909ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jobjectArray retArray;
9919ff7d2235427b211344fa58b608424805a21aa24Peng Xu
99219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (initJni(env, instance) < 0) {
993b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi        return nullptr;
9949ff7d2235427b211344fa58b608424805a21aa24Peng Xu    }
9959ff7d2235427b211344fa58b608424805a21aa24Peng Xu
9962c697fb4a8b8f8c0a2acf1fb15027f363f74c2dcAshutosh Joshi    initContextHubService();
997adf75e31f52a7a935a66a884fb55631c7309ee75Ashutosh Joshi
998b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    if (db.hubInfo.numHubs > 1) {
99919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        ALOGW("Clamping the number of hubs to 1");
100019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        db.hubInfo.numHubs = 1;
1001b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
1002b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi
1003b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, nullptr);
10049ff7d2235427b211344fa58b608424805a21aa24Peng Xu
10059ff7d2235427b211344fa58b608424805a21aa24Peng Xu    for(int i = 0; i < db.hubInfo.numHubs; i++) {
100619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        hub = constructJContextHubInfo(env, db.hubInfo.hubs[i]);
10079ff7d2235427b211344fa58b608424805a21aa24Peng Xu        env->SetObjectArrayElement(retArray, i, hub);
10089ff7d2235427b211344fa58b608424805a21aa24Peng Xu    }
10099ff7d2235427b211344fa58b608424805a21aa24Peng Xu
10109ff7d2235427b211344fa58b608424805a21aa24Peng Xu    return retArray;
10119ff7d2235427b211344fa58b608424805a21aa24Peng Xu}
10129ff7d2235427b211344fa58b608424805a21aa24Peng Xu
10136644c4547ce849327197786f02da7a045a860aceBrian DuddieResult sendLoadNanoAppRequest(uint32_t hubId,
10146644c4547ce849327197786f02da7a045a860aceBrian Duddie                              jbyte *data,
10156644c4547ce849327197786f02da7a045a860aceBrian Duddie                              size_t dataBufferLength) {
10166644c4547ce849327197786f02da7a045a860aceBrian Duddie    auto header = reinterpret_cast<const NanoAppBinaryHeader *>(data);
10176644c4547ce849327197786f02da7a045a860aceBrian Duddie    Result result;
10186644c4547ce849327197786f02da7a045a860aceBrian Duddie
10196644c4547ce849327197786f02da7a045a860aceBrian Duddie    if (dataBufferLength < sizeof(NanoAppBinaryHeader)) {
10206644c4547ce849327197786f02da7a045a860aceBrian Duddie        ALOGE("Got short NanoApp, length %zu", dataBufferLength);
10216644c4547ce849327197786f02da7a045a860aceBrian Duddie        result = Result::BAD_PARAMS;
10226644c4547ce849327197786f02da7a045a860aceBrian Duddie    } else if (header->headerVersion != htole32(kNanoAppBinaryHeaderVersion)) {
10236644c4547ce849327197786f02da7a045a860aceBrian Duddie        ALOGE("Got unexpected NanoApp header version %" PRIu32,
10246644c4547ce849327197786f02da7a045a860aceBrian Duddie              letoh32(header->headerVersion));
10256644c4547ce849327197786f02da7a045a860aceBrian Duddie        result = Result::BAD_PARAMS;
10266644c4547ce849327197786f02da7a045a860aceBrian Duddie    } else {
10276644c4547ce849327197786f02da7a045a860aceBrian Duddie        NanoAppBinary nanoapp;
10286644c4547ce849327197786f02da7a045a860aceBrian Duddie
10296644c4547ce849327197786f02da7a045a860aceBrian Duddie        // Data from the common nanoapp header goes into explicit fields
10306644c4547ce849327197786f02da7a045a860aceBrian Duddie        nanoapp.appId      = letoh64(header->appId);
10316644c4547ce849327197786f02da7a045a860aceBrian Duddie        nanoapp.appVersion = letoh32(header->appVersion);
10326644c4547ce849327197786f02da7a045a860aceBrian Duddie        nanoapp.flags      = letoh32(header->flags);
10336644c4547ce849327197786f02da7a045a860aceBrian Duddie        nanoapp.targetChreApiMajorVersion = header->targetChreApiMajorVersion;
10346644c4547ce849327197786f02da7a045a860aceBrian Duddie        nanoapp.targetChreApiMinorVersion = header->targetChreApiMinorVersion;
10356644c4547ce849327197786f02da7a045a860aceBrian Duddie
10366644c4547ce849327197786f02da7a045a860aceBrian Duddie        // Everything past the header goes in customBinary
10376644c4547ce849327197786f02da7a045a860aceBrian Duddie        auto dataBytes = reinterpret_cast<const uint8_t *>(data);
10386644c4547ce849327197786f02da7a045a860aceBrian Duddie        std::vector<uint8_t> customBinary(
10396644c4547ce849327197786f02da7a045a860aceBrian Duddie            dataBytes + sizeof(NanoAppBinaryHeader),
10406644c4547ce849327197786f02da7a045a860aceBrian Duddie            dataBytes + dataBufferLength);
10416644c4547ce849327197786f02da7a045a860aceBrian Duddie        nanoapp.customBinary = std::move(customBinary);
10426644c4547ce849327197786f02da7a045a860aceBrian Duddie
10436644c4547ce849327197786f02da7a045a860aceBrian Duddie        ALOGW("Calling Load NanoApp on hub %d", hubId);
10446644c4547ce849327197786f02da7a045a860aceBrian Duddie        result = db.hubInfo.contextHub->loadNanoApp(hubId,
10456644c4547ce849327197786f02da7a045a860aceBrian Duddie                                                    nanoapp,
10466644c4547ce849327197786f02da7a045a860aceBrian Duddie                                                    CONTEXT_HUB_LOAD_APP);
10476644c4547ce849327197786f02da7a045a860aceBrian Duddie    }
10486644c4547ce849327197786f02da7a045a860aceBrian Duddie
10496644c4547ce849327197786f02da7a045a860aceBrian Duddie    return result;
10506644c4547ce849327197786f02da7a045a860aceBrian Duddie}
10516644c4547ce849327197786f02da7a045a860aceBrian Duddie
105219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshijint nativeSendMessage(JNIEnv *env,
105319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       jobject instance,
105419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       jintArray header_,
105519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       jbyteArray data_) {
105619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    // With the new binderized HAL definition, this function can be made much simpler.
105719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    // All the magic can be removed. This is not however needed for the default implementation
105819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    // TODO :: Change the JNI interface to conform to the new HAL interface and clean up this
105919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    // function
1060b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    jint retVal = -1; // Default to failure
10619ff7d2235427b211344fa58b608424805a21aa24Peng Xu
10629ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jint *header = env->GetIntArrayElements(header_, 0);
10638c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie    size_t numHeaderElements = env->GetArrayLength(header_);
10649ff7d2235427b211344fa58b608424805a21aa24Peng Xu    jbyte *data = env->GetByteArrayElements(data_, 0);
10658c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie    size_t dataBufferLength = env->GetArrayLength(data_);
10669ff7d2235427b211344fa58b608424805a21aa24Peng Xu
106754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (numHeaderElements < MSG_HEADER_SIZE) {
106854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        ALOGW("Malformed header len");
106954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return -1;
107054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
107154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
10728c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie    jint appInstanceHandle = header[HEADER_FIELD_APP_INSTANCE];
107354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    uint32_t msgType = header[HEADER_FIELD_MSG_TYPE];
107454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    int hubHandle = -1;
107554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    uint64_t appId;
107654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
107754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (msgType == CONTEXT_HUB_UNLOAD_APP) {
107819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        hubHandle = getHubHandleForAppInstance(appInstanceHandle);
107954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    } else if (msgType == CONTEXT_HUB_LOAD_APP) {
108054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        if (numHeaderElements < MSG_HEADER_SIZE_LOAD_APP) {
108154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            return -1;
108254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        }
108354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        uint64_t appIdLo = header[HEADER_FIELD_LOAD_APP_ID_LO];
108454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        uint64_t appIdHi = header[HEADER_FIELD_LOAD_APP_ID_HI];
108554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        appId = appIdHi << 32 | appIdLo;
108654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
108754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        hubHandle = header[HEADER_FIELD_HUB_HANDLE];
108854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    } else {
108954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        hubHandle = header[HEADER_FIELD_HUB_HANDLE];
109054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
109154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
10928c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie    uint32_t hubId = -1;
10938c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie    if (!getHubIdForHubHandle(hubHandle, &hubId)) {
109454787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        ALOGD("Invalid hub Handle %d", hubHandle);
109554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        return -1;
109654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
109754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
109854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (msgType == CONTEXT_HUB_LOAD_APP ||
109954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        msgType == CONTEXT_HUB_UNLOAD_APP) {
110054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
110119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        db.txnManager.closeAnyStaleTxns();
110219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
110319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        if (db.txnManager.isTxnPending()) {
110419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            // TODO : There is a race conditio
110554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            ALOGW("Cannot load or unload app while a transaction is pending !");
110654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            return -1;
110719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        } else if (msgType == CONTEXT_HUB_LOAD_APP) {
110854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            if (startLoadAppTxn(appId, hubHandle) != 0) {
1109118644056f3c442f0aa9451aaeac8e8b35dde3f8Ashutosh Joshi                ALOGW("Cannot Start Load Transaction");
111054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi                return -1;
111154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            }
111254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
111354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            if (startUnloadAppTxn(appInstanceHandle) != 0) {
1114118644056f3c442f0aa9451aaeac8e8b35dde3f8Ashutosh Joshi                ALOGW("Cannot Start UnLoad Transaction");
111554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi                return -1;
111654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            }
111754787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        }
111854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
111954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
112019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    Result result;
112154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
112254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    if (msgType == CONTEXT_HUB_UNLOAD_APP) {
11238c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie        ALOGW("Calling UnLoad NanoApp for app %" PRIx64 " on hub %" PRIu32,
112419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              db.appInstances[appInstanceHandle].appInfo.appId,
112519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi              hubId);
112619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        result = db.hubInfo.contextHub->unloadNanoApp(
112719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                hubId, db.appInstances[appInstanceHandle].appInfo.appId, CONTEXT_HUB_UNLOAD_APP);
112854787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    } else {
11298c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie        if (appInstanceHandle == OS_APP_ID) {
113019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            if (msgType == CONTEXT_HUB_LOAD_APP) {
11316644c4547ce849327197786f02da7a045a860aceBrian Duddie                result = sendLoadNanoAppRequest(hubId, data, dataBufferLength);
11320e5a2ab7c3ae3d798072fec0dd8407c50c862515Brian Duddie            } else if (msgType == CONTEXT_HUB_QUERY_APPS) {
11330e5a2ab7c3ae3d798072fec0dd8407c50c862515Brian Duddie                result = db.hubInfo.contextHub->queryApps(hubId);
113419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            } else {
113519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                ALOGD("Dropping OS addresses message of type - %" PRIu32, msgType);
113619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                result = Result::BAD_PARAMS;
113719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            }
1138cafdee9a72652354c5bde0b13c86dac3d88ac2aeAshutosh Joshi        } else {
11398c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie            appId = getAppIdForAppInstance(appInstanceHandle);
11408c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie            if (appId == static_cast<uint64_t>(INVALID_APP_ID)) {
11418c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie                ALOGD("Cannot find application instance %d", appInstanceHandle);
11428c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie                result = Result::BAD_PARAMS;
11438c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie            } else if (hubHandle != getHubHandleForAppInstance(appInstanceHandle)) {
11448c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie                ALOGE("Given hubHandle (%d) doesn't match expected for app instance (%d)",
11458c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie                      hubHandle,
11468c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie                      getHubHandleForAppInstance(appInstanceHandle));
11478c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie                result = Result::BAD_PARAMS;
11488c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie            } else {
114919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                ContextHubMsg msg;
115019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                msg.appName = appId;
115119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                msg.msgType = msgType;
115219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                msg.msg.setToExternal((unsigned char *)data, dataBufferLength);
115319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi
11548c51b00e4c017dcd7bb24a51aa50f87ac3540208Brian Duddie                ALOGW("Sending msg of type %" PRIu32 " len %zu to app %" PRIx64 " on hub %" PRIu32,
115519753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       msgType,
115619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       dataBufferLength,
115719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       appId,
115819753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                       hubId);
115919753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi                result = db.hubInfo.contextHub->sendMessageToHub(hubId, msg);
116019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            }
116119753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        }
116254787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi    }
116354787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi
116419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    if (result != Result::OK) {
116554787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        ALOGD("Send Message failure - %d", retVal);
116654787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        if (msgType == CONTEXT_HUB_LOAD_APP) {
1167ca9c676099aafaa371abeadffcdbb96d5ed3a674Greg Kaiser            jint ignored;
1168ca9c676099aafaa371abeadffcdbb96d5ed3a674Greg Kaiser            closeLoadTxn(false, &ignored);
116954787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
117054787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi            closeUnloadTxn(false);
117154787a5f9ffe7a15784049b00f664fac37c53b95Ashutosh Joshi        }
117219753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi    } else {
117319753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi        retVal = 0;
1174b741e3b374e7eebf96e2104dec5caccf723b2a39Ashutosh Joshi    }
11759ff7d2235427b211344fa58b608424805a21aa24Peng Xu
11769ff7d2235427b211344fa58b608424805a21aa24Peng Xu    env->ReleaseIntArrayElements(header_, header, 0);
11779ff7d2235427b211344fa58b608424805a21aa24Peng Xu    env->ReleaseByteArrayElements(data_, data, 0);
11789ff7d2235427b211344fa58b608424805a21aa24Peng Xu
11799ff7d2235427b211344fa58b608424805a21aa24Peng Xu    return retVal;
11809ff7d2235427b211344fa58b608424805a21aa24Peng Xu}
11819ff7d2235427b211344fa58b608424805a21aa24Peng Xu
11829ff7d2235427b211344fa58b608424805a21aa24Peng Xu//--------------------------------------------------------------------------------------------------
11839ff7d2235427b211344fa58b608424805a21aa24Peng Xu//
118419753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshiconst JNINativeMethod gContextHubServiceMethods[] = {
11859ff7d2235427b211344fa58b608424805a21aa24Peng Xu    {"nativeInitialize",
118619753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            "()[Landroid/hardware/location/ContextHubInfo;",
118719753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            reinterpret_cast<void*>(nativeInitialize)},
11889ff7d2235427b211344fa58b608424805a21aa24Peng Xu    {"nativeSendMessage",
11899ff7d2235427b211344fa58b608424805a21aa24Peng Xu            "([I[B)I",
119019753cca3f49db2ca66106393d8302c0555fae79Ashutosh Joshi            reinterpret_cast<void*>(nativeSendMessage)}
11919ff7d2235427b211344fa58b608424805a21aa24Peng Xu};
11929ff7d2235427b211344fa58b608424805a21aa24Peng Xu
1193420e45e9cb004ea6c6e11f69adcdbf3dac5fc800Ashutosh Joshiint register_android_server_location_ContextHubService(JNIEnv *env)
11949ff7d2235427b211344fa58b608424805a21aa24Peng Xu{
1195420e45e9cb004ea6c6e11f69adcdbf3dac5fc800Ashutosh Joshi    RegisterMethodsOrDie(env, "com/android/server/location/ContextHubService",
11969ff7d2235427b211344fa58b608424805a21aa24Peng Xu            gContextHubServiceMethods, NELEM(gContextHubServiceMethods));
11979ff7d2235427b211344fa58b608424805a21aa24Peng Xu
11989ff7d2235427b211344fa58b608424805a21aa24Peng Xu    return 0;
11999ff7d2235427b211344fa58b608424805a21aa24Peng Xu}
1200420e45e9cb004ea6c6e11f69adcdbf3dac5fc800Ashutosh Joshi
1201420e45e9cb004ea6c6e11f69adcdbf3dac5fc800Ashutosh Joshi}//namespace android
1202