Loading core/jni/android_hardware_location_ContextHubService.cpp +72 −37 Original line number Diff line number Diff line Loading @@ -337,11 +337,15 @@ static int set_dest_app(hub_message_t *msg, jint id) { return 0; } static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) { static void query_hub_for_apps(uint32_t hubHandle) { hub_message_t msg; query_apps_request_t queryMsg; queryMsg.app_name.id = appId; // TODO(b/30835598): When we're able to tell which request our // response matches, then we should allow this to be more // targetted, instead of always being every app in the // system. queryMsg.app_name.id = ALL_APPS; msg.message_type = CONTEXT_HUB_QUERY_APPS; msg.message_len = sizeof(queryMsg); Loading @@ -354,9 +358,9 @@ static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) { } } static void sendQueryForApps(uint64_t appId) { static void sendQueryForApps() { for (int i = 0; i < db.hubInfo.numHubs; i++ ) { query_hub_for_apps(appId, i); query_hub_for_apps(i); } } Loading Loading @@ -386,9 +390,6 @@ static jint generate_id() { static jint add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, jint appInstanceHandle, JNIEnv *env) { ALOGI("Loading App"); // Not checking if the apps are indeed distinct app_instance_info_s entry; assert(appInfo); Loading @@ -404,13 +405,14 @@ static jint add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, db.appInstances[appInstanceHandle] = entry; // Finally - let the service know of this app instance // Finally - let the service know of this app instance, to populate // the Java cache. env->CallIntMethod(db.jniInfo.jContextHubService, db.jniInfo.contextHubServiceAddAppInstance, hubHandle, entry.instanceId, entry.truncName, entry.appInfo.version); ALOGW("%s App 0x%" PRIx64 " on hub Handle %" PRId32 ALOGI("%s App 0x%" PRIx64 " on hub Handle %" PRId32 " as appInstance %" PRId32, action, entry.truncName, entry.hubHandle, appInstanceHandle); Loading Loading @@ -532,7 +534,7 @@ static void initContextHubService() { } } sendQueryForApps(ALL_APPS); sendQueryForApps(); } else { ALOGW("No Context Hub Module present"); } Loading Loading @@ -577,15 +579,62 @@ int handle_query_apps_response(const uint8_t *msg, int msgLen, } int numApps = msgLen / sizeof(hub_app_info); hub_app_info info; const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg; for (int i = 0; i < numApps; i++, unalignedInfoAddr++) { memcpy(&info, unalignedInfoAddr, sizeof(info)); // We use this information to sync our JNI and Java caches of nanoapp info. // We want to accomplish two things here: // 1) Remove entries from our caches which are stale, and pertained to // apps no longer running on Context Hub. // 2) Populate our caches with the latest information of all these apps. // We make a couple of assumptions here: // A) The JNI and Java caches are in sync with each other (this isn't // necessarily true; any failure of a single call into Java land to // update its cache will leave that cache in a bad state. For NYC, // we're willing to tolerate this for now). // B) The total number of apps is relatively small, so horribly inefficent // algorithms aren't too painful. // C) We're going to call this relatively infrequently, so its inefficency // isn't a big impact. // (1). Looking for stale cache entries. Yes, this is O(N^2). See // assumption (B). Per assumption (A), it is sufficient to iterate // over just the JNI cache. auto end = db.appInstances.end(); for (auto current = db.appInstances.begin(); current != end; ) { app_instance_info_s cache_entry = current->second; // We perform our iteration here because if we call // delete_app_instance() below, it will erase() this entry. current++; bool entryIsStale = true; for (int i = 0; i < numApps; i++) { // We use memcmp since this could be unaligned. if (memcmp(&unalignedInfoAddr[i].app_name.id, &cache_entry.appInfo.app_name.id, sizeof(cache_entry.appInfo.app_name.id)) == 0) { // We found a match; this entry is current. entryIsStale = false; break; } } if (entryIsStale) { delete_app_instance(cache_entry.instanceId, env); } } // (2). Update our caches with the latest. for (int i = 0; i < numApps; i++) { hub_app_info query_info; memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info)); // We will only have one instance of the app // TODO : Change this logic once we support multiple instances of the same app jint appInstance = get_app_instance_for_app_id(info.app_name.id); add_app_instance(&info, hubHandle, appInstance, env); jint appInstance = get_app_instance_for_app_id(query_info.app_name.id); if (appInstance == -1) { // This is a previously unknown app, let's allocate an "id" for it. appInstance = generate_id(); } add_app_instance(&query_info, hubHandle, appInstance, env); } return 0; Loading Loading @@ -709,7 +758,12 @@ static bool closeLoadTxn(bool success, jint *appInstanceHandle) { ALOGW("Could not attach to JVM !"); success = false; } sendQueryForApps(info->appInfo.app_name.id); // While we just called add_app_instance above, our info->appInfo was // incomplete (for example, the 'version' is hardcoded to -1). So we // trigger an additional query to the CHRE, so we'll be able to get // all the app "info", and have our JNI and Java caches with the // full information. sendQueryForApps(); } else { ALOGW("Could not load the app successfully ! Unexpected failure"); *appInstanceHandle = INVALID_APP_ID; Loading Loading @@ -739,24 +793,6 @@ static bool isValidOsStatus(const uint8_t *msg, size_t msgLen, 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 !"); env = nullptr; } 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; Loading Loading @@ -824,8 +860,7 @@ static int handle_os_message(uint32_t msgType, uint32_t hubHandle, ALOGW("Context Hub handle %d restarted", hubHandle); closeTxn(); passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0); invalidateNanoApps(hubHandle); query_hub_for_apps(ALL_APPS, hubHandle); query_hub_for_apps(hubHandle); retVal = 0; } break; Loading Loading
core/jni/android_hardware_location_ContextHubService.cpp +72 −37 Original line number Diff line number Diff line Loading @@ -337,11 +337,15 @@ static int set_dest_app(hub_message_t *msg, jint id) { return 0; } static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) { static void query_hub_for_apps(uint32_t hubHandle) { hub_message_t msg; query_apps_request_t queryMsg; queryMsg.app_name.id = appId; // TODO(b/30835598): When we're able to tell which request our // response matches, then we should allow this to be more // targetted, instead of always being every app in the // system. queryMsg.app_name.id = ALL_APPS; msg.message_type = CONTEXT_HUB_QUERY_APPS; msg.message_len = sizeof(queryMsg); Loading @@ -354,9 +358,9 @@ static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) { } } static void sendQueryForApps(uint64_t appId) { static void sendQueryForApps() { for (int i = 0; i < db.hubInfo.numHubs; i++ ) { query_hub_for_apps(appId, i); query_hub_for_apps(i); } } Loading Loading @@ -386,9 +390,6 @@ static jint generate_id() { static jint add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, jint appInstanceHandle, JNIEnv *env) { ALOGI("Loading App"); // Not checking if the apps are indeed distinct app_instance_info_s entry; assert(appInfo); Loading @@ -404,13 +405,14 @@ static jint add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, db.appInstances[appInstanceHandle] = entry; // Finally - let the service know of this app instance // Finally - let the service know of this app instance, to populate // the Java cache. env->CallIntMethod(db.jniInfo.jContextHubService, db.jniInfo.contextHubServiceAddAppInstance, hubHandle, entry.instanceId, entry.truncName, entry.appInfo.version); ALOGW("%s App 0x%" PRIx64 " on hub Handle %" PRId32 ALOGI("%s App 0x%" PRIx64 " on hub Handle %" PRId32 " as appInstance %" PRId32, action, entry.truncName, entry.hubHandle, appInstanceHandle); Loading Loading @@ -532,7 +534,7 @@ static void initContextHubService() { } } sendQueryForApps(ALL_APPS); sendQueryForApps(); } else { ALOGW("No Context Hub Module present"); } Loading Loading @@ -577,15 +579,62 @@ int handle_query_apps_response(const uint8_t *msg, int msgLen, } int numApps = msgLen / sizeof(hub_app_info); hub_app_info info; const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg; for (int i = 0; i < numApps; i++, unalignedInfoAddr++) { memcpy(&info, unalignedInfoAddr, sizeof(info)); // We use this information to sync our JNI and Java caches of nanoapp info. // We want to accomplish two things here: // 1) Remove entries from our caches which are stale, and pertained to // apps no longer running on Context Hub. // 2) Populate our caches with the latest information of all these apps. // We make a couple of assumptions here: // A) The JNI and Java caches are in sync with each other (this isn't // necessarily true; any failure of a single call into Java land to // update its cache will leave that cache in a bad state. For NYC, // we're willing to tolerate this for now). // B) The total number of apps is relatively small, so horribly inefficent // algorithms aren't too painful. // C) We're going to call this relatively infrequently, so its inefficency // isn't a big impact. // (1). Looking for stale cache entries. Yes, this is O(N^2). See // assumption (B). Per assumption (A), it is sufficient to iterate // over just the JNI cache. auto end = db.appInstances.end(); for (auto current = db.appInstances.begin(); current != end; ) { app_instance_info_s cache_entry = current->second; // We perform our iteration here because if we call // delete_app_instance() below, it will erase() this entry. current++; bool entryIsStale = true; for (int i = 0; i < numApps; i++) { // We use memcmp since this could be unaligned. if (memcmp(&unalignedInfoAddr[i].app_name.id, &cache_entry.appInfo.app_name.id, sizeof(cache_entry.appInfo.app_name.id)) == 0) { // We found a match; this entry is current. entryIsStale = false; break; } } if (entryIsStale) { delete_app_instance(cache_entry.instanceId, env); } } // (2). Update our caches with the latest. for (int i = 0; i < numApps; i++) { hub_app_info query_info; memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info)); // We will only have one instance of the app // TODO : Change this logic once we support multiple instances of the same app jint appInstance = get_app_instance_for_app_id(info.app_name.id); add_app_instance(&info, hubHandle, appInstance, env); jint appInstance = get_app_instance_for_app_id(query_info.app_name.id); if (appInstance == -1) { // This is a previously unknown app, let's allocate an "id" for it. appInstance = generate_id(); } add_app_instance(&query_info, hubHandle, appInstance, env); } return 0; Loading Loading @@ -709,7 +758,12 @@ static bool closeLoadTxn(bool success, jint *appInstanceHandle) { ALOGW("Could not attach to JVM !"); success = false; } sendQueryForApps(info->appInfo.app_name.id); // While we just called add_app_instance above, our info->appInfo was // incomplete (for example, the 'version' is hardcoded to -1). So we // trigger an additional query to the CHRE, so we'll be able to get // all the app "info", and have our JNI and Java caches with the // full information. sendQueryForApps(); } else { ALOGW("Could not load the app successfully ! Unexpected failure"); *appInstanceHandle = INVALID_APP_ID; Loading Loading @@ -739,24 +793,6 @@ static bool isValidOsStatus(const uint8_t *msg, size_t msgLen, 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 !"); env = nullptr; } 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; Loading Loading @@ -824,8 +860,7 @@ static int handle_os_message(uint32_t msgType, uint32_t hubHandle, ALOGW("Context Hub handle %d restarted", hubHandle); closeTxn(); passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0); invalidateNanoApps(hubHandle); query_hub_for_apps(ALL_APPS, hubHandle); query_hub_for_apps(hubHandle); retVal = 0; } break; Loading