1
0
mirror of https://github.com/wjwwood/serial.git synced 2026-01-23 04:04:54 +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:
Cheng Zhong 2016-01-25 14:21:14 +08:00
parent 3fc56e3379
commit f8553a1424
81 changed files with 15 additions and 7085 deletions

View File

@ -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
View 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)

View File

@ -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'])
}

View File

@ -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 *;
#}

View File

@ -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>

View File

@ -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.");
}
}
}

View File

@ -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;
}

View File

@ -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.&lt;YOUR_LOG_TAG> &lt;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.&lt;YOUR_LOG_TAG>=&lt;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];
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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.");
}
}
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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

View File

@ -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.

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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);
}

View File

@ -1 +0,0 @@
../../../../../src/impl/list_ports/list_ports_linux.cc

View File

@ -1 +0,0 @@
../../../../../src/serial.cc

View File

@ -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

View File

@ -1 +0,0 @@
../../../../../src/impl/unix.cc

View File

@ -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);
}
}

View File

@ -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')
}

View File

@ -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 *;
#}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);
}
}

View File

@ -1 +0,0 @@
include ':library', ':sample'