blob: 7a8a574b119e317f10e338227071d41e2621600c [file] [log] [blame]
Peng Xu9ff7d222016-02-11 13:02:05 -08001/*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "context_hub.h"
18
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070019#define LOG_NDEBUG 0
20#define LOG_TAG "ContextHubService"
21
22#include <inttypes.h>
23#include <jni.h>
Ashutosh Joshi54787a52016-04-27 11:19:16 -070024#include <mutex>
Peng Xu9ff7d222016-02-11 13:02:05 -080025#include <string.h>
26#include <stdint.h>
27#include <stdio.h>
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070028#include <stdlib.h>
Ashutosh Joshi54787a52016-04-27 11:19:16 -070029#include <unordered_map>
30#include <queue>
Peng Xu9ff7d222016-02-11 13:02:05 -080031
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070032#include <cutils/log.h>
33
Peng Xu9ff7d222016-02-11 13:02:05 -080034#include "JNIHelp.h"
35#include "core_jni_helpers.h"
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070036
Ashutosh Joshi54787a52016-04-27 11:19:16 -070037static constexpr int OS_APP_ID = -1;
38static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070039
Ashutosh Joshi54787a52016-04-27 11:19:16 -070040static constexpr int MIN_APP_ID = 1;
41static constexpr int MAX_APP_ID = 128;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070042
Ashutosh Joshi54787a52016-04-27 11:19:16 -070043static constexpr size_t MSG_HEADER_SIZE = 4;
44static constexpr size_t HEADER_FIELD_MSG_TYPE = 0;
45static constexpr size_t HEADER_FIELD_MSG_VERSION = 1;
46static constexpr size_t HEADER_FIELD_HUB_HANDLE = 2;
47static constexpr size_t HEADER_FIELD_APP_INSTANCE = 3;
48
49static constexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
50static constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
51static constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
Peng Xu9ff7d222016-02-11 13:02:05 -080052
Peng Xu9ff7d222016-02-11 13:02:05 -080053namespace android {
54
55namespace {
56
Peng Xu9ff7d222016-02-11 13:02:05 -080057/*
58 * Finds the length of a statically-sized array using template trickery that
59 * also prevents it from being applied to the wrong type.
60 */
61template <typename T, size_t N>
62constexpr size_t array_length(T (&)[N]) { return N; }
63
64struct jniInfo_s {
65 JavaVM *vm;
66 jclass contextHubInfoClass;
67 jclass contextHubServiceClass;
68 jclass memoryRegionsClass;
69
70 jobject jContextHubService;
71
72 jmethodID msgReceiptCallBack;
73
74 jmethodID contextHubInfoCtor;
75 jmethodID contextHubInfoSetId;
76 jmethodID contextHubInfoSetName;
77 jmethodID contextHubInfoSetVendor;
78 jmethodID contextHubInfoSetToolchain;
79 jmethodID contextHubInfoSetPlatformVersion;
80 jmethodID contextHubInfoSetStaticSwVersion;
81 jmethodID contextHubInfoSetToolchainVersion;
82 jmethodID contextHubInfoSetPeakMips;
83 jmethodID contextHubInfoSetStoppedPowerDrawMw;
84 jmethodID contextHubInfoSetSleepPowerDrawMw;
85 jmethodID contextHubInfoSetPeakPowerDrawMw;
86 jmethodID contextHubInfoSetSupportedSensors;
87 jmethodID contextHubInfoSetMemoryRegions;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070088 jmethodID contextHubInfoSetMaxPacketLenBytes;
Peng Xu9ff7d222016-02-11 13:02:05 -080089
90 jmethodID contextHubServiceMsgReceiptCallback;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070091 jmethodID contextHubServiceAddAppInstance;
Ashutosh Joshi54787a52016-04-27 11:19:16 -070092 jmethodID contextHubServiceDeleteAppInstance;
Peng Xu9ff7d222016-02-11 13:02:05 -080093};
94
95struct context_hub_info_s {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -070096 uint32_t *cookies;
Peng Xu9ff7d222016-02-11 13:02:05 -080097 int numHubs;
98 const struct context_hub_t *hubs;
99 struct context_hub_module_t *contextHubModule;
100};
101
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700102struct app_instance_info_s {
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700103 uint64_t truncName; // Possibly truncated name for logging
104 uint32_t hubHandle; // Id of the hub this app is on
105 int instanceId; // system wide unique instance id - assigned
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700106 struct hub_app_info appInfo; // returned from the HAL
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700107};
108
109/*
110 * TODO(ashutoshj): From original code review:
111 *
112 * So, I feel like we could possible do a better job of organizing this code,
113 * and being more C++-y. Consider something like this:
114 * class TxnManager {
115 * public:
116 * TxnManager();
117 * ~TxnManager();
118 * int add(hub_message_e identifier, void *data);
119 * int close();
120 * bool isPending() const;
121 * int fetchData(hub_message_e *identifier, void **data) const;
122 *
123 * private:
124 * bool mPending;
125 * mutable std::mutex mLock;
126 * hub_message_e mIdentifier;
127 * void *mData;
128 * };
129 *
130 * And then, for example, we'd have things like:
131 * TxnManager::TxnManager() : mPending(false), mLock(), mIdentifier(), mData(nullptr) {}
132 * int TxnManager::add(hub_message_e identifier, void *data) {
133 * std::lock_guard<std::mutex> lock(mLock);
134 * mPending = true;
135 * mData = txnData;
136 * mIdentifier = txnIdentifier;
137 * return 0;
138 * }
139 * And then calling code would look like:
140 * if (!db.txnManager.add(CONTEXT_HUB_LOAD_APP, txnInfo)) {
141 *
142 * This would make it clearer the nothing is manipulating any state within TxnManager
143 * unsafely and outside of these couple of calls.
144 */
145struct txnManager_s {
146 bool txnPending; // Is a transaction pending
147 std::mutex m; // mutex for manager
148 hub_messages_e txnIdentifier; // What are we doing
149 void *txnData; // Details
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700150};
151
Peng Xu9ff7d222016-02-11 13:02:05 -0800152struct contextHubServiceDb_s {
153 int initialized;
154 context_hub_info_s hubInfo;
155 jniInfo_s jniInfo;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700156 std::queue<int> freeIds;
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700157 std::unordered_map<int, app_instance_info_s> appInstances;
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700158 txnManager_s txnManager;
Peng Xu9ff7d222016-02-11 13:02:05 -0800159};
160
161} // unnamed namespace
162
163static contextHubServiceDb_s db;
164
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700165static bool initTxnManager() {
166 txnManager_s *mgr = &db.txnManager;
167
168 mgr->txnData = nullptr;
169 mgr->txnPending = false;
170 return true;
171}
172
173static int addTxn(hub_messages_e txnIdentifier, void *txnData) {
174 txnManager_s *mgr = &db.txnManager;
175
176 std::lock_guard<std::mutex>lock(mgr->m);
177
178 mgr->txnPending = true;
179 mgr->txnData = txnData;
180 mgr->txnIdentifier = txnIdentifier;
181
182 return 0;
183}
184
185static int closeTxn() {
186 txnManager_s *mgr = &db.txnManager;
187 std::lock_guard<std::mutex>lock(mgr->m);
188 mgr->txnPending = false;
189 free(mgr->txnData);
190 mgr->txnData = nullptr;
191
192 return 0;
193}
194
195static bool isTxnPending() {
196 txnManager_s *mgr = &db.txnManager;
197 std::lock_guard<std::mutex>lock(mgr->m);
198 return mgr->txnPending;
199}
200
201static int fetchTxnData(hub_messages_e *id, void **data) {
202 txnManager_s *mgr = &db.txnManager;
203
204 if (!id || !data) {
205 ALOGW("Null params id %p, data %p", id, data);
206 return -1;
207 }
208
209 std::lock_guard<std::mutex>lock(mgr->m);
210 if (!mgr->txnPending) {
211 ALOGW("No Transactions pending");
212 return -1;
213 }
214
215 // else
216 *id = mgr->txnIdentifier;
217 *data = mgr->txnData;
218 return 0;
219}
220
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700221int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg,
Peng Xu9ff7d222016-02-11 13:02:05 -0800222 void *cookie);
223
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700224const context_hub_t *get_hub_info(int hubHandle) {
225 if (hubHandle >= 0 && hubHandle < db.hubInfo.numHubs) {
226 return &db.hubInfo.hubs[hubHandle];
227 }
228 return nullptr;
229}
230
231static int send_msg_to_hub(const hub_message_t *msg, int hubHandle) {
232 const context_hub_t *info = get_hub_info(hubHandle);
233
234 if (info) {
235 return db.hubInfo.contextHubModule->send_message(info->hub_id, msg);
236 } else {
237 ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle);
238 return -1;
239 }
240}
241
242static int set_os_app_as_destination(hub_message_t *msg, int hubHandle) {
243 const context_hub_t *info = get_hub_info(hubHandle);
244
245 if (info) {
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700246 msg->app_name = info->os_app_name;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700247 return 0;
248 } else {
249 ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle);
250 return -1;
251 }
252}
253
Ashutosh Joshicafdee92016-04-04 16:19:29 -0700254static int get_hub_id_for_hub_handle(int hubHandle) {
255 if (hubHandle < 0 || hubHandle >= db.hubInfo.numHubs) {
256 return -1;
257 } else {
258 return db.hubInfo.hubs[hubHandle].hub_id;
259 }
260}
261
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700262static int get_hub_handle_for_app_instance(int id) {
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700263 if (!db.appInstances.count(id)) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700264 ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
265 return -1;
266 }
267
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700268 return db.appInstances[id].hubHandle;
269}
270
271static int get_hub_id_for_app_instance(int id) {
272 int hubHandle = get_hub_handle_for_app_instance(id);
273
274 if (hubHandle < 0) {
275 return -1;
276 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700277
278 return db.hubInfo.hubs[hubHandle].hub_id;
279}
280
destradaa6469c232016-04-27 17:53:23 -0700281static int get_app_instance_for_app_id(uint64_t app_id) {
282 auto end = db.appInstances.end();
283 for (auto current = db.appInstances.begin(); current != end; ++current) {
284 if (current->second.appInfo.app_name.id == app_id) {
285 return current->first;
286 }
287 }
destradaa3cd73052016-04-29 13:11:33 -0700288 ALOGD("Cannot find app for app instance %" PRIu64 ".", app_id);
destradaa6469c232016-04-27 17:53:23 -0700289 return -1;
290}
291
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700292static int set_dest_app(hub_message_t *msg, int id) {
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700293 if (!db.appInstances.count(id)) {
destradaa6469c232016-04-27 17:53:23 -0700294 ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700295 return -1;
296 }
297
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700298 msg->app_name = db.appInstances[id].appInfo.app_name;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700299 return 0;
300}
301
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700302static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700303 hub_message_t msg;
Ashutosh Joshi848c8c42016-07-06 13:54:28 -0700304 query_apps_request_t queryMsg;
305
306 queryMsg.app_name.id = NANOAPP_VENDOR_ALL_APPS;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700307
308 msg.message_type = CONTEXT_HUB_QUERY_APPS;
Ashutosh Joshi848c8c42016-07-06 13:54:28 -0700309 msg.message_len = sizeof(queryMsg);
310 msg.message = &queryMsg;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700311
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700312 ALOGD("Sending query for apps to hub %" PRIu32, hubHandle);
313 set_os_app_as_destination(&msg, hubHandle);
314 if (send_msg_to_hub(&msg, hubHandle) != 0) {
315 ALOGW("Could not query hub %" PRIu32 " for apps", hubHandle);
316 }
317}
318
319static void sendQueryForApps(uint64_t appId) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700320 for (int i = 0; i < db.hubInfo.numHubs; i++ ) {
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700321 query_hub_for_apps(appId, i);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700322 }
323}
324
325static int return_id(int id) {
326 // Note : This method is not thread safe.
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700327 // id returned is guaranteed to be in use
328 if (id >= 0) {
329 db.freeIds.push(id);
330 return 0;
331 }
332
333 return -1;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700334}
335
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700336static int generate_id() {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700337 // Note : This method is not thread safe.
338 int retVal = -1;
339
340 if (!db.freeIds.empty()) {
341 retVal = db.freeIds.front();
342 db.freeIds.pop();
343 }
344
345 return retVal;
346}
347
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700348
349static int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle,
350 int appInstanceHandle, JNIEnv *env) {
351
352 ALOGI("Loading App");
353
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700354 // Not checking if the apps are indeed distinct
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700355 app_instance_info_s entry;
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700356 assert(appInfo);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700357
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700358 if (db.appInstances.count(appInstanceHandle) == 0) {
359 appInstanceHandle = generate_id();
360 if (appInstanceHandle < 0) {
361 ALOGE("Cannot find resources to add app instance %d",
362 appInstanceHandle);
363 return -1;
364 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700365 }
366
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700367 entry.appInfo = *appInfo;
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700368
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700369 entry.instanceId = appInstanceHandle;
370 entry.truncName = appInfo->app_name.id;
371 entry.hubHandle = hubHandle;
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700372
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700373 db.appInstances[appInstanceHandle] = entry;
374
375 // Finally - let the service know of this app instance
376 env->CallIntMethod(db.jniInfo.jContextHubService,
377 db.jniInfo.contextHubServiceAddAppInstance,
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700378 hubHandle, entry.instanceId, entry.truncName,
379 entry.appInfo.version);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700380
381 ALOGW("Added App 0x%" PRIx64 " on hub Handle %" PRId32
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700382 " as appInstance %d", entry.truncName,
383 entry.hubHandle, appInstanceHandle);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700384
385 return appInstanceHandle;
386}
387
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700388int delete_app_instance(int id, JNIEnv *env) {
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700389 if (!db.appInstances.count(id)) {
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700390 ALOGW("Cannot find App id : %d", id);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700391 return -1;
392 }
393
394 return_id(id);
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700395 db.appInstances.erase(id);
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700396 if (env->CallIntMethod(db.jniInfo.jContextHubService,
397 db.jniInfo.contextHubServiceDeleteAppInstance,
398 id) != 0) {
399 ALOGW("Could not delete App id : %d", id);
400 return -1;
401 }
402
403 ALOGI("Deleted App id : %d", id);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700404
405 return 0;
406}
407
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700408static int startLoadAppTxn(uint64_t appId, int hubHandle) {
409 app_instance_info_s *txnInfo = (app_instance_info_s *)malloc(sizeof(app_instance_info_s));
410 int instanceId = generate_id();
411
412 if (!txnInfo || instanceId < 0) {
413 return_id(instanceId);
414 free(txnInfo);
415 return -1;
416 }
417
418 txnInfo->truncName = appId;
419 txnInfo->hubHandle = hubHandle;
420 txnInfo->instanceId = instanceId;
421
422 txnInfo->appInfo.app_name.id = appId;
423 txnInfo->appInfo.num_mem_ranges = 0;
424 txnInfo->appInfo.version = -1; // Awaited
425
Ashutosh Joshi11864402016-07-15 13:46:22 -0700426 if (addTxn(CONTEXT_HUB_LOAD_APP, txnInfo) != 0) {
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700427 return_id(instanceId);
428 free(txnInfo);
429 return -1;
430 }
431
432 return 0;
433}
434
435static int startUnloadAppTxn(uint32_t appInstanceHandle) {
436 uint32_t *txnData = (uint32_t *) malloc(sizeof(uint32_t));
437 if (!txnData) {
438 ALOGW("Cannot allocate memory to start unload transaction");
439 return -1;
440 }
441
442 *txnData = appInstanceHandle;
443
444 if (addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) {
445 free(txnData);
446 ALOGW("Cannot start transaction to unload app");
447 return -1;
448 }
449
450 return 0;
451}
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700452
Peng Xu9ff7d222016-02-11 13:02:05 -0800453static void initContextHubService() {
454 int err = 0;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700455 db.hubInfo.hubs = nullptr;
Peng Xu9ff7d222016-02-11 13:02:05 -0800456 db.hubInfo.numHubs = 0;
Peng Xu9ff7d222016-02-11 13:02:05 -0800457 int i;
458
459 err = hw_get_module(CONTEXT_HUB_MODULE_ID,
460 (hw_module_t const**)(&db.hubInfo.contextHubModule));
461
462 if (err) {
463 ALOGE("** Could not load %s module : err %s", CONTEXT_HUB_MODULE_ID,
464 strerror(-err));
465 }
466
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700467 // Prep for storing app info
468 for(i = MIN_APP_ID; i <= MAX_APP_ID; i++) {
469 db.freeIds.push(i);
470 }
Ashutosh Joshiadf75e32016-03-29 09:19:56 -0700471
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700472 initTxnManager();
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700473 if (db.hubInfo.contextHubModule) {
474 int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
475 &db.hubInfo.hubs);
476 ALOGD("ContextHubModule returned %d hubs ", retNumHubs);
477 db.hubInfo.numHubs = retNumHubs;
478
479 if (db.hubInfo.numHubs > 0) {
480 db.hubInfo.numHubs = retNumHubs;
481 db.hubInfo.cookies = (uint32_t *)malloc(sizeof(uint32_t) * db.hubInfo.numHubs);
482
483 if (!db.hubInfo.cookies) {
484 ALOGW("Ran out of memory allocating cookies, bailing");
485 return;
486 }
487
488 for (i = 0; i < db.hubInfo.numHubs; i++) {
489 db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id;
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700490 ALOGI("Subscribing to hubHandle %d with OS App name %" PRIu64, i, db.hubInfo.hubs[i].os_app_name.id);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700491 if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
492 context_hub_callback,
493 &db.hubInfo.cookies[i]) == 0) {
494 }
495 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800496 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700497
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700498 sendQueryForApps(ALL_APPS);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700499 } else {
500 ALOGW("No Context Hub Module present");
Peng Xu9ff7d222016-02-11 13:02:05 -0800501 }
502}
503
destradaa6469c232016-04-27 17:53:23 -0700504static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_t msgLen) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800505 JNIEnv *env;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700506
507 if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
Peng Xu9ff7d222016-02-11 13:02:05 -0800508 return -1;
509 }
510
511 jbyteArray jmsg = env->NewByteArray(msgLen);
Greg Kaiserbece5992016-05-09 10:23:56 -0700512 if (jmsg == nullptr) {
513 ALOGW("Can't allocate %zu byte array", msgLen);
514 return -1;
515 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800516 jintArray jheader = env->NewIntArray(headerLen);
Greg Kaiserbece5992016-05-09 10:23:56 -0700517 if (jheader == nullptr) {
518 env->DeleteLocalRef(jmsg);
519 ALOGW("Can't allocate %zu int array", headerLen);
520 return -1;
521 }
Peng Xu9ff7d222016-02-11 13:02:05 -0800522
523 env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
524 env->SetIntArrayRegion(jheader, 0, headerLen, (jint *)header);
525
Greg Kaiserbece5992016-05-09 10:23:56 -0700526 int ret = (env->CallIntMethod(db.jniInfo.jContextHubService,
Peng Xu9ff7d222016-02-11 13:02:05 -0800527 db.jniInfo.contextHubServiceMsgReceiptCallback,
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700528 jheader, jmsg) != 0);
Greg Kaiserbece5992016-05-09 10:23:56 -0700529 env->DeleteLocalRef(jmsg);
530 env->DeleteLocalRef(jheader);
531
532 return ret;
Peng Xu9ff7d222016-02-11 13:02:05 -0800533}
534
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700535int handle_query_apps_response(const uint8_t *msg, int msgLen,
536 uint32_t hubHandle) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700537 JNIEnv *env;
538 if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
539 return -1;
540 }
541
542 int numApps = msgLen/sizeof(hub_app_info);
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700543 hub_app_info info;
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700544 const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700545
Alexey Polyudovab2d4452016-04-08 09:56:35 -0700546 for (int i = 0; i < numApps; i++, unalignedInfoAddr++) {
547 memcpy(&info, unalignedInfoAddr, sizeof(info));
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700548 // We will only have one instance of the app
549 // TODO : Change this logic once we support multiple instances of the same app
550 int appInstance = get_app_instance_for_app_id(info.app_name.id);
551 add_app_instance(&info, hubHandle, appInstance, env);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700552 }
553
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700554 return 0;
555}
556
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700557static void passOnOsResponse(uint32_t hubHandle, uint32_t msgType,
558 status_response_t *rsp, int8_t *additionalData,
559 size_t additionalDataLen) {
560 JNIEnv *env;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700561
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700562 if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
563 ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32, msgType);
564 return;
565 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700566
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700567 uint32_t header[MSG_HEADER_SIZE];
568 memset(header, 0, sizeof(header));
569
570 if (!additionalData) {
571 additionalDataLen = 0; // clamp
572 }
573 int msgLen = 1 + additionalDataLen;
574
575 int8_t *msg = new int8_t[msgLen];
576
577 if (!msg) {
578 ALOGW("Unexpected : Ran out of memory, cannot send response");
579 return;
580 }
581
582 header[HEADER_FIELD_MSG_TYPE] = msgType;
583 header[HEADER_FIELD_MSG_VERSION] = 0;
584 header[HEADER_FIELD_HUB_HANDLE] = hubHandle;
585 header[HEADER_FIELD_APP_INSTANCE] = OS_APP_ID;
586
587 msg[0] = rsp->result;
588
589 if (additionalData) {
590 memcpy(&msg[1], additionalData, additionalDataLen);
591 }
592
593 jbyteArray jmsg = env->NewByteArray(msgLen);
594 jintArray jheader = env->NewIntArray(sizeof(header));
595
596 env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
597 env->SetIntArrayRegion(jheader, 0, sizeof(header), (jint *)header);
598
599 ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32,
600 header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE],
601 header[HEADER_FIELD_HUB_HANDLE]);
602
603 env->CallIntMethod(db.jniInfo.jContextHubService,
604 db.jniInfo.contextHubServiceMsgReceiptCallback,
605 jheader, jmsg);
Andrew Rossignol52dda592016-08-09 10:54:38 -0700606 env->DeleteLocalRef(jmsg);
607 env->DeleteLocalRef(jheader);
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700608
609 delete[] msg;
610}
611
612void closeUnloadTxn(bool success) {
613 void *txnData = nullptr;
614 hub_messages_e txnId;
615
616 if (success && fetchTxnData(&txnId, &txnData) == 0 &&
617 txnId == CONTEXT_HUB_UNLOAD_APP) {
618 db.appInstances.erase(*(uint32_t *)txnData);
619 } else {
620 ALOGW("Could not unload the app successfully ! success %d, txnData %p", success, txnData);
621 }
622
623 closeTxn();
624}
625
626void closeLoadTxn(bool success, int *appInstanceHandle) {
627 void *txnData;
628 hub_messages_e txnId;
629
630 if (success && fetchTxnData(&txnId, &txnData) == 0 &&
631 txnId == CONTEXT_HUB_LOAD_APP) {
632 app_instance_info_s *info = (app_instance_info_s *)txnData;
633 *appInstanceHandle = info->instanceId;
634
635 JNIEnv *env;
636 if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) == JNI_OK) {
637 add_app_instance(&info->appInfo, info->hubHandle, info->instanceId, env);
638 } else {
639 ALOGW("Could not attach to JVM !");
640 }
641 sendQueryForApps(info->appInfo.app_name.id);
642 } else {
643 ALOGW("Could not load the app successfully ! Unexpected failure");
644 }
645
646 closeTxn();
647}
648
649static bool isValidOsStatus(const uint8_t *msg, size_t msgLen,
650 status_response_t *rsp) {
651 // Workaround a bug in some HALs
652 if (msgLen == 1) {
653 rsp->result = msg[0];
654 return true;
655 }
656
657 if (!msg || msgLen != sizeof(*rsp)) {
658 ALOGW("Received invalid response %p of size %zu", msg, msgLen);
659 return false;
660 }
661
662 memcpy(rsp, msg, sizeof(*rsp));
663
664 // No sanity checks on return values
665 return true;
666}
667
668static void invalidateNanoApps(uint32_t hubHandle) {
669 JNIEnv *env;
670
671 if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
672 ALOGW("Could not attach to JVM !");
673 }
674
675 auto end = db.appInstances.end();
676 for (auto current = db.appInstances.begin(); current != end; ) {
677 app_instance_info_s info = current->second;
678 current++;
679 if (info.hubHandle == hubHandle) {
680 delete_app_instance(info.instanceId, env);
681 }
682 }
683}
684
685static int handle_os_message(uint32_t msgType, uint32_t hubHandle,
686 const uint8_t *msg, int msgLen) {
687 int retVal = -1;
688
689 ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
690 hubHandle, msgType, msgLen);
691
692 struct status_response_t rsp;
Ashutosh Joshi6239cc62016-04-04 16:19:29 -0700693
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700694 switch(msgType) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700695
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700696 case CONTEXT_HUB_APPS_ENABLE:
697 case CONTEXT_HUB_APPS_DISABLE:
698 case CONTEXT_HUB_LOAD_APP:
699 case CONTEXT_HUB_UNLOAD_APP:
700 if (isValidOsStatus(msg, msgLen, &rsp)) {
701 if (msgType == CONTEXT_HUB_LOAD_APP) {
702 int appInstanceHandle;
703 closeLoadTxn(rsp.result == 0, &appInstanceHandle);
704 passOnOsResponse(hubHandle, msgType, &rsp, (int8_t *)(&appInstanceHandle),
705 sizeof(appInstanceHandle));
706 } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
707 closeUnloadTxn(rsp.result == 0);
708 passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
709 } else {
710 passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
711 }
712 retVal = 0;
713 }
714 break;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700715
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700716 case CONTEXT_HUB_QUERY_APPS:
717 rsp.result = 0;
718 retVal = handle_query_apps_response(msg, msgLen, hubHandle);
719 passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
720 break;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700721
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700722 case CONTEXT_HUB_QUERY_MEMORY:
723 // Deferring this use
724 retVal = 0;
725 break;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700726
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700727 case CONTEXT_HUB_OS_REBOOT:
728 if (isValidOsStatus(msg, msgLen, &rsp)) {
729 rsp.result = 0;
730 ALOGW("Context Hub handle %d restarted", hubHandle);
Ashutosh Joshi11864402016-07-15 13:46:22 -0700731 closeTxn();
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700732 passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
733 invalidateNanoApps(hubHandle);
734 query_hub_for_apps(ALL_APPS, hubHandle);
735 retVal = 0;
736 }
737 break;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700738
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700739 default:
740 retVal = -1;
741 break;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700742 }
743
744 return retVal;
745}
746
747static bool sanity_check_cookie(void *cookie, uint32_t hub_id) {
748 int *ptr = (int *)cookie;
749
750 if (!ptr || *ptr >= db.hubInfo.numHubs) {
751 return false;
752 }
753
754 if (db.hubInfo.hubs[*ptr].hub_id != hub_id) {
755 return false;
756 } else {
757 return true;
758 }
759}
760
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700761
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700762int context_hub_callback(uint32_t hubId,
763 const struct hub_message_t *msg,
Peng Xu9ff7d222016-02-11 13:02:05 -0800764 void *cookie) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700765 if (!msg) {
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700766 ALOGW("NULL message");
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700767 return -1;
768 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700769 if (!sanity_check_cookie(cookie, hubId)) {
770 ALOGW("Incorrect cookie %" PRId32 " for cookie %p! Bailing",
771 hubId, cookie);
772
773 return -1;
774 }
775
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700776
destradaa6469c232016-04-27 17:53:23 -0700777 uint32_t messageType = msg->message_type;
778 uint32_t hubHandle = *(uint32_t*) cookie;
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700779
destradaa6469c232016-04-27 17:53:23 -0700780 if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700781 handle_os_message(messageType, hubHandle, (uint8_t*) msg->message, msg->message_len);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700782 } else {
destradaa6469c232016-04-27 17:53:23 -0700783 int appHandle = get_app_instance_for_app_id(msg->app_name.id);
784 if (appHandle < 0) {
785 ALOGE("Filtering out message due to invalid App Instance.");
786 } else {
787 uint32_t msgHeader[MSG_HEADER_SIZE] = {};
788 msgHeader[HEADER_FIELD_MSG_TYPE] = messageType;
789 msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
790 msgHeader[HEADER_FIELD_APP_INSTANCE] = appHandle;
791 onMessageReceipt(msgHeader, MSG_HEADER_SIZE, (char*) msg->message, msg->message_len);
792 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700793 }
794
795 return 0;
Peng Xu9ff7d222016-02-11 13:02:05 -0800796}
797
798static int init_jni(JNIEnv *env, jobject instance) {
799
800 if (env->GetJavaVM(&db.jniInfo.vm) != JNI_OK) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700801 return -1;
Peng Xu9ff7d222016-02-11 13:02:05 -0800802 }
803
804 db.jniInfo.jContextHubService = env->NewGlobalRef(instance);
805
806 db.jniInfo.contextHubInfoClass =
807 env->FindClass("android/hardware/location/ContextHubInfo");
808
809 db.jniInfo.contextHubServiceClass =
810 env->FindClass("android/hardware/location/ContextHubService");
811
812 db.jniInfo.memoryRegionsClass =
813 env->FindClass("android/hardware/location/MemoryRegion");
814
Peng Xu9ff7d222016-02-11 13:02:05 -0800815 db.jniInfo.contextHubInfoCtor =
816 env->GetMethodID(db.jniInfo.contextHubInfoClass, "<init>", "()V");
817 db.jniInfo.contextHubInfoSetId =
818 env->GetMethodID(db.jniInfo.contextHubInfoClass, "setId", "(I)V");
819 db.jniInfo.contextHubInfoSetName =
820 env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName",
821 "(Ljava/lang/String;)V");
822
823 db.jniInfo.contextHubInfoSetVendor =
824 env->GetMethodID(db.jniInfo.contextHubInfoClass,
825 "setVendor", "(Ljava/lang/String;)V");
826 db.jniInfo.contextHubInfoSetToolchain =
827 env->GetMethodID(db.jniInfo.contextHubInfoClass,
828 "setToolchain", "(Ljava/lang/String;)V");
829 db.jniInfo.contextHubInfoSetPlatformVersion =
830 env->GetMethodID(db.jniInfo.contextHubInfoClass,
831 "setPlatformVersion", "(I)V");
832 db.jniInfo.contextHubInfoSetStaticSwVersion =
833 env->GetMethodID(db.jniInfo.contextHubInfoClass,
834 "setStaticSwVersion", "(I)V");
835 db.jniInfo.contextHubInfoSetToolchainVersion =
836 env->GetMethodID(db.jniInfo.contextHubInfoClass,
837 "setToolchainVersion", "(I)V");
838 db.jniInfo.contextHubInfoSetPeakMips =
839 env->GetMethodID(db.jniInfo.contextHubInfoClass,
840 "setPeakMips", "(F)V");
841 db.jniInfo.contextHubInfoSetStoppedPowerDrawMw =
842 env->GetMethodID(db.jniInfo.contextHubInfoClass,
843 "setStoppedPowerDrawMw", "(F)V");
844 db.jniInfo.contextHubInfoSetSleepPowerDrawMw =
845 env->GetMethodID(db.jniInfo.contextHubInfoClass,
846 "setSleepPowerDrawMw", "(F)V");
847 db.jniInfo.contextHubInfoSetPeakPowerDrawMw =
848 env->GetMethodID(db.jniInfo.contextHubInfoClass,
849 "setPeakPowerDrawMw", "(F)V");
850 db.jniInfo.contextHubInfoSetSupportedSensors =
851 env->GetMethodID(db.jniInfo.contextHubInfoClass,
852 "setSupportedSensors", "([I)V");
853 db.jniInfo.contextHubInfoSetMemoryRegions =
854 env->GetMethodID(db.jniInfo.contextHubInfoClass,
855 "setMemoryRegions", "([Landroid/hardware/location/MemoryRegion;)V");
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700856 db.jniInfo.contextHubInfoSetMaxPacketLenBytes =
857 env->GetMethodID(db.jniInfo.contextHubInfoClass,
858 "setMaxPacketLenBytes", "(I)V");
Peng Xu9ff7d222016-02-11 13:02:05 -0800859
860
861 db.jniInfo.contextHubServiceMsgReceiptCallback =
862 env->GetMethodID(db.jniInfo.contextHubServiceClass, "onMessageReceipt",
863 "([I[B)I");
864 db.jniInfo.contextHubInfoSetName =
865 env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName",
866 "(Ljava/lang/String;)V");
867
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700868 db.jniInfo.contextHubServiceAddAppInstance =
869 env->GetMethodID(db.jniInfo.contextHubServiceClass,
870 "addAppInstance", "(IIJI)I");
871
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700872 db.jniInfo.contextHubServiceDeleteAppInstance =
873 env->GetMethodID(db.jniInfo.contextHubServiceClass,
874 "deleteAppInstance", "(I)I");
Peng Xu9ff7d222016-02-11 13:02:05 -0800875
876 return 0;
877}
878
879static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t *hub) {
880 jstring jstrBuf;
881 jintArray jintBuf;
882 jobjectArray jmemBuf;
883
Peng Xu9ff7d222016-02-11 13:02:05 -0800884 jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass,
885 db.jniInfo.contextHubInfoCtor);
886 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id);
887
888 jstrBuf = env->NewStringUTF(hub->name);
889 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetName, jstrBuf);
Greg Kaiserbece5992016-05-09 10:23:56 -0700890 env->DeleteLocalRef(jstrBuf);
Peng Xu9ff7d222016-02-11 13:02:05 -0800891
892 jstrBuf = env->NewStringUTF(hub->vendor);
893 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetVendor, jstrBuf);
Greg Kaiserbece5992016-05-09 10:23:56 -0700894 env->DeleteLocalRef(jstrBuf);
Peng Xu9ff7d222016-02-11 13:02:05 -0800895
896 jstrBuf = env->NewStringUTF(hub->toolchain);
897 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchain, jstrBuf);
Greg Kaiserbece5992016-05-09 10:23:56 -0700898 env->DeleteLocalRef(jstrBuf);
Peng Xu9ff7d222016-02-11 13:02:05 -0800899
900 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub->platform_version);
901 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub->toolchain_version);
902 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub->peak_mips);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700903 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw,
904 hub->stopped_power_draw_mw);
905 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw,
906 hub->sleep_power_draw_mw);
907 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw,
908 hub->peak_power_draw_mw);
909 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMaxPacketLenBytes,
910 hub->max_supported_msg_len);
911
Peng Xu9ff7d222016-02-11 13:02:05 -0800912
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700913 jintBuf = env->NewIntArray(hub->num_connected_sensors);
914 int *connectedSensors = new int[hub->num_connected_sensors];
915
916 if (!connectedSensors) {
917 ALOGW("Cannot allocate memory! Unexpected");
918 assert(false);
919 } else {
920 for (unsigned int i = 0; i < hub->num_connected_sensors; i++) {
921 connectedSensors[i] = hub->connected_sensors[i].sensor_id;
922 }
923 }
924
925 env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
926 connectedSensors);
927
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700928 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
Greg Kaiserbece5992016-05-09 10:23:56 -0700929 env->DeleteLocalRef(jintBuf);
Peng Xu9ff7d222016-02-11 13:02:05 -0800930
931 // We are not getting the memory regions from the CH Hal - change this when it is available
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700932 jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, nullptr);
Peng Xu9ff7d222016-02-11 13:02:05 -0800933 // Note the zero size above. We do not need to set any elements
934 env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMemoryRegions, jmemBuf);
Greg Kaiserbece5992016-05-09 10:23:56 -0700935 env->DeleteLocalRef(jmemBuf);
Peng Xu9ff7d222016-02-11 13:02:05 -0800936
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700937
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700938 delete[] connectedSensors;
Peng Xu9ff7d222016-02-11 13:02:05 -0800939 return jHub;
940}
941
942static jobjectArray nativeInitialize(JNIEnv *env, jobject instance)
943{
944 jobject hub;
945 jobjectArray retArray;
946
Peng Xu9ff7d222016-02-11 13:02:05 -0800947 if (init_jni(env, instance) < 0) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700948 return nullptr;
Peng Xu9ff7d222016-02-11 13:02:05 -0800949 }
950
Peng Xu9ff7d222016-02-11 13:02:05 -0800951 initContextHubService();
952
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700953 if (db.hubInfo.numHubs > 1) {
954 ALOGW("Clamping the number of hubs to 1");
955 db.hubInfo.numHubs = 1;
956 }
957
958 retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, nullptr);
Peng Xu9ff7d222016-02-11 13:02:05 -0800959
960 for(int i = 0; i < db.hubInfo.numHubs; i++) {
961 hub = constructJContextHubInfo(env, &db.hubInfo.hubs[i]);
962 env->SetObjectArrayElement(retArray, i, hub);
963 }
964
965 return retArray;
966}
967
968static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
969 jbyteArray data_) {
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700970 jint retVal = -1; // Default to failure
Peng Xu9ff7d222016-02-11 13:02:05 -0800971
972 jint *header = env->GetIntArrayElements(header_, 0);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -0700973 unsigned int numHeaderElements = env->GetArrayLength(header_);
Peng Xu9ff7d222016-02-11 13:02:05 -0800974 jbyte *data = env->GetByteArrayElements(data_, 0);
975 int dataBufferLength = env->GetArrayLength(data_);
976
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700977 if (numHeaderElements < MSG_HEADER_SIZE) {
978 ALOGW("Malformed header len");
979 return -1;
980 }
Ashutosh Joshicafdee92016-04-04 16:19:29 -0700981
Ashutosh Joshi54787a52016-04-27 11:19:16 -0700982 uint32_t appInstanceHandle = header[HEADER_FIELD_APP_INSTANCE];
983 uint32_t msgType = header[HEADER_FIELD_MSG_TYPE];
984 int hubHandle = -1;
985 int hubId;
986 uint64_t appId;
987
988 if (msgType == CONTEXT_HUB_UNLOAD_APP) {
989 hubHandle = get_hub_handle_for_app_instance(appInstanceHandle);
990 } else if (msgType == CONTEXT_HUB_LOAD_APP) {
991 if (numHeaderElements < MSG_HEADER_SIZE_LOAD_APP) {
992 return -1;
993 }
994 uint64_t appIdLo = header[HEADER_FIELD_LOAD_APP_ID_LO];
995 uint64_t appIdHi = header[HEADER_FIELD_LOAD_APP_ID_HI];
996 appId = appIdHi << 32 | appIdLo;
997
998 hubHandle = header[HEADER_FIELD_HUB_HANDLE];
999 } else {
1000 hubHandle = header[HEADER_FIELD_HUB_HANDLE];
1001 }
1002
1003 if (hubHandle < 0) {
1004 ALOGD("Invalid hub Handle %d", hubHandle);
1005 return -1;
1006 }
1007
1008 if (msgType == CONTEXT_HUB_LOAD_APP ||
1009 msgType == CONTEXT_HUB_UNLOAD_APP) {
1010
1011 if (isTxnPending()) {
1012 ALOGW("Cannot load or unload app while a transaction is pending !");
1013 return -1;
1014 }
1015
1016 if (msgType == CONTEXT_HUB_LOAD_APP) {
1017 if (startLoadAppTxn(appId, hubHandle) != 0) {
Ashutosh Joshi11864402016-07-15 13:46:22 -07001018 ALOGW("Cannot Start Load Transaction");
Ashutosh Joshi54787a52016-04-27 11:19:16 -07001019 return -1;
1020 }
1021 } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
1022 if (startUnloadAppTxn(appInstanceHandle) != 0) {
Ashutosh Joshi11864402016-07-15 13:46:22 -07001023 ALOGW("Cannot Start UnLoad Transaction");
Ashutosh Joshi54787a52016-04-27 11:19:16 -07001024 return -1;
1025 }
1026 }
1027 }
1028
1029 bool setAddressSuccess = false;
1030 hub_message_t msg;
1031
1032 msg.message_type = msgType;
1033
1034 if (msgType == CONTEXT_HUB_UNLOAD_APP) {
1035 msg.message_len = sizeof(db.appInstances[appInstanceHandle].appInfo.app_name);
1036 msg.message = &db.appInstances[appInstanceHandle].appInfo.app_name;
1037 setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
1038 hubId = get_hub_id_for_hub_handle(hubHandle);
1039 } else {
1040 msg.message_len = dataBufferLength;
1041 msg.message = data;
Ashutosh Joshicafdee92016-04-04 16:19:29 -07001042
1043 if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) {
Ashutosh Joshi54787a52016-04-27 11:19:16 -07001044 setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
1045 hubId = get_hub_id_for_hub_handle(hubHandle);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -07001046 } else {
Ashutosh Joshicafdee92016-04-04 16:19:29 -07001047 setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0);
1048 hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]);
1049 }
Ashutosh Joshi54787a52016-04-27 11:19:16 -07001050 }
Ashutosh Joshicafdee92016-04-04 16:19:29 -07001051
Ashutosh Joshi54787a52016-04-27 11:19:16 -07001052 if (setAddressSuccess && hubId >= 0) {
1053 ALOGD("Asking HAL to remove app");
1054 retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
Ashutosh Joshib741e3b2016-03-29 09:19:56 -07001055 } else {
Ashutosh Joshi54787a52016-04-27 11:19:16 -07001056 ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
1057 header[HEADER_FIELD_APP_INSTANCE],
1058 header[HEADER_FIELD_HUB_HANDLE],
1059 (int)setAddressSuccess);
1060 }
1061
1062 if (retVal != 0) {
1063 ALOGD("Send Message failure - %d", retVal);
1064 if (msgType == CONTEXT_HUB_LOAD_APP) {
1065 closeLoadTxn(false, nullptr);
1066 } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
1067 closeUnloadTxn(false);
1068 }
Ashutosh Joshib741e3b2016-03-29 09:19:56 -07001069 }
Peng Xu9ff7d222016-02-11 13:02:05 -08001070
1071 env->ReleaseIntArrayElements(header_, header, 0);
1072 env->ReleaseByteArrayElements(data_, data, 0);
1073
1074 return retVal;
1075}
1076
1077//--------------------------------------------------------------------------------------------------
1078//
1079static const JNINativeMethod gContextHubServiceMethods[] = {
1080 {"nativeInitialize",
1081 "()[Landroid/hardware/location/ContextHubInfo;",
1082 (void*)nativeInitialize },
1083 {"nativeSendMessage",
1084 "([I[B)I",
1085 (void*)nativeSendMessage }
1086};
1087
1088}//namespace android
1089
1090using namespace android;
1091
1092int register_android_hardware_location_ContextHubService(JNIEnv *env)
1093{
1094 RegisterMethodsOrDie(env, "android/hardware/location/ContextHubService",
1095 gContextHubServiceMethods, NELEM(gContextHubServiceMethods));
1096
1097 return 0;
1098}