mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-22 19:54:57 +08:00
Removed non-C++ code
Removed android specific files: - Android JNI bridges C++ and java codes (will move to a new repository) - Android library project and sample project - Build files for android
This commit is contained in:
parent
3fc56e3379
commit
f8553a1424
@ -1,24 +0,0 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.5.0'
|
||||
//classpath "com.android.tools.build:gradle-experimental:0.6.0-alpha5"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
15
android/jni/Android.mk
Normal file
15
android/jni/Android.mk
Normal file
@ -0,0 +1,15 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := serial
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/include\
|
||||
$(LOCAL_PATH)/../../include
|
||||
|
||||
LOCAL_SRC_FILES := glob.c \
|
||||
../../src/serial.cc \
|
||||
../../src/impl/unix.cc \
|
||||
../../src/impl/list_ports/list_ports_linux.cc
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
@ -1,49 +0,0 @@
|
||||
apply plugin: 'com.android.library'
|
||||
//apply plugin: 'com.android.model.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
//useDeprecatedNdk true
|
||||
|
||||
/*
|
||||
ndk {
|
||||
moduleName "serial"
|
||||
}
|
||||
*/
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jni.srcDirs = [] //disable automatic ndk-build call
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
jniDebuggable true
|
||||
}
|
||||
}
|
||||
dexOptions {
|
||||
incremental true
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
17
android/library/proguard-rules.pro
vendored
17
android/library/proguard-rules.pro
vendored
@ -1,17 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /mnt/android/android-sdk-linux_x86/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="serial.android"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application
|
||||
android:allowBackup="true" />
|
||||
</manifest>
|
||||
@ -1,50 +0,0 @@
|
||||
package serial;
|
||||
|
||||
/**
|
||||
* Enumeration defines the possible bytesizes for the serial port.
|
||||
*/
|
||||
public enum ByteSize {
|
||||
/**
|
||||
* Use 5 bits in a byte.
|
||||
*/
|
||||
FiveBits(5),
|
||||
/**
|
||||
* Use 6 bits in a byte.
|
||||
*/
|
||||
SixBits(6),
|
||||
/**
|
||||
* Use 7 bits in a byte.
|
||||
*/
|
||||
SevenBits(7),
|
||||
/**
|
||||
* Use 8 bits in a byte.
|
||||
*
|
||||
* This is the default.
|
||||
*/
|
||||
EightBits(8);
|
||||
|
||||
/**
|
||||
* Number of bits in a single byte.
|
||||
*/
|
||||
public final int bitLength;
|
||||
|
||||
ByteSize(int bitLength) {
|
||||
this.bitLength = bitLength;
|
||||
}
|
||||
|
||||
static ByteSize fromValue(int value) {
|
||||
switch (value) {
|
||||
case 5:
|
||||
return FiveBits;
|
||||
case 6:
|
||||
return SixBits;
|
||||
case 7:
|
||||
return SevenBits;
|
||||
case 8:
|
||||
return EightBits;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid value.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package serial;
|
||||
|
||||
/**
|
||||
* Enumeration defines the possible flowcontrol types for the serial port.
|
||||
*/
|
||||
public enum FlowControl {
|
||||
/**
|
||||
* Use none flow control.
|
||||
*
|
||||
* This is the default.
|
||||
*/
|
||||
None,
|
||||
/**
|
||||
* Use software flow control.
|
||||
*/
|
||||
Software,
|
||||
/**
|
||||
* Use hardware flow control.
|
||||
*/
|
||||
Hardware;
|
||||
}
|
||||
@ -1,599 +0,0 @@
|
||||
package serial;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
|
||||
import serial.android.BuildConfig;
|
||||
|
||||
/**
|
||||
* Log replacement for {@link android.util.Log}.
|
||||
*
|
||||
* @author chzhong
|
||||
*/
|
||||
public final class Log {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String MESSAGE_TEMPLATE = "[%s]%s";
|
||||
|
||||
private static Object sSyncObject = new Object();
|
||||
|
||||
/**
|
||||
* Priority constant for enable all loggings.
|
||||
*/
|
||||
public static final int ALL = -1;
|
||||
|
||||
/**
|
||||
* Priority constant for {@link #println(int, String, String)} or
|
||||
* {@link #setFilterLevel(int)} methods; use Log.v.
|
||||
*/
|
||||
public static final int VERBOSE = 2;
|
||||
|
||||
/**
|
||||
* Priority constant for the {@link #println(int, String, String)} or
|
||||
* {@link #setFilterLevel(int)} method; use Log.d.
|
||||
*/
|
||||
public static final int DEBUG = 3;
|
||||
|
||||
/**
|
||||
* Priority constant for the {@link #println(int, String, String)} or
|
||||
* {@link #setFilterLevel(int)} method; use Log.i.
|
||||
*/
|
||||
public static final int INFO = 4;
|
||||
|
||||
/**
|
||||
* Priority constant for the {@link #println(int, String, String)} or
|
||||
* {@link #setFilterLevel(int)} method; use Log.w.
|
||||
*/
|
||||
public static final int WARN = 5;
|
||||
|
||||
/**
|
||||
* Priority constant for the {@link #println(int, String, String)} or
|
||||
* {@link #setFilterLevel(int)} method; use Log.e.
|
||||
*/
|
||||
public static final int ERROR = 6;
|
||||
|
||||
/**
|
||||
* Priority constant for the {@link #println(int, String, String)} or
|
||||
* {@link #setFilterLevel(int)} method.
|
||||
*/
|
||||
public static final int ASSERT = 7;
|
||||
|
||||
/**
|
||||
* Priority constant for disable all loggings.
|
||||
*/
|
||||
public static final int NONE = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Filter level of logs. Only levels greater or equals this level will be
|
||||
* output to LogCat.
|
||||
*/
|
||||
private static int sFilterLevel = BuildConfig.DEBUG ? ALL : WARN;
|
||||
|
||||
private static String sApplicationTag;
|
||||
|
||||
/**
|
||||
* Set the default tag for this application.
|
||||
*
|
||||
* @param tag The tag of the application.
|
||||
*/
|
||||
public static void setApplicationTag(String tag) {
|
||||
sApplicationTag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default tag of the application.
|
||||
*
|
||||
* @return The default tag of the application.
|
||||
*/
|
||||
public static String getApplicationTag() {
|
||||
return sApplicationTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filter level of logs. Only levels greater or equals this level
|
||||
* will be output to LogCat.
|
||||
*
|
||||
* @param level The filter level.
|
||||
*/
|
||||
public static void setFilterLevel(int level) {
|
||||
synchronized (sSyncObject) {
|
||||
sFilterLevel = level;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filter level of logs. Only levels greater or equals this level
|
||||
* will be output to LogCat.
|
||||
*
|
||||
* @return Current filter level.
|
||||
*/
|
||||
public static int getFilterLevel() {
|
||||
return sFilterLevel;
|
||||
}
|
||||
|
||||
private Log() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #VERBOSE} log message.
|
||||
*
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int v(String msg) {
|
||||
return println(VERBOSE, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #VERBOSE} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int v(String tag, String msg) {
|
||||
return println(VERBOSE, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #VERBOSE} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param format The format of the message you would like logged.
|
||||
* @param args The arguments used to format the message.
|
||||
*/
|
||||
public static int v(String tag, String format, Object... args) {
|
||||
if (VERBOSE < sFilterLevel)
|
||||
return 0;
|
||||
String msg = formatString(format, args);
|
||||
return println(VERBOSE, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #VERBOSE} log message and log the exception.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static int v(String tag, String msg, Throwable tr) {
|
||||
return println(VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #DEBUG} log message.
|
||||
*
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int d(String msg) {
|
||||
return println(DEBUG, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #DEBUG} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int d(String tag, String msg) {
|
||||
return println(DEBUG, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #DEBUG} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param format The format of the message you would like logged.
|
||||
* @param args The arguments used to format the message.
|
||||
*/
|
||||
public static int d(String tag, String format, Object... args) {
|
||||
if (DEBUG < sFilterLevel)
|
||||
return 0;
|
||||
String msg = formatString(format, args);
|
||||
return println(DEBUG, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #DEBUG} log message and log the exception.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static int d(String tag, String msg, Throwable tr) {
|
||||
return println(DEBUG, tag, msg + '\n' + getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an {@link #INFO} log message.
|
||||
*
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int i(String msg) {
|
||||
return println(INFO, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an {@link #INFO} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int i(String tag, String msg) {
|
||||
return println(INFO, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an {@link #INFO} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param format The format of the message you would like logged.
|
||||
* @param args The arguments used to format the message.
|
||||
*/
|
||||
public static int i(String tag, String format, Object... args) {
|
||||
if (INFO < sFilterLevel)
|
||||
return 0;
|
||||
String msg = formatString(format, args);
|
||||
return println(INFO, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #INFO} log message and log the exception.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static int i(String tag, String msg, Throwable tr) {
|
||||
return println(INFO, tag, msg + '\n' + getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #WARN} log message.
|
||||
*
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int w(String msg) {
|
||||
return println(WARN, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #WARN} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int w(String tag, String msg) {
|
||||
return println(WARN, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #WARN} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param format The format of the message you would like logged.
|
||||
* @param args The arguments used to format the message.
|
||||
*/
|
||||
public static int w(String tag, String format, Object... args) {
|
||||
if (WARN < sFilterLevel)
|
||||
return 0;
|
||||
String msg = formatString(format, args);
|
||||
return println(WARN, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #WARN} log message and log the exception.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static int w(String tag, String msg, Throwable tr) {
|
||||
return println(WARN, tag, msg + '\n' + getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether or not a log for the specified tag is loggable at
|
||||
* the specified level. The default level of any tag is set to INFO. This
|
||||
* means that any level above and including INFO will be logged. Before you
|
||||
* make any calls to a logging method you should check to see if your tag
|
||||
* should be logged. You can change the default level by setting a system
|
||||
* property: 'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>' Where level is
|
||||
* either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPRESS
|
||||
* will turn off all logging for your tag. You can also create a local.prop
|
||||
* file that with the following in it:
|
||||
* 'log.tag.<YOUR_LOG_TAG>=<LEVEL>' and place that in
|
||||
* /data/local.prop.
|
||||
*
|
||||
* @param tag The tag to check.
|
||||
* @param level The level to check.
|
||||
* @return Whether or not that this is allowed to be logged.
|
||||
* @throws IllegalArgumentException is thrown if the tag.length() > 23.
|
||||
*/
|
||||
public static boolean isLoggable(String tag, int level) {
|
||||
return android.util.Log.isLoggable(tag, level);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a {@link #WARN} log message and log the exception.
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static int w(String tag, Throwable tr) {
|
||||
return println(WARN, tag, getStackTraceString(tr));
|
||||
}
|
||||
|
||||
public static int w(Throwable tr) {
|
||||
return println(WARN, null, getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an {@link #ERROR} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param format The format of the message you would like logged.
|
||||
* @param args The arguments used to format the message.
|
||||
*/
|
||||
public static int e(String tag, String format, Object... args) {
|
||||
if (ERROR < sFilterLevel)
|
||||
return 0;
|
||||
String msg = formatString(format, args);
|
||||
return println(ERROR, tag, msg);
|
||||
}
|
||||
|
||||
private static String formatString(String format, Object... args) {
|
||||
try {
|
||||
return String.format(Locale.US, format, args);
|
||||
} catch (Exception e) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(format);
|
||||
for (Object arg : args) {
|
||||
builder.append(arg.toString());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an {@link #ERROR} log message.
|
||||
*
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int e(String msg) {
|
||||
return println(ERROR, null, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an {@link #ERROR} log message.
|
||||
*
|
||||
* @param tr The throwable you would like logged.
|
||||
*/
|
||||
public static int e(Throwable tr) {
|
||||
return println(ERROR, null, getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an {@link #ERROR} log message.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
*/
|
||||
public static int e(String tag, String msg) {
|
||||
return println(ERROR, tag, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #ERROR} log message and log the exception.
|
||||
*
|
||||
* @param msg The message you would like logged.
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static int e(String msg, Throwable tr) {
|
||||
return println(ERROR, null, msg + '\n' + getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link #ERROR} log message and log the exception.
|
||||
*
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static int e(String tag, String msg, Throwable tr) {
|
||||
return println(ERROR, tag, msg + '\n' + getStackTraceString(tr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handy function to get a loggable stack trace from a Throwable
|
||||
*
|
||||
* @param tr An exception to log
|
||||
*/
|
||||
public static String getStackTraceString(Throwable tr) {
|
||||
if (tr == null) {
|
||||
return "";
|
||||
}
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
tr.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Low-level logging call.
|
||||
*
|
||||
* @param priority The priority/type of this log message
|
||||
* @param tag Used to identify the source of a log message. It usually
|
||||
* identifies the class or activity where the log call occurs.
|
||||
* @param msg The message you would like logged.
|
||||
* @return The number of bytes written.
|
||||
*/
|
||||
public static int println(int priority, String tag, String msg) {
|
||||
msg = (msg == null) ? "" : msg;
|
||||
|
||||
int result = 0;
|
||||
if (priority >= sFilterLevel) {
|
||||
if (TextUtils.isEmpty(sApplicationTag) || sApplicationTag.equals(tag)) {
|
||||
result = android.util.Log.println(priority, tag, msg);
|
||||
} else if (TextUtils.isEmpty(tag) && !TextUtils.isEmpty(sApplicationTag)) {
|
||||
result = android.util.Log.println(priority, sApplicationTag, msg);
|
||||
} else {
|
||||
String message = formatString(MESSAGE_TEMPLATE, tag, msg);
|
||||
result = android.util.Log.println(priority, sApplicationTag, message);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void myAssert(boolean condition, String message) {
|
||||
if (sFilterLevel == ALL && !condition) {
|
||||
throw new AssertionError(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link StackTraceElement} for current method's caller.
|
||||
*
|
||||
* <p>For example:</p>
|
||||
* <pre>
|
||||
* void foo() {
|
||||
* bar();
|
||||
* }
|
||||
*
|
||||
* void bar() {
|
||||
* StackTraceElement caller = getCallerFrame();
|
||||
*
|
||||
* // Will print "foo".
|
||||
* System.println(caller.getMethodName());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p> Might be {@code null}. If you call this from static void main(String[]).
|
||||
*
|
||||
* @return the stack frame of current method's caller.
|
||||
*/
|
||||
public static StackTraceElement getCallerFrame() {
|
||||
/*
|
||||
* traces = {
|
||||
* nativeGetStackTrace,
|
||||
* Thread.getStackTrace,
|
||||
* getStackFrameAt(2),
|
||||
* getCurrentFrame, ... [3]
|
||||
* <current>, ... [3 + 1]
|
||||
* <caller>, ... [3 + 2]
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
return getStackFrameAt(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link StackTraceElement} for current method.
|
||||
*
|
||||
* <p>For example:</p>
|
||||
* <pre>
|
||||
* void foo() {
|
||||
* bar();
|
||||
* }
|
||||
*
|
||||
* void bar() {
|
||||
* StackTraceElement current = getCurrentFrame();
|
||||
*
|
||||
* // Will print "bar".
|
||||
* System.println(current.getMethodName());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return the stack frame of current method's caller.
|
||||
*/
|
||||
public static StackTraceElement getCurrentFrame() {
|
||||
/*
|
||||
* traces = {
|
||||
* nativeGetStackTrace,
|
||||
* Thread.getStackTrace,
|
||||
* getStackFrameAt(1),
|
||||
* getCurrentFrame, ... [3]
|
||||
* <current>, ... [3 + 1]
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
return getStackFrameAt(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return specified {@link StackTraceElement} on the call stack, relative to current method.
|
||||
*
|
||||
* <p>For example:</p>
|
||||
* <pre>
|
||||
* void main() {
|
||||
* stub();
|
||||
* }
|
||||
*
|
||||
* void stub() {
|
||||
* foo();
|
||||
* }
|
||||
* void foo() {
|
||||
* bar();
|
||||
* }
|
||||
*
|
||||
* void bar() {
|
||||
* // Will print "bar"
|
||||
* System.println(getStackFrameAt(0).getMethodName());
|
||||
* // Will print "foo"
|
||||
* System.println(getStackFrameAt(1).getMethodName());
|
||||
* // Will print "stub"
|
||||
* System.println(getStackFrameAt(2).getMethodName());
|
||||
* // Will print "main"
|
||||
* System.println(getStackFrameAt(3).getMethodName());
|
||||
* // Will print "null"
|
||||
* System.println(getStackFrameAt(4));
|
||||
* System.println(getStackFrameAt(-1));
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param offset the offset of the call stack from current method. 0 means current methods, 1 means caller, etc.
|
||||
* @return the stack frame of current method's caller.
|
||||
*/
|
||||
public static StackTraceElement getStackFrameAt(int offset) {
|
||||
if (offset < 0) {
|
||||
return null;
|
||||
}
|
||||
/*
|
||||
* traces = {
|
||||
* nativeGetStackTrace,
|
||||
* Thread.getStackTrace,
|
||||
* getStackFrameAt(offset),
|
||||
* <current>, ... [3 + 0], offset 0
|
||||
* <caller>, ... [3 + 1], offset 1
|
||||
* <super caller>, ... [3 + 2], offset 2
|
||||
* <grand caller>, ... [3 + 3], offset 3
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
StackTraceElement[] traces = Thread.currentThread().getStackTrace();
|
||||
if (traces.length < 4 + offset) {
|
||||
// The stack at offset is underflow...
|
||||
return null;
|
||||
}
|
||||
return traces[3 + offset];
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package serial;
|
||||
|
||||
/**
|
||||
* Enumeration defines the possible parity types for the serial port.
|
||||
*/
|
||||
public enum Parity {
|
||||
/**
|
||||
* Use none parity type.
|
||||
*
|
||||
* This is the default.
|
||||
*/
|
||||
None,
|
||||
/**
|
||||
* Use odd parity types
|
||||
*/
|
||||
Odd,
|
||||
/**
|
||||
* Use even parity type
|
||||
*/
|
||||
Even,
|
||||
/**
|
||||
* Use mark parity type.
|
||||
*
|
||||
*/
|
||||
Mark,
|
||||
/**
|
||||
* Use space parity type.
|
||||
*
|
||||
*/
|
||||
Space;
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
package serial;
|
||||
|
||||
/**
|
||||
* Created by chzhong on 1/20/16.
|
||||
*/
|
||||
public final class PortInfo {
|
||||
|
||||
/**
|
||||
* Address of the serial port (this can be passed to the constructor of Serial).
|
||||
*/
|
||||
public final String port;
|
||||
|
||||
/**
|
||||
* Human readable description of serial device if available.
|
||||
*/
|
||||
public final String description;
|
||||
|
||||
/**
|
||||
* Hardware ID (e.g. VID:PID of USB serial devices) or "n/a" if not available.
|
||||
*/
|
||||
public final String hardwareId;
|
||||
|
||||
PortInfo(String port, String description, String hardwareId) {
|
||||
this.port = port;
|
||||
this.description = description;
|
||||
this.hardwareId = hardwareId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s (%s)", description, port);
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
package serial;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by chzhong on 1/20/16.
|
||||
*/
|
||||
public class PortNotOpenedException extends IllegalStateException {
|
||||
|
||||
static final String formatMessage(String message, StackTraceElement frame) {
|
||||
return String.format(Locale.getDefault(), "%s. (%s.%s @ %s:%d)",
|
||||
message, frame.getClassName(), frame.getMethodName(),
|
||||
frame.getFileName(), frame.getLineNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PortNotOpenedException} with the current stack trace
|
||||
* and the specified detail message.
|
||||
*
|
||||
* @param detailMessage the detail message for this exception.
|
||||
* @param frame the frame of the wrong call.
|
||||
*/
|
||||
PortNotOpenedException(String detailMessage, StackTraceElement frame) {
|
||||
super(formatMessage(detailMessage, frame));
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
||||
package serial;
|
||||
|
||||
/**
|
||||
* Created by chzhong on 1/20/16.
|
||||
*/
|
||||
public class SerialException extends RuntimeException {
|
||||
/**
|
||||
* Constructs a new {@code SerialException} with the current stack trace
|
||||
* and the specified detail message.
|
||||
*
|
||||
* @param detailMessage the detail message for this exception.
|
||||
*/
|
||||
public SerialException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PortNotOpenedException} with the current stack trace,
|
||||
* the specified detail message and the specified cause.
|
||||
*
|
||||
* @param detailMessage the detail message for this exception.
|
||||
* @param throwable
|
||||
*/
|
||||
public SerialException(String detailMessage, Throwable throwable) {
|
||||
super(detailMessage, throwable);
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package serial;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by chzhong on 1/20/16.
|
||||
*/
|
||||
public class SerialIOException extends IOException {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SerialIOException} with its stack trace and detail
|
||||
* message filled in.
|
||||
*
|
||||
* @param detailMessage the detail message for this exception.
|
||||
*/
|
||||
public SerialIOException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class with detail message and cause
|
||||
* filled in.
|
||||
*
|
||||
* @param message The detail message for the exception.
|
||||
* @param cause The detail cause for the exception.
|
||||
* @since 1.6
|
||||
*/
|
||||
public SerialIOException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package serial;
|
||||
|
||||
/**
|
||||
* Enumeration defines the possible stopbit types for the serial port.
|
||||
*/
|
||||
public enum Stopbits {
|
||||
/**
|
||||
* Use 1 as stop bit.
|
||||
*
|
||||
* This is the default.
|
||||
*/
|
||||
One(1),
|
||||
/**
|
||||
* Use 2 as stop bit.
|
||||
*/
|
||||
Two(2),
|
||||
/**
|
||||
* Use 1.5 as stopbit.
|
||||
*/
|
||||
OnePointFive(3);
|
||||
|
||||
/**
|
||||
* Internal value of the enumeration.
|
||||
*/
|
||||
public final int value;
|
||||
|
||||
Stopbits(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
static Stopbits fromValue(int value) {
|
||||
switch (value) {
|
||||
case 1:
|
||||
return One;
|
||||
case 2:
|
||||
return Two;
|
||||
case 3:
|
||||
return OnePointFive;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid value.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
package serial;
|
||||
|
||||
/**
|
||||
* Structure for setting the timeout of the serial port, times are
|
||||
* in milliseconds.
|
||||
*
|
||||
* In order to disable the interbyte timeout, set it to {@link #MAX}.
|
||||
*/
|
||||
public final class Timeout {
|
||||
|
||||
/**
|
||||
* Value that represents interbyte timeout should be disabled.
|
||||
*
|
||||
* This is an unsigned value.
|
||||
*/
|
||||
public static final int MAX = -1;
|
||||
|
||||
/**
|
||||
* Convenience function to generate Timeout structs using a
|
||||
* single absolute timeout.
|
||||
*
|
||||
* @param timeout A long that defines the time in milliseconds until a
|
||||
* timeout occurs after a call to read or write is made.
|
||||
* @return Timeout struct that represents this simple timeout provided.
|
||||
*/
|
||||
public static final Timeout simpleTimeout(int timeout) {
|
||||
return new Timeout(MAX, timeout, 0, timeout, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of milliseconds between bytes received to timeout on.
|
||||
*/
|
||||
int inter_byte_timeout;
|
||||
/**
|
||||
* A constant number of milliseconds to wait after calling read.
|
||||
*/
|
||||
int read_timeout_constant;
|
||||
/**
|
||||
* A multiplier against the number of requested bytes to wait after
|
||||
* calling read.
|
||||
*/
|
||||
int read_timeout_multiplier;
|
||||
/**
|
||||
* A constant number of milliseconds to wait after calling write.
|
||||
*/
|
||||
int write_timeout_constant;
|
||||
/**
|
||||
* A multiplier against the number of requested bytes to wait after
|
||||
* calling write.
|
||||
*/
|
||||
int write_timeout_multiplier;
|
||||
|
||||
public Timeout() {
|
||||
this(0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to generate Timeout structs using a
|
||||
* single absolute timeout.
|
||||
*
|
||||
* @param timeout A long that defines the time in milliseconds until a
|
||||
* timeout occurs after a call to read or write is made.
|
||||
* @return Timeout struct that represents this simple timeout provided.
|
||||
*/
|
||||
public Timeout(int timeout) {
|
||||
this(MAX, timeout, 0, timeout, 0);
|
||||
}
|
||||
|
||||
public Timeout(int inter_byte_timeout, int read_timeout_constant, int read_timeout_multiplier, int write_timeout_constant, int write_timeout_multiplier) {
|
||||
this.inter_byte_timeout = inter_byte_timeout;
|
||||
this.read_timeout_constant = read_timeout_constant;
|
||||
this.read_timeout_multiplier = read_timeout_multiplier;
|
||||
this.write_timeout_constant = write_timeout_constant;
|
||||
this.write_timeout_multiplier = write_timeout_multiplier;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
$(call import-add-path,$(LOCAL_PATH)/libs)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := serial
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/include \
|
||||
$(LOCAL_PATH)/libs
|
||||
|
||||
LOCAL_SRC_FILES := glob.c \
|
||||
serial.cc \
|
||||
serial_unix.cc \
|
||||
serial_jni.cc \
|
||||
list_ports_linux.cc \
|
||||
jni_utility.cc \
|
||||
jni_main.cc
|
||||
|
||||
LOCAL_STATIC_LIBRARIES += nativehelper
|
||||
LOCAL_LDLIBS := -llog -lz
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module,nativehelper)
|
||||
@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
ARGS=$(getopt -o "d" -l "debug" -n "build-jni.sh" -- "$@");
|
||||
|
||||
eval set -- "$ARGS";
|
||||
|
||||
JNI_ARGS="NDK_LIBS_OUT=../jniLibs"
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-d|--debug)
|
||||
shift
|
||||
JNI_ARGS="$JNI_ARGS NDK_DEBUG=1"
|
||||
break;
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Remove '--'
|
||||
shift
|
||||
|
||||
ndk-build $JNI_ARGS
|
||||
@ -1,60 +0,0 @@
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jni_utility.h"
|
||||
#include "log.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct RegistrationMethod {
|
||||
const char* name;
|
||||
int (*func)(JNIEnv*);
|
||||
};
|
||||
|
||||
extern int registerSerial(JNIEnv* env);
|
||||
|
||||
static RegistrationMethod gRegMethods[] = {
|
||||
{ "Serial", registerSerial },
|
||||
};
|
||||
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
{
|
||||
LOGV("JNI_OnLoad");
|
||||
JNIEnv* env = NULL;
|
||||
jint result = -1;
|
||||
|
||||
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
|
||||
LOGE("GetEnv failed!");
|
||||
return result;
|
||||
}
|
||||
if (!env)
|
||||
LOGE("Could not retrieve the env!");
|
||||
|
||||
// Save the JavaVM pointer for use globally.
|
||||
setJavaVM(vm);
|
||||
|
||||
const RegistrationMethod* method = gRegMethods;
|
||||
const RegistrationMethod* end = method + sizeof(gRegMethods) / sizeof(RegistrationMethod);
|
||||
while (method != end) {
|
||||
if (method->func(env) < 0) {
|
||||
LOGE("%s registration failed!", method->name);
|
||||
return result;
|
||||
}
|
||||
//LOGV("%s registration done.", method->name);
|
||||
method++;
|
||||
}
|
||||
|
||||
// Initialize rand() function. The rand() function is used in
|
||||
// FileSystemAndroid to create a random temporary filename.
|
||||
srand(time(NULL));
|
||||
LOGV("JNI_OnLoad done.");
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <jni_utility.h>
|
||||
|
||||
static JavaVM* jvm = 0;
|
||||
static jobject gClassLoader;
|
||||
static jmethodID gFindClassMethod;
|
||||
|
||||
static jclass gStringClass = 0;
|
||||
static jmethodID gGetBytesMid = 0;
|
||||
static jmethodID gNewStringMid = 0;
|
||||
|
||||
static jobject gTrue = 0;
|
||||
static jobject gFalse = 0;
|
||||
static jclass gLongClass = 0;
|
||||
static jmethodID gLongValueOf = 0;
|
||||
static jclass gIntClass = 0;
|
||||
static jmethodID gIntValueOf = 0;
|
||||
|
||||
void setupGlobalClassLoader()
|
||||
{
|
||||
JNIEnv* env = getJNIEnv();
|
||||
ScopedLocalRef<jclass> coreJniClass(env, env->FindClass("serial/Serial"));
|
||||
ScopedLocalRef<jclass> classClass(env, env->GetObjectClass(coreJniClass.get()));
|
||||
ScopedLocalRef<jclass> classLoaderClass(env, env->FindClass("java/lang/ClassLoader"));
|
||||
jmethodID getClassLoaderMethod = env->GetMethodID(classClass.get(), "getClassLoader",
|
||||
"()Ljava/lang/ClassLoader;");
|
||||
ScopedLocalRef<jobject> classLoader(env, env->CallObjectMethod(coreJniClass.get(), getClassLoaderMethod));
|
||||
gClassLoader = env->NewGlobalRef(classLoader.get());
|
||||
//LOGV("gClassLoader is %p", gClassLoader);
|
||||
gFindClassMethod = env->GetMethodID(classLoaderClass.get(), "findClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
//LOGV("gFindClassMethod is %p", gFindClassMethod);
|
||||
|
||||
ScopedLocalRef<jclass> stringClass(env, env->FindClass("java/lang/String"));
|
||||
gStringClass = (jclass)env->NewGlobalRef(stringClass.get());
|
||||
//LOGV("gStringClass is %p", gStringClass);
|
||||
gGetBytesMid = env->GetMethodID (gStringClass, "getBytes", "()[B");
|
||||
//LOGV("gGetBytesMid is %p", gGetBytesMid);
|
||||
gNewStringMid = env->GetMethodID(gStringClass, "<init>", "([B)V");
|
||||
//LOGV("gNewStringMid is %p", gNewStringMid);
|
||||
|
||||
ScopedLocalRef<jclass> booleanCls(env, env->FindClass("java/lang/Boolean"));
|
||||
ScopedLocalRef<jobject> t(env, callJNIStaticMethod<jobject>(
|
||||
booleanCls.get(), "valueOf", "(Z)Ljava/lang/Boolean;", JNI_TRUE));
|
||||
gTrue = env->NewGlobalRef(t.get());
|
||||
//LOGV("gTrue is %p", gTrue);
|
||||
ScopedLocalRef<jobject> f(env, callJNIStaticMethod<jobject>(
|
||||
booleanCls.get(), "valueOf", "(Z)Ljava/lang/Boolean;", JNI_FALSE));
|
||||
gFalse = env->NewGlobalRef(f.get());
|
||||
//LOGV("gFalse is %p", gFalse);
|
||||
|
||||
ScopedLocalRef<jclass> longCls(env, env->FindClass("java/lang/Long"));
|
||||
gLongClass = (jclass)env->NewGlobalRef(longCls.get());
|
||||
gLongValueOf = env->GetStaticMethodID(gLongClass, "valueOf", "(J)Ljava/lang/Long;");
|
||||
|
||||
ScopedLocalRef<jclass> intCls(env, env->FindClass("java/lang/Integer"));
|
||||
gIntClass = (jclass)env->NewGlobalRef(intCls.get());
|
||||
gIntValueOf = env->GetStaticMethodID(gIntClass, "valueOf", "(I)Ljava/lang/Integer;");
|
||||
}
|
||||
|
||||
jclass findClass(const char* name, int flags /*= FIND_CLASS_USE_CLASS_LOADER*/)
|
||||
{
|
||||
JNIEnv *env = getJNIEnv();
|
||||
jclass cls;
|
||||
if ((flags & FIND_CLASS_USE_CLASS_LOADER) == FIND_CLASS_USE_CLASS_LOADER) {
|
||||
ScopedLocalRef<jstring> jname(env, env->NewStringUTF(name));
|
||||
cls = static_cast<jclass>(env->CallObjectMethod(gClassLoader, gFindClassMethod, jname.get()));
|
||||
} else {
|
||||
cls = env->FindClass(name);
|
||||
}
|
||||
checkException(env);
|
||||
|
||||
if ((flags & FIND_CLASS_RETURN_GLOBAL_REF) == FIND_CLASS_RETURN_GLOBAL_REF) {
|
||||
jclass localClass = cls;
|
||||
cls = (jclass)env->NewGlobalRef(localClass);
|
||||
env->DeleteLocalRef(localClass);
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
||||
// Provide the ability for an outside component to specify the JavaVM to use
|
||||
// If the jvm value is set, the getJavaVM function below will just return.
|
||||
// In getJNIEnv(), if AttachCurrentThread is called to a VM that is already
|
||||
// attached, the result is a no-op.
|
||||
void setJavaVM(JavaVM* javaVM)
|
||||
{
|
||||
jvm = javaVM;
|
||||
setupGlobalClassLoader();
|
||||
}
|
||||
|
||||
JavaVM* getJavaVM()
|
||||
{
|
||||
if (jvm)
|
||||
return jvm;
|
||||
LOGE("JavaVM is null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void detachCurrentThread(void *data)
|
||||
{
|
||||
getJavaVM()->DetachCurrentThread();
|
||||
}
|
||||
|
||||
JNIEnv* getJNIEnv()
|
||||
{
|
||||
union {
|
||||
JNIEnv* env;
|
||||
void* dummy;
|
||||
} u;
|
||||
jint jniError = 0;
|
||||
|
||||
jniError = getJavaVM()->AttachCurrentThread(&u.env, 0);
|
||||
if (jniError == JNI_OK) {
|
||||
return u.env;
|
||||
}
|
||||
LOGE("AttachCurrentThread failed, returned %ld", static_cast<long>(jniError));
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool checkException(JNIEnv* env) {
|
||||
if (env->ExceptionCheck() != 0) {
|
||||
LOGE("*** Uncaught exception returned from Java call!\n");
|
||||
env->ExceptionDescribe();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string jstringToStdString(JNIEnv* env, jstring jstr) {
|
||||
if (!jstr || !env)
|
||||
return std::string();
|
||||
|
||||
std::string result;
|
||||
ScopedLocalRef<jbyteArray> barr(env,
|
||||
(jbyteArray) env->CallObjectMethod(jstr, gGetBytesMid));
|
||||
jsize alen = env->GetArrayLength(barr.get());
|
||||
jbyte * ba = env->GetByteArrayElements(barr.get(), JNI_FALSE);
|
||||
if (alen> 0) {
|
||||
char* rtn = (char *) malloc (alen + 1);
|
||||
memcpy(rtn, ba, alen);
|
||||
rtn [alen] = 0;
|
||||
result.assign(rtn);
|
||||
}
|
||||
env->ReleaseByteArrayElements(barr.get(), ba, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
jstring stdStringToJstring(JNIEnv* env, const std::string& str) {
|
||||
//return env->NewStringUTF(str.c_str());
|
||||
const char* bytes = str.c_str();
|
||||
size_t size = str.size();
|
||||
ScopedLocalRef<jbyteArray> result(env, env->NewByteArray(size));
|
||||
env->SetByteArrayRegion(result.get(), 0, size, (jbyte*)bytes);
|
||||
jstring ret = (jstring) env->NewObject(gStringClass, gNewStringMid, result.get());
|
||||
return ret;
|
||||
}
|
||||
|
||||
jobjectArray createStringArray(JNIEnv *env, int size) {
|
||||
return env->NewObjectArray(size, gStringClass, NULL);
|
||||
}
|
||||
|
||||
void callJNIVoidMethod(jobject obj, const char* methodName, const char* methodSignature, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, methodSignature);
|
||||
|
||||
callJNIMethodV<void>(obj, methodName, methodSignature, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void callJNIVoidMethodID(jobject obj, jmethodID mid, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, mid);
|
||||
|
||||
callJNIMethodIDV<void>(obj, mid, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void callJNIStaticVoidMethod(const char* className, const char* methodName, const char* methodSignature, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, methodSignature);
|
||||
|
||||
JNIEnv *env = getJNIEnv();
|
||||
ScopedLocalRef<jclass> cls(env, findClass(className));
|
||||
if (checkException(env)) {
|
||||
return;
|
||||
}
|
||||
if (cls.get() && env) {
|
||||
jmethodID mid = env->GetStaticMethodID(cls.get(), methodName, methodSignature);
|
||||
if (mid)
|
||||
JNICaller<void>::callStaticV(cls.get(), mid, args);
|
||||
else {
|
||||
env->ExceptionDescribe();
|
||||
LOGE("Could not find method: %s for %p", methodName, cls.get());
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
jobject toJavaBoolean(bool value)
|
||||
{
|
||||
if (value) {
|
||||
return gTrue;
|
||||
} else {
|
||||
return gFalse;
|
||||
}
|
||||
}
|
||||
|
||||
jobject toJavaLong(jlong value)
|
||||
{
|
||||
return callJNIStaticMethod<jobject>(gLongClass, gLongValueOf, value);
|
||||
}
|
||||
|
||||
jobject toJavaInt(jint value)
|
||||
{
|
||||
return callJNIStaticMethod<jobject>(gIntClass, gIntValueOf, value);
|
||||
}
|
||||
|
||||
jobject newJavaObject(const char* className)
|
||||
{
|
||||
JNIEnv *env = getJNIEnv();
|
||||
ScopedLocalRef<jclass> cls(env, findClass(className));
|
||||
if (cls.get()) {
|
||||
jmethodID mid = env->GetMethodID(cls.get(), "<init>", "()V");
|
||||
if (mid) {
|
||||
return env->NewObject(cls.get(), mid);
|
||||
} else {
|
||||
LOGE("Could not find method %s", "<init>()V");
|
||||
}
|
||||
env->ExceptionDescribe();
|
||||
} else {
|
||||
env->ExceptionDescribe();
|
||||
LOGE("Could not find class %s", className);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::list<std::string> jstringArrayToStdStringList(jobjectArray jstringArray)
|
||||
{
|
||||
std::list<std::string> list;
|
||||
JNIEnv *env = getJNIEnv();
|
||||
jsize size = env->GetArrayLength(jstringArray);
|
||||
for (int i = 0; i < size; i++) {
|
||||
ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(jstringArray, i));
|
||||
if (item.get()) {
|
||||
list.push_back(jstringToStdString((jstring)item.get()));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef NATIVEHELPER_ALOGPRIV_H_
|
||||
#define NATIVEHELPER_ALOGPRIV_H_
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#ifndef LOG_NDEBUG
|
||||
#ifdef NDEBUG
|
||||
#define LOG_NDEBUG 1
|
||||
#else
|
||||
#define LOG_NDEBUG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Basic log message macros intended to emulate the behavior of log/log.h
|
||||
* in system core. This should be dependent only on ndk exposed logging
|
||||
* functionality.
|
||||
*/
|
||||
|
||||
#ifndef ALOG
|
||||
#define ALOG(priority, tag, fmt...) \
|
||||
__android_log_print(ANDROID_##priority, tag, fmt)
|
||||
#endif
|
||||
|
||||
#ifndef ALOGV
|
||||
#if LOG_NDEBUG
|
||||
#define ALOGV(...) ((void)0)
|
||||
#else
|
||||
#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALOGD
|
||||
#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#ifndef ALOGI
|
||||
#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#ifndef ALOGW
|
||||
#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#ifndef ALOGE
|
||||
#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -1,33 +0,0 @@
|
||||
# Copyright (C) 2009 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.
|
||||
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := nativehelper
|
||||
LOCAL_CLANG := true
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/include/nativehelper
|
||||
LOCAL_SRC_FILES := \
|
||||
JNIHelp.cpp \
|
||||
JniConstants.cpp \
|
||||
toStringArray.cpp
|
||||
|
||||
LOCAL_EXPORT_CPPFLAGS := -I$(LOCAL_PATH)/include
|
||||
LOCAL_CFLAGS := -Werror
|
||||
LOCAL_SRC_FILES := $(LOCAL_SRC_FILES)
|
||||
#LOCAL_LDFLAGS := -llog -ldl
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@ -1,341 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "JNIHelp"
|
||||
|
||||
#include "JniConstants.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "ALog-priv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.)
|
||||
*/
|
||||
template<typename T>
|
||||
class scoped_local_ref {
|
||||
public:
|
||||
scoped_local_ref(C_JNIEnv* env, T localRef = NULL)
|
||||
: mEnv(env), mLocalRef(localRef)
|
||||
{
|
||||
}
|
||||
|
||||
~scoped_local_ref() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset(T localRef = NULL) {
|
||||
if (mLocalRef != NULL) {
|
||||
(*mEnv)->DeleteLocalRef(reinterpret_cast<JNIEnv*>(mEnv), mLocalRef);
|
||||
mLocalRef = localRef;
|
||||
}
|
||||
}
|
||||
|
||||
T get() const {
|
||||
return mLocalRef;
|
||||
}
|
||||
|
||||
private:
|
||||
C_JNIEnv* mEnv;
|
||||
T mLocalRef;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
scoped_local_ref(const scoped_local_ref&);
|
||||
void operator=(const scoped_local_ref&);
|
||||
};
|
||||
|
||||
static jclass findClass(C_JNIEnv* env, const char* className) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
return (*env)->FindClass(e, className);
|
||||
}
|
||||
|
||||
extern "C" int jniRegisterNativeMethods(C_JNIEnv* env, const char* className,
|
||||
const JNINativeMethod* gMethods, int numMethods)
|
||||
{
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
|
||||
ALOGV("Registering %s's %d native methods...", className, numMethods);
|
||||
|
||||
scoped_local_ref<jclass> c(env, findClass(env, className));
|
||||
if (c.get() == NULL) {
|
||||
char* msg;
|
||||
asprintf(&msg, "Native registration unable to find class '%s'; aborting...", className);
|
||||
e->FatalError(msg);
|
||||
}
|
||||
|
||||
if ((*env)->RegisterNatives(e, c.get(), gMethods, numMethods) < 0) {
|
||||
char* msg;
|
||||
asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className);
|
||||
e->FatalError(msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a human-readable summary of an exception object. The buffer will
|
||||
* be populated with the "binary" class name and, if present, the
|
||||
* exception message.
|
||||
*/
|
||||
static bool getExceptionSummary(C_JNIEnv* env, jthrowable exception, std::string& result) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
|
||||
/* get the name of the exception's class */
|
||||
scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
|
||||
scoped_local_ref<jclass> classClass(env,
|
||||
(*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail
|
||||
jmethodID classGetNameMethod =
|
||||
(*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;");
|
||||
scoped_local_ref<jstring> classNameStr(env,
|
||||
(jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod));
|
||||
if (classNameStr.get() == NULL) {
|
||||
(*env)->ExceptionClear(e);
|
||||
result = "<error getting class name>";
|
||||
return false;
|
||||
}
|
||||
const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL);
|
||||
if (classNameChars == NULL) {
|
||||
(*env)->ExceptionClear(e);
|
||||
result = "<error getting class name UTF-8>";
|
||||
return false;
|
||||
}
|
||||
result += classNameChars;
|
||||
(*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars);
|
||||
|
||||
/* if the exception has a detail message, get that */
|
||||
jmethodID getMessage =
|
||||
(*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;");
|
||||
scoped_local_ref<jstring> messageStr(env,
|
||||
(jstring) (*env)->CallObjectMethod(e, exception, getMessage));
|
||||
if (messageStr.get() == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
result += ": ";
|
||||
|
||||
const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
|
||||
if (messageChars != NULL) {
|
||||
result += messageChars;
|
||||
(*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars);
|
||||
} else {
|
||||
result += "<error getting message>";
|
||||
(*env)->ExceptionClear(e); // clear OOM
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an exception (with stack trace) as a string.
|
||||
*/
|
||||
static bool getStackTrace(C_JNIEnv* env, jthrowable exception, std::string& result) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
|
||||
scoped_local_ref<jclass> stringWriterClass(env, findClass(env, "java/io/StringWriter"));
|
||||
if (stringWriterClass.get() == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID stringWriterCtor = (*env)->GetMethodID(e, stringWriterClass.get(), "<init>", "()V");
|
||||
jmethodID stringWriterToStringMethod =
|
||||
(*env)->GetMethodID(e, stringWriterClass.get(), "toString", "()Ljava/lang/String;");
|
||||
|
||||
scoped_local_ref<jclass> printWriterClass(env, findClass(env, "java/io/PrintWriter"));
|
||||
if (printWriterClass.get() == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID printWriterCtor =
|
||||
(*env)->GetMethodID(e, printWriterClass.get(), "<init>", "(Ljava/io/Writer;)V");
|
||||
|
||||
scoped_local_ref<jobject> stringWriter(env,
|
||||
(*env)->NewObject(e, stringWriterClass.get(), stringWriterCtor));
|
||||
if (stringWriter.get() == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scoped_local_ref<jobject> printWriter(env,
|
||||
(*env)->NewObject(e, printWriterClass.get(), printWriterCtor, stringWriter.get()));
|
||||
if (printWriter.get() == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail
|
||||
jmethodID printStackTraceMethod =
|
||||
(*env)->GetMethodID(e, exceptionClass.get(), "printStackTrace", "(Ljava/io/PrintWriter;)V");
|
||||
(*env)->CallVoidMethod(e, exception, printStackTraceMethod, printWriter.get());
|
||||
|
||||
if ((*env)->ExceptionCheck(e)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scoped_local_ref<jstring> messageStr(env,
|
||||
(jstring) (*env)->CallObjectMethod(e, stringWriter.get(), stringWriterToStringMethod));
|
||||
if (messageStr.get() == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* utfChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL);
|
||||
if (utfChars == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = utfChars;
|
||||
|
||||
(*env)->ReleaseStringUTFChars(e, messageStr.get(), utfChars);
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" int jniThrowException(C_JNIEnv* env, const char* className, const char* msg) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
|
||||
if ((*env)->ExceptionCheck(e)) {
|
||||
/* TODO: consider creating the new exception with this as "cause" */
|
||||
scoped_local_ref<jthrowable> exception(env, (*env)->ExceptionOccurred(e));
|
||||
(*env)->ExceptionClear(e);
|
||||
|
||||
if (exception.get() != NULL) {
|
||||
std::string text;
|
||||
getExceptionSummary(env, exception.get(), text);
|
||||
ALOGW("Discarding pending exception (%s) to throw %s", text.c_str(), className);
|
||||
}
|
||||
}
|
||||
|
||||
scoped_local_ref<jclass> exceptionClass(env, findClass(env, className));
|
||||
if (exceptionClass.get() == NULL) {
|
||||
ALOGE("Unable to find exception class %s", className);
|
||||
/* ClassNotFoundException now pending */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*env)->ThrowNew(e, exceptionClass.get(), msg) != JNI_OK) {
|
||||
ALOGE("Failed throwing '%s' '%s'", className, msg);
|
||||
/* an exception, most likely OOM, will now be pending */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args) {
|
||||
char msgBuf[512];
|
||||
vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
|
||||
return jniThrowException(env, className, msgBuf);
|
||||
}
|
||||
|
||||
int jniThrowNullPointerException(C_JNIEnv* env, const char* msg) {
|
||||
return jniThrowException(env, "java/lang/NullPointerException", msg);
|
||||
}
|
||||
|
||||
int jniThrowRuntimeException(C_JNIEnv* env, const char* msg) {
|
||||
return jniThrowException(env, "java/lang/RuntimeException", msg);
|
||||
}
|
||||
|
||||
int jniThrowIOException(C_JNIEnv* env, int errnum) {
|
||||
char buffer[80];
|
||||
const char* message = jniStrError(errnum, buffer, sizeof(buffer));
|
||||
return jniThrowException(env, "java/io/IOException", message);
|
||||
}
|
||||
|
||||
static std::string jniGetStackTrace(C_JNIEnv* env, jthrowable exception) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
|
||||
scoped_local_ref<jthrowable> currentException(env, (*env)->ExceptionOccurred(e));
|
||||
if (exception == NULL) {
|
||||
exception = currentException.get();
|
||||
if (exception == NULL) {
|
||||
return "<no pending exception>";
|
||||
}
|
||||
}
|
||||
|
||||
if (currentException.get() != NULL) {
|
||||
(*env)->ExceptionClear(e);
|
||||
}
|
||||
|
||||
std::string trace;
|
||||
if (!getStackTrace(env, exception, trace)) {
|
||||
(*env)->ExceptionClear(e);
|
||||
getExceptionSummary(env, exception, trace);
|
||||
}
|
||||
|
||||
if (currentException.get() != NULL) {
|
||||
(*env)->Throw(e, currentException.get()); // rethrow
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception) {
|
||||
std::string trace(jniGetStackTrace(env, exception));
|
||||
__android_log_write(priority, tag, trace.c_str());
|
||||
}
|
||||
|
||||
const char* jniStrError(int errnum, char* buf, size_t buflen) {
|
||||
#if __GLIBC__
|
||||
// Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int.
|
||||
// char *strerror_r(int errnum, char *buf, size_t n);
|
||||
return strerror_r(errnum, buf, buflen);
|
||||
#else
|
||||
int rc = strerror_r(errnum, buf, buflen);
|
||||
if (rc != 0) {
|
||||
// (POSIX only guarantees a value other than 0. The safest
|
||||
// way to implement this function is to use C++ and overload on the
|
||||
// type of strerror_r to accurately distinguish GNU from POSIX.)
|
||||
snprintf(buf, buflen, "errno %d", errnum);
|
||||
}
|
||||
return buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
static jmethodID ctor = e->GetMethodID(JniConstants::fileDescriptorClass, "<init>", "()V");
|
||||
jobject fileDescriptor = (*env)->NewObject(e, JniConstants::fileDescriptorClass, ctor);
|
||||
// NOTE: NewObject ensures that an OutOfMemoryError will be seen by the Java
|
||||
// caller if the alloc fails, so we just return NULL when that happens.
|
||||
if (fileDescriptor != NULL) {
|
||||
jniSetFileDescriptorOfFD(env, fileDescriptor, fd);
|
||||
}
|
||||
return fileDescriptor;
|
||||
}
|
||||
|
||||
int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
|
||||
if (fileDescriptor != NULL) {
|
||||
return (*env)->GetIntField(e, fileDescriptor, fid);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
|
||||
(*env)->SetIntField(e, fileDescriptor, fid, value);
|
||||
}
|
||||
|
||||
jobject jniGetReferent(C_JNIEnv* env, jobject ref) {
|
||||
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
|
||||
static jmethodID get = e->GetMethodID(JniConstants::referenceClass, "get", "()Ljava/lang/Object;");
|
||||
return (*env)->CallObjectMethod(e, ref, get);
|
||||
}
|
||||
|
||||
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "JniConstants"
|
||||
|
||||
#include "ALog-priv.h"
|
||||
#include "JniConstants.h"
|
||||
#include "ScopedLocalRef.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
jclass JniConstants::bidiRunClass;
|
||||
jclass JniConstants::bigDecimalClass;
|
||||
jclass JniConstants::booleanClass;
|
||||
jclass JniConstants::byteArrayClass;
|
||||
jclass JniConstants::byteClass;
|
||||
jclass JniConstants::calendarClass;
|
||||
jclass JniConstants::characterClass;
|
||||
jclass JniConstants::charsetICUClass;
|
||||
jclass JniConstants::constructorClass;
|
||||
jclass JniConstants::deflaterClass;
|
||||
jclass JniConstants::doubleClass;
|
||||
jclass JniConstants::errnoExceptionClass;
|
||||
jclass JniConstants::fieldClass;
|
||||
jclass JniConstants::fieldPositionIteratorClass;
|
||||
jclass JniConstants::fileDescriptorClass;
|
||||
jclass JniConstants::floatClass;
|
||||
jclass JniConstants::gaiExceptionClass;
|
||||
jclass JniConstants::inet6AddressClass;
|
||||
jclass JniConstants::inetAddressClass;
|
||||
jclass JniConstants::inetSocketAddressClass;
|
||||
jclass JniConstants::inetUnixAddressClass;
|
||||
jclass JniConstants::inflaterClass;
|
||||
jclass JniConstants::inputStreamClass;
|
||||
jclass JniConstants::integerClass;
|
||||
jclass JniConstants::localeDataClass;
|
||||
jclass JniConstants::longClass;
|
||||
jclass JniConstants::methodClass;
|
||||
jclass JniConstants::mutableIntClass;
|
||||
jclass JniConstants::mutableLongClass;
|
||||
jclass JniConstants::objectClass;
|
||||
jclass JniConstants::objectArrayClass;
|
||||
jclass JniConstants::outputStreamClass;
|
||||
jclass JniConstants::parsePositionClass;
|
||||
jclass JniConstants::patternSyntaxExceptionClass;
|
||||
jclass JniConstants::realToStringClass;
|
||||
jclass JniConstants::referenceClass;
|
||||
jclass JniConstants::shortClass;
|
||||
jclass JniConstants::socketClass;
|
||||
jclass JniConstants::socketImplClass;
|
||||
jclass JniConstants::stringClass;
|
||||
jclass JniConstants::structAddrinfoClass;
|
||||
jclass JniConstants::structFlockClass;
|
||||
jclass JniConstants::structGroupReqClass;
|
||||
jclass JniConstants::structGroupSourceReqClass;
|
||||
jclass JniConstants::structLingerClass;
|
||||
jclass JniConstants::structPasswdClass;
|
||||
jclass JniConstants::structPollfdClass;
|
||||
jclass JniConstants::structStatClass;
|
||||
jclass JniConstants::structStatVfsClass;
|
||||
jclass JniConstants::structTimevalClass;
|
||||
jclass JniConstants::structUcredClass;
|
||||
jclass JniConstants::structUtsnameClass;
|
||||
|
||||
static jclass findClass(JNIEnv* env, const char* name) {
|
||||
ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
|
||||
jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
|
||||
if (result == NULL) {
|
||||
ALOGE("failed to find class '%s'", name);
|
||||
abort();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void JniConstants::init(JNIEnv* env) {
|
||||
bidiRunClass = findClass(env, "java/text/Bidi$Run");
|
||||
bigDecimalClass = findClass(env, "java/math/BigDecimal");
|
||||
booleanClass = findClass(env, "java/lang/Boolean");
|
||||
byteClass = findClass(env, "java/lang/Byte");
|
||||
byteArrayClass = findClass(env, "[B");
|
||||
calendarClass = findClass(env, "java/util/Calendar");
|
||||
characterClass = findClass(env, "java/lang/Character");
|
||||
charsetICUClass = findClass(env, "java/nio/charset/CharsetICU");
|
||||
constructorClass = findClass(env, "java/lang/reflect/Constructor");
|
||||
floatClass = findClass(env, "java/lang/Float");
|
||||
deflaterClass = findClass(env, "java/util/zip/Deflater");
|
||||
doubleClass = findClass(env, "java/lang/Double");
|
||||
errnoExceptionClass = findClass(env, "android/system/ErrnoException");
|
||||
fieldClass = findClass(env, "java/lang/reflect/Field");
|
||||
fieldPositionIteratorClass = findClass(env, "libcore/icu/NativeDecimalFormat$FieldPositionIterator");
|
||||
fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
|
||||
gaiExceptionClass = findClass(env, "android/system/GaiException");
|
||||
inet6AddressClass = findClass(env, "java/net/Inet6Address");
|
||||
inetAddressClass = findClass(env, "java/net/InetAddress");
|
||||
inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
|
||||
inetUnixAddressClass = findClass(env, "java/net/InetUnixAddress");
|
||||
inflaterClass = findClass(env, "java/util/zip/Inflater");
|
||||
inputStreamClass = findClass(env, "java/io/InputStream");
|
||||
integerClass = findClass(env, "java/lang/Integer");
|
||||
localeDataClass = findClass(env, "libcore/icu/LocaleData");
|
||||
longClass = findClass(env, "java/lang/Long");
|
||||
methodClass = findClass(env, "java/lang/reflect/Method");
|
||||
mutableIntClass = findClass(env, "android/util/MutableInt");
|
||||
mutableLongClass = findClass(env, "android/util/MutableLong");
|
||||
objectClass = findClass(env, "java/lang/Object");
|
||||
objectArrayClass = findClass(env, "[Ljava/lang/Object;");
|
||||
outputStreamClass = findClass(env, "java/io/OutputStream");
|
||||
parsePositionClass = findClass(env, "java/text/ParsePosition");
|
||||
patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException");
|
||||
realToStringClass = findClass(env, "java/lang/RealToString");
|
||||
referenceClass = findClass(env, "java/lang/ref/Reference");
|
||||
shortClass = findClass(env, "java/lang/Short");
|
||||
socketClass = findClass(env, "java/net/Socket");
|
||||
socketImplClass = findClass(env, "java/net/SocketImpl");
|
||||
stringClass = findClass(env, "java/lang/String");
|
||||
structAddrinfoClass = findClass(env, "android/system/StructAddrinfo");
|
||||
structFlockClass = findClass(env, "android/system/StructFlock");
|
||||
structGroupReqClass = findClass(env, "android/system/StructGroupReq");
|
||||
structGroupSourceReqClass = findClass(env, "android/system/StructGroupSourceReq");
|
||||
structLingerClass = findClass(env, "android/system/StructLinger");
|
||||
structPasswdClass = findClass(env, "android/system/StructPasswd");
|
||||
structPollfdClass = findClass(env, "android/system/StructPollfd");
|
||||
structStatClass = findClass(env, "android/system/StructStat");
|
||||
structStatVfsClass = findClass(env, "android/system/StructStatVfs");
|
||||
structTimevalClass = findClass(env, "android/system/StructTimeval");
|
||||
structUcredClass = findClass(env, "android/system/StructUcred");
|
||||
structUtsnameClass = findClass(env, "android/system/StructUtsname");
|
||||
}
|
||||
@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#include "JniInvocation.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#define LOG_TAG "JniInvocation"
|
||||
#include "cutils/log.h"
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
#include "cutils/properties.h"
|
||||
#endif
|
||||
|
||||
JniInvocation* JniInvocation::jni_invocation_ = NULL;
|
||||
|
||||
JniInvocation::JniInvocation() :
|
||||
handle_(NULL),
|
||||
JNI_GetDefaultJavaVMInitArgs_(NULL),
|
||||
JNI_CreateJavaVM_(NULL),
|
||||
JNI_GetCreatedJavaVMs_(NULL) {
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized");
|
||||
jni_invocation_ = this;
|
||||
}
|
||||
|
||||
JniInvocation::~JniInvocation() {
|
||||
jni_invocation_ = NULL;
|
||||
if (handle_ != NULL) {
|
||||
dlclose(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2";
|
||||
static const char* kDebuggableSystemProperty = "ro.debuggable";
|
||||
static const char* kDebuggableFallback = "0"; // Not debuggable.
|
||||
#endif
|
||||
static const char* kLibraryFallback = "libart.so";
|
||||
|
||||
const char* JniInvocation::GetLibrary(const char* library) {
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
char default_library[PROPERTY_VALUE_MAX];
|
||||
|
||||
char debuggable[PROPERTY_VALUE_MAX];
|
||||
property_get(kDebuggableSystemProperty, debuggable, kDebuggableFallback);
|
||||
|
||||
if (strcmp(debuggable, "1") != 0) {
|
||||
// Not a debuggable build.
|
||||
// Do not allow arbitrary library. Ignore the library parameter. This
|
||||
// will also ignore the default library, but initialize to empty string
|
||||
// for cleanliness.
|
||||
library = kLibraryFallback;
|
||||
default_library[0] = 0;
|
||||
} else {
|
||||
// Debuggable build.
|
||||
// Accept the library parameter. For the case it is NULL, load the default
|
||||
// library from the system property.
|
||||
property_get(kLibrarySystemProperty, default_library, kLibraryFallback);
|
||||
}
|
||||
#else
|
||||
const char* default_library = kLibraryFallback;
|
||||
#endif
|
||||
if (library == NULL) {
|
||||
library = default_library;
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
bool JniInvocation::Init(const char* library) {
|
||||
library = GetLibrary(library);
|
||||
|
||||
handle_ = dlopen(library, RTLD_NOW);
|
||||
if (handle_ == NULL) {
|
||||
if (strcmp(library, kLibraryFallback) == 0) {
|
||||
// Nothing else to try.
|
||||
ALOGE("Failed to dlopen %s: %s", library, dlerror());
|
||||
return false;
|
||||
}
|
||||
// Note that this is enough to get something like the zygote
|
||||
// running, we can't property_set here to fix this for the future
|
||||
// because we are root and not the system user. See
|
||||
// RuntimeInit.commonInit for where we fix up the property to
|
||||
// avoid future fallbacks. http://b/11463182
|
||||
ALOGW("Falling back from %s to %s after dlopen error: %s",
|
||||
library, kLibraryFallback, dlerror());
|
||||
library = kLibraryFallback;
|
||||
handle_ = dlopen(library, RTLD_NOW);
|
||||
if (handle_ == NULL) {
|
||||
ALOGE("Failed to dlopen %s: %s", library, dlerror());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
|
||||
"JNI_GetDefaultJavaVMInitArgs")) {
|
||||
return false;
|
||||
}
|
||||
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
|
||||
"JNI_CreateJavaVM")) {
|
||||
return false;
|
||||
}
|
||||
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
|
||||
"JNI_GetCreatedJavaVMs")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
jint JniInvocation::JNI_GetDefaultJavaVMInitArgs(void* vmargs) {
|
||||
return JNI_GetDefaultJavaVMInitArgs_(vmargs);
|
||||
}
|
||||
|
||||
jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
|
||||
return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
|
||||
}
|
||||
|
||||
jint JniInvocation::JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) {
|
||||
return JNI_GetCreatedJavaVMs_(vms, size, vm_count);
|
||||
}
|
||||
|
||||
bool JniInvocation::FindSymbol(void** pointer, const char* symbol) {
|
||||
*pointer = dlsym(handle_, symbol);
|
||||
if (*pointer == NULL) {
|
||||
ALOGE("Failed to find symbol %s: %s\n", symbol, dlerror());
|
||||
dlclose(handle_);
|
||||
handle_ = NULL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JniInvocation& JniInvocation::GetJniInvocation() {
|
||||
LOG_ALWAYS_FATAL_IF(jni_invocation_ == NULL,
|
||||
"Failed to create JniInvocation instance before using JNI invocation API");
|
||||
return *jni_invocation_;
|
||||
}
|
||||
|
||||
extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
|
||||
return JniInvocation::GetJniInvocation().JNI_GetDefaultJavaVMInitArgs(vm_args);
|
||||
}
|
||||
|
||||
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
|
||||
return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
|
||||
}
|
||||
|
||||
extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) {
|
||||
return JniInvocation::GetJniInvocation().JNI_GetCreatedJavaVMs(vms, size, vm_count);
|
||||
}
|
||||
@ -1,190 +0,0 @@
|
||||
|
||||
Copyright (c) 2005-2008, 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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
Support functions for Android's class libraries
|
||||
|
||||
|
||||
These are VM-agnostic native functions that implement methods for system
|
||||
class libraries. All code here:
|
||||
|
||||
- MUST not be associated with an android.* class (that code lives in
|
||||
frameworks/base/).
|
||||
- SHOULD be written in C rather than C++ where possible.
|
||||
|
||||
Some helper functions are defined in include/nativehelper/JNIHelp.h.
|
||||
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* JNI helper functions.
|
||||
*
|
||||
* This file may be included by C or C++ code, which is trouble because jni.h
|
||||
* uses different typedefs for JNIEnv in each language.
|
||||
*
|
||||
* TODO: remove C support.
|
||||
*/
|
||||
#ifndef NATIVEHELPER_JNIHELP_H_
|
||||
#define NATIVEHELPER_JNIHELP_H_
|
||||
|
||||
#include "jni.h"
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef NELEM
|
||||
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Register one or more native methods with a particular class.
|
||||
* "className" looks like "java/lang/String". Aborts on failure.
|
||||
* TODO: fix all callers and change the return type to void.
|
||||
*/
|
||||
int jniRegisterNativeMethods(C_JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods);
|
||||
|
||||
/*
|
||||
* Throw an exception with the specified class and an optional message.
|
||||
*
|
||||
* The "className" argument will be passed directly to FindClass, which
|
||||
* takes strings with slashes (e.g. "java/lang/Object").
|
||||
*
|
||||
* If an exception is currently pending, we log a warning message and
|
||||
* clear it.
|
||||
*
|
||||
* Returns 0 on success, nonzero if something failed (e.g. the exception
|
||||
* class couldn't be found, so *an* exception will still be pending).
|
||||
*
|
||||
* Currently aborts the VM if it can't throw the exception.
|
||||
*/
|
||||
int jniThrowException(C_JNIEnv* env, const char* className, const char* msg);
|
||||
|
||||
/*
|
||||
* Throw a java.lang.NullPointerException, with an optional message.
|
||||
*/
|
||||
int jniThrowNullPointerException(C_JNIEnv* env, const char* msg);
|
||||
|
||||
/*
|
||||
* Throw a java.lang.RuntimeException, with an optional message.
|
||||
*/
|
||||
int jniThrowRuntimeException(C_JNIEnv* env, const char* msg);
|
||||
|
||||
/*
|
||||
* Throw a java.io.IOException, generating the message from errno.
|
||||
*/
|
||||
int jniThrowIOException(C_JNIEnv* env, int errnum);
|
||||
|
||||
/*
|
||||
* Return a pointer to a locale-dependent error string explaining errno
|
||||
* value 'errnum'. The returned pointer may or may not be equal to 'buf'.
|
||||
* This function is thread-safe (unlike strerror) and portable (unlike
|
||||
* strerror_r).
|
||||
*/
|
||||
const char* jniStrError(int errnum, char* buf, size_t buflen);
|
||||
|
||||
/*
|
||||
* Returns a new java.io.FileDescriptor for the given int fd.
|
||||
*/
|
||||
jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd);
|
||||
|
||||
/*
|
||||
* Returns the int fd from a java.io.FileDescriptor.
|
||||
*/
|
||||
int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor);
|
||||
|
||||
/*
|
||||
* Sets the int fd in a java.io.FileDescriptor.
|
||||
*/
|
||||
void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value);
|
||||
|
||||
/*
|
||||
* Returns the reference from a java.lang.ref.Reference.
|
||||
*/
|
||||
jobject jniGetReferent(C_JNIEnv* env, jobject ref);
|
||||
|
||||
/*
|
||||
* Log a message and an exception.
|
||||
* If exception is NULL, logs the current exception in the JNI environment.
|
||||
*/
|
||||
void jniLogException(C_JNIEnv* env, int priority, const char* tag, jthrowable exception);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* For C++ code, we provide inlines that map to the C functions. g++ always
|
||||
* inlines these, even on non-optimized builds.
|
||||
*/
|
||||
#if defined(__cplusplus)
|
||||
inline int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) {
|
||||
return jniRegisterNativeMethods(&env->functions, className, gMethods, numMethods);
|
||||
}
|
||||
|
||||
inline int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
|
||||
return jniThrowException(&env->functions, className, msg);
|
||||
}
|
||||
|
||||
extern "C" int jniThrowExceptionFmt(C_JNIEnv* env, const char* className, const char* fmt, va_list args);
|
||||
|
||||
/*
|
||||
* Equivalent to jniThrowException but with a printf-like format string and
|
||||
* variable-length argument list. This is only available in C++.
|
||||
*/
|
||||
inline int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
return jniThrowExceptionFmt(&env->functions, className, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
inline int jniThrowNullPointerException(JNIEnv* env, const char* msg) {
|
||||
return jniThrowNullPointerException(&env->functions, msg);
|
||||
}
|
||||
|
||||
inline int jniThrowRuntimeException(JNIEnv* env, const char* msg) {
|
||||
return jniThrowRuntimeException(&env->functions, msg);
|
||||
}
|
||||
|
||||
inline int jniThrowIOException(JNIEnv* env, int errnum) {
|
||||
return jniThrowIOException(&env->functions, errnum);
|
||||
}
|
||||
|
||||
inline jobject jniCreateFileDescriptor(JNIEnv* env, int fd) {
|
||||
return jniCreateFileDescriptor(&env->functions, fd);
|
||||
}
|
||||
|
||||
inline int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
|
||||
return jniGetFDFromFileDescriptor(&env->functions, fileDescriptor);
|
||||
}
|
||||
|
||||
inline void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
|
||||
jniSetFileDescriptorOfFD(&env->functions, fileDescriptor, value);
|
||||
}
|
||||
|
||||
inline jobject jniGetReferent(JNIEnv* env, jobject ref) {
|
||||
return jniGetReferent(&env->functions, ref);
|
||||
}
|
||||
|
||||
inline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) {
|
||||
jniLogException(&env->functions, priority, tag, exception);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
|
||||
* <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
|
||||
* not already defined, then define it here.
|
||||
*/
|
||||
#ifndef TEMP_FAILURE_RETRY
|
||||
/* Used to retry syscalls that can return EINTR. */
|
||||
#define TEMP_FAILURE_RETRY(exp) ({ \
|
||||
typeof (exp) _rc; \
|
||||
do { \
|
||||
_rc = (exp); \
|
||||
} while (_rc == -1 && errno == EINTR); \
|
||||
_rc; })
|
||||
#endif
|
||||
|
||||
#endif /* NATIVEHELPER_JNIHELP_H_ */
|
||||
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef JNI_CONSTANTS_H_included
|
||||
#define JNI_CONSTANTS_H_included
|
||||
|
||||
#include "JNIHelp.h"
|
||||
|
||||
/**
|
||||
* A cache to avoid calling FindClass at runtime.
|
||||
*
|
||||
* Class lookup is relatively expensive (2.5us on passion-eng at the time of writing), so we do
|
||||
* all such lookups eagerly at startup. This means that code that never uses, say,
|
||||
* java.util.zip.Deflater still has to pay for the lookup, but it means that on a device the cost
|
||||
* is definitely paid during boot and amortized. A central cache also removes the temptation to
|
||||
* dynamically call FindClass rather than add a small cache to each file that needs one. Another
|
||||
* cost is that each class cached here requires a global reference, though in practice we save
|
||||
* enough by not having a global reference for each file that uses a class such as java.lang.String
|
||||
* which is used in several files.
|
||||
*
|
||||
* FindClass is still called in a couple of situations: when throwing exceptions, and in some of
|
||||
* the serialization code. The former is clearly not a performance case, and we're currently
|
||||
* assuming that neither is the latter.
|
||||
*
|
||||
* TODO: similar arguments hold for field and method IDs; we should cache them centrally too.
|
||||
*/
|
||||
struct JniConstants {
|
||||
static void init(JNIEnv* env);
|
||||
|
||||
static jclass bidiRunClass;
|
||||
static jclass bigDecimalClass;
|
||||
static jclass booleanClass;
|
||||
static jclass byteArrayClass;
|
||||
static jclass byteClass;
|
||||
static jclass calendarClass;
|
||||
static jclass characterClass;
|
||||
static jclass charsetICUClass;
|
||||
static jclass constructorClass;
|
||||
static jclass deflaterClass;
|
||||
static jclass doubleClass;
|
||||
static jclass errnoExceptionClass;
|
||||
static jclass fieldClass;
|
||||
static jclass fieldPositionIteratorClass;
|
||||
static jclass fileDescriptorClass;
|
||||
static jclass floatClass;
|
||||
static jclass gaiExceptionClass;
|
||||
static jclass inet6AddressClass;
|
||||
static jclass inetAddressClass;
|
||||
static jclass inetSocketAddressClass;
|
||||
static jclass inetUnixAddressClass;
|
||||
static jclass inflaterClass;
|
||||
static jclass inputStreamClass;
|
||||
static jclass integerClass;
|
||||
static jclass localeDataClass;
|
||||
static jclass longClass;
|
||||
static jclass methodClass;
|
||||
static jclass mutableIntClass;
|
||||
static jclass mutableLongClass;
|
||||
static jclass objectClass;
|
||||
static jclass objectArrayClass;
|
||||
static jclass outputStreamClass;
|
||||
static jclass parsePositionClass;
|
||||
static jclass patternSyntaxExceptionClass;
|
||||
static jclass realToStringClass;
|
||||
static jclass referenceClass;
|
||||
static jclass shortClass;
|
||||
static jclass socketClass;
|
||||
static jclass socketImplClass;
|
||||
static jclass stringClass;
|
||||
static jclass structAddrinfoClass;
|
||||
static jclass structFlockClass;
|
||||
static jclass structGroupReqClass;
|
||||
static jclass structGroupSourceReqClass;
|
||||
static jclass structLingerClass;
|
||||
static jclass structPasswdClass;
|
||||
static jclass structPollfdClass;
|
||||
static jclass structStatClass;
|
||||
static jclass structStatVfsClass;
|
||||
static jclass structTimevalClass;
|
||||
static jclass structUcredClass;
|
||||
static jclass structUtsnameClass;
|
||||
};
|
||||
|
||||
#define NATIVE_METHOD(className, functionName, signature) \
|
||||
{ #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
|
||||
|
||||
#endif // JNI_CONSTANTS_H_included
|
||||
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
#ifndef JNI_INVOCATION_H_included
|
||||
#define JNI_INVOCATION_H_included
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
// JniInvocation adds a layer of indirection for applications using
|
||||
// the JNI invocation API to allow the JNI implementation to be
|
||||
// selected dynamically. Apps can specify a specific implementation to
|
||||
// be used by calling InitJniInvocation. If this is not done, the
|
||||
// library will chosen based on the value of Android system property
|
||||
// persist.sys.dalvik.vm.lib on the device, and otherwise fall back to
|
||||
// a hard-coded default implementation.
|
||||
class JniInvocation {
|
||||
public:
|
||||
JniInvocation();
|
||||
|
||||
~JniInvocation();
|
||||
|
||||
// Initialize JNI invocation API. library should specifiy a valid
|
||||
// shared library for opening via dlopen providing a JNI invocation
|
||||
// implementation, or null to allow defaulting via
|
||||
// persist.sys.dalvik.vm.lib.
|
||||
bool Init(const char* library);
|
||||
|
||||
// Exposes which library is actually loaded from the given name.
|
||||
static const char* GetLibrary(const char* library);
|
||||
|
||||
private:
|
||||
|
||||
bool FindSymbol(void** pointer, const char* symbol);
|
||||
|
||||
static JniInvocation& GetJniInvocation();
|
||||
|
||||
jint JNI_GetDefaultJavaVMInitArgs(void* vmargs);
|
||||
jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
|
||||
jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count);
|
||||
|
||||
static JniInvocation* jni_invocation_;
|
||||
|
||||
void* handle_;
|
||||
jint (*JNI_GetDefaultJavaVMInitArgs_)(void*);
|
||||
jint (*JNI_CreateJavaVM_)(JavaVM**, JNIEnv**, void*);
|
||||
jint (*JNI_GetCreatedJavaVMs_)(JavaVM**, jsize, jsize*);
|
||||
|
||||
friend jint JNI_GetDefaultJavaVMInitArgs(void* vm_args);
|
||||
friend jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
|
||||
friend jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count);
|
||||
};
|
||||
|
||||
#endif // JNI_INVOCATION_H_included
|
||||
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_BYTES_H_included
|
||||
#define SCOPED_BYTES_H_included
|
||||
|
||||
#include "JNIHelp.h"
|
||||
|
||||
/**
|
||||
* ScopedBytesRO and ScopedBytesRW attempt to paper over the differences between byte[]s and
|
||||
* ByteBuffers. This in turn helps paper over the differences between non-direct ByteBuffers backed
|
||||
* by byte[]s, direct ByteBuffers backed by bytes[]s, and direct ByteBuffers not backed by byte[]s.
|
||||
* (On Android, this last group only contains MappedByteBuffers.)
|
||||
*/
|
||||
template<bool readOnly>
|
||||
class ScopedBytes {
|
||||
public:
|
||||
ScopedBytes(JNIEnv* env, jbyteArray object)
|
||||
: mEnv(env), mByteArray(object), mPtr(NULL)
|
||||
{
|
||||
if (mByteArray == NULL) {
|
||||
jniThrowNullPointerException(mEnv, NULL);
|
||||
} else {
|
||||
mPtr = mEnv->GetByteArrayElements(mByteArray, NULL);
|
||||
mLength = mEnv->GetArrayLength(mByteArray);
|
||||
}
|
||||
}
|
||||
|
||||
~ScopedBytes() {
|
||||
if (mByteArray != NULL) {
|
||||
mEnv->ReleaseByteArrayElements(mByteArray, mPtr, readOnly ? JNI_ABORT : 0);
|
||||
}
|
||||
}
|
||||
jsize length() {
|
||||
return mLength;
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* mEnv;
|
||||
jbyteArray mByteArray;
|
||||
|
||||
protected:
|
||||
jbyte* mPtr;
|
||||
jsize mLength;
|
||||
|
||||
private:
|
||||
// Disallow copy and assignment.
|
||||
ScopedBytes(const ScopedBytes&);
|
||||
void operator=(const ScopedBytes&);
|
||||
};
|
||||
|
||||
class ScopedBytesRO : public ScopedBytes<true> {
|
||||
public:
|
||||
ScopedBytesRO(JNIEnv* env, jbyteArray object) : ScopedBytes<true>(env, object) {}
|
||||
const jbyte* get() const {
|
||||
return mPtr;
|
||||
}
|
||||
};
|
||||
|
||||
class ScopedBytesRW : public ScopedBytes<false> {
|
||||
public:
|
||||
ScopedBytesRW(JNIEnv* env, jbyteArray object) : ScopedBytes<false>(env, object) {}
|
||||
jbyte* get() {
|
||||
return mPtr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SCOPED_BYTES_H_included
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_FD_H_included
|
||||
#define SCOPED_FD_H_included
|
||||
|
||||
#include <unistd.h>
|
||||
#include "JNIHelp.h" // for TEMP_FAILURE_RETRY
|
||||
|
||||
// A smart pointer that closes the given fd on going out of scope.
|
||||
// Use this when the fd is incidental to the purpose of your function,
|
||||
// but needs to be cleaned up on exit.
|
||||
class ScopedFd {
|
||||
public:
|
||||
explicit ScopedFd(int fd) : fd(fd) {
|
||||
}
|
||||
|
||||
~ScopedFd() {
|
||||
reset();
|
||||
}
|
||||
|
||||
int get() const {
|
||||
return fd;
|
||||
}
|
||||
|
||||
int release() __attribute__((warn_unused_result)) {
|
||||
int localFd = fd;
|
||||
fd = -1;
|
||||
return localFd;
|
||||
}
|
||||
|
||||
void reset(int new_fd = -1) {
|
||||
if (fd != -1) {
|
||||
TEMP_FAILURE_RETRY(close(fd));
|
||||
}
|
||||
fd = new_fd;
|
||||
}
|
||||
|
||||
private:
|
||||
int fd;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
ScopedFd(const ScopedFd&);
|
||||
void operator=(const ScopedFd&);
|
||||
};
|
||||
|
||||
#endif // SCOPED_FD_H_included
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_LOCAL_FRAME_H_included
|
||||
#define SCOPED_LOCAL_FRAME_H_included
|
||||
|
||||
#include "JNIHelp.h"
|
||||
|
||||
class ScopedLocalFrame {
|
||||
public:
|
||||
ScopedLocalFrame(JNIEnv* env) : mEnv(env) {
|
||||
mEnv->PushLocalFrame(128);
|
||||
}
|
||||
|
||||
~ScopedLocalFrame() {
|
||||
mEnv->PopLocalFrame(NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* mEnv;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
ScopedLocalFrame(const ScopedLocalFrame&);
|
||||
void operator=(const ScopedLocalFrame&);
|
||||
};
|
||||
|
||||
#endif // SCOPED_LOCAL_FRAME_H_included
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_LOCAL_REF_H_included
|
||||
#define SCOPED_LOCAL_REF_H_included
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// A smart pointer that deletes a JNI local reference when it goes out of scope.
|
||||
template<typename T>
|
||||
class ScopedLocalRef {
|
||||
public:
|
||||
ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) {
|
||||
}
|
||||
|
||||
~ScopedLocalRef() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset(T ptr = NULL) {
|
||||
if (ptr != mLocalRef) {
|
||||
if (mLocalRef != NULL) {
|
||||
mEnv->DeleteLocalRef(mLocalRef);
|
||||
}
|
||||
mLocalRef = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
T release() __attribute__((warn_unused_result)) {
|
||||
T localRef = mLocalRef;
|
||||
mLocalRef = NULL;
|
||||
return localRef;
|
||||
}
|
||||
|
||||
T get() const {
|
||||
return mLocalRef;
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* mEnv;
|
||||
T mLocalRef;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
ScopedLocalRef(const ScopedLocalRef&);
|
||||
void operator=(const ScopedLocalRef&);
|
||||
};
|
||||
|
||||
#endif // SCOPED_LOCAL_REF_H_included
|
||||
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_PRIMITIVE_ARRAY_H_included
|
||||
#define SCOPED_PRIMITIVE_ARRAY_H_included
|
||||
|
||||
#include "JNIHelp.h"
|
||||
|
||||
// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO,
|
||||
// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide
|
||||
// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write
|
||||
// access and should be used by default.
|
||||
#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \
|
||||
class Scoped ## NAME ## ArrayRO { \
|
||||
public: \
|
||||
explicit Scoped ## NAME ## ArrayRO(JNIEnv* env) \
|
||||
: mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \
|
||||
Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
|
||||
: mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
|
||||
if (mJavaArray == NULL) { \
|
||||
jniThrowNullPointerException(mEnv, NULL); \
|
||||
} else { \
|
||||
mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
|
||||
} \
|
||||
} \
|
||||
~Scoped ## NAME ## ArrayRO() { \
|
||||
if (mRawArray) { \
|
||||
mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \
|
||||
} \
|
||||
} \
|
||||
void reset(PRIMITIVE_TYPE ## Array javaArray) { \
|
||||
mJavaArray = javaArray; \
|
||||
mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
|
||||
} \
|
||||
const PRIMITIVE_TYPE* get() const { return mRawArray; } \
|
||||
PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
|
||||
const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
|
||||
size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
|
||||
private: \
|
||||
JNIEnv* mEnv; \
|
||||
PRIMITIVE_TYPE ## Array mJavaArray; \
|
||||
PRIMITIVE_TYPE* mRawArray; \
|
||||
Scoped ## NAME ## ArrayRO(const Scoped ## NAME ## ArrayRO&); \
|
||||
void operator=(const Scoped ## NAME ## ArrayRO&); \
|
||||
}
|
||||
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
|
||||
|
||||
#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO
|
||||
|
||||
// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW,
|
||||
// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide
|
||||
// convenient read-write access to Java arrays from JNI code. These are more expensive,
|
||||
// since they entail a copy back onto the Java heap, and should only be used when necessary.
|
||||
#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \
|
||||
class Scoped ## NAME ## ArrayRW { \
|
||||
public: \
|
||||
explicit Scoped ## NAME ## ArrayRW(JNIEnv* env) \
|
||||
: mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \
|
||||
Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
|
||||
: mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
|
||||
if (mJavaArray == NULL) { \
|
||||
jniThrowNullPointerException(mEnv, NULL); \
|
||||
} else { \
|
||||
mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
|
||||
} \
|
||||
} \
|
||||
~Scoped ## NAME ## ArrayRW() { \
|
||||
if (mRawArray) { \
|
||||
mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \
|
||||
} \
|
||||
} \
|
||||
void reset(PRIMITIVE_TYPE ## Array javaArray) { \
|
||||
mJavaArray = javaArray; \
|
||||
mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
|
||||
} \
|
||||
const PRIMITIVE_TYPE* get() const { return mRawArray; } \
|
||||
PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
|
||||
const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
|
||||
PRIMITIVE_TYPE* get() { return mRawArray; } \
|
||||
PRIMITIVE_TYPE& operator[](size_t n) { return mRawArray[n]; } \
|
||||
size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
|
||||
private: \
|
||||
JNIEnv* mEnv; \
|
||||
PRIMITIVE_TYPE ## Array mJavaArray; \
|
||||
PRIMITIVE_TYPE* mRawArray; \
|
||||
Scoped ## NAME ## ArrayRW(const Scoped ## NAME ## ArrayRW&); \
|
||||
void operator=(const Scoped ## NAME ## ArrayRW&); \
|
||||
}
|
||||
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long);
|
||||
INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short);
|
||||
|
||||
#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW
|
||||
|
||||
#endif // SCOPED_PRIMITIVE_ARRAY_H_included
|
||||
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_STRING_CHARS_H_included
|
||||
#define SCOPED_STRING_CHARS_H_included
|
||||
|
||||
#include "JNIHelp.h"
|
||||
|
||||
// A smart pointer that provides access to a jchar* given a JNI jstring.
|
||||
// Unlike GetStringChars, we throw NullPointerException rather than abort if
|
||||
// passed a null jstring, and get will return NULL.
|
||||
// This makes the correct idiom very simple:
|
||||
//
|
||||
// ScopedStringChars name(env, java_name);
|
||||
// if (name.get() == NULL) {
|
||||
// return NULL;
|
||||
// }
|
||||
class ScopedStringChars {
|
||||
public:
|
||||
ScopedStringChars(JNIEnv* env, jstring s) : env_(env), string_(s), size_(0) {
|
||||
if (s == NULL) {
|
||||
chars_ = NULL;
|
||||
jniThrowNullPointerException(env, NULL);
|
||||
} else {
|
||||
chars_ = env->GetStringChars(string_, NULL);
|
||||
if (chars_ != NULL) {
|
||||
size_ = env->GetStringLength(string_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~ScopedStringChars() {
|
||||
if (chars_ != NULL) {
|
||||
env_->ReleaseStringChars(string_, chars_);
|
||||
}
|
||||
}
|
||||
|
||||
const jchar* get() const {
|
||||
return chars_;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
const jchar& operator[](size_t n) const {
|
||||
return chars_[n];
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jstring string_;
|
||||
const jchar* chars_;
|
||||
size_t size_;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
ScopedStringChars(const ScopedStringChars&);
|
||||
void operator=(const ScopedStringChars&);
|
||||
};
|
||||
|
||||
#endif // SCOPED_STRING_CHARS_H_included
|
||||
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef SCOPED_UTF_CHARS_H_included
|
||||
#define SCOPED_UTF_CHARS_H_included
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include <string.h>
|
||||
|
||||
// A smart pointer that provides read-only access to a Java string's UTF chars.
|
||||
// Unlike GetStringUTFChars, we throw NullPointerException rather than abort if
|
||||
// passed a null jstring, and c_str will return NULL.
|
||||
// This makes the correct idiom very simple:
|
||||
//
|
||||
// ScopedUtfChars name(env, java_name);
|
||||
// if (name.c_str() == NULL) {
|
||||
// return NULL;
|
||||
// }
|
||||
class ScopedUtfChars {
|
||||
public:
|
||||
ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
|
||||
if (s == NULL) {
|
||||
utf_chars_ = NULL;
|
||||
jniThrowNullPointerException(env, NULL);
|
||||
} else {
|
||||
utf_chars_ = env->GetStringUTFChars(s, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
~ScopedUtfChars() {
|
||||
if (utf_chars_) {
|
||||
env_->ReleaseStringUTFChars(string_, utf_chars_);
|
||||
}
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
return utf_chars_;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return strlen(utf_chars_);
|
||||
}
|
||||
|
||||
const char& operator[](size_t n) const {
|
||||
return utf_chars_[n];
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jstring string_;
|
||||
const char* utf_chars_;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
ScopedUtfChars(const ScopedUtfChars&);
|
||||
void operator=(const ScopedUtfChars&);
|
||||
};
|
||||
|
||||
#endif // SCOPED_UTF_CHARS_H_included
|
||||
@ -1,241 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
|
||||
#ifndef UNIQUE_PTR_H_included
|
||||
#define UNIQUE_PTR_H_included
|
||||
|
||||
#include <cstdlib> // For NULL.
|
||||
|
||||
// This is a fake declaration of std::swap to avoid including <algorithm>
|
||||
namespace std {
|
||||
template <class T> void swap(T&, T&);
|
||||
}
|
||||
|
||||
// Default deleter for pointer types.
|
||||
template <typename T>
|
||||
struct DefaultDelete {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
DefaultDelete() {}
|
||||
void operator()(T* p) const {
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
|
||||
// Default deleter for array types.
|
||||
template <typename T>
|
||||
struct DefaultDelete<T[]> {
|
||||
enum { type_must_be_complete = sizeof(T) };
|
||||
void operator()(T* p) const {
|
||||
delete[] p;
|
||||
}
|
||||
};
|
||||
|
||||
// A smart pointer that deletes the given pointer on destruction.
|
||||
// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
|
||||
// and boost::scoped_array).
|
||||
// Named to be in keeping with Android style but also to avoid
|
||||
// collision with any other implementation, until we can switch over
|
||||
// to unique_ptr.
|
||||
// Use thus:
|
||||
// UniquePtr<C> c(new C);
|
||||
template <typename T, typename D = DefaultDelete<T> >
|
||||
class UniquePtr {
|
||||
public:
|
||||
// Construct a new UniquePtr, taking ownership of the given raw pointer.
|
||||
explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
|
||||
}
|
||||
|
||||
~UniquePtr() {
|
||||
reset();
|
||||
}
|
||||
|
||||
// Accessors.
|
||||
T& operator*() const { return *mPtr; }
|
||||
T* operator->() const { return mPtr; }
|
||||
T* get() const { return mPtr; }
|
||||
|
||||
// Returns the raw pointer and hands over ownership to the caller.
|
||||
// The pointer will not be deleted by UniquePtr.
|
||||
T* release() __attribute__((warn_unused_result)) {
|
||||
T* result = mPtr;
|
||||
mPtr = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Takes ownership of the given raw pointer.
|
||||
// If this smart pointer previously owned a different raw pointer, that
|
||||
// raw pointer will be freed.
|
||||
void reset(T* ptr = NULL) {
|
||||
if (ptr != mPtr) {
|
||||
D()(mPtr);
|
||||
mPtr = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Swap with another unique pointer.
|
||||
void swap(UniquePtr<T>& other) {
|
||||
std::swap(mPtr, other.mPtr);
|
||||
}
|
||||
|
||||
private:
|
||||
// The raw pointer.
|
||||
T* mPtr;
|
||||
|
||||
// Comparing unique pointers is probably a mistake, since they're unique.
|
||||
template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
|
||||
template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
UniquePtr(const UniquePtr&);
|
||||
void operator=(const UniquePtr&);
|
||||
};
|
||||
|
||||
// Partial specialization for array types. Like std::unique_ptr, this removes
|
||||
// operator* and operator-> but adds operator[].
|
||||
template <typename T, typename D>
|
||||
class UniquePtr<T[], D> {
|
||||
public:
|
||||
explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
|
||||
}
|
||||
|
||||
~UniquePtr() {
|
||||
reset();
|
||||
}
|
||||
|
||||
T& operator[](size_t i) const {
|
||||
return mPtr[i];
|
||||
}
|
||||
T* get() const { return mPtr; }
|
||||
|
||||
T* release() __attribute__((warn_unused_result)) {
|
||||
T* result = mPtr;
|
||||
mPtr = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void reset(T* ptr = NULL) {
|
||||
if (ptr != mPtr) {
|
||||
D()(mPtr);
|
||||
mPtr = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T* mPtr;
|
||||
|
||||
// Disallow copy and assignment.
|
||||
UniquePtr(const UniquePtr&);
|
||||
void operator=(const UniquePtr&);
|
||||
};
|
||||
|
||||
#if UNIQUE_PTR_TESTS
|
||||
|
||||
// Run these tests with:
|
||||
// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static void assert(bool b) {
|
||||
if (!b) {
|
||||
fprintf(stderr, "FAIL\n");
|
||||
abort();
|
||||
}
|
||||
fprintf(stderr, "OK\n");
|
||||
}
|
||||
static int cCount = 0;
|
||||
struct C {
|
||||
C() { ++cCount; }
|
||||
~C() { --cCount; }
|
||||
};
|
||||
static bool freed = false;
|
||||
struct Freer {
|
||||
void operator()(int* p) {
|
||||
assert(*p == 123);
|
||||
free(p);
|
||||
freed = true;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
//
|
||||
// UniquePtr<T> tests...
|
||||
//
|
||||
|
||||
// Can we free a single object?
|
||||
{
|
||||
UniquePtr<C> c(new C);
|
||||
assert(cCount == 1);
|
||||
}
|
||||
assert(cCount == 0);
|
||||
// Does release work?
|
||||
C* rawC;
|
||||
{
|
||||
UniquePtr<C> c(new C);
|
||||
assert(cCount == 1);
|
||||
rawC = c.release();
|
||||
}
|
||||
assert(cCount == 1);
|
||||
delete rawC;
|
||||
// Does reset work?
|
||||
{
|
||||
UniquePtr<C> c(new C);
|
||||
assert(cCount == 1);
|
||||
c.reset(new C);
|
||||
assert(cCount == 1);
|
||||
}
|
||||
assert(cCount == 0);
|
||||
|
||||
//
|
||||
// UniquePtr<T[]> tests...
|
||||
//
|
||||
|
||||
// Can we free an array?
|
||||
{
|
||||
UniquePtr<C[]> cs(new C[4]);
|
||||
assert(cCount == 4);
|
||||
}
|
||||
assert(cCount == 0);
|
||||
// Does release work?
|
||||
{
|
||||
UniquePtr<C[]> c(new C[4]);
|
||||
assert(cCount == 4);
|
||||
rawC = c.release();
|
||||
}
|
||||
assert(cCount == 4);
|
||||
delete[] rawC;
|
||||
// Does reset work?
|
||||
{
|
||||
UniquePtr<C[]> c(new C[4]);
|
||||
assert(cCount == 4);
|
||||
c.reset(new C[2]);
|
||||
assert(cCount == 2);
|
||||
}
|
||||
assert(cCount == 0);
|
||||
|
||||
//
|
||||
// Custom deleter tests...
|
||||
//
|
||||
assert(!freed);
|
||||
{
|
||||
UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
|
||||
*i = 123;
|
||||
}
|
||||
assert(freed);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // UNIQUE_PTR_H_included
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
#ifndef TO_STRING_ARRAY_H_included
|
||||
#define TO_STRING_ARRAY_H_included
|
||||
|
||||
#include "jni.h"
|
||||
#include "ScopedLocalRef.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
jobjectArray newStringArray(JNIEnv* env, size_t count);
|
||||
|
||||
template <typename Counter, typename Getter>
|
||||
jobjectArray toStringArray(JNIEnv* env, Counter* counter, Getter* getter) {
|
||||
size_t count = (*counter)();
|
||||
jobjectArray result = newStringArray(env, count);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
ScopedLocalRef<jstring> s(env, env->NewStringUTF((*getter)(i)));
|
||||
if (env->ExceptionCheck()) {
|
||||
return NULL;
|
||||
}
|
||||
env->SetObjectArrayElement(result, i, s.get());
|
||||
if (env->ExceptionCheck()) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct VectorCounter {
|
||||
const std::vector<std::string>& strings;
|
||||
VectorCounter(const std::vector<std::string>& strings) : strings(strings) {}
|
||||
size_t operator()() {
|
||||
return strings.size();
|
||||
}
|
||||
};
|
||||
struct VectorGetter {
|
||||
const std::vector<std::string>& strings;
|
||||
VectorGetter(const std::vector<std::string>& strings) : strings(strings) {}
|
||||
const char* operator()(size_t i) {
|
||||
return strings[i].c_str();
|
||||
}
|
||||
};
|
||||
|
||||
inline jobjectArray toStringArray(JNIEnv* env, const std::vector<std::string>& strings) {
|
||||
VectorCounter counter(strings);
|
||||
VectorGetter getter(strings);
|
||||
return toStringArray<VectorCounter, VectorGetter>(env, &counter, &getter);
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray toStringArray(JNIEnv* env, const char* const* strings);
|
||||
|
||||
#endif // TO_STRING_ARRAY_H_included
|
||||
@ -1,35 +0,0 @@
|
||||
# Build the unit tests.
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Target unit test.
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := JniInvocation_test
|
||||
LOCAL_CLANG := true
|
||||
LOCAL_SRC_FILES := JniInvocation_test.cpp
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libnativehelper
|
||||
|
||||
include external/libcxx/libcxx.mk
|
||||
|
||||
LOCAL_MULTILIB := both
|
||||
LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
|
||||
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
||||
# Host unit test.
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := JniInvocation_test
|
||||
LOCAL_CLANG := true
|
||||
LOCAL_SRC_FILES := JniInvocation_test.cpp
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libnativehelper
|
||||
|
||||
include external/libcxx/libcxx.mk
|
||||
|
||||
LOCAL_MULTILIB := both
|
||||
LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
|
||||
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
|
||||
include $(BUILD_HOST_NATIVE_TEST)
|
||||
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "NativeBridge_test"
|
||||
|
||||
#include <JniInvocation.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#if defined(HAVE_ANDROID_OS) && defined(__BIONIC__)
|
||||
#define HAVE_TEST_STUFF 1
|
||||
#else
|
||||
#undef HAVE_TEST_STUFF
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TEST_STUFF
|
||||
|
||||
// Ability to have fake local system properties.
|
||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||
#include <sys/_system_properties.h>
|
||||
|
||||
extern void *__system_property_area__;
|
||||
|
||||
struct LocalPropertyTestState {
|
||||
LocalPropertyTestState() : valid(false) {
|
||||
const char* ANDROID_DATA = getenv("ANDROID_DATA");
|
||||
char dir_template[PATH_MAX];
|
||||
snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", ANDROID_DATA);
|
||||
char* dirname = mkdtemp(dir_template);
|
||||
if (!dirname) {
|
||||
fprintf(stderr, "making temp file for test state failed (is %s writable?): %s",
|
||||
dir_template, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
old_pa = __system_property_area__;
|
||||
__system_property_area__ = NULL;
|
||||
|
||||
pa_dirname = dirname;
|
||||
pa_filename = pa_dirname + "/__properties__";
|
||||
|
||||
__system_property_set_filename(pa_filename.c_str());
|
||||
__system_property_area_init();
|
||||
valid = true;
|
||||
}
|
||||
|
||||
~LocalPropertyTestState() {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
__system_property_area__ = old_pa;
|
||||
|
||||
__system_property_set_filename(PROP_FILENAME);
|
||||
unlink(pa_filename.c_str());
|
||||
rmdir(pa_dirname.c_str());
|
||||
}
|
||||
public:
|
||||
bool valid;
|
||||
private:
|
||||
std::string pa_dirname;
|
||||
std::string pa_filename;
|
||||
void *old_pa;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
|
||||
class JNIInvocationTest : public testing::Test {
|
||||
};
|
||||
|
||||
#ifdef HAVE_TEST_STUFF
|
||||
static const char* kDebuggableSystemProperty = "ro.debuggable";
|
||||
static const char* kIsDebuggableValue = "1";
|
||||
static const char* kIsNotDebuggableValue = "0";
|
||||
|
||||
static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2";
|
||||
static const char* kTestNonNull = "libartd.so";
|
||||
static const char* kTestNonNull2 = "libartd2.so";
|
||||
static const char* kExpected = "libart.so";
|
||||
#endif
|
||||
|
||||
TEST_F(JNIInvocationTest, Debuggable) {
|
||||
#ifdef HAVE_TEST_STUFF
|
||||
LocalPropertyTestState pa;
|
||||
ASSERT_TRUE(pa.valid);
|
||||
ASSERT_EQ(0, __system_property_add(kDebuggableSystemProperty, 13, kIsDebuggableValue, 1));
|
||||
ASSERT_EQ(0, __system_property_add(kLibrarySystemProperty, 27, kTestNonNull2, 11));
|
||||
|
||||
const char* result = JniInvocation::GetLibrary(NULL);
|
||||
EXPECT_FALSE(result == NULL);
|
||||
if (result != NULL) {
|
||||
EXPECT_TRUE(strcmp(result, kTestNonNull2) == 0);
|
||||
EXPECT_FALSE(strcmp(result, kExpected) == 0);
|
||||
}
|
||||
|
||||
result = JniInvocation::GetLibrary(kTestNonNull);
|
||||
EXPECT_FALSE(result == NULL);
|
||||
if (result != NULL) {
|
||||
EXPECT_TRUE(strcmp(result, kTestNonNull) == 0);
|
||||
EXPECT_FALSE(strcmp(result, kTestNonNull2) == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(JNIInvocationTest, NonDebuggable) {
|
||||
#ifdef HAVE_TEST_STUFF
|
||||
LocalPropertyTestState pa;
|
||||
ASSERT_TRUE(pa.valid);
|
||||
ASSERT_EQ(0, __system_property_add(kDebuggableSystemProperty, 13, kIsNotDebuggableValue, 1));
|
||||
|
||||
const char* result = JniInvocation::GetLibrary(NULL);
|
||||
EXPECT_FALSE(result == NULL);
|
||||
if (result != NULL) {
|
||||
EXPECT_TRUE(strcmp(result, kExpected) == 0);
|
||||
EXPECT_FALSE(strcmp(result, kTestNonNull) == 0);
|
||||
EXPECT_FALSE(strcmp(result, kTestNonNull2) == 0);
|
||||
}
|
||||
|
||||
result = JniInvocation::GetLibrary(kTestNonNull);
|
||||
EXPECT_FALSE(result == NULL);
|
||||
if (result != NULL) {
|
||||
EXPECT_TRUE(strcmp(result, kExpected) == 0);
|
||||
EXPECT_FALSE(strcmp(result, kTestNonNull) == 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
#include "JniConstants.h"
|
||||
#include "toStringArray.h"
|
||||
|
||||
jobjectArray newStringArray(JNIEnv* env, size_t count) {
|
||||
return env->NewObjectArray(count, JniConstants::stringClass, NULL);
|
||||
}
|
||||
|
||||
struct ArrayCounter {
|
||||
const char* const* strings;
|
||||
ArrayCounter(const char* const* strings) : strings(strings) {}
|
||||
size_t operator()() {
|
||||
size_t count = 0;
|
||||
while (strings[count] != NULL) {
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArrayGetter {
|
||||
const char* const* strings;
|
||||
ArrayGetter(const char* const* strings) : strings(strings) {}
|
||||
const char* operator()(size_t i) {
|
||||
return strings[i];
|
||||
}
|
||||
};
|
||||
|
||||
jobjectArray toStringArray(JNIEnv* env, const char* const* strings) {
|
||||
ArrayCounter counter(strings);
|
||||
ArrayGetter getter(strings);
|
||||
return toStringArray(env, &counter, &getter);
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
../../../../../src/impl/list_ports/list_ports_linux.cc
|
||||
@ -1 +0,0 @@
|
||||
../../../../../src/serial.cc
|
||||
@ -1,466 +0,0 @@
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include "jni_utility.h"
|
||||
#include <serial/serial.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace serial;
|
||||
|
||||
#define MAKE_TIMEOUT(env,in,out) jint* _array = (env)->GetIntArrayElements((in), NULL); \
|
||||
if (_array[0] == -1) {\
|
||||
_array[0] = Timeout::max();\
|
||||
}\
|
||||
Timeout out(_array[0], _array[1], _array[2], _array[3], _array[4]);\
|
||||
env->ReleaseIntArrayElements((in), _array, JNI_ABORT)
|
||||
|
||||
|
||||
#define _BEGIN_TRY try {
|
||||
#define _CATCH(cpp_ex) } catch (cpp_ex& _ex) {
|
||||
#define _CATCH_AND_THROW(env, cpp_ex, java_ex) } catch (cpp_ex& _ex) { \
|
||||
LOGE("%s", _ex.what());\
|
||||
(env)->ThrowNew(java_ex, _ex.what());
|
||||
#define _END_TRY }
|
||||
|
||||
static jclass gSerialExceptionClass = 0;
|
||||
static jclass gSerialIOExceptionClass = 0;
|
||||
static jclass gIllegalArgumentException = 0;
|
||||
|
||||
static jobjectArray native_listPorts(JNIEnv *env, jobject)
|
||||
{
|
||||
std::vector<PortInfo> ports = list_ports();
|
||||
jobjectArray portDescs = createStringArray(env, ports.size());
|
||||
int i = 0;
|
||||
for(std::vector<PortInfo>::iterator it = ports.begin(); it < ports.end(); ++it, ++i) {
|
||||
std::string desc;
|
||||
desc += it->port;
|
||||
desc.push_back('\t');
|
||||
desc += it->description;
|
||||
desc.push_back('\t');
|
||||
desc += it->hardware_id;
|
||||
env->SetObjectArrayElement(portDescs, i, stdStringToJstring(desc));
|
||||
}
|
||||
|
||||
return portDescs;
|
||||
}
|
||||
|
||||
static jlong native_create(JNIEnv *env, jobject, jstring jport, jint baudrate, jintArray jtimeout, jint bytesize, jint parity, jint stopbits, jint flowcontrol)
|
||||
{
|
||||
std::string port = jstringToStdString(jport);
|
||||
MAKE_TIMEOUT(env, jtimeout, timeout);
|
||||
|
||||
Serial * com = NULL;
|
||||
_BEGIN_TRY
|
||||
Serial * com = new Serial(port, (uint32_t)baudrate, timeout,
|
||||
bytesize_t(bytesize), parity_t(parity), stopbits_t(stopbits), flowcontrol_t(flowcontrol));
|
||||
LOGD("Native serial port object %p.", com);
|
||||
return (jlong)com;
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
return (jlong)com;
|
||||
}
|
||||
|
||||
static void native_destory(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
if (com)
|
||||
delete com;
|
||||
}
|
||||
|
||||
static void native_open(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->open();
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jboolean native_isOpen(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
return com->isOpen() ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static void native_close(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->close();
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jint native_available(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
return (jint)com->available();
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_END_TRY
|
||||
return -1;
|
||||
}
|
||||
|
||||
static jboolean native_waitReadable(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
return com->waitReadable() ? JNI_TRUE : JNI_FALSE;
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_END_TRY
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static void native_waitByteTimes(JNIEnv *env, jobject, jlong ptr, jint count)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
com->waitByteTimes(count);
|
||||
}
|
||||
|
||||
static jint native_read(JNIEnv *env, jobject, jlong ptr, jbyteArray jbuffer, jint offset, jint size)
|
||||
{
|
||||
LOGI("native_read(0x%08llx,%p,%d,%d)", ptr, jbuffer, offset, size);
|
||||
Serial * com = (Serial *)ptr;
|
||||
jbyte* jarray = env->GetByteArrayElements(jbuffer, NULL);
|
||||
if (jarray) {
|
||||
uint8_t * buffer = (uint8_t *)(jarray + offset);
|
||||
LOGI("buffer = %p, size=%d", buffer, size);
|
||||
_BEGIN_TRY
|
||||
int bytesRead = com->read(buffer, (size_t)size);
|
||||
LOGI("bytes read = %d", bytesRead);
|
||||
env->ReleaseByteArrayElements(jbuffer, jarray, 0);
|
||||
return (jint)bytesRead;
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
env->ReleaseByteArrayElements(jbuffer, jarray, JNI_ABORT);
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
env->ReleaseByteArrayElements(jbuffer, jarray, JNI_ABORT);
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
env->ReleaseByteArrayElements(jbuffer, jarray, JNI_ABORT);
|
||||
_END_TRY
|
||||
return -1;
|
||||
}
|
||||
return -1; // Failed
|
||||
}
|
||||
|
||||
static jstring native_readline(JNIEnv *env, jobject, jlong ptr, jint size, jstring jeol)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
std::string eol = jstringToStdString(jeol);
|
||||
_BEGIN_TRY
|
||||
std::string line = com->readline(size, eol);
|
||||
return stdStringToJstring(line);
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_END_TRY
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static jobjectArray native_readlines(JNIEnv *env, jobject, jlong ptr, jint size, jstring jeol)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
std::string eol = jstringToStdString(jeol);
|
||||
jobjectArray jlines = NULL;
|
||||
_BEGIN_TRY
|
||||
vector<string> lines = com->readlines(size, eol);
|
||||
jlines = createStringArray(env, lines.size());
|
||||
int i = 0;
|
||||
for(vector<string>::iterator it = lines.begin(); it < lines.end(); ++it, ++i) {
|
||||
env->SetObjectArrayElement(jlines, i, stdStringToJstring(*it));
|
||||
}
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_END_TRY
|
||||
return jlines;
|
||||
}
|
||||
|
||||
static jint native_write(JNIEnv *env, jobject, jlong ptr, jbyteArray jdata, jint size)
|
||||
{
|
||||
LOGI("native_write(0x%08llx,%p,%d)", ptr, jdata, size);
|
||||
Serial * com = (Serial *)ptr;
|
||||
jbyte* jarray = env->GetByteArrayElements(jdata, NULL);
|
||||
if (jarray) {
|
||||
uint8_t * data = (uint8_t *)jarray;
|
||||
LOGI("data = %p, size=%d", data, size);
|
||||
_BEGIN_TRY
|
||||
int bytesWritten = com->write(data, (size_t)size);
|
||||
LOGI("bytes written = %d", bytesWritten);
|
||||
env->ReleaseByteArrayElements(jdata, jarray, JNI_ABORT);
|
||||
return (jint)bytesWritten;
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
env->ReleaseByteArrayElements(jdata, jarray, JNI_ABORT);
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
env->ReleaseByteArrayElements(jdata, jarray, JNI_ABORT);
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
env->ReleaseByteArrayElements(jdata, jarray, JNI_ABORT);
|
||||
_END_TRY
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void native_setPort(JNIEnv *env, jobject, jlong ptr, jstring jport)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
std::string port = jstringToStdString(jport);
|
||||
com->setPort(port);
|
||||
}
|
||||
|
||||
static jstring native_getPort(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
std::string port = com->getPort();
|
||||
return stdStringToJstring(port);
|
||||
}
|
||||
|
||||
static void native_setBaudrate(JNIEnv *env, jobject, jlong ptr, jint baudrate)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setBaudrate((uint32_t)baudrate);
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jint native_getBaudrate(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
return (jint)com->getBaudrate();
|
||||
}
|
||||
|
||||
static void native_setTimeout(JNIEnv *env, jobject, jlong ptr, jintArray jtimeout)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
MAKE_TIMEOUT(env, jtimeout, timeout);
|
||||
com->setTimeout(timeout);
|
||||
}
|
||||
|
||||
static void native_setBytesize(JNIEnv *env, jobject, jlong ptr, jint bytesize)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setBytesize(bytesize_t(bytesize));
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jint native_getBytesize(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
return (jint)com->getBytesize();
|
||||
}
|
||||
|
||||
static void native_setParity(JNIEnv *env, jobject, jlong ptr, jint parity)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setParity(parity_t(parity));
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jint native_getParity(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
return (jint)com->getParity();
|
||||
}
|
||||
|
||||
static void native_setStopbits(JNIEnv *env, jobject, jlong ptr, jint stopbits)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setStopbits(stopbits_t(stopbits));
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jint native_getStopbits(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
return (jint)com->getStopbits();
|
||||
}
|
||||
|
||||
static void native_setFlowcontrol(JNIEnv *env, jobject, jlong ptr, jint flowcontrol)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setFlowcontrol(flowcontrol_t(flowcontrol));
|
||||
_CATCH_AND_THROW(env, invalid_argument, gIllegalArgumentException)
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jint native_getFlowcontrol(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
return (jint)com->getFlowcontrol();
|
||||
}
|
||||
|
||||
static void native_flush(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
com->flush();
|
||||
}
|
||||
|
||||
static void native_flushInput(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
com->flushInput();
|
||||
}
|
||||
|
||||
static void native_flushOutput(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
com->flushOutput();
|
||||
}
|
||||
|
||||
static void native_sendBreak(JNIEnv *env, jobject, jlong ptr, jint duration)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
com->sendBreak((int)duration);
|
||||
}
|
||||
|
||||
static void native_setBreak(JNIEnv *env, jobject, jlong ptr, jboolean level)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setBreak((bool)level);
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static void native_setRTS(JNIEnv *env, jobject, jlong ptr, jboolean level)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setRTS((bool)level);
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static void native_setDTR(JNIEnv *env, jobject, jlong ptr, jboolean level)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
com->setDTR((bool)level);
|
||||
_CATCH_AND_THROW(env, IOException, gSerialIOExceptionClass)
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
}
|
||||
|
||||
static jboolean native_waitForChange(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
return com->waitForChange() ? JNI_TRUE : JNI_FALSE;
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean native_getCTS(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
return com->getCTS() ? JNI_TRUE : JNI_FALSE;
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean native_getDSR(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
return com->getDSR() ? JNI_TRUE : JNI_FALSE;
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean native_getRI(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
return com->getRI() ? JNI_TRUE : JNI_FALSE;
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean native_getCD(JNIEnv *env, jobject, jlong ptr)
|
||||
{
|
||||
Serial * com = (Serial *)ptr;
|
||||
_BEGIN_TRY
|
||||
return com->getCD() ? JNI_TRUE : JNI_FALSE;
|
||||
_CATCH_AND_THROW(env, SerialException, gSerialExceptionClass)
|
||||
_END_TRY
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static JNINativeMethod gSerialMethods[] = {
|
||||
{ "native_listPorts", "()[Ljava/lang/String;", (void*) native_listPorts },
|
||||
{ "native_create", "(Ljava/lang/String;I[IIIII)J", (void*) native_create },
|
||||
{ "native_destory", "(J)V", (void*) native_destory },
|
||||
{ "native_open", "(J)V", (void*) native_open },
|
||||
{ "native_isOpen", "(J)Z", (void*) native_isOpen },
|
||||
{ "native_close", "(J)V", (void*) native_close },
|
||||
{ "native_available", "(J)I", (void*) native_available },
|
||||
{ "native_waitReadable", "(J)Z", (void*) native_waitReadable },
|
||||
{ "native_waitByteTimes", "(JI)V", (void*) native_waitByteTimes },
|
||||
{ "native_read", "(J[BII)I", (void*) native_read },
|
||||
{ "native_readline", "(JILjava/lang/String;)Ljava/lang/String;", (void*) native_readline },
|
||||
{ "native_readlines", "(JILjava/lang/String;)[Ljava/lang/String;", (void*) native_readlines },
|
||||
{ "native_write", "(J[BI)I", (void*) native_write },
|
||||
{ "native_setPort", "(JLjava/lang/String;)V", (void*) native_setPort },
|
||||
{ "native_getPort", "(J)Ljava/lang/String;", (void*) native_getPort },
|
||||
{ "native_setBaudrate", "(JI)V", (void*) native_setBaudrate },
|
||||
{ "native_getBaudrate", "(J)I", (void*) native_getBaudrate },
|
||||
{ "native_setTimeout", "(J[I)V", (void*) native_setTimeout },
|
||||
{ "native_setBytesize", "(JI)V", (void*) native_setBytesize },
|
||||
{ "native_getBytesize", "(J)I", (void*) native_getBytesize },
|
||||
{ "native_setParity", "(JI)V", (void*) native_setParity },
|
||||
{ "native_getParity", "(J)I", (void*) native_getParity },
|
||||
{ "native_setStopbits", "(JI)V", (void*) native_setStopbits },
|
||||
{ "native_getStopbits", "(J)I", (void*) native_getStopbits },
|
||||
{ "native_setFlowcontrol", "(JI)V", (void*) native_setFlowcontrol },
|
||||
{ "native_getFlowcontrol", "(J)I", (void*) native_getFlowcontrol },
|
||||
{ "native_flush", "(J)V", (void*) native_flush },
|
||||
{ "native_flushInput", "(J)V", (void*) native_flushInput },
|
||||
{ "native_flushOutput", "(J)V", (void*) native_flushOutput },
|
||||
{ "native_sendBreak", "(JI)V", (void*) native_sendBreak },
|
||||
{ "native_setBreak", "(JZ)V", (void*) native_setBreak },
|
||||
{ "native_setRTS", "(JZ)V", (void*) native_setRTS },
|
||||
{ "native_setDTR", "(JZ)V", (void*) native_setDTR },
|
||||
{ "native_waitForChange", "(J)Z", (void*) native_waitForChange },
|
||||
{ "native_getCTS", "(J)Z", (void*) native_getCTS },
|
||||
{ "native_getDSR", "(J)Z", (void*) native_getDSR },
|
||||
{ "native_getRI", "(J)Z", (void*) native_getRI },
|
||||
{ "native_getCD", "(J)Z", (void*) native_getCD },
|
||||
};
|
||||
|
||||
int registerSerial(JNIEnv* env)
|
||||
{
|
||||
gSerialExceptionClass = findClass("serial/SerialException", FIND_CLASS_RETURN_GLOBAL_REF);
|
||||
gSerialIOExceptionClass = findClass("serial/SerialIOException", FIND_CLASS_RETURN_GLOBAL_REF);
|
||||
gIllegalArgumentException = findClass("java/lang/IllegalArgumentException", FIND_CLASS_RETURN_GLOBAL_REF);
|
||||
return jniRegisterNativeMethods(env, "serial/Serial", gSerialMethods, NELEM(gSerialMethods));
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -1 +0,0 @@
|
||||
../../../../../src/impl/unix.cc
|
||||
@ -1,15 +0,0 @@
|
||||
package serial.android;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* To work on unit tests, switch the Test Artifact in the Build Variants view.
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "serial.android.sample"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
||||
compile 'com.android.support:design:23.1.1'
|
||||
|
||||
compile project(':library')
|
||||
}
|
||||
17
android/sample/proguard-rules.pro
vendored
17
android/sample/proguard-rules.pro
vendored
@ -1,17 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /mnt/android/android-sdk-linux_x86/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@ -1,13 +0,0 @@
|
||||
package serial.android.sample;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="serial.android.sample" >
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -1,250 +0,0 @@
|
||||
package serial.android.sample;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import serial.PortInfo;
|
||||
import serial.Serial;
|
||||
import serial.SerialIOException;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private Spinner mSpinnerPorts;
|
||||
private boolean mHexMode;
|
||||
private TextView mTextAvailable;
|
||||
private TextView mTextOutput;
|
||||
private TextView mTextInput;
|
||||
private Button mButtonSend;
|
||||
private Button mButtonRead;
|
||||
private ToggleButton mButtonConnectDisconnect;
|
||||
private Serial mPort;
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
mSpinnerPorts = (Spinner) findViewById(R.id.spinnerPorts);
|
||||
mTextOutput = (TextView) findViewById(R.id.dataReceived);
|
||||
mTextInput = (TextView) findViewById(R.id.dataToSend);
|
||||
mTextAvailable = (TextView) findViewById(R.id.lblAvailable);
|
||||
|
||||
mButtonSend = (Button) findViewById(R.id.btnSend);
|
||||
mButtonRead = (Button) findViewById(R.id.btnRead);
|
||||
mButtonConnectDisconnect = (ToggleButton) findViewById(R.id.tbConnect);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
loadPorts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
MenuItem refreshItem = menu.findItem(R.id.action_reload);
|
||||
refreshItem.setEnabled(mPort == null);
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
boolean handled = true;
|
||||
switch (id) {
|
||||
case R.id.action_reload:
|
||||
loadPorts();
|
||||
break;
|
||||
case R.id.action_hex:
|
||||
item.setChecked(!item.isChecked());
|
||||
mHexMode = item.isChecked();
|
||||
clearInput();
|
||||
clearOutput();
|
||||
Toast.makeText(MainActivity.this, "Not implemented.", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return handled || super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void clearOutput() {
|
||||
mTextOutput.setText("");
|
||||
}
|
||||
|
||||
private void clearInput() {
|
||||
mTextInput.setText("");
|
||||
}
|
||||
|
||||
private void loadPorts() {
|
||||
PortInfo[] ports = Serial.listPorts();
|
||||
PortAdapter adapter = new PortAdapter(getApplicationContext(), ports);
|
||||
mSpinnerPorts.setAdapter(adapter);
|
||||
mButtonConnectDisconnect.setChecked(false);
|
||||
mButtonConnectDisconnect.setEnabled(!adapter.isEmpty());
|
||||
}
|
||||
|
||||
public void onConnectDisconnectClick(View view) {
|
||||
if (mPort != null) {
|
||||
try {
|
||||
mPort.close();
|
||||
} catch (IOException e) {
|
||||
// Never get here
|
||||
}
|
||||
mSpinnerPorts.setEnabled(true);
|
||||
mButtonRead.setEnabled(false);
|
||||
mButtonSend.setEnabled(false);
|
||||
mTextInput.setEnabled(false);
|
||||
mPort = null;
|
||||
} else {
|
||||
clearInput();
|
||||
clearOutput();
|
||||
PortInfo portInfo = (PortInfo) mSpinnerPorts.getSelectedItem();
|
||||
Serial port;
|
||||
try {
|
||||
port = new Serial.Builder(portInfo.port, Serial.BAUDRATE_115200).create();
|
||||
if (port.isValid() && port.isOpen()) {
|
||||
mPort = port;
|
||||
mSpinnerPorts.setEnabled(false);
|
||||
mButtonRead.setEnabled(true);
|
||||
mButtonSend.setEnabled(true);
|
||||
mTextInput.setEnabled(true);
|
||||
checkAvailableData();
|
||||
}
|
||||
} catch (SerialIOException e) {
|
||||
Toast.makeText(MainActivity.this, getString(R.string.toast_connect_failed, portInfo.port), Toast.LENGTH_SHORT).show();
|
||||
mTextOutput.setText(e.getMessage());
|
||||
mButtonConnectDisconnect.setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSendClick(View view) {
|
||||
if (mPort != null) {
|
||||
String text = mTextInput.getText().toString();
|
||||
try {
|
||||
int bytesWritten = mPort.write(text);
|
||||
updateAvailableData();
|
||||
clearInput();
|
||||
Toast.makeText(MainActivity.this, getString(R.string.toast_send_success, bytesWritten, mPort.getPort()), Toast.LENGTH_SHORT).show();
|
||||
} catch (SerialIOException e) {
|
||||
Toast.makeText(MainActivity.this, getString(R.string.toast_send_failed, mPort.getPort()), Toast.LENGTH_SHORT).show();
|
||||
mTextOutput.setText(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onReadClick(View view) {
|
||||
if (mPort != null) {
|
||||
String[] lines;
|
||||
try {
|
||||
clearOutput();
|
||||
byte[] data = mPort.read();
|
||||
String s = new String(data);
|
||||
mTextOutput.append(s);
|
||||
Toast.makeText(MainActivity.this, getString(R.string.toast_read_success, data.length, mPort.getPort()), Toast.LENGTH_SHORT).show();
|
||||
updateAvailableData();
|
||||
} catch (SerialIOException e) {
|
||||
Toast.makeText(MainActivity.this, getString(R.string.toast_send_failed, mPort.getPort()), Toast.LENGTH_SHORT).show();
|
||||
mTextOutput.setText(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAvailableData() {
|
||||
updateAvailableData(100L);
|
||||
}
|
||||
|
||||
private void updateAvailableData(long timeout) {
|
||||
if (timeout <= 0) {
|
||||
checkAvailableData();
|
||||
} else {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
checkAvailableData();
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAvailableData() {
|
||||
try {
|
||||
mTextAvailable.setText(getString(R.string.hint_available_bytes, mPort.available()));
|
||||
} catch (SerialIOException e) {
|
||||
mTextAvailable.setText(R.string.hint_unknown_bytes);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class PortAdapter extends ArrayAdapter<PortInfo> {
|
||||
|
||||
public PortAdapter(Context context, PortInfo[] ports) {
|
||||
super(context, android.R.layout.simple_spinner_item, android.R.id.text1, ports);
|
||||
setDropDownViewResource(android.R.layout.simple_list_item_2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view = super.getView(position, convertView, parent);
|
||||
if (view != convertView) {
|
||||
// We created a new view.
|
||||
TextView textView = (TextView)view;
|
||||
textView.setTextColor(Color.BLACK);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(int position, View convertView, ViewGroup parent) {
|
||||
View view = super.getDropDownView(position, convertView, parent);
|
||||
if (view != convertView) {
|
||||
// We created a new view.
|
||||
TextView descriptionView = (TextView)view.findViewById(android.R.id.text1);
|
||||
TextView portView = (TextView)view.findViewById(android.R.id.text2);
|
||||
PortInfo portInfo = getItem(position);
|
||||
descriptionView.setText(portInfo.description);
|
||||
descriptionView.setTextColor(Color.BLACK);
|
||||
portView.setText(portInfo.port);
|
||||
portView.setTextColor(Color.BLACK);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="serial.android.sample.MainActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
@ -1,144 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:showIn="@layout/activity_main"
|
||||
tools:context="serial.android.sample.MainActivity">
|
||||
|
||||
<ToggleButton
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/tbConnect"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:textOff="@string/action_connect"
|
||||
android:textOn="@string/action_disconnect"
|
||||
android:onClick="onConnectDisconnectClick"/>
|
||||
|
||||
<TextView
|
||||
android:text="@string/hint_ports"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@android:style/TextAppearance.Large"
|
||||
android:id="@+id/lblPorts"
|
||||
android:layout_toLeftOf="@+id/tbConnect"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignBottom="@+id/tbConnect"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="center_vertical|left"/>
|
||||
|
||||
<Spinner
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/spinnerPorts"
|
||||
android:layout_below="@+id/tbConnect"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/btnSend"
|
||||
android:layout_below="@+id/spinnerPorts"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:text="@string/action_send"
|
||||
android:enabled="false"
|
||||
android:onClick="onSendClick"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="@string/hint_send"
|
||||
android:id="@+id/lblSend"
|
||||
android:layout_below="@+id/spinnerPorts"
|
||||
android:layout_toLeftOf="@+id/btnSend"
|
||||
android:layout_alignBottom="@+id/btnSend"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:gravity="center_vertical|left"/>
|
||||
|
||||
|
||||
<EditText
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:ems="14"
|
||||
android:id="@+id/dataToSend"
|
||||
android:layout_below="@+id/btnSend"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:hint="@string/hint_send_textbox"
|
||||
android:minLines="6"
|
||||
android:maxLines="6"
|
||||
android:lines="6"
|
||||
android:gravity="top"
|
||||
android:enabled="false"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/btnRead"
|
||||
android:layout_below="@+id/dataToSend"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:text="@string/action_read"
|
||||
android:enabled="false"
|
||||
android:onClick="onReadClick"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="@string/hint_unknown_bytes"
|
||||
android:id="@+id/lblAvailable"
|
||||
android:layout_below="@+id/dataToSend"
|
||||
android:layout_toLeftOf="@+id/btnRead"
|
||||
android:layout_alignBottom="@+id/btnRead"
|
||||
android:gravity="center_vertical|right"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="@string/hint_received"
|
||||
android:id="@+id/lblReceived"
|
||||
android:layout_below="@+id/dataToSend"
|
||||
android:layout_toLeftOf="@+id/lblAvailable"
|
||||
android:layout_alignBottom="@+id/lblAvailable"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:gravity="center_vertical|left"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="14"
|
||||
android:id="@+id/dataReceived"
|
||||
android:minLines="7"
|
||||
android:maxLines="7"
|
||||
android:lines="7"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/btnRead"
|
||||
android:hint="@string/hint_received_textbox"
|
||||
android:focusable="false"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@ -1,14 +0,0 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="serial.android.sample.MainActivity" >
|
||||
<item android:id="@+id/action_reload"
|
||||
android:title="@string/action_reload"
|
||||
android:orderInCategory="100"
|
||||
app:showAsAction="never" />
|
||||
<item android:id="@+id/action_hex"
|
||||
android:title="@string/hint_hex_mode"
|
||||
android:orderInCategory="99"
|
||||
android:checkable="true"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
@ -1,8 +0,0 @@
|
||||
<resources>>
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
</resources>
|
||||
@ -1,6 +0,0 @@
|
||||
<resources>
|
||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||
(such as screen margins) for screens with more than 820dp of available width. This
|
||||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||
</resources>
|
||||
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">libserial 示例</string>
|
||||
<string name="action_connect">链接</string>
|
||||
<string name="action_disconnect">断开</string>
|
||||
<string name="action_read">读取</string>
|
||||
<string name="action_send">发送</string>
|
||||
<string name="action_reload">刷新串口</string>
|
||||
<string name="hint_hex_mode">Hex 模式</string>
|
||||
<string name="hint_ports">串口</string>
|
||||
<string name="hint_received">接收到的数据</string>
|
||||
<string name="hint_received_textbox">点击“读取”然后在这里可以看到接收到的数据。</string>
|
||||
<string name="hint_send">要发送的数据</string>
|
||||
<string name="hint_send_textbox">输入要发送的然后点击“发送”即可把数据发送到串口。</string>
|
||||
<string name="toast_send_failed">向 %s 发送数据失败。</string>
|
||||
<string name="toast_connect_failed">链接 %s 失败。</string>
|
||||
<string name="toast_read_failed">读取 %s 的数据失败。</string>
|
||||
<string name="toast_read_success">从 %2$s 读取了 %1$d 字节的数据。</string>
|
||||
<string name="toast_send_success">向 %2$s 发送了 %1$d 字节的数据。</string>
|
||||
</resources>
|
||||
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
</resources>
|
||||
@ -1,6 +0,0 @@
|
||||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
||||
@ -1,29 +0,0 @@
|
||||
<resources>
|
||||
<string name="app_name">Serial Sample</string>
|
||||
<string name="action_reload">Reload Ports</string>
|
||||
<string name="action_connect">Connect</string>
|
||||
<string name="action_disconnect">Disconnect</string>
|
||||
|
||||
<string name="action_send">Send</string>
|
||||
<string name="action_read">Read</string>
|
||||
|
||||
<string name="hint_ports">Ports</string>
|
||||
<string name="hint_send">Data to send</string>
|
||||
<string name="hint_received">Received data</string>
|
||||
<string name="hint_hex_mode">Hex Mode</string>
|
||||
|
||||
<string name="hint_available_bytes" translatable="false">%,3d</string>
|
||||
<string name="hint_unknown_bytes" translatable="false">\?\?\?</string>
|
||||
|
||||
<string name="hint_received_textbox">Click \"Read\" and received messages will be display here.</string>
|
||||
<string name="hint_send_textbox">Write your message and click \"Send\" to deliver message to connected port.</string>
|
||||
|
||||
<string name="toast_connect_failed">Failed to connect %s.</string>
|
||||
|
||||
<string name="toast_send_failed">Failed to write to %s.</string>
|
||||
<string name="toast_send_success">Sent %1$d byte(s) to %2$s.</string>
|
||||
|
||||
<string name="toast_read_failed">Failed to read from %s.</string>
|
||||
<string name="toast_read_success">Read %1$d byte(s) from %2$s.</string>
|
||||
|
||||
</resources>
|
||||
@ -1,17 +0,0 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
|
||||
|
||||
</resources>
|
||||
@ -1,15 +0,0 @@
|
||||
package serial.android.sample;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* To work on unit tests, switch the Test Artifact in the Build Variants view.
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
include ':library', ':sample'
|
||||
Loading…
x
Reference in New Issue
Block a user