Merge "Add state for loading/unloading apps" into nyc-mr1-dev

This commit is contained in:
Ashutosh Joshi
2016-07-13 21:51:30 +00:00
committed by Android (Google) Code Review
2 changed files with 556 additions and 119 deletions

View File

@@ -16,6 +16,11 @@
package android.hardware.location;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -53,10 +58,14 @@ public class ContextHubService extends IContextHubService.Stub {
private static final int PRE_LOADED_APP_MEM_REQ = 0;
private static final int MSG_HEADER_SIZE = 4;
private static final int MSG_FIELD_TYPE = 0;
private static final int MSG_FIELD_VERSION = 1;
private static final int MSG_FIELD_HUB_HANDLE = 2;
private static final int MSG_FIELD_APP_INSTANCE = 3;
private static final int HEADER_FIELD_MSG_TYPE = 0;
private static final int HEADER_FIELD_MSG_VERSION = 1;
private static final int HEADER_FIELD_HUB_HANDLE = 2;
private static final int HEADER_FIELD_APP_INSTANCE = 3;
private static final int HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
private static final int HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
private static final int MSG_LOAD_APP_HEADER_SIZE = MSG_HEADER_SIZE + 2;
private static final int OS_APP_INSTANCE = -1;
@@ -146,11 +155,16 @@ public class ContextHubService extends IContextHubService.Stub {
return -1;
}
int[] msgHeader = new int[MSG_HEADER_SIZE];
msgHeader[MSG_FIELD_HUB_HANDLE] = contextHubHandle;
msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
msgHeader[MSG_FIELD_VERSION] = 0;
msgHeader[MSG_FIELD_TYPE] = MSG_LOAD_NANO_APP;
int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE];
msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle;
msgHeader[HEADER_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP;
long appId = app.getAppId();
msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF);
if (nativeSendMessage(msgHeader, app.getAppBinary()) != 0) {
return -1;
@@ -169,12 +183,14 @@ public class ContextHubService extends IContextHubService.Stub {
// Call Native interface here
int[] msgHeader = new int[MSG_HEADER_SIZE];
msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
msgHeader[MSG_FIELD_VERSION] = 0;
msgHeader[MSG_FIELD_TYPE] = MSG_UNLOAD_NANO_APP;
msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppInstanceHandle;
msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_UNLOAD_NANO_APP;
if (nativeSendMessage(msgHeader, null) != 0) {
byte msg[] = new byte[0];
if (nativeSendMessage(msgHeader, msg) != 0) {
return -1;
}
@@ -222,10 +238,10 @@ public class ContextHubService extends IContextHubService.Stub {
checkPermissions();
int[] msgHeader = new int[MSG_HEADER_SIZE];
msgHeader[MSG_FIELD_HUB_HANDLE] = hubHandle;
msgHeader[MSG_FIELD_APP_INSTANCE] = nanoAppHandle;
msgHeader[MSG_FIELD_VERSION] = msg.getVersion();
msgHeader[MSG_FIELD_TYPE] = msg.getMsgType();
msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle;
msgHeader[HEADER_FIELD_MSG_VERSION] = msg.getVersion();
msgHeader[HEADER_FIELD_MSG_TYPE] = msg.getMsgType();
return nativeSendMessage(msgHeader, msg.getData());
}
@@ -269,15 +285,17 @@ public class ContextHubService extends IContextHubService.Stub {
Log.v(TAG, "No message callbacks registered.");
return 0;
}
ContextHubMessage message =
new ContextHubMessage(header[MSG_FIELD_TYPE], header[MSG_FIELD_VERSION], data);
ContextHubMessage msg = new ContextHubMessage(header[HEADER_FIELD_MSG_TYPE],
header[HEADER_FIELD_MSG_VERSION],
data);
for (int i = 0; i < callbacksCount; ++i) {
IContextHubCallback callback = mCallbacksList.getBroadcastItem(i);
try {
callback.onMessageReceipt(
header[MSG_FIELD_HUB_HANDLE],
header[MSG_FIELD_APP_INSTANCE],
message);
header[HEADER_FIELD_HUB_HANDLE],
header[HEADER_FIELD_APP_INSTANCE],
msg);
} catch (RemoteException e) {
Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ").");
continue;
@@ -308,12 +326,20 @@ public class ContextHubService extends IContextHubService.Stub {
return 0;
}
private int deleteAppInstance(int appInstanceHandle) {
if (mNanoAppHash.remove(appInstanceHandle) == null) {
return -1;
}
return 0;
}
private void sendVrStateChangeMessageToApp(NanoAppInstanceInfo app, boolean vrModeEnabled) {
int[] msgHeader = new int[MSG_HEADER_SIZE];
msgHeader[MSG_FIELD_TYPE] = 0;
msgHeader[MSG_FIELD_VERSION] = 0;
msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
msgHeader[MSG_FIELD_APP_INSTANCE] = app.getHandle();
msgHeader[HEADER_FIELD_MSG_TYPE] = 0;
msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
msgHeader[HEADER_FIELD_APP_INSTANCE] = app.getHandle();
byte[] data = new byte[1];
data[0] = (byte) ((vrModeEnabled) ? 1 : 0);

View File

@@ -21,28 +21,34 @@
#include <inttypes.h>
#include <jni.h>
#include <queue>
#include <unordered_map>
#include <mutex>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unordered_map>
#include <queue>
#include <cutils/log.h>
#include "JNIHelp.h"
#include "core_jni_helpers.h"
static constexpr int OS_APP_ID=-1;
static constexpr int OS_APP_ID = -1;
static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
static constexpr int MIN_APP_ID=1;
static constexpr int MAX_APP_ID=128;
static constexpr int MIN_APP_ID = 1;
static constexpr int MAX_APP_ID = 128;
static constexpr size_t MSG_HEADER_SIZE=4;
static constexpr int HEADER_FIELD_MSG_TYPE=0;
//static constexpr int HEADER_FIELD_MSG_VERSION=1;
static constexpr int HEADER_FIELD_HUB_HANDLE=2;
static constexpr int HEADER_FIELD_APP_INSTANCE=3;
static constexpr size_t MSG_HEADER_SIZE = 4;
static constexpr size_t HEADER_FIELD_MSG_TYPE = 0;
static constexpr size_t HEADER_FIELD_MSG_VERSION = 1;
static constexpr size_t HEADER_FIELD_HUB_HANDLE = 2;
static constexpr size_t HEADER_FIELD_APP_INSTANCE = 3;
static constexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
static constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
static constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
namespace android {
@@ -83,6 +89,7 @@ struct jniInfo_s {
jmethodID contextHubServiceMsgReceiptCallback;
jmethodID contextHubServiceAddAppInstance;
jmethodID contextHubServiceDeleteAppInstance;
};
struct context_hub_info_s {
@@ -93,10 +100,53 @@ struct context_hub_info_s {
};
struct app_instance_info_s {
uint32_t hubHandle; // Id of the hub this app is on
int instanceId; // systemwide unique instance id - assigned
uint64_t truncName; // Possibly truncated name for logging
uint32_t hubHandle; // Id of the hub this app is on
int instanceId; // system wide unique instance id - assigned
struct hub_app_info appInfo; // returned from the HAL
uint64_t truncName; // Possibly truncated name - logging
};
/*
* TODO(ashutoshj): From original code review:
*
* So, I feel like we could possible do a better job of organizing this code,
* and being more C++-y. Consider something like this:
* class TxnManager {
* public:
* TxnManager();
* ~TxnManager();
* int add(hub_message_e identifier, void *data);
* int close();
* bool isPending() const;
* int fetchData(hub_message_e *identifier, void **data) const;
*
* private:
* bool mPending;
* mutable std::mutex mLock;
* hub_message_e mIdentifier;
* void *mData;
* };
*
* And then, for example, we'd have things like:
* TxnManager::TxnManager() : mPending(false), mLock(), mIdentifier(), mData(nullptr) {}
* int TxnManager::add(hub_message_e identifier, void *data) {
* std::lock_guard<std::mutex> lock(mLock);
* mPending = true;
* mData = txnData;
* mIdentifier = txnIdentifier;
* return 0;
* }
* And then calling code would look like:
* if (!db.txnManager.add(CONTEXT_HUB_LOAD_APP, txnInfo)) {
*
* This would make it clearer the nothing is manipulating any state within TxnManager
* unsafely and outside of these couple of calls.
*/
struct txnManager_s {
bool txnPending; // Is a transaction pending
std::mutex m; // mutex for manager
hub_messages_e txnIdentifier; // What are we doing
void *txnData; // Details
};
struct contextHubServiceDb_s {
@@ -105,12 +155,69 @@ struct contextHubServiceDb_s {
jniInfo_s jniInfo;
std::queue<int> freeIds;
std::unordered_map<int, app_instance_info_s> appInstances;
txnManager_s txnManager;
};
} // unnamed namespace
static contextHubServiceDb_s db;
static bool initTxnManager() {
txnManager_s *mgr = &db.txnManager;
mgr->txnData = nullptr;
mgr->txnPending = false;
return true;
}
static int addTxn(hub_messages_e txnIdentifier, void *txnData) {
txnManager_s *mgr = &db.txnManager;
std::lock_guard<std::mutex>lock(mgr->m);
mgr->txnPending = true;
mgr->txnData = txnData;
mgr->txnIdentifier = txnIdentifier;
return 0;
}
static int closeTxn() {
txnManager_s *mgr = &db.txnManager;
std::lock_guard<std::mutex>lock(mgr->m);
mgr->txnPending = false;
free(mgr->txnData);
mgr->txnData = nullptr;
return 0;
}
static bool isTxnPending() {
txnManager_s *mgr = &db.txnManager;
std::lock_guard<std::mutex>lock(mgr->m);
return mgr->txnPending;
}
static int fetchTxnData(hub_messages_e *id, void **data) {
txnManager_s *mgr = &db.txnManager;
if (!id || !data) {
ALOGW("Null params id %p, data %p", id, data);
return -1;
}
std::lock_guard<std::mutex>lock(mgr->m);
if (!mgr->txnPending) {
ALOGW("No Transactions pending");
return -1;
}
// else
*id = mgr->txnIdentifier;
*data = mgr->txnData;
return 0;
}
int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg,
void *cookie);
@@ -152,13 +259,21 @@ static int get_hub_id_for_hub_handle(int hubHandle) {
}
}
static int get_hub_id_for_app_instance(int id) {
static int get_hub_handle_for_app_instance(int id) {
if (!db.appInstances.count(id)) {
ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
return -1;
}
int hubHandle = db.appInstances[id].hubHandle;
return db.appInstances[id].hubHandle;
}
static int get_hub_id_for_app_instance(int id) {
int hubHandle = get_hub_handle_for_app_instance(id);
if (hubHandle < 0) {
return -1;
}
return db.hubInfo.hubs[hubHandle].hub_id;
}
@@ -184,7 +299,7 @@ static int set_dest_app(hub_message_t *msg, int id) {
return 0;
}
static void send_query_for_apps() {
static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) {
hub_message_t msg;
query_apps_request_t queryMsg;
@@ -194,23 +309,31 @@ static void send_query_for_apps() {
msg.message_len = sizeof(queryMsg);
msg.message = &queryMsg;
ALOGD("Sending query for apps to hub %" PRIu32, hubHandle);
set_os_app_as_destination(&msg, hubHandle);
if (send_msg_to_hub(&msg, hubHandle) != 0) {
ALOGW("Could not query hub %" PRIu32 " for apps", hubHandle);
}
}
static void sendQueryForApps(uint64_t appId) {
for (int i = 0; i < db.hubInfo.numHubs; i++ ) {
ALOGD("Sending query for apps to hub %d", i);
set_os_app_as_destination(&msg, i);
if (send_msg_to_hub(&msg, i) != 0) {
ALOGW("Could not query hub %i for apps", i);
}
query_hub_for_apps(appId, i);
}
}
static int return_id(int id) {
// Note : This method is not thread safe.
// id returned is guarenteed to be in use
db.freeIds.push(id);
return 0;
// id returned is guaranteed to be in use
if (id >= 0) {
db.freeIds.push(id);
return 0;
}
return -1;
}
static int generate_id(void) {
static int generate_id() {
// Note : This method is not thread safe.
int retVal = -1;
@@ -222,23 +345,31 @@ static int generate_id(void) {
return retVal;
}
int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *env) {
static int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle,
int appInstanceHandle, JNIEnv *env) {
ALOGI("Loading App");
// Not checking if the apps are indeed distinct
app_instance_info_s entry;
int appInstanceHandle = generate_id();
assert(appInfo);
if (appInstanceHandle < 0) {
ALOGE("Cannot find resources to add app instance %d",
appInstanceHandle);
return -1;
if (db.appInstances.count(appInstanceHandle) == 0) {
appInstanceHandle = generate_id();
if (appInstanceHandle < 0) {
ALOGE("Cannot find resources to add app instance %d",
appInstanceHandle);
return -1;
}
}
entry.appInfo = *appInfo;
entry.instanceId = appInstanceHandle;
entry.truncName = appInfo->app_name.id;
entry.hubHandle = hubHandle;
db.appInstances[appInstanceHandle] = entry;
// Finally - let the service know of this app instance
@@ -254,17 +385,70 @@ int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *en
return appInstanceHandle;
}
int delete_app_instance(int id) {
int delete_app_instance(int id, JNIEnv *env) {
if (!db.appInstances.count(id)) {
ALOGW("Cannot find App id : %d", id);
return -1;
}
return_id(id);
db.appInstances.erase(id);
if (env->CallIntMethod(db.jniInfo.jContextHubService,
db.jniInfo.contextHubServiceDeleteAppInstance,
id) != 0) {
ALOGW("Could not delete App id : %d", id);
return -1;
}
ALOGI("Deleted App id : %d", id);
return 0;
}
static int startLoadAppTxn(uint64_t appId, int hubHandle) {
app_instance_info_s *txnInfo = (app_instance_info_s *)malloc(sizeof(app_instance_info_s));
int instanceId = generate_id();
if (!txnInfo || instanceId < 0) {
return_id(instanceId);
free(txnInfo);
return -1;
}
txnInfo->truncName = appId;
txnInfo->hubHandle = hubHandle;
txnInfo->instanceId = instanceId;
txnInfo->appInfo.app_name.id = appId;
txnInfo->appInfo.num_mem_ranges = 0;
txnInfo->appInfo.version = -1; // Awaited
if (!addTxn(CONTEXT_HUB_LOAD_APP, txnInfo)) {
return_id(instanceId);
free(txnInfo);
return -1;
}
return 0;
}
static int startUnloadAppTxn(uint32_t appInstanceHandle) {
uint32_t *txnData = (uint32_t *) malloc(sizeof(uint32_t));
if (!txnData) {
ALOGW("Cannot allocate memory to start unload transaction");
return -1;
}
*txnData = appInstanceHandle;
if (addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) {
free(txnData);
ALOGW("Cannot start transaction to unload app");
return -1;
}
return 0;
}
static void initContextHubService() {
int err = 0;
@@ -285,6 +469,7 @@ static void initContextHubService() {
db.freeIds.push(i);
}
initTxnManager();
if (db.hubInfo.contextHubModule) {
int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
&db.hubInfo.hubs);
@@ -302,6 +487,7 @@ static void initContextHubService() {
for (i = 0; i < db.hubInfo.numHubs; i++) {
db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id;
ALOGI("Subscribing to hubHandle %d with OS App name %" PRIu64, i, db.hubInfo.hubs[i].os_app_name.id);
if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
context_hub_callback,
&db.hubInfo.cookies[i]) == 0) {
@@ -309,7 +495,7 @@ static void initContextHubService() {
}
}
send_query_for_apps();
sendQueryForApps(ALL_APPS);
} else {
ALOGW("No Context Hub Module present");
}
@@ -346,7 +532,8 @@ static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_
return ret;
}
int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
int handle_query_apps_response(const uint8_t *msg, int msgLen,
uint32_t hubHandle) {
JNIEnv *env;
if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
return -1;
@@ -354,53 +541,200 @@ int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
int numApps = msgLen/sizeof(hub_app_info);
hub_app_info info;
hub_app_info *unalignedInfoAddr = (hub_app_info*)msg;
const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg;
for (int i = 0; i < numApps; i++, unalignedInfoAddr++) {
memcpy(&info, unalignedInfoAddr, sizeof(info));
add_app_instance(&info, hubHandle, env);
// We will only have one instance of the app
// TODO : Change this logic once we support multiple instances of the same app
int appInstance = get_app_instance_for_app_id(info.app_name.id);
add_app_instance(&info, hubHandle, appInstance, env);
}
return 0;
}
static void passOnOsResponse(uint32_t hubHandle, uint32_t msgType,
status_response_t *rsp, int8_t *additionalData,
size_t additionalDataLen) {
JNIEnv *env;
int handle_os_message(uint32_t msgType, uint32_t hubHandle,
char *msg, int msgLen) {
int retVal;
if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32, msgType);
return;
}
//ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
// hubHandle, msgType, msgLen);
uint32_t header[MSG_HEADER_SIZE];
memset(header, 0, sizeof(header));
if (!additionalData) {
additionalDataLen = 0; // clamp
}
int msgLen = 1 + additionalDataLen;
int8_t *msg = new int8_t[msgLen];
if (!msg) {
ALOGW("Unexpected : Ran out of memory, cannot send response");
return;
}
header[HEADER_FIELD_MSG_TYPE] = msgType;
header[HEADER_FIELD_MSG_VERSION] = 0;
header[HEADER_FIELD_HUB_HANDLE] = hubHandle;
header[HEADER_FIELD_APP_INSTANCE] = OS_APP_ID;
msg[0] = rsp->result;
if (additionalData) {
memcpy(&msg[1], additionalData, additionalDataLen);
}
jbyteArray jmsg = env->NewByteArray(msgLen);
jintArray jheader = env->NewIntArray(sizeof(header));
env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
env->SetIntArrayRegion(jheader, 0, sizeof(header), (jint *)header);
ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32,
header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE],
header[HEADER_FIELD_HUB_HANDLE]);
env->CallIntMethod(db.jniInfo.jContextHubService,
db.jniInfo.contextHubServiceMsgReceiptCallback,
jheader, jmsg);
delete[] msg;
}
void closeUnloadTxn(bool success) {
void *txnData;
hub_messages_e txnId;
if (success && fetchTxnData(&txnId, &txnData) == 0 &&
txnId == CONTEXT_HUB_UNLOAD_APP) {
db.appInstances.erase(*(uint32_t *)txnData);
} else {
ALOGW("Could not unload the app successfully ! success %d, txnData %p", success, txnData);
}
closeTxn();
}
void closeLoadTxn(bool success, int *appInstanceHandle) {
void *txnData;
hub_messages_e txnId;
if (success && fetchTxnData(&txnId, &txnData) == 0 &&
txnId == CONTEXT_HUB_LOAD_APP) {
app_instance_info_s *info = (app_instance_info_s *)txnData;
*appInstanceHandle = info->instanceId;
JNIEnv *env;
if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) == JNI_OK) {
add_app_instance(&info->appInfo, info->hubHandle, info->instanceId, env);
} else {
ALOGW("Could not attach to JVM !");
}
sendQueryForApps(info->appInfo.app_name.id);
} else {
ALOGW("Could not load the app successfully ! Unexpected failure");
}
closeTxn();
}
static bool isValidOsStatus(const uint8_t *msg, size_t msgLen,
status_response_t *rsp) {
// Workaround a bug in some HALs
if (msgLen == 1) {
rsp->result = msg[0];
return true;
}
if (!msg || msgLen != sizeof(*rsp)) {
ALOGW("Received invalid response %p of size %d", msg, msgLen);
return false;
}
memcpy(rsp, msg, sizeof(*rsp));
// No sanity checks on return values
return true;
}
static void invalidateNanoApps(uint32_t hubHandle) {
JNIEnv *env;
if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
ALOGW("Could not attach to JVM !");
}
auto end = db.appInstances.end();
for (auto current = db.appInstances.begin(); current != end; ) {
app_instance_info_s info = current->second;
current++;
if (info.hubHandle == hubHandle) {
delete_app_instance(info.instanceId, env);
}
}
}
static int handle_os_message(uint32_t msgType, uint32_t hubHandle,
const uint8_t *msg, int msgLen) {
int retVal = -1;
ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
hubHandle, msgType, msgLen);
switch(msgType) {
case CONTEXT_HUB_APPS_ENABLE:
retVal = 0;
break;
struct status_response_t rsp;
case CONTEXT_HUB_APPS_DISABLE:
retVal = 0;
break;
case CONTEXT_HUB_APPS_ENABLE:
case CONTEXT_HUB_APPS_DISABLE:
case CONTEXT_HUB_LOAD_APP:
case CONTEXT_HUB_UNLOAD_APP:
if (isValidOsStatus(msg, msgLen, &rsp)) {
if (msgType == CONTEXT_HUB_LOAD_APP) {
int appInstanceHandle;
closeLoadTxn(rsp.result == 0, &appInstanceHandle);
passOnOsResponse(hubHandle, msgType, &rsp, (int8_t *)(&appInstanceHandle),
sizeof(appInstanceHandle));
} else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
closeUnloadTxn(rsp.result == 0);
passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
} else {
passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
}
retVal = 0;
}
break;
case CONTEXT_HUB_LOAD_APP:
retVal = 0;
break;
case CONTEXT_HUB_QUERY_APPS:
rsp.result = 0;
retVal = handle_query_apps_response(msg, msgLen, hubHandle);
passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
break;
case CONTEXT_HUB_UNLOAD_APP:
retVal = 0;
break;
case CONTEXT_HUB_QUERY_MEMORY:
// Deferring this use
retVal = 0;
break;
case CONTEXT_HUB_QUERY_APPS:
retVal = handle_query_apps_response(msg, msgLen, hubHandle);
break;
case CONTEXT_HUB_QUERY_MEMORY:
retVal = 0;
break;
default:
retVal = -1;
break;
case CONTEXT_HUB_OS_REBOOT:
if (isValidOsStatus(msg, msgLen, &rsp)) {
rsp.result = 0;
ALOGW("Context Hub handle %d restarted", hubHandle);
passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
invalidateNanoApps(hubHandle);
query_hub_for_apps(ALL_APPS, hubHandle);
retVal = 0;
}
break;
default:
retVal = -1;
break;
}
return retVal;
@@ -420,10 +754,12 @@ static bool sanity_check_cookie(void *cookie, uint32_t hub_id) {
}
}
int context_hub_callback(uint32_t hubId,
const struct hub_message_t *msg,
void *cookie) {
if (!msg) {
ALOGW("NULL message");
return -1;
}
if (!sanity_check_cookie(cookie, hubId)) {
@@ -433,11 +769,12 @@ int context_hub_callback(uint32_t hubId,
return -1;
}
uint32_t messageType = msg->message_type;
uint32_t hubHandle = *(uint32_t*) cookie;
if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
handle_os_message(messageType, hubHandle, (char*) msg->message, msg->message_len);
handle_os_message(messageType, hubHandle, (uint8_t*) msg->message, msg->message_len);
} else {
int appHandle = get_app_instance_for_app_id(msg->app_name.id);
if (appHandle < 0) {
@@ -528,7 +865,9 @@ static int init_jni(JNIEnv *env, jobject instance) {
env->GetMethodID(db.jniInfo.contextHubServiceClass,
"addAppInstance", "(IIJI)I");
db.jniInfo.contextHubServiceDeleteAppInstance =
env->GetMethodID(db.jniInfo.contextHubServiceClass,
"deleteAppInstance", "(I)I");
return 0;
}
@@ -538,8 +877,6 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
jintArray jintBuf;
jobjectArray jmemBuf;
int dummyConnectedSensors[] = {1, 2, 3, 4, 5};
jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass,
db.jniInfo.contextHubInfoCtor);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id);
@@ -569,11 +906,21 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
hub->max_supported_msg_len);
// TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors);
// TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
// hub->connected_sensors);
jintBuf = env->NewIntArray(array_length(dummyConnectedSensors));
env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors);
jintBuf = env->NewIntArray(hub->num_connected_sensors);
int *connectedSensors = new int[hub->num_connected_sensors];
if (!connectedSensors) {
ALOGW("Cannot allocate memory! Unexpected");
assert(false);
} else {
for (unsigned int i = 0; i < hub->num_connected_sensors; i++) {
connectedSensors[i] = hub->connected_sensors[i].sensor_id;
}
}
env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
connectedSensors);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
env->DeleteLocalRef(jintBuf);
@@ -584,6 +931,7 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
env->DeleteLocalRef(jmemBuf);
delete[] connectedSensors;
return jHub;
}
@@ -622,33 +970,96 @@ static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
jbyte *data = env->GetByteArrayElements(data_, 0);
int dataBufferLength = env->GetArrayLength(data_);
if (numHeaderElements < MSG_HEADER_SIZE) {
ALOGW("Malformed header len");
return -1;
}
if (numHeaderElements >= MSG_HEADER_SIZE) {
bool setAddressSuccess;
int hubId;
hub_message_t msg;
uint32_t appInstanceHandle = header[HEADER_FIELD_APP_INSTANCE];
uint32_t msgType = header[HEADER_FIELD_MSG_TYPE];
int hubHandle = -1;
int hubId;
uint64_t appId;
if (msgType == CONTEXT_HUB_UNLOAD_APP) {
hubHandle = get_hub_handle_for_app_instance(appInstanceHandle);
} else if (msgType == CONTEXT_HUB_LOAD_APP) {
if (numHeaderElements < MSG_HEADER_SIZE_LOAD_APP) {
return -1;
}
uint64_t appIdLo = header[HEADER_FIELD_LOAD_APP_ID_LO];
uint64_t appIdHi = header[HEADER_FIELD_LOAD_APP_ID_HI];
appId = appIdHi << 32 | appIdLo;
hubHandle = header[HEADER_FIELD_HUB_HANDLE];
} else {
hubHandle = header[HEADER_FIELD_HUB_HANDLE];
}
if (hubHandle < 0) {
ALOGD("Invalid hub Handle %d", hubHandle);
return -1;
}
if (msgType == CONTEXT_HUB_LOAD_APP ||
msgType == CONTEXT_HUB_UNLOAD_APP) {
if (isTxnPending()) {
ALOGW("Cannot load or unload app while a transaction is pending !");
return -1;
}
if (msgType == CONTEXT_HUB_LOAD_APP) {
if (startLoadAppTxn(appId, hubHandle) != 0) {
return -1;
}
} else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
if (startUnloadAppTxn(appInstanceHandle) != 0) {
return -1;
}
}
}
bool setAddressSuccess = false;
hub_message_t msg;
msg.message_type = msgType;
if (msgType == CONTEXT_HUB_UNLOAD_APP) {
msg.message_len = sizeof(db.appInstances[appInstanceHandle].appInfo.app_name);
msg.message = &db.appInstances[appInstanceHandle].appInfo.app_name;
setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
hubId = get_hub_id_for_hub_handle(hubHandle);
} else {
msg.message_len = dataBufferLength;
msg.message = data;
if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) {
setAddressSuccess = (set_os_app_as_destination(&msg, header[HEADER_FIELD_HUB_HANDLE]) == 0);
hubId = get_hub_id_for_hub_handle(header[HEADER_FIELD_HUB_HANDLE]);
setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
hubId = get_hub_id_for_hub_handle(hubHandle);
} else {
setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0);
hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]);
}
}
if (setAddressSuccess && hubId >= 0) {
msg.message_type = header[HEADER_FIELD_MSG_TYPE];
msg.message_len = dataBufferLength;
msg.message = data;
retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
} else {
ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
header[HEADER_FIELD_APP_INSTANCE],
header[HEADER_FIELD_HUB_HANDLE],
(int)setAddressSuccess);
}
if (setAddressSuccess && hubId >= 0) {
ALOGD("Asking HAL to remove app");
retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
} else {
ALOGD("Malformed header len");
ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
header[HEADER_FIELD_APP_INSTANCE],
header[HEADER_FIELD_HUB_HANDLE],
(int)setAddressSuccess);
}
if (retVal != 0) {
ALOGD("Send Message failure - %d", retVal);
if (msgType == CONTEXT_HUB_LOAD_APP) {
closeLoadTxn(false, nullptr);
} else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
closeUnloadTxn(false);
}
}
env->ReleaseIntArrayElements(header_, header, 0);