diff options
author | Vinit Deshpande <vinitd@google.com> | 2015-08-06 04:52:49 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-08-06 04:52:49 +0000 |
commit | 9152c50087c0293bdfd2526fd88a967ea7a1763c (patch) | |
tree | 828d8935bdda5e236d4a07705b1d7c76375ad396 /service/jni | |
parent | ee0a0132ebb0d7e9baf42e778ea9c094966ffb14 (diff) | |
parent | 7d519b6686ece717fd3890c0656b46155c22a377 (diff) | |
download | android_frameworks_opt_net_wifi-9152c50087c0293bdfd2526fd88a967ea7a1763c.tar.gz android_frameworks_opt_net_wifi-9152c50087c0293bdfd2526fd88a967ea7a1763c.tar.bz2 android_frameworks_opt_net_wifi-9152c50087c0293bdfd2526fd88a967ea7a1763c.zip |
Merge "Fix refcounting of objects and data in WifiNative" into mnc-dev
Diffstat (limited to 'service/jni')
-rw-r--r-- | service/jni/com_android_server_wifi_WifiNative.cpp | 1045 | ||||
-rw-r--r-- | service/jni/jni_helper.cpp | 532 | ||||
-rw-r--r-- | service/jni/jni_helper.h | 183 |
3 files changed, 979 insertions, 781 deletions
diff --git a/service/jni/com_android_server_wifi_WifiNative.cpp b/service/jni/com_android_server_wifi_WifiNative.cpp index 7556b1e67..3c7270a94 100644 --- a/service/jni/com_android_server_wifi_WifiNative.cpp +++ b/service/jni/com_android_server_wifi_WifiNative.cpp @@ -17,7 +17,9 @@ #define LOG_TAG "wifi" #include "jni.h" +#include "JniConstants.h" #include <ScopedUtfChars.h> +#include <ScopedBytes.h> #include <utils/misc.h> #include <android_runtime/AndroidRuntime.h> #include <utils/Log.h> @@ -215,69 +217,55 @@ static const char *WifiHandleVarName = "sWifiHalHandle"; static const char *WifiIfaceHandleVarName = "sWifiIfaceHandles"; static jmethodID OnScanResultsMethodID; -static JNIEnv *getEnv() { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - return env; +static wifi_handle getWifiHandle(JNIHelper &helper, jclass cls) { + return (wifi_handle) helper.getStaticLongField(cls, WifiHandleVarName); } -static wifi_handle getWifiHandle(JNIEnv *env, jclass cls) { - return (wifi_handle) getStaticLongField(env, cls, WifiHandleVarName); +static wifi_interface_handle getIfaceHandle(JNIHelper &helper, jclass cls, jint index) { + return (wifi_interface_handle) helper.getStaticLongArrayField(cls, WifiIfaceHandleVarName, index); } -static wifi_interface_handle getIfaceHandle(JNIEnv *env, jclass cls, jint index) { - return (wifi_interface_handle) getStaticLongArrayField(env, cls, WifiIfaceHandleVarName, index); -} - -jboolean setSSIDField(JNIEnv *env, jobject obj, const char *rawSsid) { - - jmethodID methodID = env->GetStaticMethodID(mCls, "setSsid", "([BLandroid/net/wifi/ScanResult;)Z"); - if (methodID == NULL) { - ALOGE("Error in getting method ID setSsid"); - return false; - } +jboolean setSSIDField(JNIHelper helper, jobject scanResult, const char *rawSsid) { int len = strlen(rawSsid); if (len > 0) { - jbyteArray ssidBytes = env->NewByteArray(len); - env->SetByteArrayRegion(ssidBytes, 0, len, (jbyte *) rawSsid); - jboolean ret = env->CallStaticBooleanMethod(mCls, methodID, ssidBytes, obj); - env->DeleteLocalRef(ssidBytes); + JNIObject<jbyteArray> ssidBytes = helper.newByteArray(len); + helper.setByteArrayRegion(ssidBytes, 0, len, (jbyte *) rawSsid); + jboolean ret = helper.callStaticMethod(mCls, + "setSsid", "([BLandroid/net/wifi/ScanResult;)Z", ssidBytes.get(), scanResult); return ret; } else { //empty SSID or SSID start with \0 return true; } } - -static jobject createScanResult(JNIEnv *env, wifi_scan_result *result) { +static JNIObject<jobject> createScanResult(JNIHelper &helper, wifi_scan_result *result) { // ALOGD("creating scan result"); - jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); + JNIObject<jobject> scanResult = helper.createObject("android/net/wifi/ScanResult"); if (scanResult == NULL) { ALOGE("Error in creating scan result"); - return NULL; + return JNIObject<jobject>(helper, NULL); } ALOGV("setting SSID to %s", result->ssid); - if(!setSSIDField(env, scanResult, result->ssid)) { + if (!setSSIDField(helper, scanResult, result->ssid)) { ALOGE("Error on set SSID"); - return NULL; + return JNIObject<jobject>(helper, NULL); } char bssid[32]; sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->bssid[0], result->bssid[1], result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); - //jstring jbssid = env->NewStringUTF(bssid); - setStringField(env, scanResult, "BSSID", bssid); + helper.setStringField(scanResult, "BSSID", bssid); - setIntField(env, scanResult, "level", result->rssi); - setIntField(env, scanResult, "frequency", result->channel); - setLongField(env, scanResult, "timestamp", result->ts); + helper.setIntField(scanResult, "level", result->rssi); + helper.setIntField(scanResult, "frequency", result->channel); + helper.setLongField(scanResult, "timestamp", result->ts); return scanResult; } @@ -340,7 +328,8 @@ static jboolean android_net_wifi_toggle_interface(JNIEnv* env, jclass cls, int t } static jboolean android_net_wifi_startHal(JNIEnv* env, jclass cls) { - wifi_handle halHandle = getWifiHandle(env, cls); + JNIHelper helper(env); + wifi_handle halHandle = getWifiHandle(helper, cls); if (halHandle == NULL) { if(init_wifi_hal_func_table(&hal_fn) != 0 ) { @@ -361,7 +350,7 @@ static jboolean android_net_wifi_startHal(JNIEnv* env, jclass cls) { res = hal_fn.wifi_initialize(&halHandle); if (res == WIFI_SUCCESS) { - setStaticLongField(env, cls, WifiHandleVarName, (jlong)halHandle); + helper.setStaticLongField(cls, WifiHandleVarName, (jlong)halHandle); ALOGD("Did set static halHandle = %p", halHandle); } env->GetJavaVM(&mVM); @@ -376,9 +365,10 @@ static jboolean android_net_wifi_startHal(JNIEnv* env, jclass cls) { void android_net_wifi_hal_cleaned_up_handler(wifi_handle handle) { ALOGD("In wifi cleaned up handler"); - JNIEnv * env = getEnv(); - setStaticLongField(env, mCls, WifiHandleVarName, 0); - env->DeleteGlobalRef(mCls); + JNIHelper helper(mVM); + helper.setStaticLongField(mCls, WifiHandleVarName, 0); + + helper.deleteGlobalRef(mCls); mCls = NULL; mVM = NULL; } @@ -386,7 +376,8 @@ void android_net_wifi_hal_cleaned_up_handler(wifi_handle handle) { static void android_net_wifi_stopHal(JNIEnv* env, jclass cls) { ALOGD("In wifi stop Hal"); - wifi_handle halHandle = getWifiHandle(env, cls); + JNIHelper helper(env); + wifi_handle halHandle = getWifiHandle(helper, cls); if (halHandle == NULL) return; @@ -398,14 +389,18 @@ static void android_net_wifi_waitForHalEvents(JNIEnv* env, jclass cls) { ALOGD("waitForHalEvents called, vm = %p, obj = %p, env = %p", mVM, mCls, env); - wifi_handle halHandle = getWifiHandle(env, cls); + JNIHelper helper(env); + wifi_handle halHandle = getWifiHandle(helper, cls); hal_fn.wifi_event_loop(halHandle); set_iface_flags("wlan0", 0); } static int android_net_wifi_getInterfaces(JNIEnv *env, jclass cls) { int n = 0; - wifi_handle halHandle = getWifiHandle(env, cls); + + JNIHelper helper(env); + + wifi_handle halHandle = getWifiHandle(helper, cls); wifi_interface_handle *ifaceHandles = NULL; int result = hal_fn.wifi_get_ifaces(halHandle, &n, &ifaceHandles); if (result < 0) { @@ -413,23 +408,23 @@ static int android_net_wifi_getInterfaces(JNIEnv *env, jclass cls) { } if (n < 0) { - THROW(env, "android_net_wifi_getInterfaces no interfaces"); + THROW(helper,"android_net_wifi_getInterfaces no interfaces"); return 0; } if (ifaceHandles == NULL) { - THROW(env, "android_net_wifi_getInterfaces null interface array"); + THROW(helper,"android_net_wifi_getInterfaces null interface array"); return 0; } if (n > 8) { - THROW(env, "Too many interfaces"); + THROW(helper,"Too many interfaces"); return 0; } jlongArray array = (env)->NewLongArray(n); if (array == NULL) { - THROW(env, "Error in accessing array"); + THROW(helper,"Error in accessing array"); return 0; } @@ -437,57 +432,60 @@ static int android_net_wifi_getInterfaces(JNIEnv *env, jclass cls) { for (int i = 0; i < n; i++) { elems[i] = reinterpret_cast<jlong>(ifaceHandles[i]); } - env->SetLongArrayRegion(array, 0, n, elems); - setStaticLongArrayField(env, cls, WifiIfaceHandleVarName, array); + + helper.setLongArrayRegion(array, 0, n, elems); + helper.setStaticLongArrayField(cls, WifiIfaceHandleVarName, array); return (result < 0) ? result : n; } static jstring android_net_wifi_getInterfaceName(JNIEnv *env, jclass cls, jint i) { + char buf[EVENT_BUF_SIZE]; - jlong value = getStaticLongArrayField(env, cls, WifiIfaceHandleVarName, i); + JNIHelper helper(env); + + jlong value = helper.getStaticLongArrayField(cls, WifiIfaceHandleVarName, i); wifi_interface_handle handle = (wifi_interface_handle) value; int result = hal_fn.wifi_get_iface_name(handle, buf, sizeof(buf)); if (result < 0) { return NULL; } else { - return env->NewStringUTF(buf); + JNIObject<jstring> name = helper.newStringUTF(buf); + return name.detach(); } } static void onScanResultsAvailable(wifi_request_id id, unsigned num_results) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); + JNIHelper helper(mVM); // ALOGD("onScanResultsAvailable called, vm = %p, obj = %p, env = %p", mVM, mCls, env); - reportEvent(env, mCls, "onScanResultsAvailable", "(I)V", id); + helper.reportEvent(mCls, "onScanResultsAvailable", "(I)V", id); } static void onScanEvent(wifi_scan_event event, unsigned status) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); + + JNIHelper helper(mVM); // ALOGD("onScanStatus called, vm = %p, obj = %p, env = %p", mVM, mCls, env); - reportEvent(env, mCls, "onScanStatus", "(I)V", event); + helper.reportEvent(mCls, "onScanStatus", "(I)V", event); } static void onFullScanResult(wifi_request_id id, wifi_scan_result *result) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); + JNIHelper helper(mVM); //ALOGD("onFullScanResult called, vm = %p, obj = %p, env = %p", mVM, mCls, env); - jobject scanResult = createScanResult(env, result); + JNIObject<jobject> scanResult = createScanResult(helper, result); //ALOGD("Creating a byte array of length %d", result->ie_length); - jbyteArray elements = env->NewByteArray(result->ie_length); + JNIObject<jbyteArray> elements = helper.newByteArray(result->ie_length); if (elements == NULL) { ALOGE("Error in allocating array"); return; @@ -496,30 +494,28 @@ static void onFullScanResult(wifi_request_id id, wifi_scan_result *result) { // ALOGD("Setting byte array"); jbyte *bytes = (jbyte *)&(result->ie_data[0]); - env->SetByteArrayRegion(elements, 0, result->ie_length, bytes); + helper.setByteArrayRegion(elements, 0, result->ie_length, bytes); // ALOGD("Returning result"); - reportEvent(env, mCls, "onFullScanResult", "(ILandroid/net/wifi/ScanResult;[B)V", id, - scanResult, elements); - - env->DeleteLocalRef(scanResult); - env->DeleteLocalRef(elements); + helper.reportEvent(mCls, "onFullScanResult", "(ILandroid/net/wifi/ScanResult;[B)V", id, + scanResult.get(), elements.get()); } static jboolean android_net_wifi_startScan( JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); // ALOGD("starting scan on interface[%d] = %p", iface, handle); wifi_scan_cmd_params params; memset(¶ms, 0, sizeof(params)); - params.base_period = getIntField(env, settings, "base_period_ms"); - params.max_ap_per_scan = getIntField(env, settings, "max_ap_per_scan"); - params.report_threshold_percent = getIntField(env, settings, "report_threshold_percent"); - params.report_threshold_num_scans = getIntField(env, settings, "report_threshold_num_scans"); + params.base_period = helper.getIntField(settings, "base_period_ms"); + params.max_ap_per_scan = helper.getIntField(settings, "max_ap_per_scan"); + params.report_threshold_percent = helper.getIntField(settings, "report_threshold_percent"); + params.report_threshold_num_scans = helper.getIntField(settings, "report_threshold_num_scans"); ALOGD("Initialized common fields %d, %d, %d, %d", params.base_period, params.max_ap_per_scan, params.report_threshold_percent, params.report_threshold_num_scans); @@ -527,37 +523,35 @@ static jboolean android_net_wifi_startScan( const char *bucket_array_type = "[Lcom/android/server/wifi/WifiNative$BucketSettings;"; const char *channel_array_type = "[Lcom/android/server/wifi/WifiNative$ChannelSettings;"; - jobjectArray buckets = (jobjectArray)getObjectField(env, settings, "buckets", bucket_array_type); - params.num_buckets = getIntField(env, settings, "num_buckets"); + params.num_buckets = helper.getIntField(settings, "num_buckets"); // ALOGD("Initialized num_buckets to %d", params.num_buckets); for (int i = 0; i < params.num_buckets; i++) { - jobject bucket = getObjectArrayField(env, settings, "buckets", bucket_array_type, i); + JNIObject<jobject> bucket = helper.getObjectArrayField( + settings, "buckets", bucket_array_type, i); - params.buckets[i].bucket = getIntField(env, bucket, "bucket"); - params.buckets[i].band = (wifi_band) getIntField(env, bucket, "band"); - params.buckets[i].period = getIntField(env, bucket, "period_ms"); + params.buckets[i].bucket = helper.getIntField(bucket, "bucket"); + params.buckets[i].band = (wifi_band) helper.getIntField(bucket, "band"); + params.buckets[i].period = helper.getIntField(bucket, "period_ms"); - int report_events = getIntField(env, bucket, "report_events"); + int report_events = helper.getIntField(bucket, "report_events"); params.buckets[i].report_events = report_events; ALOGD("bucket[%d] = %d:%d:%d:%d", i, params.buckets[i].bucket, params.buckets[i].band, params.buckets[i].period, report_events); - jobjectArray channels = (jobjectArray)getObjectField( - env, bucket, "channels", channel_array_type); - - params.buckets[i].num_channels = getIntField(env, bucket, "num_channels"); + params.buckets[i].num_channels = helper.getIntField(bucket, "num_channels"); // ALOGD("Initialized num_channels to %d", params.buckets[i].num_channels); for (int j = 0; j < params.buckets[i].num_channels; j++) { - jobject channel = getObjectArrayField(env, bucket, "channels", channel_array_type, j); + JNIObject<jobject> channel = helper.getObjectArrayField( + bucket, "channels", channel_array_type, j); - params.buckets[i].channels[j].channel = getIntField(env, channel, "frequency"); - params.buckets[i].channels[j].dwellTimeMs = getIntField(env, channel, "dwell_time_ms"); + params.buckets[i].channels[j].channel = helper.getIntField(channel, "frequency"); + params.buckets[i].channels[j].dwellTimeMs = helper.getIntField(channel, "dwell_time_ms"); - bool passive = getBoolField(env, channel, "passive"); + bool passive = helper.getBoolField(channel, "passive"); params.buckets[i].channels[j].passive = (passive ? 1 : 0); // ALOGD("Initialized channel %d", params.buckets[i].channels[j].channel); @@ -576,7 +570,9 @@ static jboolean android_net_wifi_startScan( } static jboolean android_net_wifi_stopScan(JNIEnv *env, jclass cls, jint iface, jint id) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); // ALOGD("stopping scan on interface[%d] = %p", iface, handle); return hal_fn.wifi_stop_gscan(id, handle) == WIFI_SUCCESS; @@ -591,16 +587,17 @@ static int compare_scan_result_timestamp(const void *v1, const void *v2) { static jobject android_net_wifi_getScanResults( JNIEnv *env, jclass cls, jint iface, jboolean flush) { + JNIHelper helper(env); wifi_cached_scan_results scan_data[64]; int num_scan_data = 64; - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); // ALOGD("getting scan results on interface[%d] = %p", iface, handle); byte b = flush ? 0xFF : 0; int result = hal_fn.wifi_get_cached_gscan_results(handle, b, num_scan_data, scan_data, &num_scan_data); if (result == WIFI_SUCCESS) { - jobjectArray scanData = createObjectArray(env, + JNIObject<jobjectArray> scanData = helper.createObjectArray( "android/net/wifi/WifiScanner$ScanData", num_scan_data); if (scanData == NULL) { ALOGE("Error in allocating array of scanData"); @@ -609,20 +606,20 @@ static jobject android_net_wifi_getScanResults( for (int i = 0; i < num_scan_data; i++) { - jobject data = createObject(env, "android/net/wifi/WifiScanner$ScanData"); + JNIObject<jobject> data = helper.createObject("android/net/wifi/WifiScanner$ScanData"); if (data == NULL) { ALOGE("Error in allocating scanData"); return NULL; } - setIntField(env, data, "mId", scan_data[i].scan_id); - setIntField(env, data, "mFlags", scan_data[i].flags); + helper.setIntField(data, "mId", scan_data[i].scan_id); + helper.setIntField(data, "mFlags", scan_data[i].flags); /* sort all scan results by timestamp */ qsort(scan_data[i].results, scan_data[i].num_results, sizeof(wifi_scan_result), compare_scan_result_timestamp); - jobjectArray scanResults = createObjectArray(env, + JNIObject<jobjectArray> scanResults = helper.createObjectArray( "android/net/wifi/ScanResult", scan_data[i].num_results); if (scanResults == NULL) { ALOGE("Error in allocating scanResult array"); @@ -632,37 +629,21 @@ static jobject android_net_wifi_getScanResults( wifi_scan_result *results = scan_data[i].results; for (int j = 0; j < scan_data[i].num_results; j++) { - jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); + JNIObject<jobject> scanResult = createScanResult(helper, &results[j]); if (scanResult == NULL) { ALOGE("Error in creating scan result"); return NULL; } - if(!setSSIDField(env, scanResult, results[j].ssid)) { - ALOGE("Error on set SSID"); - return NULL; - } - char bssid[32]; - sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", results[j].bssid[0], - results[j].bssid[1], results[j].bssid[2], results[j].bssid[3], - results[j].bssid[4], results[j].bssid[5]); - - setStringField(env, scanResult, "BSSID", bssid); - - setIntField(env, scanResult, "level", results[j].rssi); - setIntField(env, scanResult, "frequency", results[j].channel); - setLongField(env, scanResult, "timestamp", results[j].ts); - - env->SetObjectArrayElement(scanResults, j, scanResult); - env->DeleteLocalRef(scanResult); + helper.setObjectArrayElement(scanResults, j, scanResult); } - setObjectField(env, data, "mResults", "[Landroid/net/wifi/ScanResult;", scanResults); - env->SetObjectArrayElement(scanData, i, data); + helper.setObjectField(data, "mResults", "[Landroid/net/wifi/ScanResult;", scanResults); + helper.setObjectArrayElement(scanData, i, data); } // ALOGD("retrieved %d scan data from interface[%d] = %p", num_scan_data, iface, handle); - return scanData; + return scanData.detach(); } else { return NULL; } @@ -672,7 +653,8 @@ static jobject android_net_wifi_getScanResults( static jboolean android_net_wifi_getScanCapabilities( JNIEnv *env, jclass cls, jint iface, jobject capabilities) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); // ALOGD("getting scan capabilities on interface[%d] = %p", iface, handle); wifi_gscan_capabilities c; @@ -683,13 +665,13 @@ static jboolean android_net_wifi_getScanCapabilities( return JNI_FALSE; } - setIntField(env, capabilities, "max_scan_cache_size", c.max_scan_cache_size); - setIntField(env, capabilities, "max_scan_buckets", c.max_scan_buckets); - setIntField(env, capabilities, "max_ap_cache_per_scan", c.max_ap_cache_per_scan); - setIntField(env, capabilities, "max_rssi_sample_size", c.max_rssi_sample_size); - setIntField(env, capabilities, "max_scan_reporting_threshold", c.max_scan_reporting_threshold); - setIntField(env, capabilities, "max_hotlist_bssids", c.max_hotlist_bssids); - setIntField(env, capabilities, "max_significant_wifi_change_aps", + helper.setIntField(capabilities, "max_scan_cache_size", c.max_scan_cache_size); + helper.setIntField(capabilities, "max_scan_buckets", c.max_scan_buckets); + helper.setIntField(capabilities, "max_ap_cache_per_scan", c.max_ap_cache_per_scan); + helper.setIntField(capabilities, "max_rssi_sample_size", c.max_rssi_sample_size); + helper.setIntField(capabilities, "max_scan_reporting_threshold", c.max_scan_reporting_threshold); + helper.setIntField(capabilities, "max_hotlist_bssids", c.max_hotlist_bssids); + helper.setIntField(capabilities, "max_significant_wifi_change_aps", c.max_significant_wifi_change_aps); return JNI_TRUE; @@ -731,15 +713,15 @@ static void parseMacAddress(const char *str, mac_addr addr) { } static bool parseMacAddress(JNIEnv *env, jobject obj, mac_addr addr) { - jstring macAddrString = (jstring) getObjectField( - env, obj, "bssid", "Ljava/lang/String;"); - + JNIHelper helper(env); + JNIObject<jstring> macAddrString = helper.getStringField(obj, "bssid"); if (macAddrString == NULL) { ALOGE("Error getting bssid field"); return false; } - const char *bssid = env->GetStringUTFChars(macAddrString, NULL); + ScopedUtfChars chars(env, macAddrString); + const char *bssid = chars.c_str(); if (bssid == NULL) { ALOGE("Error getting bssid"); return false; @@ -752,19 +734,11 @@ static bool parseMacAddress(JNIEnv *env, jobject obj, mac_addr addr) { static void onHotlistApFound(wifi_request_id id, unsigned num_results, wifi_scan_result *results) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - - ALOGD("onHotlistApFound called, vm = %p, obj = %p, env = %p, num_results = %d", - mVM, mCls, env, num_results); + JNIHelper helper(mVM); + ALOGD("onHotlistApFound called, vm = %p, obj = %p, num_results = %d", mVM, mCls, num_results); - jclass clsScanResult = (env)->FindClass("android/net/wifi/ScanResult"); - if (clsScanResult == NULL) { - ALOGE("Error in accessing class"); - return; - } - - jobjectArray scanResults = env->NewObjectArray(num_results, clsScanResult, NULL); + JNIObject<jobjectArray> scanResults = helper.newObjectArray(num_results, + "android/net/wifi/ScanResult", NULL); if (scanResults == NULL) { ALOGE("Error in allocating array"); return; @@ -772,52 +746,29 @@ static void onHotlistApFound(wifi_request_id id, for (unsigned i = 0; i < num_results; i++) { - jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); + JNIObject<jobject> scanResult = createScanResult(helper, &results[i]); if (scanResult == NULL) { ALOGE("Error in creating scan result"); return; } - if(!setSSIDField(env, scanResult, results[i].ssid)) { - ALOGE("Can not set SSID"); - return; - } - - char bssid[32]; - sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", results[i].bssid[0], results[i].bssid[1], - results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]); - - setStringField(env, scanResult, "BSSID", bssid); + helper.setObjectArrayElement(scanResults, i, scanResult); - setIntField(env, scanResult, "level", results[i].rssi); - setIntField(env, scanResult, "frequency", results[i].channel); - setLongField(env, scanResult, "timestamp", results[i].ts); - - env->SetObjectArrayElement(scanResults, i, scanResult); - - ALOGD("Found AP %32s %s", results[i].ssid, bssid); + ALOGD("Found AP %32s", results[i].ssid); } - reportEvent(env, mCls, "onHotlistApFound", "(I[Landroid/net/wifi/ScanResult;)V", - id, scanResults); + helper.reportEvent(mCls, "onHotlistApFound", "(I[Landroid/net/wifi/ScanResult;)V", + id, scanResults.get()); } static void onHotlistApLost(wifi_request_id id, unsigned num_results, wifi_scan_result *results) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - - ALOGD("onHotlistApLost called, vm = %p, obj = %p, env = %p, num_results = %d", - mVM, mCls, env, num_results); - - jclass clsScanResult = (env)->FindClass("android/net/wifi/ScanResult"); - if (clsScanResult == NULL) { - ALOGE("Error in accessing class"); - return; - } + JNIHelper helper(mVM); + ALOGD("onHotlistApLost called, vm = %p, obj = %p, num_results = %d", mVM, mCls, num_results); - jobjectArray scanResults = env->NewObjectArray(num_results, clsScanResult, NULL); + JNIObject<jobjectArray> scanResults = helper.newObjectArray(num_results, + "android/net/wifi/ScanResult", NULL); if (scanResults == NULL) { ALOGE("Error in allocating array"); return; @@ -825,51 +776,37 @@ static void onHotlistApLost(wifi_request_id id, for (unsigned i = 0; i < num_results; i++) { - jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); + JNIObject<jobject> scanResult = createScanResult(helper, &results[i]); if (scanResult == NULL) { ALOGE("Error in creating scan result"); return; } - if(!setSSIDField(env, scanResult, results[i].ssid)) { - ALOGE("Error on set SSID"); - return; - } - - char bssid[32]; - sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", results[i].bssid[0], results[i].bssid[1], - results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]); - - setStringField(env, scanResult, "BSSID", bssid); - - setIntField(env, scanResult, "level", results[i].rssi); - setIntField(env, scanResult, "frequency", results[i].channel); - setLongField(env, scanResult, "timestamp", results[i].ts); - - env->SetObjectArrayElement(scanResults, i, scanResult); + helper.setObjectArrayElement(scanResults, i, scanResult); - ALOGD("Lost AP %32s %s", results[i].ssid, bssid); + ALOGD("Lost AP %32s", results[i].ssid); } - reportEvent(env, mCls, "onHotlistApLost", "(I[Landroid/net/wifi/ScanResult;)V", - id, scanResults); + helper.reportEvent(mCls, "onHotlistApLost", "(I[Landroid/net/wifi/ScanResult;)V", + id, scanResults.get()); } static jboolean android_net_wifi_setHotlist( JNIEnv *env, jclass cls, jint iface, jint id, jobject ap) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("setting hotlist on interface[%d] = %p", iface, handle); wifi_bssid_hotlist_params params; memset(¶ms, 0, sizeof(params)); - params.lost_ap_sample_size = getIntField(env, ap, "apLostThreshold"); + params.lost_ap_sample_size = helper.getIntField(ap, "apLostThreshold"); - jobjectArray array = (jobjectArray) getObjectField(env, ap, - "bssidInfos", "[Landroid/net/wifi/WifiScanner$BssidInfo;"); - params.num_bssid = env->GetArrayLength(array); + JNIObject<jobjectArray> array = helper.getArrayField( + ap, "bssidInfos", "[Landroid/net/wifi/WifiScanner$BssidInfo;"); + params.num_bssid = helper.getArrayLength(array); if (params.num_bssid == 0) { ALOGE("Error in accesing array"); @@ -877,16 +814,16 @@ static jboolean android_net_wifi_setHotlist( } for (int i = 0; i < params.num_bssid; i++) { - jobject objAp = env->GetObjectArrayElement(array, i); + JNIObject<jobject> objAp = helper.getObjectArrayElement(array, i); - jstring macAddrString = (jstring) getObjectField( - env, objAp, "bssid", "Ljava/lang/String;"); + JNIObject<jstring> macAddrString = helper.getStringField(objAp, "bssid"); if (macAddrString == NULL) { ALOGE("Error getting bssid field"); return false; } - const char *bssid = env->GetStringUTFChars(macAddrString, NULL); + ScopedUtfChars chars(env, macAddrString); + const char *bssid = chars.c_str(); if (bssid == NULL) { ALOGE("Error getting bssid"); return false; @@ -902,8 +839,8 @@ static jboolean android_net_wifi_setHotlist( ALOGD("Added bssid %s", bssidOut); - params.ap[i].low = getIntField(env, objAp, "low"); - params.ap[i].high = getIntField(env, objAp, "high"); + params.ap[i].low = helper.getIntField(objAp, "low"); + params.ap[i].high = helper.getIntField(objAp, "high"); } wifi_hotlist_ap_found_handler handler; @@ -914,10 +851,10 @@ static jboolean android_net_wifi_setHotlist( return hal_fn.wifi_set_bssid_hotlist(id, handle, params, handler) == WIFI_SUCCESS; } -static jboolean android_net_wifi_resetHotlist( - JNIEnv *env, jclass cls, jint iface, jint id) { +static jboolean android_net_wifi_resetHotlist(JNIEnv *env, jclass cls, jint iface, jint id) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("resetting hotlist on interface[%d] = %p", iface, handle); return hal_fn.wifi_reset_bssid_hotlist(id, handle) == WIFI_SUCCESS; @@ -925,18 +862,13 @@ static jboolean android_net_wifi_resetHotlist( void onSignificantWifiChange(wifi_request_id id, unsigned num_results, wifi_significant_change_result **results) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - ALOGD("onSignificantWifiChange called, vm = %p, obj = %p, env = %p", mVM, mCls, env); + JNIHelper helper(mVM); - jclass clsScanResult = (env)->FindClass("android/net/wifi/ScanResult"); - if (clsScanResult == NULL) { - ALOGE("Error in accessing class"); - return; - } + ALOGD("onSignificantWifiChange called, vm = %p, obj = %p", mVM, mCls); - jobjectArray scanResults = env->NewObjectArray(num_results, clsScanResult, NULL); + JNIObject<jobjectArray> scanResults = helper.newObjectArray( + num_results, "android/net/wifi/ScanResult", NULL); if (scanResults == NULL) { ALOGE("Error in allocating array"); return; @@ -946,49 +878,50 @@ void onSignificantWifiChange(wifi_request_id id, wifi_significant_change_result &result = *(results[i]); - jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); + JNIObject<jobject> scanResult = helper.createObject("android/net/wifi/ScanResult"); if (scanResult == NULL) { ALOGE("Error in creating scan result"); return; } - // setStringField(env, scanResult, "SSID", results[i].ssid); + // helper.setStringField(scanResult, "SSID", results[i].ssid); char bssid[32]; sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result.bssid[0], result.bssid[1], result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]); - setStringField(env, scanResult, "BSSID", bssid); + helper.setStringField(scanResult, "BSSID", bssid); - setIntField(env, scanResult, "level", result.rssi[0]); - setIntField(env, scanResult, "frequency", result.channel); - // setLongField(env, scanResult, "timestamp", result.ts); + helper.setIntField(scanResult, "level", result.rssi[0]); + helper.setIntField(scanResult, "frequency", result.channel); + // helper.setLongField(scanResult, "timestamp", result.ts); - env->SetObjectArrayElement(scanResults, i, scanResult); + helper.setObjectArrayElement(scanResults, i, scanResult); } - reportEvent(env, mCls, "onSignificantWifiChange", "(I[Landroid/net/wifi/ScanResult;)V", - id, scanResults); + helper.reportEvent(mCls, "onSignificantWifiChange", "(I[Landroid/net/wifi/ScanResult;)V", + id, scanResults.get()); } static jboolean android_net_wifi_trackSignificantWifiChange( JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("tracking significant wifi change on interface[%d] = %p", iface, handle); wifi_significant_change_params params; memset(¶ms, 0, sizeof(params)); - params.rssi_sample_size = getIntField(env, settings, "rssiSampleSize"); - params.lost_ap_sample_size = getIntField(env, settings, "lostApSampleSize"); - params.min_breaching = getIntField(env, settings, "minApsBreachingThreshold"); + params.rssi_sample_size = helper.getIntField(settings, "rssiSampleSize"); + params.lost_ap_sample_size = helper.getIntField(settings, "lostApSampleSize"); + params.min_breaching = helper.getIntField(settings, "minApsBreachingThreshold"); const char *bssid_info_array_type = "[Landroid/net/wifi/WifiScanner$BssidInfo;"; - jobjectArray bssids = (jobjectArray)getObjectField( - env, settings, "bssidInfos", bssid_info_array_type); - params.num_bssid = env->GetArrayLength(bssids); + JNIObject<jobjectArray> bssids = helper.getArrayField( + settings, "bssidInfos", bssid_info_array_type); + params.num_bssid = helper.getArrayLength(bssids); if (params.num_bssid == 0) { ALOGE("Error in accessing array"); @@ -999,16 +932,16 @@ static jboolean android_net_wifi_trackSignificantWifiChange( params.lost_ap_sample_size, params.min_breaching, params.num_bssid); for (int i = 0; i < params.num_bssid; i++) { - jobject objAp = env->GetObjectArrayElement(bssids, i); + JNIObject<jobject> objAp = helper.getObjectArrayElement(bssids, i); - jstring macAddrString = (jstring) getObjectField( - env, objAp, "bssid", "Ljava/lang/String;"); + JNIObject<jstring> macAddrString = helper.getStringField(objAp, "bssid"); if (macAddrString == NULL) { ALOGE("Error getting bssid field"); return false; } - const char *bssid = env->GetStringUTFChars(macAddrString, NULL); + ScopedUtfChars chars(env, macAddrString.get()); + const char *bssid = chars.c_str(); if (bssid == NULL) { ALOGE("Error getting bssid"); return false; @@ -1022,8 +955,8 @@ static jboolean android_net_wifi_trackSignificantWifiChange( sprintf(bssidOut, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - params.ap[i].low = getIntField(env, objAp, "low"); - params.ap[i].high = getIntField(env, objAp, "high"); + params.ap[i].low = helper.getIntField(objAp, "low"); + params.ap[i].high = helper.getIntField(objAp, "high"); ALOGD("Added bssid %s, [%04d, %04d]", bssidOut, params.ap[i].low, params.ap[i].high); } @@ -1040,7 +973,8 @@ static jboolean android_net_wifi_trackSignificantWifiChange( static jboolean android_net_wifi_untrackSignificantWifiChange( JNIEnv *env, jclass cls, jint iface, jint id) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("resetting significant wifi change on interface[%d] = %p", iface, handle); return hal_fn.wifi_reset_significant_change_handler(id, handle) == WIFI_SUCCESS; @@ -1066,64 +1000,69 @@ void onLinkStatsResults(wifi_request_id id, wifi_iface_stat *iface_stat, } static void android_net_wifi_setLinkLayerStats (JNIEnv *env, jclass cls, jint iface, int enable) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); wifi_link_layer_params params; params.aggressive_statistics_gathering = enable; params.mpdu_size_threshold = 128; - ALOGE("android_net_wifi_setLinkLayerStats: %u\n", enable); + + ALOGD("android_net_wifi_setLinkLayerStats: %u\n", enable); hal_fn.wifi_set_link_stats(handle, params); } static jobject android_net_wifi_getLinkLayerStats (JNIEnv *env, jclass cls, jint iface) { + JNIHelper helper(env); wifi_stats_result_handler handler; memset(&handler, 0, sizeof(handler)); handler.on_link_stats_results = &onLinkStatsResults; - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); int result = hal_fn.wifi_get_link_stats(0, handle, handler); if (result < 0) { ALOGE("android_net_wifi_getLinkLayerStats: failed to get link statistics\n"); return NULL; } - jobject wifiLinkLayerStats = createObject(env, "android/net/wifi/WifiLinkLayerStats"); + JNIObject<jobject> wifiLinkLayerStats = helper.createObject( + "android/net/wifi/WifiLinkLayerStats"); if (wifiLinkLayerStats == NULL) { ALOGE("Error in allocating wifiLinkLayerStats"); return NULL; } - setIntField(env, wifiLinkLayerStats, "beacon_rx", link_stat.beacon_rx); - setIntField(env, wifiLinkLayerStats, "rssi_mgmt", link_stat.rssi_mgmt); - setLongField(env, wifiLinkLayerStats, "rxmpdu_be", link_stat.ac[WIFI_AC_BE].rx_mpdu); - setLongField(env, wifiLinkLayerStats, "rxmpdu_bk", link_stat.ac[WIFI_AC_BK].rx_mpdu); - setLongField(env, wifiLinkLayerStats, "rxmpdu_vi", link_stat.ac[WIFI_AC_VI].rx_mpdu); - setLongField(env, wifiLinkLayerStats, "rxmpdu_vo", link_stat.ac[WIFI_AC_VO].rx_mpdu); - setLongField(env, wifiLinkLayerStats, "txmpdu_be", link_stat.ac[WIFI_AC_BE].tx_mpdu); - setLongField(env, wifiLinkLayerStats, "txmpdu_bk", link_stat.ac[WIFI_AC_BK].tx_mpdu); - setLongField(env, wifiLinkLayerStats, "txmpdu_vi", link_stat.ac[WIFI_AC_VI].tx_mpdu); - setLongField(env, wifiLinkLayerStats, "txmpdu_vo", link_stat.ac[WIFI_AC_VO].tx_mpdu); - setLongField(env, wifiLinkLayerStats, "lostmpdu_be", link_stat.ac[WIFI_AC_BE].mpdu_lost); - setLongField(env, wifiLinkLayerStats, "lostmpdu_bk", link_stat.ac[WIFI_AC_BK].mpdu_lost); - setLongField(env, wifiLinkLayerStats, "lostmpdu_vi", link_stat.ac[WIFI_AC_VI].mpdu_lost); - setLongField(env, wifiLinkLayerStats, "lostmpdu_vo", link_stat.ac[WIFI_AC_VO].mpdu_lost); - setLongField(env, wifiLinkLayerStats, "retries_be", link_stat.ac[WIFI_AC_BE].retries); - setLongField(env, wifiLinkLayerStats, "retries_bk", link_stat.ac[WIFI_AC_BK].retries); - setLongField(env, wifiLinkLayerStats, "retries_vi", link_stat.ac[WIFI_AC_VI].retries); - setLongField(env, wifiLinkLayerStats, "retries_vo", link_stat.ac[WIFI_AC_VO].retries); - - - setIntField(env, wifiLinkLayerStats, "on_time", radio_stat.on_time); - setIntField(env, wifiLinkLayerStats, "tx_time", radio_stat.tx_time); - setIntField(env, wifiLinkLayerStats, "rx_time", radio_stat.rx_time); - setIntField(env, wifiLinkLayerStats, "on_time_scan", radio_stat.on_time_scan); - - return wifiLinkLayerStats; + helper.setIntField(wifiLinkLayerStats, "beacon_rx", link_stat.beacon_rx); + helper.setIntField(wifiLinkLayerStats, "rssi_mgmt", link_stat.rssi_mgmt); + helper.setLongField(wifiLinkLayerStats, "rxmpdu_be", link_stat.ac[WIFI_AC_BE].rx_mpdu); + helper.setLongField(wifiLinkLayerStats, "rxmpdu_bk", link_stat.ac[WIFI_AC_BK].rx_mpdu); + helper.setLongField(wifiLinkLayerStats, "rxmpdu_vi", link_stat.ac[WIFI_AC_VI].rx_mpdu); + helper.setLongField(wifiLinkLayerStats, "rxmpdu_vo", link_stat.ac[WIFI_AC_VO].rx_mpdu); + helper.setLongField(wifiLinkLayerStats, "txmpdu_be", link_stat.ac[WIFI_AC_BE].tx_mpdu); + helper.setLongField(wifiLinkLayerStats, "txmpdu_bk", link_stat.ac[WIFI_AC_BK].tx_mpdu); + helper.setLongField(wifiLinkLayerStats, "txmpdu_vi", link_stat.ac[WIFI_AC_VI].tx_mpdu); + helper.setLongField(wifiLinkLayerStats, "txmpdu_vo", link_stat.ac[WIFI_AC_VO].tx_mpdu); + helper.setLongField(wifiLinkLayerStats, "lostmpdu_be", link_stat.ac[WIFI_AC_BE].mpdu_lost); + helper.setLongField(wifiLinkLayerStats, "lostmpdu_bk", link_stat.ac[WIFI_AC_BK].mpdu_lost); + helper.setLongField(wifiLinkLayerStats, "lostmpdu_vi", link_stat.ac[WIFI_AC_VI].mpdu_lost); + helper.setLongField(wifiLinkLayerStats, "lostmpdu_vo", link_stat.ac[WIFI_AC_VO].mpdu_lost); + helper.setLongField(wifiLinkLayerStats, "retries_be", link_stat.ac[WIFI_AC_BE].retries); + helper.setLongField(wifiLinkLayerStats, "retries_bk", link_stat.ac[WIFI_AC_BK].retries); + helper.setLongField(wifiLinkLayerStats, "retries_vi", link_stat.ac[WIFI_AC_VI].retries); + helper.setLongField(wifiLinkLayerStats, "retries_vo", link_stat.ac[WIFI_AC_VO].retries); + + helper.setIntField(wifiLinkLayerStats, "on_time", radio_stat.on_time); + helper.setIntField(wifiLinkLayerStats, "tx_time", radio_stat.tx_time); + helper.setIntField(wifiLinkLayerStats, "rx_time", radio_stat.rx_time); + helper.setIntField(wifiLinkLayerStats, "on_time_scan", radio_stat.on_time_scan); + + return wifiLinkLayerStats.detach(); } static jint android_net_wifi_getSupportedFeatures(JNIEnv *env, jclass cls, jint iface) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); feature_set set = 0; wifi_error result = WIFI_SUCCESS; @@ -1150,18 +1089,13 @@ static jint android_net_wifi_getSupportedFeatures(JNIEnv *env, jclass cls, jint } static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* results[]) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - ALOGD("onRttResults called, vm = %p, obj = %p, env = %p", mVM, mCls, env); + JNIHelper helper(mVM); - jclass clsRttResult = (env)->FindClass("android/net/wifi/RttManager$RttResult"); - if (clsRttResult == NULL) { - ALOGE("Error in accessing class"); - return; - } + ALOGD("onRttResults called, vm = %p, obj = %p", mVM, mCls); - jobjectArray rttResults = env->NewObjectArray(num_results, clsRttResult, NULL); + JNIObject<jobjectArray> rttResults = helper.newObjectArray( + num_results, "android/net/wifi/RttManager$RttResult", NULL); if (rttResults == NULL) { ALOGE("Error in allocating array"); return; @@ -1171,7 +1105,7 @@ static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_resu wifi_rtt_result *result = results[i]; - jobject rttResult = createObject(env, "android/net/wifi/RttManager$RttResult"); + JNIObject<jobject> rttResult = helper.createObject("android/net/wifi/RttManager$RttResult"); if (rttResult == NULL) { ALOGE("Error in creating rtt result"); return; @@ -1181,71 +1115,64 @@ static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_resu sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->addr[0], result->addr[1], result->addr[2], result->addr[3], result->addr[4], result->addr[5]); - setStringField(env, rttResult, "bssid", bssid); - setIntField(env, rttResult, "burstNumber", result->burst_num); - setIntField(env, rttResult, "measurementFrameNumber", result->measurement_number); - setIntField(env, rttResult, "successMeasurementFrameNumber", result->success_number); - setIntField(env, rttResult, "frameNumberPerBurstPeer", result->number_per_burst_peer); - setIntField(env, rttResult, "status", result->status); - setIntField(env, rttResult, "measurementType", result->type); - setIntField(env, rttResult, "retryAfterDuration", result->retry_after_duration); - setLongField(env, rttResult, "ts", result->ts); - setIntField(env, rttResult, "rssi", result->rssi); - setIntField(env, rttResult, "rssiSpread", result->rssi_spread); - setIntField(env, rttResult, "txRate", result->tx_rate.bitrate); - setIntField(env, rttResult, "rxRate", result->rx_rate.bitrate); - setLongField(env, rttResult, "rtt", result->rtt); - setLongField(env, rttResult, "rttStandardDeviation", result->rtt_sd); - setIntField(env, rttResult, "distance", result->distance); - setIntField(env, rttResult, "distanceStandardDeviation", result->distance_sd); - setIntField(env, rttResult, "distanceSpread", result->distance_spread); - setIntField(env, rttResult, "burstDuration", result->burst_duration); - setIntField(env, rttResult, "negotiatedBurstNum", result->negotiated_burst_num); - jobject LCI = createObject(env, "android/net/wifi/RttManager$WifiInformationElement"); - if (result->LCI != NULL && result->LCI->len > 0) { - ALOGD("Add LCI in result"); - setByteField(env, LCI, "id", result->LCI->id); - jbyteArray elements = env->NewByteArray(result->LCI->len); - jbyte *bytes = (jbyte *)&(result->LCI->data[0]); - env->SetByteArrayRegion(elements, 0, result->LCI->len, bytes); - setObjectField(env, LCI, "data", "[B", elements); - env->DeleteLocalRef(elements); - } else { - ALOGD("No LCI in result"); - setByteField(env, LCI, "id", (byte)(0xff)); - } - setObjectField(env, rttResult, "LCI", - "Landroid/net/wifi/RttManager$WifiInformationElement;", LCI); - - jobject LCR = createObject(env, "android/net/wifi/RttManager$WifiInformationElement"); - if (result->LCR != NULL && result->LCR->len > 0) { - ALOGD("Add LCR in result"); - setByteField(env, LCR, "id", result->LCR->id); - jbyteArray elements = env->NewByteArray(result->LCI->len); - jbyte *bytes = (jbyte *)&(result->LCR->data[0]); - env->SetByteArrayRegion(elements, 0, result->LCI->len, bytes); - setObjectField(env, LCR, "data", "[B", elements); - env->DeleteLocalRef(elements); - } else { - ALOGD("No LCR in result"); - setByteField(env, LCR, "id", (byte)(0xff)); - } - setObjectField(env, rttResult, "LCR", - "Landroid/net/wifi/RttManager$WifiInformationElement;", LCR); - - env->SetObjectArrayElement(rttResults, i, rttResult); - env->DeleteLocalRef(LCI); - env->DeleteLocalRef(LCR); - env->DeleteLocalRef(rttResult); - } - - reportEvent(env, mCls, "onRttResults", "(I[Landroid/net/wifi/RttManager$RttResult;)V", - id, rttResults); - - //clean the local reference - env->DeleteLocalRef(rttResults); - env->DeleteLocalRef(clsRttResult); + helper.setStringField(rttResult, "bssid", bssid); + helper.setIntField( rttResult, "burstNumber", result->burst_num); + helper.setIntField( rttResult, "measurementFrameNumber", result->measurement_number); + helper.setIntField( rttResult, "successMeasurementFrameNumber", result->success_number); + helper.setIntField(rttResult, "frameNumberPerBurstPeer", result->number_per_burst_peer); + helper.setIntField( rttResult, "status", result->status); + helper.setIntField( rttResult, "measurementType", result->type); + helper.setIntField(rttResult, "retryAfterDuration", result->retry_after_duration); + helper.setLongField(rttResult, "ts", result->ts); + helper.setIntField( rttResult, "rssi", result->rssi); + helper.setIntField( rttResult, "rssiSpread", result->rssi_spread); + helper.setIntField( rttResult, "txRate", result->tx_rate.bitrate); + helper.setIntField( rttResult, "rxRate", result->rx_rate.bitrate); + helper.setLongField(rttResult, "rtt", result->rtt); + helper.setLongField(rttResult, "rttStandardDeviation", result->rtt_sd); + helper.setIntField( rttResult, "distance", result->distance); + helper.setIntField( rttResult, "distanceStandardDeviation", result->distance_sd); + helper.setIntField( rttResult, "distanceSpread", result->distance_spread); + helper.setIntField( rttResult, "burstDuration", result->burst_duration); + helper.setIntField( rttResult, "negotiatedBurstNum", result->negotiated_burst_num); + + JNIObject<jobject> LCI = helper.createObject( + "android/net/wifi/RttManager$WifiInformationElement"); + if (result->LCI != NULL && result->LCI->len > 0) { + ALOGD("Add LCI in result"); + helper.setByteField(LCI, "id", result->LCI->id); + JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len); + jbyte *bytes = (jbyte *)&(result->LCI->data[0]); + helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes); + helper.setObjectField(LCI, "data", "[B", elements); + } else { + ALOGD("No LCI in result"); + helper.setByteField(LCI, "id", (byte)(0xff)); + } + helper.setObjectField(rttResult, "LCI", + "Landroid/net/wifi/RttManager$WifiInformationElement;", LCI); + + JNIObject<jobject> LCR = helper.createObject( + "android/net/wifi/RttManager$WifiInformationElement"); + if (result->LCR != NULL && result->LCR->len > 0) { + ALOGD("Add LCR in result"); + helper.setByteField(LCR, "id", result->LCR->id); + JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len); + jbyte *bytes = (jbyte *)&(result->LCR->data[0]); + helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes); + helper.setObjectField(LCR, "data", "[B", elements); + } else { + ALOGD("No LCR in result"); + helper.setByteField(LCR, "id", (byte)(0xff)); + } + helper.setObjectField(rttResult, "LCR", + "Landroid/net/wifi/RttManager$WifiInformationElement;", LCR); + + helper.setObjectArrayElement(rttResults, i, rttResult); + } + helper.reportEvent(mCls, "onRttResults", "(I[Landroid/net/wifi/RttManager$RttResult;)V", + id, rttResults.get()); } const int MaxRttConfigs = 16; @@ -1253,20 +1180,22 @@ const int MaxRttConfigs = 16; static jboolean android_net_wifi_requestRange( JNIEnv *env, jclass cls, jint iface, jint id, jobject params) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("sending rtt request [%d] = %p", id, handle); wifi_rtt_config configs[MaxRttConfigs]; memset(&configs, 0, sizeof(configs)); - int len = env->GetArrayLength((jobjectArray)params); + int len = helper.getArrayLength((jobjectArray)params); if (len > MaxRttConfigs) { return false; } for (int i = 0; i < len; i++) { - jobject param = env->GetObjectArrayElement((jobjectArray)params, i); + JNIObject<jobject> param = helper.getObjectArrayElement((jobjectArray)params, i); if (param == NULL) { ALOGD("could not get element %d", i); continue; @@ -1275,24 +1204,24 @@ static jboolean android_net_wifi_requestRange( wifi_rtt_config &config = configs[i]; parseMacAddress(env, param, config.addr); - config.type = (wifi_rtt_type)getIntField(env, param, "requestType"); - config.peer = (rtt_peer_type)getIntField(env, param, "deviceType"); - config.channel.center_freq = getIntField(env, param, "frequency"); - config.channel.width = (wifi_channel_width) getIntField(env, param, "channelWidth"); - config.channel.center_freq0 = getIntField(env, param, "centerFreq0"); - config.channel.center_freq1 = getIntField(env, param, "centerFreq1"); - - config.num_burst = getIntField(env, param, "numberBurst"); - config.burst_period = (unsigned) getIntField(env, param, "interval"); - config.num_frames_per_burst = (unsigned) getIntField(env, param, "numSamplesPerBurst"); - config.num_retries_per_rtt_frame = (unsigned) getIntField(env, param, + config.type = (wifi_rtt_type)helper.getIntField(param, "requestType"); + config.peer = (rtt_peer_type)helper.getIntField(param, "deviceType"); + config.channel.center_freq = helper.getIntField(param, "frequency"); + config.channel.width = (wifi_channel_width) helper.getIntField(param, "channelWidth"); + config.channel.center_freq0 = helper.getIntField(param, "centerFreq0"); + config.channel.center_freq1 = helper.getIntField(param, "centerFreq1"); + + config.num_burst = helper.getIntField(param, "numberBurst"); + config.burst_period = (unsigned) helper.getIntField(param, "interval"); + config.num_frames_per_burst = (unsigned) helper.getIntField(param, "numSamplesPerBurst"); + config.num_retries_per_rtt_frame = (unsigned) helper.getIntField(param, "numRetriesPerMeasurementFrame"); - config.num_retries_per_ftmr = (unsigned) getIntField(env, param, "numRetriesPerFTMR"); - config.LCI_request = getBoolField(env, param, "LCIRequest") ? 1 : 0; - config.LCR_request = getBoolField(env, param, "LCRRequest") ? 1 : 0; - config.burst_duration = (unsigned) getIntField(env, param, "burstTimeout"); - config.preamble = (wifi_rtt_preamble) getIntField(env, param, "preamble"); - config.bw = (wifi_rtt_bw) getIntField(env, param, "bandwidth"); + config.num_retries_per_ftmr = (unsigned) helper.getIntField(param, "numRetriesPerFTMR"); + config.LCI_request = helper.getBoolField(param, "LCIRequest") ? 1 : 0; + config.LCR_request = helper.getBoolField(param, "LCRRequest") ? 1 : 0; + config.burst_duration = (unsigned) helper.getIntField(param, "burstTimeout"); + config.preamble = (wifi_rtt_preamble) helper.getIntField(param, "preamble"); + config.bw = (wifi_rtt_bw) helper.getIntField(param, "bandwidth"); ALOGD("RTT request destination %d: type is %d, peer is %d, bw is %d, center_freq is %d ", i, config.type,config.peer, config.channel.width, config.channel.center_freq); @@ -1316,20 +1245,21 @@ static jboolean android_net_wifi_requestRange( static jboolean android_net_wifi_cancelRange( JNIEnv *env, jclass cls, jint iface, jint id, jobject params) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("cancelling rtt request [%d] = %p", id, handle); mac_addr addrs[MaxRttConfigs]; memset(&addrs, 0, sizeof(addrs)); - int len = env->GetArrayLength((jobjectArray)params); + int len = helper.getArrayLength((jobjectArray)params); if (len > MaxRttConfigs) { return false; } for (int i = 0; i < len; i++) { - jobject param = env->GetObjectArrayElement((jobjectArray)params, i); + JNIObject<jobject> param = helper.getObjectArrayElement(params, i); if (param == NULL) { ALOGD("could not get element %d", i); continue; @@ -1344,17 +1274,19 @@ static jboolean android_net_wifi_cancelRange( static jboolean android_net_wifi_setScanningMacOui(JNIEnv *env, jclass cls, jint iface, jbyteArray param) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("setting scan oui %p", handle); static const unsigned oui_len = 3; /* OUI is upper 3 bytes of mac_address */ - int len = env->GetArrayLength(param); + int len = helper.getArrayLength(param); if (len != oui_len) { ALOGE("invalid oui length %d", len); return false; } - jbyte* bytes = env->GetByteArrayElements(param, NULL); + ScopedBytesRO paramBytes(env, param); + const jbyte* bytes = paramBytes.get(); if (bytes == NULL) { ALOGE("failed to get array"); return false; @@ -1370,7 +1302,8 @@ static jboolean android_net_wifi_is_get_channels_for_band_supported(JNIEnv *env, static jintArray android_net_wifi_getValidChannels(JNIEnv *env, jclass cls, jint iface, jint band) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("getting valid channels %p", handle); static const int MaxChannels = 64; @@ -1380,14 +1313,14 @@ static jintArray android_net_wifi_getValidChannels(JNIEnv *env, jclass cls, channels, &num_channels); if (result == WIFI_SUCCESS) { - jintArray channelArray = env->NewIntArray(num_channels); + JNIObject<jintArray> channelArray = helper.newIntArray(num_channels); if (channelArray == NULL) { ALOGE("failed to allocate channel list"); return NULL; } - env->SetIntArrayRegion(channelArray, 0, num_channels, channels); - return channelArray; + helper.setIntArrayRegion(channelArray, 0, num_channels, channels); + return channelArray.detach(); } else { ALOGE("failed to get channel list : %d", result); return NULL; @@ -1395,7 +1328,9 @@ static jintArray android_net_wifi_getValidChannels(JNIEnv *env, jclass cls, } static jboolean android_net_wifi_setDfsFlag(JNIEnv *env, jclass cls, jint iface, jboolean dfs) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("setting dfs flag to %s, %p", dfs ? "true" : "false", handle); u32 nodfs = dfs ? 0 : 1; @@ -1404,23 +1339,26 @@ static jboolean android_net_wifi_setDfsFlag(JNIEnv *env, jclass cls, jint iface, } static jobject android_net_wifi_get_rtt_capabilities(JNIEnv *env, jclass cls, jint iface) { + + JNIHelper helper(env); wifi_rtt_capabilities rtt_capabilities; - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); wifi_error ret = hal_fn.wifi_get_rtt_capabilities(handle, &rtt_capabilities); if(WIFI_SUCCESS == ret) { - jobject capabilities = createObject(env, "android/net/wifi/RttManager$RttCapabilities"); - setBooleanField(env, capabilities, "oneSidedRttSupported", + JNIObject<jobject> capabilities = helper.createObject( + "android/net/wifi/RttManager$RttCapabilities"); + helper.setBooleanField(capabilities, "oneSidedRttSupported", rtt_capabilities.rtt_one_sided_supported == 1); - setBooleanField(env, capabilities, "twoSided11McRttSupported", + helper.setBooleanField(capabilities, "twoSided11McRttSupported", rtt_capabilities.rtt_ftm_supported == 1); - setBooleanField(env, capabilities, "lciSupported", + helper.setBooleanField(capabilities, "lciSupported", rtt_capabilities.lci_support); - setBooleanField(env,capabilities, "lcrSupported", + helper.setBooleanField(capabilities, "lcrSupported", rtt_capabilities.lcr_support); - setIntField(env, capabilities, "preambleSupported", + helper.setIntField(capabilities, "preambleSupported", rtt_capabilities.preamble_support); - setIntField(env, capabilities, "bwSupported", + helper.setIntField(capabilities, "bwSupported", rtt_capabilities.bw_support); ALOGD("One side RTT is: %s", rtt_capabilities.rtt_one_sided_supported ==1 ? "support" : "not support"); @@ -1432,7 +1370,7 @@ static jobject android_net_wifi_get_rtt_capabilities(JNIEnv *env, jclass cls, ji ALOGD("Support Preamble is : %d support BW is %d", rtt_capabilities.preamble_support, rtt_capabilities.bw_support); - return capabilities; + return capabilities.detach(); } else { return NULL; } @@ -1441,19 +1379,22 @@ static jobject android_net_wifi_get_rtt_capabilities(JNIEnv *env, jclass cls, ji static jboolean android_net_wifi_set_Country_Code_Hal(JNIEnv *env,jclass cls, jint iface, jstring country_code) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); - const char *country = env->GetStringUTFChars(country_code, NULL); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); + + ScopedUtfChars chars(env, country_code); + const char *country = chars.c_str(); ALOGD("set country code: %s", country); wifi_error res = hal_fn.wifi_set_country_code(handle, country); - env->ReleaseStringUTFChars(country_code, country); - return res == WIFI_SUCCESS; } static jboolean android_net_wifi_enable_disable_tdls(JNIEnv *env,jclass cls, jint iface, jboolean enable, jstring addr) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); mac_addr address; parseMacAddress(env, addr, address); @@ -1468,23 +1409,25 @@ static jboolean android_net_wifi_enable_disable_tdls(JNIEnv *env,jclass cls, jin } static void on_tdls_state_changed(mac_addr addr, wifi_tdls_status status) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - ALOGD("on_tdls_state_changed is called: vm = %p, obj = %p, env = %p", mVM, mCls, env); + JNIHelper helper(mVM); + + ALOGD("on_tdls_state_changed is called: vm = %p, obj = %p", mVM, mCls); char mac[32]; sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); - jstring mac_address = env->NewStringUTF(mac); - reportEvent(env, mCls, "onTdlsStatus", "(Ljava/lang/StringII;)V", - mac_address, status.state, status.reason); + JNIObject<jstring> mac_address = helper.newStringUTF(mac); + helper.reportEvent(mCls, "onTdlsStatus", "(Ljava/lang/StringII;)V", + mac_address.get(), status.state, status.reason); } static jobject android_net_wifi_get_tdls_status(JNIEnv *env,jclass cls, jint iface,jstring addr) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); mac_addr address; parseMacAddress(env, addr, address); @@ -1497,30 +1440,33 @@ static jobject android_net_wifi_get_tdls_status(JNIEnv *env,jclass cls, jint ifa if (ret != WIFI_SUCCESS) { return NULL; } else { - jobject tdls_status = createObject(env, "com/android/server/wifi/WifiNative$TdlsStatus"); - setIntField(env, tdls_status, "channel", status.channel); - setIntField(env, tdls_status, "global_operating_class", status.global_operating_class); - setIntField(env, tdls_status, "state", status.state); - setIntField(env, tdls_status, "reason", status.reason); - return tdls_status; + JNIObject<jobject> tdls_status = helper.createObject( + "com/android/server/wifi/WifiNative$TdlsStatus"); + helper.setIntField(tdls_status, "channel", status.channel); + helper.setIntField(tdls_status, "global_operating_class", status.global_operating_class); + helper.setIntField(tdls_status, "state", status.state); + helper.setIntField(tdls_status, "reason", status.reason); + return tdls_status.detach(); } } static jobject android_net_wifi_get_tdls_capabilities(JNIEnv *env, jclass cls, jint iface) { + + JNIHelper helper(env); wifi_tdls_capabilities tdls_capabilities; - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); wifi_error ret = hal_fn.wifi_get_tdls_capabilities(handle, &tdls_capabilities); - if(WIFI_SUCCESS == ret) { - jobject capabilities = createObject(env, + if (WIFI_SUCCESS == ret) { + JNIObject<jobject> capabilities = helper.createObject( "com/android/server/wifi/WifiNative$TdlsCapabilities"); - setIntField(env, capabilities, "maxConcurrentTdlsSessionNumber", + helper.setIntField(capabilities, "maxConcurrentTdlsSessionNumber", tdls_capabilities.max_concurrent_tdls_session_num); - setBooleanField(env, capabilities, "isGlobalTdlsSupported", + helper.setBooleanField(capabilities, "isGlobalTdlsSupported", tdls_capabilities.is_global_tdls_supported == 1); - setBooleanField(env, capabilities, "isPerMacTdlsSupported", + helper.setBooleanField(capabilities, "isPerMacTdlsSupported", tdls_capabilities.is_per_mac_tdls_supported == 1); - setBooleanField(env,capabilities, "isOffChannelTdlsSupported", + helper.setBooleanField(capabilities, "isOffChannelTdlsSupported", tdls_capabilities.is_off_channel_tdls_supported); ALOGD("TDLS Max Concurrent Tdls Session Number is: %d", @@ -1532,7 +1478,7 @@ static jobject android_net_wifi_get_tdls_capabilities(JNIEnv *env, jclass cls, j ALOGD("Off Channel Tdls is: %s", tdls_capabilities.is_off_channel_tdls_supported == 1 ? "support" : "not support"); - return capabilities; + return capabilities.detach(); } else { return NULL; } @@ -1543,18 +1489,20 @@ static jobject android_net_wifi_get_tdls_capabilities(JNIEnv *env, jclass cls, j // ---------------------------------------------------------------------------- static jint android_net_wifi_get_supported_logger_feature(JNIEnv *env, jclass cls, jint iface){ //Not implemented yet - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); return -1; } static jobject android_net_wifi_get_driver_version(JNIEnv *env, jclass cls, jint iface) { //Need to be fixed. The memory should be allocated from lower layer //char *buffer = NULL; + JNIHelper helper(env); int buffer_length = 256; char *buffer = (char *)malloc(buffer_length); if (!buffer) return NULL; memset(buffer, 0, buffer_length); - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("android_net_wifi_get_driver_version = %p", handle); @@ -1566,11 +1514,12 @@ static jobject android_net_wifi_get_driver_version(JNIEnv *env, jclass cls, jint if (result == WIFI_SUCCESS) { ALOGD("buffer is %p, length is %d", buffer, buffer_length); - jstring driver_version = env->NewStringUTF(buffer); + JNIObject<jstring> driver_version = helper.newStringUTF(buffer); free(buffer); - return driver_version; + return driver_version.detach(); } else { ALOGD("Fail to get driver version"); + free(buffer); return NULL; } } @@ -1578,11 +1527,12 @@ static jobject android_net_wifi_get_driver_version(JNIEnv *env, jclass cls, jint static jobject android_net_wifi_get_firmware_version(JNIEnv *env, jclass cls, jint iface) { //char *buffer = NULL; + JNIHelper helper(env); int buffer_length = 256; char *buffer = (char *)malloc(buffer_length); if (!buffer) return NULL; memset(buffer, 0, buffer_length); - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("android_net_wifi_get_firmware_version = %p", handle); @@ -1594,20 +1544,22 @@ static jobject android_net_wifi_get_firmware_version(JNIEnv *env, jclass cls, ji if (result == WIFI_SUCCESS) { ALOGD("buffer is %p, length is %d", buffer, buffer_length); - jstring firmware_version = env->NewStringUTF(buffer); + JNIObject<jstring> firmware_version = helper.newStringUTF(buffer); free(buffer); - return firmware_version; + return firmware_version.detach(); } else { ALOGD("Fail to get Firmware version"); + free(buffer); return NULL; } } static jobject android_net_wifi_get_ring_buffer_status (JNIEnv *env, jclass cls, jint iface) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); - ALOGD(" android_net_wifi_get_ring_buffer_status = %p", handle); + ALOGD("android_net_wifi_get_ring_buffer_status = %p", handle); if (handle == 0) { return NULL; @@ -1622,40 +1574,42 @@ static jobject android_net_wifi_get_ring_buffer_status (JNIEnv *env, jclass cls, wifi_error result = hal_fn.wifi_get_ring_buffers_status(handle, &num_rings, status); if (result == WIFI_SUCCESS) { ALOGD("status is %p, number is %d", status, num_rings); - jclass clsRingBufferStatus = - (env)->FindClass("com/android/server/wifi/WifiNative$RingBufferStatus"); - if (clsRingBufferStatus == NULL) { - ALOGE("Error in accessing class"); - free(status); - return NULL; - } - jobjectArray ringBuffersStatus = env->NewObjectArray(num_rings,clsRingBufferStatus, NULL); + + JNIObject<jobjectArray> ringBuffersStatus = helper.newObjectArray( + num_rings, "com/android/server/wifi/WifiNative$RingBufferStatus", NULL); + wifi_ring_buffer_status *tmp = status; for(u32 i = 0; i < num_rings; i++, tmp++) { - jobject ringStatus = createObject(env, + + JNIObject<jobject> ringStatus = helper.createObject( "com/android/server/wifi/WifiNative$RingBufferStatus"); + if (ringStatus == NULL) { ALOGE("Error in creating ringBufferStatus"); free(status); return NULL; } + char name[32]; for(int j = 0; j < 32; j++) { name[j] = tmp->name[j]; } - setStringField(env, ringStatus, "name", name); - setIntField(env, ringStatus, "flag", tmp->flags); - setIntField(env, ringStatus, "ringBufferId", tmp->ring_id); - setIntField(env, ringStatus, "ringBufferByteSize", tmp->ring_buffer_byte_size); - setIntField(env, ringStatus, "verboseLevel", tmp->verbose_level); - setIntField(env, ringStatus, "writtenBytes", tmp->written_bytes); - setIntField(env, ringStatus, "readBytes", tmp->read_bytes); - setIntField(env, ringStatus, "writtenRecords", tmp->written_records); - env->SetObjectArrayElement(ringBuffersStatus, i, ringStatus); + + helper.setStringField(ringStatus, "name", name); + helper.setIntField(ringStatus, "flag", tmp->flags); + helper.setIntField(ringStatus, "ringBufferId", tmp->ring_id); + helper.setIntField(ringStatus, "ringBufferByteSize", tmp->ring_buffer_byte_size); + helper.setIntField(ringStatus, "verboseLevel", tmp->verbose_level); + helper.setIntField(ringStatus, "writtenBytes", tmp->written_bytes); + helper.setIntField(ringStatus, "readBytes", tmp->read_bytes); + helper.setIntField(ringStatus, "writtenRecords", tmp->written_records); + + helper.setObjectArrayElement(ringBuffersStatus, i, ringStatus); } + free(status); - return ringBuffersStatus; + return ringBuffersStatus.detach(); } else { free(status); return NULL; @@ -1671,51 +1625,48 @@ static void on_ring_buffer_data(char *ring_name, char *buffer, int buffer_size, return; } - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); + + JNIHelper helper(mVM); /* ALOGD("on_ring_buffer_data called, vm = %p, obj = %p, env = %p buffer size = %d", mVM, mCls, env, buffer_size); */ - jobject ringStatus = createObject(env, + JNIObject<jobject> ringStatus = helper.createObject( "com/android/server/wifi/WifiNative$RingBufferStatus"); if (status == NULL) { ALOGE("Error in creating ringBufferStatus"); return; } - setStringField(env, ringStatus, "name", ring_name); - setIntField(env, ringStatus, "flag", status->flags); - setIntField(env, ringStatus, "ringBufferId", status->ring_id); - setIntField(env, ringStatus, "ringBufferByteSize", status->ring_buffer_byte_size); - setIntField(env, ringStatus, "verboseLevel", status->verbose_level); - setIntField(env, ringStatus, "writtenBytes", status->written_bytes); - setIntField(env, ringStatus, "readBytes", status->read_bytes); - setIntField(env, ringStatus, "writtenRecords", status->written_records); - - jbyteArray bytes = env->NewByteArray(buffer_size); - env->SetByteArrayRegion(bytes, 0, buffer_size, (jbyte*)buffer); + helper.setStringField(ringStatus, "name", ring_name); + helper.setIntField(ringStatus, "flag", status->flags); + helper.setIntField(ringStatus, "ringBufferId", status->ring_id); + helper.setIntField(ringStatus, "ringBufferByteSize", status->ring_buffer_byte_size); + helper.setIntField(ringStatus, "verboseLevel", status->verbose_level); + helper.setIntField(ringStatus, "writtenBytes", status->written_bytes); + helper.setIntField(ringStatus, "readBytes", status->read_bytes); + helper.setIntField(ringStatus, "writtenRecords", status->written_records); - reportEvent(env, mCls,"onRingBufferData", - "(Lcom/android/server/wifi/WifiNative$RingBufferStatus;[B)V", ringStatus, bytes); + JNIObject<jbyteArray> bytes = helper.newByteArray(buffer_size); + helper.setByteArrayRegion(bytes, 0, buffer_size, (jbyte*)buffer); - env->DeleteLocalRef(bytes); - env->DeleteLocalRef(ringStatus); + helper.reportEvent(mCls,"onRingBufferData", + "(Lcom/android/server/wifi/WifiNative$RingBufferStatus;[B)V", + ringStatus.get(), bytes.get()); } static void on_alert_data(wifi_request_id id, char *buffer, int buffer_size, int err_code){ - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - ALOGD(" on_alert_data called, vm = %p, obj = %p, env = %p buffer_size = %d, error code = %d" - , mVM, mCls, env, buffer_size, err_code); + + JNIHelper helper(mVM); + ALOGD("on_alert_data called, vm = %p, obj = %p, buffer_size = %d, error code = %d" + , mVM, mCls, buffer_size, err_code); if (buffer_size > 0) { - jbyteArray records = env->NewByteArray(buffer_size); + JNIObject<jbyteArray> records = helper.newByteArray(buffer_size); jbyte *bytes = (jbyte *) buffer; - env->SetByteArrayRegion(records, 0,buffer_size, bytes); - reportEvent(env, mCls,"onWifiAlert","([BI)V", records, err_code); - env->DeleteLocalRef(records); + helper.setByteArrayRegion(records, 0,buffer_size, bytes); + helper.reportEvent(mCls,"onWifiAlert","([BI)V", records.get(), err_code); } else { - reportEvent(env, mCls,"onWifiAlert","([BI)V", NULL, err_code); + helper.reportEvent(mCls,"onWifiAlert","([BI)V", NULL, err_code); } } @@ -1723,7 +1674,8 @@ static void on_alert_data(wifi_request_id id, char *buffer, int buffer_size, int static jboolean android_net_wifi_start_logging_ring_buffer(JNIEnv *env, jclass cls, jint iface, jint verbose_level,jint flags, jint max_interval,jint min_data_size, jstring ring_name) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("android_net_wifi_start_logging_ring_buffer = %p", handle); @@ -1731,61 +1683,52 @@ static jboolean android_net_wifi_start_logging_ring_buffer(JNIEnv *env, jclass c return false; } - const char* ring_name_const_char = env->GetStringUTFChars(ring_name, JNI_FALSE); - int len; - for(len = 0; ring_name_const_char[len] != 0; len++); - - char* ring_name_char = (char*) malloc(len+1); - memcpy(ring_name_char, ring_name_const_char, len+1); - - int ret = hal_fn.wifi_start_logging(handle, verbose_level, flags, max_interval, min_data_size, - ring_name_char); + ScopedUtfChars chars(env, ring_name); + const char* ring_name_const_char = chars.c_str(); + int ret = hal_fn.wifi_start_logging(handle, verbose_level, + flags, max_interval, min_data_size, const_cast<char *>(ring_name_const_char)); if (ret != WIFI_SUCCESS) { - ALOGE("Fail to start logging for ring %s", ring_name); + ALOGE("Fail to start logging for ring %s", ring_name_const_char); } else { - ALOGD("start logging for ring %s", ring_name); + ALOGD("start logging for ring %s", ring_name_const_char); } - env->ReleaseStringUTFChars(ring_name, ring_name_char); + return ret == WIFI_SUCCESS; } static jboolean android_net_wifi_get_ring_buffer_data(JNIEnv *env, jclass cls, jint iface, jstring ring_name) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); - // ALOGD("android_net_wifi_get_ring_buffer_data = %p", handle); - - const char* ring_name_const_char = env->GetStringUTFChars(ring_name, JNI_FALSE); - int len; - for(len = 0; ring_name_const_char[len] != 0; len++); - char* ring_name_char = (char*) malloc(len+1); - memcpy(ring_name_char, ring_name_const_char, len+1); - int result = hal_fn.wifi_get_ring_data(handle, ring_name_char); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); + // ALOGD("android_net_wifi_get_ring_buffer_data = %p", handle); - env->ReleaseStringUTFChars(ring_name, ring_name_char); + ScopedUtfChars chars(env, ring_name); + const char* ring_name_const_char = chars.c_str(); + int result = hal_fn.wifi_get_ring_data(handle, const_cast<char *>(ring_name_const_char)); return result == WIFI_SUCCESS; } void on_firmware_memory_dump(char *buffer, int buffer_size) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); + + JNIHelper helper(mVM); /* ALOGD("on_firmware_memory_dump called, vm = %p, obj = %p, env = %p buffer_size = %d" , mVM, mCls, env, buffer_size); */ if (buffer_size > 0) { - jbyteArray dump = env->NewByteArray(buffer_size); + JNIObject<jbyteArray> dump = helper.newByteArray(buffer_size); jbyte *bytes = (jbyte *) (buffer); - env->SetByteArrayRegion(dump, 0, buffer_size, bytes); - reportEvent(env, mCls,"onWifiFwMemoryAvailable","([B)V", dump); - env->DeleteLocalRef(dump); + helper.setByteArrayRegion(dump, 0, buffer_size, bytes); + helper.reportEvent(mCls,"onWifiFwMemoryAvailable","([B)V", dump.get()); } - } static jboolean android_net_wifi_get_fw_memory_dump(JNIEnv *env, jclass cls, jint iface){ - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); // ALOGD("android_net_wifi_get_fw_memory_dump = %p", handle); if (handle == NULL) { @@ -1801,7 +1744,9 @@ static jboolean android_net_wifi_get_fw_memory_dump(JNIEnv *env, jclass cls, jin } static jboolean android_net_wifi_set_log_handler(JNIEnv *env, jclass cls, jint iface, jint id) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("android_net_wifi_set_log_handler = %p", handle); //initialize the handler on first time @@ -1826,7 +1771,9 @@ static jboolean android_net_wifi_set_log_handler(JNIEnv *env, jclass cls, jint i } static jboolean android_net_wifi_reset_log_handler(JNIEnv *env, jclass cls, jint iface, jint id) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); //reset alter handler ALOGD("android_net_wifi_reset_alert_handler = %p", handle); @@ -1854,35 +1801,33 @@ static jboolean android_net_wifi_reset_log_handler(JNIEnv *env, jclass cls, jint static void onPnoNetworkFound(wifi_request_id id, unsigned num_results, wifi_scan_result *results) { - JNIEnv *env = NULL; - mVM->AttachCurrentThread(&env, NULL); - ALOGD("onPnoNetworkFound called, vm = %p, obj = %p, env = %p, num_results %u", - mVM, mCls, env, num_results); + JNIHelper helper(mVM); + + ALOGD("onPnoNetworkFound called, vm = %p, obj = %p, num_results %u", mVM, mCls, num_results); if (results == 0 || num_results == 0) { ALOGE("onPnoNetworkFound: Error no results"); return; } - jobject scanResult; jbyte *bytes; - jobjectArray scanResults; + JNIObject<jobjectArray> scanResults(helper, NULL); //jbyteArray elements; for (unsigned i=0; i<num_results; i++) { - scanResult = createScanResult(env, &results[i]); + JNIObject<jobject> scanResult = createScanResult(helper, &results[i]); if (i == 0) { - scanResults = env->NewObjectArray(num_results, - env->FindClass("android/net/wifi/ScanResult"), scanResult); + scanResults = helper.newObjectArray( + num_results, "android/net/wifi/ScanResult", scanResult); if (scanResults == 0) { ALOGD("cant allocate array"); } else { - ALOGD("allocated array %u", env->GetArrayLength(scanResults)); + ALOGD("allocated array %u", helper.getArrayLength(scanResults)); } } else { - env->SetObjectArrayElement(scanResults, i, scanResult); + helper.setObjectArrayElement(scanResults, i, scanResult); } ALOGD("Scan result with ie length %d, i %u, <%s> rssi=%d %02x:%02x:%02x:%02x:%02x:%02x", @@ -1890,7 +1835,7 @@ static void onPnoNetworkFound(wifi_request_id id, results[i].bssid[1],results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]); - /*elements = env->NewByteArray(results->ie_length); + /*elements = helper.newByteArray(results->ie_length); if (elements == NULL) { ALOGE("Error in allocating array"); return; @@ -1899,7 +1844,7 @@ static void onPnoNetworkFound(wifi_request_id id, //ALOGD("onPnoNetworkFound: Setting byte array"); //bytes = (jbyte *)&(results->ie_data[0]); - //env->SetByteArrayRegion(elements, 0, results->ie_length, bytes); + //helper.setByteArrayRegion(elements, 0, results->ie_length, bytes); //ALOGD("onPnoNetworkFound: Returning result"); } @@ -1907,21 +1852,19 @@ static void onPnoNetworkFound(wifi_request_id id, ALOGD("calling report"); - reportEvent(env, mCls, "onPnoNetworkFound", "(I[Landroid/net/wifi/ScanResult;)V", id, - scanResults); + helper.reportEvent(mCls, "onPnoNetworkFound", "(I[Landroid/net/wifi/ScanResult;)V", id, + scanResults.get()); ALOGD("free ref"); - - env->DeleteLocalRef(scanResults); - //env->DeleteLocalRef(elements); } static jboolean android_net_wifi_setPnoListNative( JNIEnv *env, jclass cls, jint iface, jint id, jobject list) { + JNIHelper helper(env); wifi_epno_handler handler; handler.on_network_found = &onPnoNetworkFound; - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("configure ePno list request [%d] = %p", id, handle); if (list == NULL) { @@ -1934,27 +1877,27 @@ static jboolean android_net_wifi_setPnoListNative( wifi_epno_network net_list[MAX_PNO_SSID]; memset(&net_list, 0, sizeof(net_list)); - size_t len = env->GetArrayLength((jobjectArray)list); + size_t len = helper.getArrayLength((jobjectArray)list); if (len > (size_t)MAX_PNO_SSID) { return false; } for (unsigned int i = 0; i < len; i++) { - jobject pno_net = env->GetObjectArrayElement((jobjectArray)list, i); + JNIObject<jobject> pno_net = helper.getObjectArrayElement((jobjectArray)list, i); if (pno_net == NULL) { ALOGD("setPnoListNative: could not get element %d", i); continue; } - jstring sssid = (jstring) getObjectField( - env, pno_net, "SSID", "Ljava/lang/String;"); + JNIObject<jstring> sssid = helper.getStringField(pno_net, "SSID"); if (sssid == NULL) { ALOGE("Error setPnoListNative: getting ssid field"); return false; } - const char *ssid = env->GetStringUTFChars(sssid, NULL); + ScopedUtfChars chars(env, (jstring)sssid.get()); + const char *ssid = chars.c_str(); if (ssid == NULL) { ALOGE("Error setPnoListNative: getting ssid"); return false; @@ -1964,6 +1907,7 @@ static jboolean android_net_wifi_setPnoListNative( ALOGE("Error setPnoListNative: long ssid %u", strnlen((const char*)ssid, 256)); return false; } + if (ssid_len > 1 && ssid[0] == '"' && ssid[ssid_len-1]) { // strip leading and trailing '"' @@ -1976,11 +1920,11 @@ static jboolean android_net_wifi_setPnoListNative( } memcpy(net_list[i].ssid, ssid, ssid_len); - int rssit = getIntField(env, pno_net, "rssi_threshold"); + int rssit = helper.getIntField(pno_net, "rssi_threshold"); net_list[i].rssi_threshold = (byte)rssit; - int a = getIntField(env, pno_net, "auth"); + int a = helper.getIntField(pno_net, "auth"); net_list[i].auth_bit_field = a; - int f = getIntField(env, pno_net, "flags"); + int f = helper.getIntField(pno_net, "flags"); net_list[i].flags = f; ALOGE(" setPnoListNative: idx %u rssi %d/%d auth %x/%x flags %x/%x [%s]", i, (signed)net_list[i].rssi_threshold, net_list[i].rssi_threshold, @@ -1996,21 +1940,22 @@ static jboolean android_net_wifi_setPnoListNative( static jboolean android_net_wifi_setLazyRoam( JNIEnv *env, jclass cls, jint iface, jint id, jboolean enabled, jobject roam_param) { + JNIHelper helper(env); wifi_error status = WIFI_SUCCESS; wifi_roam_params params; memset(¶ms, 0, sizeof(params)); - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("configure lazy roam request [%d] = %p", id, handle); if (roam_param != NULL) { - params.A_band_boost_threshold = getIntField(env, roam_param, "A_band_boost_threshold"); - params.A_band_penalty_threshold = getIntField(env, roam_param, "A_band_penalty_threshold"); - params.A_band_boost_factor = getIntField(env, roam_param, "A_band_boost_factor"); - params.A_band_penalty_factor = getIntField(env, roam_param, "A_band_penalty_factor"); - params.A_band_max_boost = getIntField(env, roam_param, "A_band_max_boost"); - params.lazy_roam_hysteresis = getIntField(env, roam_param, "lazy_roam_hysteresis"); - params.alert_roam_rssi_trigger = getIntField(env, roam_param, "alert_roam_rssi_trigger"); + params.A_band_boost_threshold = helper.getIntField(roam_param, "A_band_boost_threshold"); + params.A_band_penalty_threshold = helper.getIntField(roam_param, "A_band_penalty_threshold"); + params.A_band_boost_factor = helper.getIntField(roam_param, "A_band_boost_factor"); + params.A_band_penalty_factor = helper.getIntField(roam_param, "A_band_penalty_factor"); + params.A_band_max_boost = helper.getIntField(roam_param, "A_band_max_boost"); + params.lazy_roam_hysteresis = helper.getIntField(roam_param, "lazy_roam_hysteresis"); + params.alert_roam_rssi_trigger = helper.getIntField(roam_param, "alert_roam_rssi_trigger"); status = hal_fn.wifi_set_gscan_roam_params(id, handle, ¶ms); } ALOGE("android_net_wifi_setLazyRoam configured params status=%d\n", status); @@ -2026,28 +1971,31 @@ static jboolean android_net_wifi_setLazyRoam( static jboolean android_net_wifi_setBssidBlacklist( JNIEnv *env, jclass cls, jint iface, jint id, jobject list) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("configure BSSID black list request [%d] = %p", id, handle); wifi_bssid_params params; memset(¶ms, 0, sizeof(params)); if (list != NULL) { - size_t len = env->GetArrayLength((jobjectArray)list); + size_t len = helper.getArrayLength((jobjectArray)list); if (len > (size_t)MAX_BLACKLIST_BSSID) { return false; } for (unsigned int i = 0; i < len; i++) { - jstring jbssid = (jstring)env->GetObjectArrayElement((jobjectArray)list, i); + JNIObject<jobject> jbssid = helper.getObjectArrayElement(list, i); if (jbssid == NULL) { ALOGD("configure BSSID blacklist: could not get element %d", i); continue; } - const char *bssid = env->GetStringUTFChars(jbssid, NULL); + + ScopedUtfChars chars(env, (jstring)jbssid.get()); + const char *bssid = chars.c_str(); if (bssid == NULL) { - ALOGE("Error getting bssid"); - return false; + ALOGE("Error getting bssid"); + return false; } mac_addr addr; @@ -2061,7 +2009,6 @@ static jboolean android_net_wifi_setBssidBlacklist( ALOGD("BSSID blacklist: added bssid %s", bssidOut); params.num_bssid++; - } } @@ -2072,40 +2019,44 @@ static jboolean android_net_wifi_setBssidBlacklist( static jboolean android_net_wifi_setSsidWhitelist( JNIEnv *env, jclass cls, jint iface, jint id, jobject list) { - wifi_interface_handle handle = getIfaceHandle(env, cls, iface); + JNIHelper helper(env); + wifi_interface_handle handle = getIfaceHandle(helper, cls, iface); ALOGD("configure SSID white list request [%d] = %p", id, handle); wifi_ssid *ssids = NULL; int num_ssids = 0; if (list != NULL) { - size_t len = env->GetArrayLength((jobjectArray)list); + size_t len = helper.getArrayLength((jobjectArray)list); if (len > 0) { - ssids = (wifi_ssid *)malloc(len * sizeof (wifi_ssid)); - if (!ssids) return false; - memset(ssids, 0, len * sizeof (wifi_ssid)); + ssids = (wifi_ssid *)malloc(len * sizeof (wifi_ssid)); + if (!ssids) return false; + memset(ssids, 0, len * sizeof (wifi_ssid)); for (unsigned int i = 0; i < len; i++) { - jstring jssid = (jstring)env->GetObjectArrayElement((jobjectArray)list, i); + JNIObject<jobject> jssid = helper.getObjectArrayElement(list, i); if (jssid == NULL) { ALOGD("configure SSID whitelist: could not get element %d", i); free(ssids); return false; } - const char *ssid = env->GetStringUTFChars(jssid, NULL); - if (ssid == NULL) { - ALOGE("Error getting sssid"); + + ScopedUtfChars chars(env, (jstring)jssid.get()); + const char *utf = chars.c_str(); + if (utf == NULL) { + ALOGE("Error getting sssid"); free(ssids); return false; } - int slen = strnlen(ssid, 33); + + int slen = strnlen(utf, 33); if (slen <= 0 || slen > 32) { ALOGE("Error wrong ssid length %d", slen); free(ssids); return false; } - memcpy(ssids[i].ssid, ssid, slen); + memcpy(ssids[i].ssid, utf, slen); num_ssids++; - ALOGD("SSID white list: added ssid %s", ssid); + ALOGD("SSID white list: added ssid %s", utf); } } } diff --git a/service/jni/jni_helper.cpp b/service/jni/jni_helper.cpp index ef67391b5..73209619e 100644 --- a/service/jni/jni_helper.cpp +++ b/service/jni/jni_helper.cpp @@ -31,471 +31,593 @@ namespace android { /* JNI Helpers for wifi_hal implementation */ -void throwException( JNIEnv *env, const char *message, int line ) +JNIHelper::JNIHelper(JavaVM *vm) +{ + vm->AttachCurrentThread(&mEnv, NULL); + mVM = vm; +} + +JNIHelper::JNIHelper(JNIEnv *env) +{ + mVM = NULL; + mEnv = env; +} + +JNIHelper::~JNIHelper() +{ + if (mVM != NULL) { + // mVM->DetachCurrentThread(); /* 'attempting to detach while still running code' */ + mVM = NULL; /* not really required; but may help debugging */ + mEnv = NULL; /* not really required; but may help debugging */ + } +} + +jobject JNIHelper::newGlobalRef(jobject obj) { + return mEnv->NewGlobalRef(obj); +} + +void JNIHelper::deleteGlobalRef(jobject obj) { + mEnv->DeleteGlobalRef(obj); +} + +jobject JNIHelper::newLocalRef(jobject obj) { + return mEnv->NewLocalRef(obj); +} + +void JNIHelper::deleteLocalRef(jobject obj) { + mEnv->DeleteLocalRef(obj); +} + +void JNIHelper::throwException(const char *message, int line) { ALOGE("error at line %d: %s", line, message); const char *className = "java/lang/Exception"; - jclass exClass = (env)->FindClass(className ); + jclass exClass = mEnv->FindClass(className ); if ( exClass == NULL ) { ALOGE("Could not find exception class to throw error"); ALOGE("error at line %d: %s", line, message); return; } - (env)->ThrowNew(exClass, message); + mEnv->ThrowNew(exClass, message); } -jboolean getBoolField(JNIEnv *env, jobject obj, const char *name) +jboolean JNIHelper::getBoolField(jobject obj, const char *name) { - jclass cls = (env)->GetObjectClass(obj); - jfieldID field = (env)->GetFieldID(cls, name, "Z"); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, "Z"); if (field == 0) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return 0; } - jboolean value = (env)->GetBooleanField(obj, field); - env->DeleteLocalRef(cls); - return value; + return mEnv->GetBooleanField(obj, field); } -jint getIntField(JNIEnv *env, jobject obj, const char *name) +jint JNIHelper::getIntField(jobject obj, const char *name) { - jclass cls = (env)->GetObjectClass(obj); - jfieldID field = (env)->GetFieldID(cls, name, "I"); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, "I"); if (field == 0) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return 0; } - jint value = (env)->GetIntField(obj, field); - env->DeleteLocalRef(cls); - return value; + return mEnv->GetIntField(obj, field); } -jbyte getByteField(JNIEnv *env, jobject obj, const char *name) +jbyte JNIHelper::getByteField(jobject obj, const char *name) { - jclass cls = (env)->GetObjectClass(obj); - jfieldID field = (env)->GetFieldID(cls, name, "B"); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, "B"); if (field == 0) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return 0; } - jbyte value = (env)->GetByteField(obj, field); - env->DeleteLocalRef(cls); - return value; + return mEnv->GetByteField(obj, field); } -jlong getLongField(JNIEnv *env, jobject obj, const char *name) +jlong JNIHelper::getLongField(jobject obj, const char *name) { - jclass cls = (env)->GetObjectClass(obj); - jfieldID field = (env)->GetFieldID(cls, name, "J"); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, "J"); if (field == 0) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return 0; } - jlong value = (env)->GetLongField(obj, field); - env->DeleteLocalRef(cls); - return value; + return mEnv->GetLongField(obj, field); } -jlong getStaticLongField(JNIEnv *env, jobject obj, const char *name) +JNIObject<jstring> JNIHelper::getStringField(jobject obj, const char *name) { - jclass cls = (env)->GetObjectClass(obj); - jlong result = getStaticLongField(env, cls, name); - env->DeleteLocalRef(cls); - return result; + JNIObject<jobject> m = getObjectField(obj, name, "Ljava/lang/String;"); + if (m == NULL) { + THROW(*this, "Error in accessing field"); + return JNIObject<jstring>(*this, NULL); + } + + return JNIObject<jstring>(*this, (jstring)m.detach()); } -jlong getStaticLongField(JNIEnv *env, jclass cls, const char *name) +bool JNIHelper::getStringFieldValue(jobject obj, const char *name, char *buf, int size) { - jfieldID field = (env)->GetStaticFieldID(cls, name, "J"); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, "Ljava/lang/String;"); if (field == 0) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return 0; } - //ALOGE("getStaticLongField %s %p", name, cls); - return (env)->GetStaticLongField(cls, field); + JNIObject<jobject> value(*this, mEnv->GetObjectField(obj, field)); + JNIObject<jstring> string(*this, (jstring)value.clone()); + ScopedUtfChars chars(mEnv, string); + + const char *utf = chars.c_str(); + if (utf == NULL) { + THROW(*this, "Error in accessing value"); + return false; + } + + if (*utf != 0 && size < 1) { + return false; + } + + strncpy(buf, utf, size); + if (size > 0) { + buf[size - 1] = 0; + } + + return true; +} + +jlong JNIHelper::getStaticLongField(jobject obj, const char *name) +{ + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + return getStaticLongField(cls, name); } -jobject getObjectField(JNIEnv *env, jobject obj, const char *name, const char *type) +jlong JNIHelper::getStaticLongField(jclass cls, const char *name) { - jclass cls = (env)->GetObjectClass(obj); - jfieldID field = (env)->GetFieldID(cls, name, type); + jfieldID field = mEnv->GetStaticFieldID(cls, name, "J"); if (field == 0) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return 0; } + //ALOGE("getStaticLongField %s %p", name, cls); + return mEnv->GetStaticLongField(cls, field); +} - jobject value = (env)->GetObjectField(obj, field); - env->DeleteLocalRef(cls); - return value; +JNIObject<jobject> JNIHelper::getObjectField(jobject obj, const char *name, const char *type) +{ + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, type); + if (field == 0) { + THROW(*this, "Error in accessing field"); + return JNIObject<jobject>(*this, NULL); + } + + return JNIObject<jobject>(*this, mEnv->GetObjectField(obj, field)); +} + +JNIObject<jobjectArray> JNIHelper::getArrayField(jobject obj, const char *name, const char *type) +{ + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, type); + if (field == 0) { + THROW(*this, "Error in accessing field"); + return JNIObject<jobjectArray>(*this, NULL); + } + + return JNIObject<jobjectArray>(*this, (jobjectArray)mEnv->GetObjectField(obj, field)); } -jlong getLongArrayField(JNIEnv *env, jobject obj, const char *name, int index) +jlong JNIHelper::getLongArrayField(jobject obj, const char *name, int index) { - jclass cls = (env)->GetObjectClass(obj); - jfieldID field = (env)->GetFieldID(cls, name, "[J"); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, "[J"); if (field == 0) { - THROW(env, "Error in accessing field definition"); + THROW(*this, "Error in accessing field definition"); return 0; } - jlongArray array = (jlongArray)(env)->GetObjectField(obj, field); + JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetObjectField(obj, field)); if (array == NULL) { - THROW(env, "Error in accessing array"); + THROW(*this, "Error in accessing array"); return 0; } - jlong *elem = (env)->GetLongArrayElements(array, 0); + jlong *elem = mEnv->GetLongArrayElements(array, 0); if (elem == NULL) { - THROW(env, "Error in accessing index element"); + THROW(*this, "Error in accessing index element"); return 0; } jlong value = elem[index]; - (env)->ReleaseLongArrayElements(array, elem, 0); - - env->DeleteLocalRef(array); - env->DeleteLocalRef(cls); - + mEnv->ReleaseLongArrayElements(array, elem, 0); return value; } -jlong getStaticLongArrayField(JNIEnv *env, jobject obj, const char *name, int index) +jlong JNIHelper::getStaticLongArrayField(jobject obj, const char *name, int index) { - jclass cls = (env)->GetObjectClass(obj); - jlong result = getStaticLongArrayField(env, cls, name, index); - env->DeleteLocalRef(cls); - return result; + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + return getStaticLongArrayField(cls, name, index); } -jlong getStaticLongArrayField(JNIEnv *env, jclass cls, const char *name, int index) +jlong JNIHelper::getStaticLongArrayField(jclass cls, const char *name, int index) { - jfieldID field = (env)->GetStaticFieldID(cls, name, "[J"); + jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J"); if (field == 0) { - THROW(env, "Error in accessing field definition"); + THROW(*this, "Error in accessing field definition"); return 0; } - jlongArray array = (jlongArray)(env)->GetStaticObjectField(cls, field); - jlong *elem = (env)->GetLongArrayElements(array, 0); + JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetStaticObjectField(cls, field)); + jlong *elem = mEnv->GetLongArrayElements(array, 0); if (elem == NULL) { - THROW(env, "Error in accessing index element"); + THROW(*this, "Error in accessing index element"); return 0; } jlong value = elem[index]; - (env)->ReleaseLongArrayElements(array, elem, 0); - - env->DeleteLocalRef(array); + mEnv->ReleaseLongArrayElements(array, elem, 0); return value; } -jobject getObjectArrayField(JNIEnv *env, jobject obj, const char *name, const char *type, int index) +JNIObject<jobject> JNIHelper::getObjectArrayField(jobject obj, const char *name, const char *type, +int index) { - jclass cls = (env)->GetObjectClass(obj); - jfieldID field = (env)->GetFieldID(cls, name, type); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); + jfieldID field = mEnv->GetFieldID(cls, name, type); if (field == 0) { - THROW(env, "Error in accessing field definition"); - return 0; + THROW(*this, "Error in accessing field definition"); + return JNIObject<jobject>(*this, NULL); } - jobjectArray array = (jobjectArray)(env)->GetObjectField(obj, field); - jobject elem = (env)->GetObjectArrayElement(array, index); - if (elem == NULL) { - THROW(env, "Error in accessing index element"); - return 0; + JNIObject<jobjectArray> array(*this, (jobjectArray)mEnv->GetObjectField(obj, field)); + JNIObject<jobject> elem(*this, mEnv->GetObjectArrayElement(array, index)); + if (elem.isNull()) { + THROW(*this, "Error in accessing index element"); + return JNIObject<jobject>(*this, NULL); } - - env->DeleteLocalRef(array); - env->DeleteLocalRef(cls); return elem; } -void setIntField(JNIEnv *env, jobject obj, const char *name, jint value) +void JNIHelper::setIntField(jobject obj, const char *name, jint value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing class"); + THROW(*this, "Error in accessing class"); return; } - jfieldID field = (env)->GetFieldID(cls, name, "I"); + jfieldID field = mEnv->GetFieldID(cls, name, "I"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetIntField(obj, field, value); - env->DeleteLocalRef(cls); + mEnv->SetIntField(obj, field, value); } -void setByteField(JNIEnv *env, jobject obj, const char *name, jbyte value) +void JNIHelper::setByteField(jobject obj, const char *name, jbyte value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing class"); + THROW(*this, "Error in accessing class"); return; } - jfieldID field = (env)->GetFieldID(cls, name, "B"); + jfieldID field = mEnv->GetFieldID(cls, name, "B"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetByteField(obj, field, value); - env->DeleteLocalRef(cls); + mEnv->SetByteField(obj, field, value); } -void setBooleanField(JNIEnv *env, jobject obj, const char *name, jboolean value) +void JNIHelper::setBooleanField(jobject obj, const char *name, jboolean value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing class"); + THROW(*this, "Error in accessing class"); return; } - jfieldID field = (env)->GetFieldID(cls, name, "Z"); + jfieldID field = mEnv->GetFieldID(cls, name, "Z"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetBooleanField(obj, field, value); - env->DeleteLocalRef(cls); + mEnv->SetBooleanField(obj, field, value); } -void setLongField(JNIEnv *env, jobject obj, const char *name, jlong value) +void JNIHelper::setLongField(jobject obj, const char *name, jlong value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing class"); + THROW(*this, "Error in accessing class"); return; } - jfieldID field = (env)->GetFieldID(cls, name, "J"); + jfieldID field = mEnv->GetFieldID(cls, name, "J"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetLongField(obj, field, value); - env->DeleteLocalRef(cls); + mEnv->SetLongField(obj, field, value); } -void setStaticLongField(JNIEnv *env, jobject obj, const char *name, jlong value) +void JNIHelper::setStaticLongField(jobject obj, const char *name, jlong value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing class"); + THROW(*this, "Error in accessing class"); return; } - setStaticLongField(env, cls, name, value); - env->DeleteLocalRef(cls); + setStaticLongField(cls, name, value); } -void setStaticLongField(JNIEnv *env, jclass cls, const char *name, jlong value) +void JNIHelper::setStaticLongField(jclass cls, const char *name, jlong value) { - jfieldID field = (env)->GetStaticFieldID(cls, name, "J"); + jfieldID field = mEnv->GetStaticFieldID(cls, name, "J"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetStaticLongField(cls, field, value); + mEnv->SetStaticLongField(cls, field, value); } -void setLongArrayField(JNIEnv *env, jobject obj, const char *name, jlongArray value) +void JNIHelper::setLongArrayField(jobject obj, const char *name, jlongArray value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; - } else { - ALOGD("cls = %p", cls); } - jfieldID field = (env)->GetFieldID(cls, name, "[J"); + jfieldID field = mEnv->GetFieldID(cls, name, "[J"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetObjectField(obj, field, value); - ALOGD("array field set"); - - env->DeleteLocalRef(cls); + mEnv->SetObjectField(obj, field, value); } -void setStaticLongArrayField(JNIEnv *env, jobject obj, const char *name, jlongArray value) +void JNIHelper::setStaticLongArrayField(jobject obj, const char *name, jlongArray value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; - } else { - ALOGD("cls = %p", cls); } - setStaticLongArrayField(env, cls, name, value); - env->DeleteLocalRef(cls); + setStaticLongArrayField(cls, name, value); } -void setStaticLongArrayField(JNIEnv *env, jclass cls, const char *name, jlongArray value) +void JNIHelper::setStaticLongArrayField(jclass cls, const char *name, jlongArray value) { - jfieldID field = (env)->GetStaticFieldID(cls, name, "[J"); + jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetStaticObjectField(cls, field, value); + mEnv->SetStaticObjectField(cls, field, value); ALOGD("array field set"); } -void setLongArrayElement(JNIEnv *env, jobject obj, const char *name, int index, jlong value) +void JNIHelper::setLongArrayElement(jobject obj, const char *name, int index, jlong value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; - } else { - ALOGD("cls = %p", cls); } - jfieldID field = (env)->GetFieldID(cls, name, "[J"); + jfieldID field = mEnv->GetFieldID(cls, name, "[J"); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; - } else { - ALOGD("field = %p", field); } - jlongArray array = (jlongArray)(env)->GetObjectField(obj, field); + JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetObjectField(obj, field)); if (array == NULL) { - THROW(env, "Error in accessing array"); + THROW(*this, "Error in accessing array"); return; - } else { - ALOGD("array = %p", array); } - jlong *elem = (env)->GetLongArrayElements(array, NULL); + jlong *elem = mEnv->GetLongArrayElements(array, NULL); if (elem == NULL) { - THROW(env, "Error in accessing index element"); + THROW(*this, "Error in accessing index element"); return; } elem[index] = value; - env->ReleaseLongArrayElements(array, elem, 0); - env->DeleteLocalRef(array); - env->DeleteLocalRef(cls); + mEnv->ReleaseLongArrayElements(array, elem, 0); } -void setObjectField(JNIEnv *env, jobject obj, const char *name, const char *type, jobject value) +void JNIHelper::setObjectField(jobject obj, const char *name, const char *type, jobject value) { - jclass cls = (env)->GetObjectClass(obj); + JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); if (cls == NULL) { - THROW(env, "Error in accessing class"); + THROW(*this, "Error in accessing class"); return; } - jfieldID field = (env)->GetFieldID(cls, name, type); + jfieldID field = mEnv->GetFieldID(cls, name, type); if (field == NULL) { - THROW(env, "Error in accessing field"); + THROW(*this, "Error in accessing field"); return; } - (env)->SetObjectField(obj, field, value); - env->DeleteLocalRef(cls); + mEnv->SetObjectField(obj, field, value); } -jboolean setStringField(JNIEnv *env, jobject obj, const char *name, const char *value) +jboolean JNIHelper::setStringField(jobject obj, const char *name, const char *value) { + JNIObject<jstring> str(*this, mEnv->NewStringUTF(value)); - jstring str = env->NewStringUTF(value); - - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - env->ExceptionClear(); + if (mEnv->ExceptionCheck()) { + mEnv->ExceptionDescribe(); + mEnv->ExceptionClear(); return false; } if (str == NULL) { - ALOGE("Error in string allocation"); + THROW(*this, "Error creating string"); return false; } - setObjectField(env, obj, name, "Ljava/lang/String;", str); - env->DeleteLocalRef(str); + setObjectField(obj, name, "Ljava/lang/String;", str); return true; } -void reportEvent(JNIEnv *env, jclass cls, const char *method, const char *signature, ...) +void JNIHelper::reportEvent(jclass cls, const char *method, const char *signature, ...) { va_list params; va_start(params, signature); - jmethodID methodID = env->GetStaticMethodID(cls, method, signature); - if (methodID == NULL) { + jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature); + if (methodID == 0) { ALOGE("Error in getting method ID"); return; } - env->CallStaticVoidMethodV(cls, methodID, params); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - env->ExceptionClear(); + mEnv->CallStaticVoidMethodV(cls, methodID, params); + if (mEnv->ExceptionCheck()) { + mEnv->ExceptionDescribe(); + mEnv->ExceptionClear(); + } + + va_end(params); +} + +jboolean JNIHelper::callStaticMethod(jclass cls, const char *method, const char *signature, ...) +{ + va_list params; + va_start(params, signature); + + jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature); + if (methodID == 0) { + ALOGE("Error in getting method ID"); + return false; + } + + jboolean result = mEnv->CallStaticBooleanMethodV(cls, methodID, params); + if (mEnv->ExceptionCheck()) { + mEnv->ExceptionDescribe(); + mEnv->ExceptionClear(); + return false; } + va_end(params); + return result; } -jobject createObject(JNIEnv *env, const char *className) +JNIObject<jobject> JNIHelper::createObject(const char *className) { - jclass cls = env->FindClass(className); + JNIObject<jclass> cls(*this, mEnv->FindClass(className)); if (cls == NULL) { ALOGE("Error in finding class %s", className); - return NULL; + return JNIObject<jobject>(*this, NULL); } - jmethodID constructor = env->GetMethodID(cls, "<init>", "()V"); - if (constructor == NULL) { + jmethodID constructor = mEnv->GetMethodID(cls, "<init>", "()V"); + if (constructor == 0) { ALOGE("Error in constructor ID for %s", className); - return NULL; + return JNIObject<jobject>(*this, NULL); } - jobject obj = env->NewObject(cls, constructor); + + JNIObject<jobject> obj(*this, mEnv->NewObject(cls, constructor)); if (obj == NULL) { ALOGE("Could not create new object of %s", className); - return NULL; + return JNIObject<jobject>(*this, NULL); } - env->DeleteLocalRef(cls); return obj; } -jobjectArray createObjectArray(JNIEnv *env, const char *className, int num) +JNIObject<jobjectArray> JNIHelper::createObjectArray(const char *className, int num) { - jclass cls = env->FindClass(className); + JNIObject<jclass> cls(*this, mEnv->FindClass(className)); if (cls == NULL) { ALOGE("Error in finding class %s", className); - return NULL; + return JNIObject<jobjectArray>(*this, NULL); } - jobjectArray array = env->NewObjectArray(num, cls, NULL); - if (array == NULL) { + JNIObject<jobject> array(*this, mEnv->NewObjectArray(num, cls.get(), NULL)); + if (array.get() == NULL) { ALOGE("Error in creating array of class %s", className); - return NULL; + return JNIObject<jobjectArray>(*this, NULL); } - env->DeleteLocalRef(cls); - return array; + return JNIObject<jobjectArray>(*this, (jobjectArray)array.detach()); +} + +JNIObject<jobject> JNIHelper::getObjectArrayElement(jobjectArray array, int index) +{ + return JNIObject<jobject>(*this, mEnv->GetObjectArrayElement(array, index)); +} + +JNIObject<jobject> JNIHelper::getObjectArrayElement(jobject array, int index) +{ + return getObjectArrayElement((jobjectArray)array, index); +} + +int JNIHelper::getArrayLength(jarray array) { + return mEnv->GetArrayLength(array); +} + +JNIObject<jobjectArray> JNIHelper::newObjectArray(int num, const char *className, jobject val) { + JNIObject<jclass> cls(*this, mEnv->FindClass(className)); + if (cls == NULL) { + ALOGE("Error in finding class %s", className); + return JNIObject<jobjectArray>(*this, NULL); + } + + return JNIObject<jobjectArray>(*this, mEnv->NewObjectArray(num, cls, val)); +} + +JNIObject<jbyteArray> JNIHelper::newByteArray(int num) { + return JNIObject<jbyteArray>(*this, mEnv->NewByteArray(num)); +} + +JNIObject<jintArray> JNIHelper::newIntArray(int num) { + return JNIObject<jintArray>(*this, mEnv->NewIntArray(num)); +} + +JNIObject<jlongArray> JNIHelper::newLongArray(int num) { + return JNIObject<jlongArray>(*this, mEnv->NewLongArray(num)); +} + +JNIObject<jstring> JNIHelper::newStringUTF(const char *utf) { + return JNIObject<jstring>(*this, mEnv->NewStringUTF(utf)); +} + +void JNIHelper::setObjectArrayElement(jobjectArray array, int index, jobject obj) { + mEnv->SetObjectArrayElement(array, index, obj); +} + +void JNIHelper::setByteArrayRegion(jbyteArray array, int from, int to, jbyte *bytes) { + mEnv->SetByteArrayRegion(array, from, to, bytes); +} + +void JNIHelper::setIntArrayRegion(jintArray array, int from, int to, jint *ints) { + mEnv->SetIntArrayRegion(array, from, to, ints); +} + +void JNIHelper::setLongArrayRegion(jlongArray array, int from, int to, jlong *longs) { + mEnv->SetLongArrayRegion(array, from, to, longs); } }; // namespace android diff --git a/service/jni/jni_helper.h b/service/jni/jni_helper.h index 5393efec0..834b0ac5f 100644 --- a/service/jni/jni_helper.h +++ b/service/jni/jni_helper.h @@ -3,33 +3,158 @@ namespace android { /* JNI Helpers for wifi_hal to WifiNative bridge implementation */ -void throwException( JNIEnv *env, const char *message, int line ); -jboolean getBoolField(JNIEnv *env, jobject obj, const char *name); -jint getIntField(JNIEnv *env, jobject obj, const char *name); -jlong getLongField(JNIEnv *env, jobject obj, const char *name); -jobject getObjectField(JNIEnv *env, jobject obj, const char *name, const char *type); -jlong getLongArrayField(JNIEnv *env, jobject obj, const char *name, int index); -jobject getObjectArrayField(JNIEnv *env, jobject obj, const char *name, const char *type, int index); -void setIntField(JNIEnv *env, jobject obj, const char *name, jint value); - void setByteField(JNIEnv *env, jobject obj, const char *name, jbyte value); - jbyte getByteField(JNIEnv *env, jobject obj, const char *name); -void setBooleanField(JNIEnv *env, jobject obj, const char *name, jboolean value); -void setLongField(JNIEnv *env, jobject obj, const char *name, jlong value); -void setLongArrayField(JNIEnv *env, jobject obj, const char *name, jlongArray value); -void setLongArrayElement(JNIEnv *env, jobject obj, const char *name, int index, jlong value); -jboolean setStringField(JNIEnv *env, jobject obj, const char *name, const char *value); -void reportEvent(JNIEnv *env, jclass cls, const char *method, const char *signature, ...); -jobject createObject(JNIEnv *env, const char *className); -jobjectArray createObjectArray(JNIEnv *env, const char *className, int size); -void setObjectField(JNIEnv *env, jobject obj, const char *name, const char *type, jobject value); - -jlong getStaticLongField(JNIEnv *env, jobject obj, const char *name); -jlong getStaticLongField(JNIEnv *env, jclass cls, const char *name); -void setStaticLongField(JNIEnv *env, jobject obj, const char *name, jlong value); -void setStaticLongField(JNIEnv *env, jclass cls, const char *name, jlong value); -jlong getStaticLongArrayField(JNIEnv *env, jobject obj, const char *name, int index); -jlong getStaticLongArrayField(JNIEnv *env, jclass cls, const char *name, int index); -void setStaticLongArrayField(JNIEnv *env, jobject obj, const char *name, jlongArray value); -void setStaticLongArrayField(JNIEnv *env, jclass obj, const char *name, jlongArray value); +class JNIHelper; + +template<typename T> +class JNIObject { +protected: + JNIHelper &mHelper; + T mObj; +public: + JNIObject(JNIHelper &helper, T obj); + JNIObject(const JNIObject<T>& rhs); + virtual ~JNIObject(); + JNIHelper& getHelper() const { + return mHelper; + } + T get() const { + return mObj; + } + operator T() const { + return mObj; + } + bool isNull() const { + return mObj == NULL; + } + void release(); + T detach() { + T tObj = mObj; + mObj = NULL; + return tObj; + } + T clone(); + JNIObject<T>& operator = (const JNIObject<T>& rhs) { + release(); + mHelper = rhs.mHelper; + mObj = rhs.mObj; + return *this; + } + void print() { + ALOGD("holding %p", mObj); + } + +private: + template<typename T2> + JNIObject(const JNIObject<T2>& rhs); +}; + +class JNIHelper { + JavaVM *mVM; + JNIEnv *mEnv; + +public : + JNIHelper(JavaVM *vm); + JNIHelper(JNIEnv *env); + ~JNIHelper(); + + void throwException(const char *message, int line); + + /* helpers to deal with members */ + jboolean getBoolField(jobject obj, const char *name); + jint getIntField(jobject obj, const char *name); + jlong getLongField(jobject obj, const char *name); + JNIObject<jstring> getStringField(jobject obj, const char *name); + bool getStringFieldValue(jobject obj, const char *name, char *buf, int size); + JNIObject<jobject> getObjectField(jobject obj, const char *name, const char *type); + JNIObject<jobjectArray> getArrayField(jobject obj, const char *name, const char *type); + jlong getLongArrayField(jobject obj, const char *name, int index); + JNIObject<jobject> getObjectArrayField( + jobject obj, const char *name, const char *type, int index); + void setIntField(jobject obj, const char *name, jint value); + void setByteField(jobject obj, const char *name, jbyte value); + jbyte getByteField(jobject obj, const char *name); + void setBooleanField(jobject obj, const char *name, jboolean value); + void setLongField(jobject obj, const char *name, jlong value); + void setLongArrayField(jobject obj, const char *name, jlongArray value); + void setLongArrayElement(jobject obj, const char *name, int index, jlong value); + jboolean setStringField(jobject obj, const char *name, const char *value); + void reportEvent(jclass cls, const char *method, const char *signature, ...); + JNIObject<jobject> createObject(const char *className); + JNIObject<jobjectArray> createObjectArray(const char *className, int size); + void setObjectField(jobject obj, const char *name, const char *type, jobject value); + + /* helpers to deal with static members */ + jlong getStaticLongField(jobject obj, const char *name); + jlong getStaticLongField(jclass cls, const char *name); + void setStaticLongField(jobject obj, const char *name, jlong value); + void setStaticLongField(jclass cls, const char *name, jlong value); + jlong getStaticLongArrayField(jobject obj, const char *name, int index); + jlong getStaticLongArrayField(jclass cls, const char *name, int index); + void setStaticLongArrayField(jobject obj, const char *name, jlongArray value); + void setStaticLongArrayField(jclass obj, const char *name, jlongArray value); + jboolean callStaticMethod(jclass cls, const char *method, const char *signature, ...); + + JNIObject<jobject> getObjectArrayElement(jobjectArray array, int index); + JNIObject<jobject> getObjectArrayElement(jobject array, int index); + int getArrayLength(jarray array); + JNIObject<jobjectArray> newObjectArray(int num, const char *className, jobject val); + JNIObject<jbyteArray> newByteArray(int num); + JNIObject<jintArray> newIntArray(int num); + JNIObject<jlongArray> newLongArray(int num); + JNIObject<jstring> newStringUTF(const char *utf); + void setObjectArrayElement(jobjectArray array, int index, jobject obj); + void setByteArrayRegion(jbyteArray array, int from, int to, jbyte *bytes); + void setIntArrayRegion(jintArray array, int from, int to, jint *ints); + void setLongArrayRegion(jlongArray array, int from, int to, jlong *longs); + + jobject newGlobalRef(jobject obj); + void deleteGlobalRef(jobject obj); + +private: + /* Jni wrappers */ + friend class JNIObject<jobject>; + friend class JNIObject<jstring>; + friend class JNIObject<jobjectArray>; + friend class JNIObject<jclass>; + friend class JNIObject<jlongArray>; + friend class JNIObject<jbyteArray>; + friend class JNIObject<jintArray>; + jobject newLocalRef(jobject obj); + void deleteLocalRef(jobject obj); +}; + +template<typename T> +JNIObject<T>::JNIObject(JNIHelper &helper, T obj) + : mHelper(helper), mObj(obj) +{ } + +template<typename T> +JNIObject<T>::JNIObject(const JNIObject<T>& rhs) + : mHelper(rhs.mHelper), mObj(NULL) +{ + mObj = (T)mHelper.newLocalRef(rhs.mObj); +} + +template<typename T> +JNIObject<T>::~JNIObject() { + release(); +} + +template<typename T> +void JNIObject<T>::release() +{ + if (mObj != NULL) { + mHelper.deleteLocalRef(mObj); + mObj = NULL; + } } -#define THROW(env, message) throwException(env, message, __LINE__) + +template<typename T> +T JNIObject<T>::clone() +{ + return mHelper.newLocalRef(mObj); +} + +} + +#define THROW(env, message) (env).throwException(message, __LINE__) |