From ff10d6ebafb5ad8645473ba8629e7dace382d1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Mon, 26 Jan 2015 19:18:34 +0100 Subject: Update ics-openvpn code --- app/build.gradle | 23 ++-- .../vending/billing/IInAppBillingService.aidl | 144 --------------------- app/src/main/java/de/blinkt/openvpn/LaunchVPN.java | 32 ++--- .../de/blinkt/openvpn/core/OpenVPNService.java | 34 ++--- .../java/de/blinkt/openvpn/core/OpenVPNThread.java | 5 +- .../de/blinkt/openvpn/fragments/LogFragment.java | 2 - 6 files changed, 39 insertions(+), 201 deletions(-) delete mode 100644 app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl (limited to 'app') diff --git a/app/build.gradle b/app/build.gradle index b5c50fa4..cf20e29f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,7 +53,7 @@ def processFileInplace(file, Closure processText) { } -task checkoutStrippedIcsOpenVPN ( type: Copy ) << { +task checkoutStrippedIcsOpenVPN ( type: Copy ) { println "checkoutStrippedIcsOpenVPN" //FIXME Checkout ics-openvpn-stripped from branch "ics-openvpn-upstream" //grgit = Grgit.open(project.file('../')) @@ -62,11 +62,11 @@ task checkoutStrippedIcsOpenVPN ( type: Copy ) << { into '../ics-openvpn-stripped' } -task copyIcsOpenVPNClasses( type: Copy ) << { +task copyIcsOpenVPNClasses( type: Copy ) { println "copyIcsOpenVPNClasses" from ('../ics-openvpn-stripped/main/') { include '**/*.java' - include '**/*.aidl' + includeEmptyDirs = false filter { @@ -78,13 +78,10 @@ task copyIcsOpenVPNClasses( type: Copy ) << { filter { line -> line.replace('package de.blinkt.openvpn;', 'package de.blinkt.openvpn;\n\nimport se.leap.bitmaskclient.R;') } - filter { - line -> line.replace('package de.blinkt.openvpn.fragments;', 'package de.blinkt.openvpn.fragments;\n\nimport se.leap.bitmaskclient.R;') - } } into '.' } -task copyIcsOpenVPNXml( type: Copy ) << { +task copyIcsOpenVPNXml( type: Copy ) { println "copyIcsOpenVPNXml" from ('../ics-openvpn-stripped/main/') { include '**/strings.xml' @@ -105,7 +102,7 @@ task copyIcsOpenVPNXml( type: Copy ) << { } into '.' } -task copyIcsOpenVPNImages( type: Copy ) << { +task copyIcsOpenVPNImages( type: Copy ) { println "copyIcsOpenVPNImages" from ('../ics-openvpn-stripped/main/') { include '**/ic_filter*.png' @@ -118,7 +115,7 @@ task copyIcsOpenVPNImages( type: Copy ) << { } into '.' } -task copyIcsOpenVPNFiles( type: Copy, dependsOn: 'checkoutStrippedIcsOpenVPN' ) << { +task copyIcsOpenVPNFiles( type: Copy, dependsOn: 'checkoutStrippedIcsOpenVPN' ) { println "copyIcsOpenVPNFiles" copyIcsOpenVPNClasses.execute() copyIcsOpenVPNXml.execute() @@ -126,7 +123,7 @@ task copyIcsOpenVPNFiles( type: Copy, dependsOn: 'checkoutStrippedIcsOpenVPN' ) } // thanks to http://pleac.sourceforge.net/pleac_groovy/fileaccess.html -task removeDuplicatedStrings( dependsOn: 'copyIcsOpenVPNFiles' ) << { +task removeDuplicatedStrings( dependsOn: 'copyIcsOpenVPNFiles' ) { println "removeDuplicatedStrings" new File('app').eachFileRecurse { if(it.name.equals('strings.xml')) { @@ -145,7 +142,7 @@ task removeDuplicatedStrings( dependsOn: 'copyIcsOpenVPNFiles' ) << { } } -task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') << { +task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') { println "mergeUntranslatable" from ('../ics-openvpn-stripped/main/') { include '**/untranslatable.xml' @@ -178,7 +175,7 @@ task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') << { delete ics_openvpn_untranslatable } -task updateIcsOpenVpn( type: Copy, dependsOn: 'mergeUntranslatable') << { +task updateIcsOpenVpn( type: Copy, dependsOn: 'mergeUntranslatable') { from('../ics-openvpn-stripped/main/src/') { include 'openvpn/**/*' include 'openssl/**/*' @@ -196,4 +193,4 @@ task buildNative ( type: Exec ) { commandLine 'sh', 'misc/build-native.sh', 'USE_BREAKPAD=0', '-j 8' } -preBuild.dependsOn buildNative \ No newline at end of file +preBuild.dependsOn buildNative diff --git a/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl b/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl deleted file mode 100644 index 2a492f78..00000000 --- a/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.vending.billing; - -import android.os.Bundle; - -/** - * InAppBillingService is the service that provides in-app billing version 3 and beyond. - * This service provides the following features: - * 1. Provides a new API to get details of in-app items published for the app including - * price, type, title and description. - * 2. The purchase flow is synchronous and purchase information is available immediately - * after it completes. - * 3. Purchase information of in-app purchases is maintained within the Google Play system - * till the purchase is consumed. - * 4. An API to consume a purchase of an inapp item. All purchases of one-time - * in-app items are consumable and thereafter can be purchased again. - * 5. An API to get current purchases of the user immediately. This will not contain any - * consumed purchases. - * - * All calls will give a response code with the following possible values - * RESULT_OK = 0 - success - * RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog - * RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested - * RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase - * RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API - * RESULT_ERROR = 6 - Fatal error during the API action - * RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned - * RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned - */ -interface IInAppBillingService { - /** - * Checks support for the requested billing API version, package and in-app type. - * Minimum API version supported by this interface is 3. - * @param apiVersion the billing version which the app is using - * @param packageName the package name of the calling app - * @param type type of the in-app item being purchased "inapp" for one-time purchases - * and "subs" for subscription. - * @return RESULT_OK(0) on success, corresponding result code on failures - */ - int isBillingSupported(int apiVersion, String packageName, String type); - - /** - * Provides details of a list of SKUs - * Given a list of SKUs of a valid type in the skusBundle, this returns a bundle - * with a list JSON strings containing the productId, price, title and description. - * This API can be called with a maximum of 20 SKUs. - * @param apiVersion billing API version that the Third-party is using - * @param packageName the package name of the calling app - * @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST" - * @return Bundle containing the following key-value pairs - * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on - * failure as listed above. - * "DETAILS_LIST" with a StringArrayList containing purchase information - * in JSON format similar to: - * '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00", - * "title : "Example Title", "description" : "This is an example description" }' - */ - Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle); - - /** - * Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU, - * the type, a unique purchase token and an optional developer payload. - * @param apiVersion billing API version that the app is using - * @param packageName package name of the calling app - * @param sku the SKU of the in-app item as published in the developer console - * @param type the type of the in-app item ("inapp" for one-time purchases - * and "subs" for subscription). - * @param developerPayload optional argument to be sent back with the purchase information - * @return Bundle containing the following key-value pairs - * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on - * failure as listed above. - * "BUY_INTENT" - PendingIntent to start the purchase flow - * - * The Pending intent should be launched with startIntentSenderForResult. When purchase flow - * has completed, the onActivityResult() will give a resultCode of OK or CANCELED. - * If the purchase is successful, the result data will contain the following key-value pairs - * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on - * failure as listed above. - * "INAPP_PURCHASE_DATA" - String in JSON format similar to - * '{"orderId":"12999763169054705758.1371079406387615", - * "packageName":"com.example.app", - * "productId":"exampleSku", - * "purchaseTime":1345678900000, - * "purchaseToken" : "122333444455555", - * "developerPayload":"example developer payload" }' - * "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that - * was signed with the private key of the developer - * TODO: change this to app-specific keys. - */ - Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type, - String developerPayload); - - /** - * Returns the current SKUs owned by the user of the type and package name specified along with - * purchase information and a signature of the data to be validated. - * This will return all SKUs that have been purchased in V3 and managed items purchased using - * V1 and V2 that have not been consumed. - * @param apiVersion billing API version that the app is using - * @param packageName package name of the calling app - * @param type the type of the in-app items being requested - * ("inapp" for one-time purchases and "subs" for subscription). - * @param continuationToken to be set as null for the first call, if the number of owned - * skus are too many, a continuationToken is returned in the response bundle. - * This method can be called again with the continuation token to get the next set of - * owned skus. - * @return Bundle containing the following key-value pairs - * "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on - * failure as listed above. - * "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs - * "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information - * "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures - * of the purchase information - * "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the - * next set of in-app purchases. Only set if the - * user has more owned skus than the current list. - */ - Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken); - - /** - * Consume the last purchase of the given SKU. This will result in this item being removed - * from all subsequent responses to getPurchases() and allow re-purchase of this item. - * @param apiVersion billing API version that the app is using - * @param packageName package name of the calling app - * @param purchaseToken token in the purchase information JSON that identifies the purchase - * to be consumed - * @return 0 if consumption succeeded. Appropriate error values for failures. - */ - int consumePurchase(int apiVersion, String packageName, String purchaseToken); -} diff --git a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java index 02abd7a1..0eb1d99c 100644 --- a/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java +++ b/app/src/main/java/de/blinkt/openvpn/LaunchVPN.java @@ -120,23 +120,23 @@ public class LaunchVPN extends Activity { @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if(requestCode==START_VPN_PROFILE) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - boolean showLogWindow = prefs.getBoolean("showlogwindow", true); - - if(!mhideLog && showLogWindow) - showLogWindow(); - new startOpenVpnThread().start(); - } else if (resultCode == Activity.RESULT_CANCELED) { - // User does not want us to start, so we just vanish - VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled, - ConnectionStatus.LEVEL_NOTCONNECTED); - - finish(); - } + super.onActivityResult(requestCode, resultCode, data); + + if(requestCode==START_VPN_PROFILE) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + boolean showlogwindow = prefs.getBoolean("showlogwindow", true); + + if(!mhideLog && showlogwindow) + showLogWindow(); + new startOpenVpnThread().start(); + } else if (resultCode == Activity.RESULT_CANCELED) { + // User does not want us to start, so we just vanish + VpnStatus.updateStateString("USER_VPN_PERMISSION_CANCELLED", "", R.string.state_user_vpn_permission_cancelled, ConnectionStatus.LEVEL_NOTCONNECTED); + + finish(); + } } + void showLogWindow() { Intent startLW = new Intent(getBaseContext(),LogWindow.class); diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index 578d95e7..3cb5527b 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -49,14 +49,12 @@ import de.blinkt.openvpn.core.VpnStatus.StateListener; import static de.blinkt.openvpn.core.NetworkSpace.ipAddress; import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTED; -import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NONETWORK; -import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_NOTCONNECTED; import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_CONNECTING_NO_SERVER_REPLY_YET; import static de.blinkt.openvpn.core.VpnStatus.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; + import se.leap.bitmaskclient.Dashboard; public class OpenVPNService extends VpnService implements StateListener, Callback, ByteCountListener { - public static final String START_SERVICE = "de.blinkt.openvpn.START_SERVICE"; public static final String START_SERVICE_STICKY = "de.blinkt.openvpn.START_SERVICE_STICKY"; public static final String ALWAYS_SHOW_NOTIFICATION = "de.blinkt.openvpn.NOTIFICATION_ALWAYS_VISIBLE"; @@ -126,7 +124,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac synchronized (mProcessLock) { mProcessThread = null; } - mConnecttime = 0; VpnStatus.removeByteCountListener(this); unregisterDeviceStateReceiver(); ProfileManager.setConntectedVpnProfileDisconnected(this); @@ -177,7 +174,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac mNotificationManager.notify(OPENVPN_STATUS, notification); - //startForeground(OPENVPN_STATUS, notification); + startForeground(OPENVPN_STATUS, notification); } private int getIconByConnectionStatus(ConnectionStatus level) { @@ -810,8 +807,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac /* Workaround for Lollipop, it does not route traffic to the VPNs own network mask */ - if (mLocalIP.len <= 31 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) - addRoute(mLocalIP); + if (mLocalIP.len <= 31 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + CIDRIP interfaceRoute = new CIDRIP(mLocalIP.mIp, mLocalIP.len); + interfaceRoute.normalise(); + addRoute(interfaceRoute); + } // Configurations are sometimes really broken... @@ -843,21 +843,6 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac mDisplayBytecount = true; mConnecttime = System.currentTimeMillis(); lowpriority = true; - if(mProfile.mPersistTun) { - NotificationManager ns = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - ns.cancel(OPENVPN_STATUS); - return; - } - } else if (level == LEVEL_NONETWORK || level == LEVEL_NOTCONNECTED) { - NotificationManager ns = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - ns.cancel(OPENVPN_STATUS); - return; - } else if (level != LEVEL_NOTCONNECTED && mConnecttime > 0) { - mDisplayBytecount = false; - String msg = "Traffic is blocked until the VPN becomes active."; - String ticker = msg; - showNotification(msg, ticker, lowpriority , 0, level); - return; } else { mDisplayBytecount = false; } @@ -868,7 +853,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac // Does not work :( String msg = getString(resid); String ticker = msg; - showNotification(msg + " " + logmessage, ticker, lowpriority , 0, level); + showNotification(msg + " " + logmessage, ticker, lowpriority, 0, level); + } } @@ -890,7 +876,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac humanReadableByteCount(diffOut / OpenVPNManagement.mBytecountInterval, true)); boolean lowpriority = !mNotificationAlwaysVisible; - //showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED); + showNotification(netstat, null, lowpriority, mConnecttime, LEVEL_CONNECTED); } } diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java index 298a6c40..d856feb7 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java @@ -32,7 +32,8 @@ import de.blinkt.openvpn.core.VpnStatus.LogItem; public class OpenVPNThread implements Runnable { private static final String DUMP_PATH_STRING = "Dump path: "; @SuppressLint("SdCardPath") - private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn[1]: syntax error:"; + private static final String BROKEN_PIE_SUPPORT = "/data/data/de.blinkt.openvpn/cache/pievpn"; + private final static String BROKEN_PIE_SUPPORT2 = "syntax error"; private static final String TAG = "OpenVPN"; public static final int M_FATAL = (1 << 4); public static final int M_NONFATAL = (1 << 5); @@ -148,7 +149,7 @@ public class OpenVPNThread implements Runnable { if (logline.startsWith(DUMP_PATH_STRING)) mDumpPath = logline.substring(DUMP_PATH_STRING.length()); - if (logline.startsWith(BROKEN_PIE_SUPPORT)) + if (logline.startsWith(BROKEN_PIE_SUPPORT) || logline.contains(BROKEN_PIE_SUPPORT2)) mBrokenPie = true; diff --git a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java index 199caa63..92bf9ad3 100644 --- a/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java +++ b/app/src/main/java/de/blinkt/openvpn/fragments/LogFragment.java @@ -7,8 +7,6 @@ package de.blinkt.openvpn.fragments; import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.R; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; -- cgit v1.2.3 From 48d6911fa5e63b458eb533e2b3d98f784496da8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 27 Jan 2015 11:11:31 +0100 Subject: Assume build process from app/ --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/build.gradle b/app/build.gradle index cf20e29f..5b507e13 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -125,7 +125,7 @@ task copyIcsOpenVPNFiles( type: Copy, dependsOn: 'checkoutStrippedIcsOpenVPN' ) // thanks to http://pleac.sourceforge.net/pleac_groovy/fileaccess.html task removeDuplicatedStrings( dependsOn: 'copyIcsOpenVPNFiles' ) { println "removeDuplicatedStrings" - new File('app').eachFileRecurse { + new File('.').eachFileRecurse { if(it.name.equals('strings.xml')) { def ics_openvpn_file = file(it.absolutePath.replace('strings.xml', 'strings-icsopenvpn.xml')) if(ics_openvpn_file.exists()) { -- cgit v1.2.3 From 81a221b2627daf122f8fcc36710eac8b3388acfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 27 Jan 2015 13:47:12 +0100 Subject: Import ics-openvpn-stripped correctly. --- app/build.gradle | 2 +- app/jni/jniglue.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/build.gradle b/app/build.gradle index 5b507e13..db928f0b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -176,7 +176,7 @@ task mergeUntranslatable( type: Copy, dependsOn: 'removeDuplicatedStrings') { } task updateIcsOpenVpn( type: Copy, dependsOn: 'mergeUntranslatable') { - from('../ics-openvpn-stripped/main/src/') { + from('../ics-openvpn-stripped/') { include 'openvpn/**/*' include 'openssl/**/*' include 'lzo/**/**' diff --git a/app/jni/jniglue.c b/app/jni/jniglue.c index d446f78c..85d2f2d5 100644 --- a/app/jni/jniglue.c +++ b/app/jni/jniglue.c @@ -14,7 +14,9 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { void android_openvpn_log(int level,const char* prefix,const char* prefix_sep,const char* m1) { +#ifndef NDEBUG __android_log_print(ANDROID_LOG_DEBUG,"openvpn","%s%s%s",prefix,prefix_sep,m1); +#endif } void Java_de_blinkt_openvpn_core_NativeUtils_jniclose(JNIEnv *env,jclass jo, jint fd) { -- cgit v1.2.3 From 6b53c24fd638dc8aaf35279c7ecadaea003f2b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 27 Jan 2015 14:06:15 +0100 Subject: Revert when Arne makes this change on ics-openvpn --- app/jni/jniglue.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/jni/jniglue.c b/app/jni/jniglue.c index 85d2f2d5..c2dd9f1e 100644 --- a/app/jni/jniglue.c +++ b/app/jni/jniglue.c @@ -7,7 +7,9 @@ #include "jniglue.h" jint JNI_OnLoad(JavaVM *vm, void *reserved) { +#ifndef NDEBUG __android_log_write(ANDROID_LOG_DEBUG,"openvpn", "Loading openvpn native library $id$ compiled on " __DATE__ " " __TIME__ ); +#endif return JNI_VERSION_1_2; } -- cgit v1.2.3