// // Created by Fear1ess on 2021/4/2. // #include "collect.h" #include "wd_jni.h" #include "utils.h" #include <stdlib.h> #include "wd_result.h" #include "wdun.h" #include <fcntl.h> #include <string.h> #include <time.h> #include <unistd.h> #include <sys/mman.h> #include <sys/sysinfo.h> #include <sys/statfs.h> #include "openssl/md5.h" #include <arpa/inet.h> #include <sys/syscall.h> #include <linux/prctl.h> #define WD_COLLECT "wd_collect" extern jobject g_app_context; extern struct wd_funcs g_funcs; IMPORTWDSYSCALL cJSON *collect_init() { return cJSON_CreateObject(); } void do_collect(JNIEnv* env) { cJSON* json = collect_init(); struct timespec ts = {0}; double start_time = 0, end_time = 0; if(WDSYSCALL(SYS_clock_gettime, CLOCK_MONOTONIC, &ts) == 0) { start_time = ts.tv_nsec / 1000000 + ts.tv_sec * 1000ULL; } collect_app_info(env, json); int permissions = collect_permissions(env, json); collect_imei(env, json); collect_android_id(env, json); collect_mac_addr(env, json); collect_build_info(env, json); collect_prop_info(env, json); collect_settings_info(env, json); collect_display_info(env, json); collect_proxy_info(env, json); collect_camera_info(env, json); collect_battery_info(env, json); collect_env(env, json); collect_libs_info(env, json); collect_cpu_info(env, json); collect_sensor_info(env, json); collect_mem_info(env, json); collect_network_info(env, json); collect_user_agent(env, json); if((permissions & PERMISSION_ACCESS_FINE_LOCATION) && (permissions & PERMISSION_ACCESS_COARSE_LOCATION)) { collect_location_info(env, json); } if((permissions & PERMISSION_READ_PHONE_STATE) && (permissions & PERMISSION_ACCESS_COARSE_LOCATION)) { collect_cell_info(env, json); } if(WDSYSCALL(SYS_clock_gettime, CLOCK_MONOTONIC, &ts) == 0) { end_time = (double)ts.tv_nsec / 1000000 + (double)ts.tv_sec * 1000ULL; } char srt[32] = {0}; snprintf(srt, 31, "%.2lf", end_time - start_time); cJSON_AddStringToObject(json, "srt", srt); const char* data = cJSON_Print(json); size_t len = strlen(data); int fd = WDSYSCALL(SYS_openat, AT_FDCWD, "/sdcard/wd_data", O_CREAT|O_RDWR|O_TRUNC, S_IRWXU); WDSYSCALL(SYS_write, fd, data, len); WDSYSCALL(SYS_close, fd); } void collect_app_info(JNIEnv* env, cJSON *json) { if((*env)->PushLocalFrame(env, 20) != JNI_OK) { loge(WD_COLLECT, "%s", "collect_app_info func call env->pushLocalFrame failed!"); return; } //package_name jobject pkgName = wdCallObjectMethod(env, g_app_context, "getPackageName", "()Ljava/lang/String;"); addJniStringToJson(env, json, "package_name", pkgName); //get packagemanager and pkginfo jobject pkgManager = wdCallObjectMethod(env, g_app_context, "getPackageManager", "()Landroid/content/pm/PackageManager;"); jobject pkgInfo = wdCallObjectMethod(env, pkgManager, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;", pkgName, 0x40); //last update time jlong lastUpdateTime = wdGetLongField(env, pkgInfo, "lastUpdateTime", "J"); cJSON_AddNumberToObject(json, "last_update_time", lastUpdateTime); //first install time jlong firstInstallTime = wdGetLongField(env, pkgInfo, "firstInstallTime", "J"); cJSON_AddNumberToObject(json, "first_install_time", firstInstallTime); //version code jint versionCode = wdGetIntField(env, pkgInfo, "versionCode", "I"); cJSON_AddNumberToObject(json, "ver_code", versionCode); //version name jobject versionName = wdGetObjectField(env, pkgInfo, "versionName", "Ljava/lang/String;"); addJniStringToJson(env, json, "versionName", versionName); //signature's sha256 jobject signatures = wdGetObjectField(env, pkgInfo, "signatures", "[Landroid/content/pm/Signature;"); jobject sig_item0 = (*env)->GetObjectArrayElement(env, signatures, 0); jobject signature = wdCallObjectMethod(env, sig_item0, "toCharsString", "()Ljava/lang/String;"); char* sha256 = (char*)malloc(64 + 1); getJniStringSha256(env, signature, sha256); cJSON_AddStringToObject(json, "signature_sha256", sha256); //app label jobject aiInfo = wdCallObjectMethod(env, g_app_context, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;"); jobject label = wdCallObjectMethod(env, pkgManager, "getApplicationLabel", "(Landroid/content/pm/ApplicationInfo;)Ljava/lang/CharSequence;", aiInfo); addJniStringToJson(env, json, "app_label", label); //app_debug & app_backup jint flags = wdGetIntField(env, aiInfo, "flags", "I"); cJSON_AddNumberToObject(json, "app_debug", (flags & (1 << 1)) ? 1 : 0); cJSON_AddNumberToObject(json, "app_backup", (flags & (1 << 15)) ? 1 : 0); logd(WD_COLLECT, "%s", "collect app info finished..."); (*env)->PopLocalFrame(env, NULL); } int collect_permissions(JNIEnv* env, cJSON* json) { int value = 0; const char* permissions[] = { "android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_PHONE_STATE", "android.permission.ACCESS_NETWORK_STATE", "android.permission.ACCESS_WIFI_STATE", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION" }; for(int i = 0; i < sizeof(permissions)/sizeof(const char*); ++i) { jstring str = (*env)->NewStringUTF(env, permissions[i]); if(wdCallIntMethod(env, g_app_context, "checkSelfPermission", "(Ljava/lang/String;)I", str) == 0) { value |= (1 << i); } (*env)->DeleteLocalRef(env, str); } return value; } void collect_imei(JNIEnv *env, cJSON *json) { //get imei from telephonymanager jstring phone_str = (*env)->NewStringUTF(env, "phone"); jobject tm = wdCallObjectMethod(env, g_app_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", phone_str); jobject imei_str = wdCallObjectMethod(env, tm, "getDeviceId", "()Ljava/lang/String;"); addJniStringToJson(env, json, "imei", imei_str); (*env)->DeleteLocalRef(env, phone_str); (*env)->DeleteLocalRef(env, tm); (*env)->DeleteLocalRef(env, imei_str); logd(WD_COLLECT, "%s", "collect imei finished..."); } void collect_android_id(JNIEnv* env, cJSON* json) { jstring key_str = (*env)->NewStringUTF(env, "android_id"); jobject cr = wdCallObjectMethod(env, g_app_context, "getContentResolver", "()Landroid/content/ContentResolver;"); jobject androidId_jstr = wdCallStaticObjectMethod(env, "android/provider/Settings$Secure", "getString", "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;", cr, key_str); addJniStringToJson(env, json, "android_id", androidId_jstr); (*env)->DeleteLocalRef(env, key_str); (*env)->DeleteLocalRef(env, cr); (*env)->DeleteLocalRef(env, androidId_jstr); logd(WD_COLLECT, "%s", "collect android_id finished..."); } void collect_mac_addr(JNIEnv *env, cJSON *json) { // //above android 11.0+ can't get mac by this method jstring name_str = (*env)->NewStringUTF(env, "wlan0"); jobject ni = wdCallStaticObjectMethod(env, "java/net/NetworkInterface", "getByName", "(Ljava/lang/String;)Ljava/net/NetworkInterface;", name_str); jbyteArray mac_byteArr = wdCallObjectMethod(env, ni, "getHardwareAddress", "()[B"); if(mac_byteArr == NULL) { cJSON_AddStringToObject(json, "mac_addr", ""); goto return_label; } jsize size = (*env)->GetArrayLength(env, mac_byteArr); jbyte* bytes = (*env)->GetByteArrayElements(env, mac_byteArr, NULL); char* out = (char*) malloc(size * 3); bytes2Hex((const uint8_t*)bytes, out, size, 1); cJSON_AddStringToObject(json, "mac_addr", out); free(out); (*env)->ReleaseByteArrayElements(env, mac_byteArr, bytes, 0); (*env)->DeleteLocalRef(env, mac_byteArr); return_label: (*env)->DeleteLocalRef(env, ni); (*env)->DeleteLocalRef(env, name_str); char* mac_addr2 = ""; int fd = WDSYSCALL(SYS_openat, AT_FDCWD, "/sys/class/net/wlan0/address", O_RDONLY, NULL); if(fd > 0) { char buf[32] = {0}; if(WDSYSCALL(SYS_read, fd, buf, 32) > 0) { mac_addr2 = buf; } } cJSON_AddStringToObject(json, "mac_addr2", mac_addr2); logd(WD_COLLECT, "%s", "collect mac_addr finished..."); } void collect_build_info(JNIEnv *env, cJSON *json) { if((*env)->PushLocalFrame(env, 20) != JNI_OK) { loge(WD_COLLECT, "%s", "collect_build_info func call env->pushLocalFrame failed!"); return; } const char* build_key[] = {"SERIAL", "BOARD", "BOOTLOADER", "CPU_ABI", "CPU_ABI2", "DEVICE", "DISPLAY", "FINGERPRINT", "HARDWARE", "HOST", "ID", "MANUFACTURER", "MODEL", "PRODUCT", "BRAND"}; cJSON* bi_json = cJSON_CreateObject(); for(int i = 0; i < sizeof(build_key)/sizeof(const char*); ++i) { jobject jstr = wdGetStaticObjectField(env, "android/os/Build", build_key[i], "Ljava/lang/String;"); addJniStringToJson(env, bi_json, build_key[i], jstr); } cJSON_AddItemToObject(json, "build", bi_json); (*env)->PopLocalFrame(env, NULL); logd(WD_COLLECT, "%s", "collect build_info finished..."); } void collect_prop_info(JNIEnv* env, cJSON* json) { if(g_funcs.wd_system_property_get == NULL) return; cJSON* pi_json = cJSON_CreateObject(); const char* prop_key[] = {"wifi.interface", "gsm.sim.state", "gsm.version.baseband", "gsm.version.ril-impl", "gsm.current.phone-type", "gsm.operator.isroaming", "gsm.network.type", "persist.sys.timezone", "init.svc.adbd", "ro.build.date.utc", "gsm.operator.alpha", "ro.opengles.version"}; char buf[64]; for(int i = 0; i < sizeof(prop_key)/sizeof(const char*); ++i) { memset((void*)buf, 0, 64); g_funcs.wd_system_property_get(prop_key[i], buf); cJSON_AddStringToObject(pi_json, prop_key[i], buf); } cJSON_AddItemToObject(json, "prop", pi_json); logd(WD_COLLECT, "%s", "collect prop_info finished..."); } void collect_settings_info(JNIEnv *env, cJSON *json) { const char* settings_secure_key[] = {"usb_mass_storage_enabled", "development_settings_enabled", "lock_pattern_autolock", "lock_pattern_visible_pattern"}; const char* settings_system_key[] = {"screen_brightness", "accelerometer_rotation", "screen_brightness_mode", "sound_effects_enabled", "screen_off_timeout"}; cJSON* si_json = cJSON_CreateObject(); for(int i = 0; i < sizeof(settings_secure_key)/sizeof(const char*); ++i) { jstring key_str = (*env)->NewStringUTF(env, settings_secure_key[i]); jobject cr = wdCallObjectMethod(env, g_app_context, "getContentResolver", "()Landroid/content/ContentResolver;"); jobject jstr = wdCallStaticObjectMethod(env, "android/provider/Settings$Secure", "getString", "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;", cr, key_str); addJniStringToJson(env, si_json, settings_secure_key[i], jstr); (*env)->DeleteLocalRef(env, key_str); (*env)->DeleteLocalRef(env, cr); (*env)->DeleteLocalRef(env, jstr); } for(int j = 0; j < sizeof(settings_system_key)/sizeof(const char*); ++j) { jstring key_str = (*env)->NewStringUTF(env, settings_system_key[j]); jobject cr = wdCallObjectMethod(env, g_app_context, "getContentResolver", "()Landroid/content/ContentResolver;"); jint value = wdCallStaticIntMethod(env, "android/provider/Settings$System", "getInt", "(Landroid/content/ContentResolver;Ljava/lang/String;)I", cr, key_str); cJSON_AddNumberToObject(si_json, settings_system_key[j], value); (*env)->DeleteLocalRef(env, key_str); (*env)->DeleteLocalRef(env, cr); } cJSON_AddItemToObject(json, "settings", si_json); logd(WD_COLLECT, "%s", "collect settings_info finished..."); } void collect_display_info(JNIEnv *env, cJSON *json) { cJSON* di_json = cJSON_CreateObject(); jobject rc = wdCallObjectMethod(env, g_app_context, "getResources", "()Landroid/content/res/Resources;"); jobject dm = wdCallObjectMethod(env, rc, "getDisplayMetrics", "()Landroid/util/DisplayMetrics;"); jint height = wdGetIntField(env, dm, "heightPixels", "I"); jint width = wdGetIntField(env, dm, "widthPixels", "I"); jint dpi = wdGetIntField(env, dm, "densityDpi", "I"); cJSON_AddNumberToObject(di_json, "height", height); cJSON_AddNumberToObject(di_json, "width", width); cJSON_AddNumberToObject(di_json, "dpi", dpi); cJSON_AddItemToObject(json, "display", di_json); (*env)->DeleteLocalRef(env, rc); (*env)->DeleteLocalRef(env, dm); logd(WD_COLLECT, "%s", "collect display_info finished..."); } void collect_proxy_info(JNIEnv *env, cJSON *json) { if(g_funcs.wd_system_property_get == NULL) return; cJSON* proxy_json = cJSON_CreateObject(); const char* prop_key[] = {"http.proxyHost", "http.proxyPort"}; char buf[32]; for(int i = 0; i < sizeof(prop_key)/sizeof(const char*); ++i) { memset((void*)buf, 0, 32); g_funcs.wd_system_property_get(prop_key[i], buf); cJSON_AddStringToObject(proxy_json, prop_key[i], buf); } cJSON_AddItemToObject(json, "proxy", proxy_json); logd(WD_COLLECT, "%s", "collect proxy_info finished..."); } void collect_camera_info(JNIEnv *env, cJSON *json) { //todo } void collect_battery_info(JNIEnv *env, cJSON *json) { cJSON* item_json = cJSON_CreateObject(); //get battery capacity jobject power_profile = wdNewObject(env, "com/android/internal/os/PowerProfile", "(Landroid/content/Context;)V", g_app_context); jstring ca_jstr = (*env)->NewStringUTF(env, "battery.capacity"); jdouble capacity = wdCallDoubleMethod(env, power_profile, "getAveragePower", "(Ljava/lang/String;)D", ca_jstr); cJSON_AddNumberToObject(item_json, "capacity", capacity); (*env)->DeleteLocalRef(env, power_profile); (*env)->DeleteLocalRef(env, ca_jstr); jobject action_jstr = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED"); jobject intent_filter = wdNewObject(env, "android/content/IntentFilter", "(Ljava/lang/String;)V", action_jstr); jobject intent = wdCallObjectMethod(env, g_app_context, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;", NULL, intent_filter); const char* key[] = {"status", "plugged", "level", "scale", "voltage", "temperature"}; for(int i = 0; i < sizeof(key)/sizeof(const char*); ++i) { jstring key_str = (*env)->NewStringUTF(env, key[i]); jint value = wdCallIntMethod(env, intent, "getIntExtra", "(Ljava/lang/String;I)I", key_str, -1); cJSON_AddNumberToObject(item_json, key[i], value); (*env)->DeleteLocalRef(env, key_str); } cJSON_AddItemToObject(json, "battery", item_json); (*env)->DeleteLocalRef(env, action_jstr); (*env)->DeleteLocalRef(env, intent_filter); (*env)->DeleteLocalRef(env, intent); logd(WD_COLLECT, "%s", "collect battery_info finished..."); } void collect_env(JNIEnv *env, cJSON *json) { //todo } void collect_libs_info(JNIEnv *env, cJSON *json) { cJSON* item = cJSON_CreateObject(); const char* lib_names[] = {"libwdun.so", "libc.so"}; int pid = WDSYSCALL(SYS_getpid); for(int j = 0; j < sizeof(lib_names)/sizeof(const char*); ++j) { char cmd[64] = {0}; char line[1024] = {0}; snprintf(cmd, 63, "cat /proc/%d/maps | grep %s", pid, lib_names[j]); FILE *fp = g_funcs.wd_popen(cmd, "r"); if(fgets(line, 1024, fp)) { int pos = 0; sscanf(line, "%*lx-%*lx %*4s %*lx %*lx:%*lx %*d%n", &pos); char* path = wd_util_trim(line + pos); int fd = WDSYSCALL(SYS_openat, AT_FDCWD, path, O_RDONLY, 0); if(fd < 0) break; int size = lseek(fd, 0, SEEK_END); //映射内存 int mmap_call_num = 222; uint8_t* base = (uint8_t*) WDSYSCALL(WD_SYS_mmap, 0, size, PROT_READ, MAP_SHARED, fd, 0); uint8_t out[16] = {0}; char md5_str[33] = {0}; MD5(base, size, out); bytes2Hex(out, md5_str, 16, 0); cJSON_AddStringToObject(item, lib_names[j], md5_str); //取消内存映射 WDSYSCALL(SYS_munmap, base, size); //关闭文件 WDSYSCALL(SYS_close, fd); } g_funcs.wd_pclose(fp); } cJSON_AddItemToObject(json, "libs", item); logd(WD_COLLECT, "%s", "collect libs_md5 finished..."); } void collect_cpu_info(JNIEnv *env, cJSON *json) { //todo } void collect_sensor_info(JNIEnv *env, cJSON *json) { cJSON *item = cJSON_CreateArray(); jstring sm_str = (*env)->NewStringUTF(env, "sensor"); jobject sm = wdCallObjectMethod(env, g_app_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", sm_str); jobject sensor_list = wdCallObjectMethod(env, sm, "getSensorList", "(I)Ljava/util/List;", -1); jint size = wdCallIntMethod(env, sensor_list, "size", "()I"); for (int i = 0; i < size; ++i) { jobject sensor = wdCallObjectMethod(env, sensor_list, "get", "(I)Ljava/lang/Object;", i); jint type = wdCallIntMethod(env, sensor, "getType", "()I"); jobject name_jstr = wdCallObjectMethod(env, sensor, "getName", "()Ljava/lang/String;"); jobject vendor_jstr = wdCallObjectMethod(env, sensor, "getVendor", "()Ljava/lang/String;"); const char *name = (*env)->GetStringUTFChars(env, name_jstr, NULL); const char *vendor = (*env)->GetStringUTFChars(env, vendor_jstr, NULL); char buf[256] = {0}; snprintf(buf, 255, "%d, %s, %s", type, name, vendor); cJSON_AddItemToArray(item, cJSON_CreateString(buf)); (*env)->ReleaseStringUTFChars(env, name_jstr, name); (*env)->ReleaseStringUTFChars(env, vendor_jstr, vendor); (*env)->DeleteLocalRef(env, sensor); } (*env)->DeleteLocalRef(env, sensor_list); (*env)->DeleteLocalRef(env, sm); (*env)->DeleteLocalRef(env, sm_str); cJSON_AddItemToObject(json, "sensor", item); logd(WD_COLLECT, "%s", "collect sensor_info finished..."); } void collect_mem_info(JNIEnv *env, cJSON *json) { cJSON* item = cJSON_CreateObject(); //get ram struct sysinfo si; if(WDSYSCALL(SYS_sysinfo, &si) == 0) { double ram_total = ((double)(si.totalram * si.mem_unit)) / 1024 / 1024 / 1024; double ram_free = ((double)(si.freeram * si.mem_unit)) / 1024 / 1024 / 1024; char ram_buf[32] = {0}; snprintf(ram_buf, 31, "%.3lf, %.3lf", ram_total, ram_free); cJSON_AddStringToObject(item, "ram", ram_buf); } //get rom struct statfs sf; if(WDSYSCALL(SYS_statfs, "/data", &sf) == 0) { double rom_total = ((double)(sf.f_blocks * sf.f_bsize)) / 1024 / 1024 / 1024; double rom_free = ((double)(sf.f_bfree * sf.f_bsize)) / 1024 / 1024 / 1024; char rom_buf[32] = {0}; snprintf(rom_buf, 31, "%.3lf, %.3lf", rom_total, rom_free); cJSON_AddStringToObject(item, "rom", rom_buf); } //get sdcard struct statfs sf2; if(WDSYSCALL(SYS_statfs, "/sdcard", &sf2) == 0) { double sdcard_total = ((double)(sf2.f_blocks * sf2.f_bsize)) / 1024 / 1024 / 1024; double sdcard_free = ((double)(sf2.f_bfree * sf2.f_bsize)) / 1024 / 1024 / 1024; char sdcard_buf[32] = {0}; snprintf(sdcard_buf, 31, "%.3lf, %.3lf", sdcard_total, sdcard_free); cJSON_AddStringToObject(item, "sdcard", sdcard_buf); } cJSON_AddItemToObject(json, "mem", item); logd(WD_COLLECT, "%s", "collect mem_info finished..."); } void collect_network_info(JNIEnv *env, cJSON *json) { jstring ci_jstr = (*env)->NewStringUTF(env, "connectivity"); jobject ci = wdCallObjectMethod(env, g_app_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", ci_jstr); jobject ni = wdCallObjectMethod(env, ci, "getActiveNetworkInfo", "()Landroid/net/NetworkInfo;"); if (ni == NULL) goto return_label; jint conn_type = wdCallIntMethod(env, ni, "getType", "()I"); //mobile if (conn_type == 0) { char *network_type = ""; jint sub_type = wdCallIntMethod(env, ni, "getSubtype", "()I"); switch (sub_type) { case 1 : case 2 : case 4 : case 7 : case 11 : case 16 : network_type = "2g"; break; case 3 : case 5 : case 6 : case 8 : case 9 : case 10 : case 12 : case 14 : case 15 : case 17 : network_type = "3g"; break; case 13 : case 18 : case 19 : network_type = "4g"; break; case 20 : network_type = "5g"; break; default: break; } cJSON_AddStringToObject(json, "network_type", network_type); } //wifi else if (conn_type == 1) { cJSON_AddStringToObject(json, "network_type", "wifi"); //get wifi ssid bssid ip, need ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION permission on Android high version jstring wm_jstr = (*env)->NewStringUTF(env, "wifi"); jobject wm = wdCallObjectMethod(env, g_app_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", wm_jstr); jobject wi = wdCallObjectMethod(env, wm, "getConnectionInfo", "()Landroid/net/wifi/WifiInfo;"); jobject ssid = wdCallObjectMethod(env, wi, "getSSID", "()Ljava/lang/String;"); addJniStringToJson(env, json, "ssid", ssid); (*env)->DeleteLocalRef(env, ssid); jobject bssid = wdCallObjectMethod(env, wi, "getBSSID", "()Ljava/lang/String;"); addJniStringToJson(env, json, "bssid", bssid); (*env)->DeleteLocalRef(env, bssid); jint wifi_ip_int = wdCallIntMethod(env, wi, "getIpAddress", "()I"); char wifi_ip[32] = {0}; inet_ntop(AF_INET, &wifi_ip_int, wifi_ip, 31); cJSON_AddStringToObject(json, "wifi_ip", wifi_ip); (*env)->DeleteLocalRef(env, wi); (*env)->DeleteLocalRef(env, wm); (*env)->DeleteLocalRef(env, wm_jstr); } (*env)->DeleteLocalRef(env, ni); return_label: (*env)->DeleteLocalRef(env, ci); (*env)->DeleteLocalRef(env, ci_jstr); logd(WD_COLLECT, "%s", "collect network info finished..."); } void collect_user_agent(JNIEnv *env, cJSON *json) { jobject ua_jstr = wdCallStaticObjectMethod(env, "android/webkit/WebSettings", "getDefaultUserAgent", "(Landroid/content/Context;)Ljava/lang/String;", g_app_context); addJniStringToJson(env, json, "user-agent", ua_jstr); (*env)->DeleteLocalRef(env, ua_jstr); logd(WD_COLLECT, "%s", "collect user agent finished..."); } void collect_location_info(JNIEnv *env, cJSON *json) { //get location info need ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION permission. cJSON* item = cJSON_CreateObject(); jstring loc_jstr = (*env)->NewStringUTF(env, "location"); jobject lm = wdCallObjectMethod(env, g_app_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", loc_jstr); jobject providers = wdCallObjectMethod(env, lm, "getAllProviders", "()Ljava/util/List;"); if(providers == NULL) goto return_label; jint size = wdCallIntMethod(env, providers, "size", "()I"); int get_loc = 0; for(int i = 0; i < size; ++i) { jobject provider_jstr = wdCallObjectMethod(env, providers, "get", "(I)Ljava/lang/Object;", i); //check if location provider is available if(wdCallBooleanMethod(env, lm, "isProviderEnabled", "(Ljava/lang/String;)Z", provider_jstr) == JNI_TRUE) { jobject loc = wdCallObjectMethod(env, lm, "getLastKnownLocation", "(Ljava/lang/String;)Landroid/location/Location;", provider_jstr); if(loc != NULL) { jdouble lat = wdCallDoubleMethod(env, loc, "getLatitude", "()D"); jdouble lon = wdCallDoubleMethod(env, loc, "getLongitude", "()D"); cJSON_AddNumberToObject(item, "lat", lat); cJSON_AddNumberToObject(item, "lon", lon); get_loc = 1; } (*env)->DeleteLocalRef(env, loc); } (*env)->DeleteLocalRef(env, provider_jstr); if(get_loc) break; } (*env)->DeleteLocalRef(env, providers); return_label: (*env)->DeleteLocalRef(env, lm); (*env)->DeleteLocalRef(env, loc_jstr); cJSON_AddItemToObject(json, "location", item); logd(WD_COLLECT, "%s", "collect location info finished..."); } void collect_cell_info(JNIEnv *env, cJSON *json) { //cell info need ACCESSS_COARSE_LOCATION permission cJSON* item = cJSON_CreateObject(); jstring phone_jstr = (*env)->NewStringUTF(env, "phone"); jobject tm = wdCallObjectMethod(env, g_app_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", phone_jstr); jobject cl = wdCallObjectMethod(env, tm, "getCellLocation", "()Landroid/telephony/CellLocation;"); if(cl == NULL) goto return_label; jclass gsm_cls = (*env)->FindClass(env, "android/telephony/gsm/GsmCellLocation"); if((*env)->IsInstanceOf(env, cl, gsm_cls) == JNI_TRUE) { jint cid = wdCallIntMethod(env, cl, "getCid", "()I"); jint lac = wdCallIntMethod(env, cl, "getLac", "()I"); jint psc = wdCallIntMethod(env, cl, "getPsc", "()I"); cJSON_AddNumberToObject(item, "cid", cid); cJSON_AddNumberToObject(item, "lac", lac); cJSON_AddNumberToObject(item, "psc", psc); } (*env)->DeleteLocalRef(env, gsm_cls); return_label: (*env)->DeleteLocalRef(env, cl); (*env)->DeleteLocalRef(env, tm); (*env)->DeleteLocalRef(env, phone_jstr); cJSON_AddItemToObject(json, "cell", item); logd(WD_COLLECT, "%s", "collect cell info finished..."); }