New Serial Manager API:
SerialManager: provides access to serial ports SerialPort: for reading and writing data to and from serial ports IO with both array based and direct ByteBuffers is supported. Accessing serial ports requires android.permission.SERIAL_PORT permission Each platform must configure list of supported serial ports in the config_serialPorts resource overlay (this is needed to prevent apps from accidentally accessing the bluetooth or other system UARTs). In addition, the platform uevent.rc file must set the owner to the /dev/tty* files to "system" so the framework can access the port. Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
committed by
Mike Lockwood
parent
341ff2b083
commit
b01e8bf57b
@@ -110,6 +110,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/content/pm/IPackageMoveObserver.aidl \
|
||||
core/java/android/content/pm/IPackageStatsObserver.aidl \
|
||||
core/java/android/database/IContentObserver.aidl \
|
||||
core/java/android/hardware/ISerialManager.aidl \
|
||||
core/java/android/hardware/usb/IUsbManager.aidl \
|
||||
core/java/android/net/IConnectivityManager.aidl \
|
||||
core/java/android/net/INetworkManagementEventObserver.aidl \
|
||||
|
||||
@@ -42,7 +42,9 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.ISerialManager;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.SerialManager;
|
||||
import android.hardware.usb.IUsbManager;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.location.CountryDetector;
|
||||
@@ -428,6 +430,12 @@ class ContextImpl extends Context {
|
||||
return new UsbManager(ctx, IUsbManager.Stub.asInterface(b));
|
||||
}});
|
||||
|
||||
registerService(SERIAL_SERVICE, new ServiceFetcher() {
|
||||
public Object createService(ContextImpl ctx) {
|
||||
IBinder b = ServiceManager.getService(SERIAL_SERVICE);
|
||||
return new SerialManager(ctx, ISerialManager.Stub.asInterface(b));
|
||||
}});
|
||||
|
||||
registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
|
||||
public Object createService(ContextImpl ctx) {
|
||||
return new Vibrator();
|
||||
|
||||
@@ -1788,6 +1788,17 @@ public abstract class Context {
|
||||
*/
|
||||
public static final String USB_SERVICE = "usb";
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a {@link
|
||||
* android.hardware.SerialManager} for access to serial ports.
|
||||
*
|
||||
* @see #getSystemService
|
||||
* @see android.harware.SerialManager
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String SERIAL_SERVICE = "serial";
|
||||
|
||||
/**
|
||||
* Determine whether the given permission is allowed for a particular
|
||||
* process and user ID running in the system.
|
||||
|
||||
29
core/java/android/hardware/ISerialManager.aidl
Normal file
29
core/java/android/hardware/ISerialManager.aidl
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package android.hardware;
|
||||
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
/** @hide */
|
||||
interface ISerialManager
|
||||
{
|
||||
/* Returns a list of all available serial ports */
|
||||
String[] getSerialPorts();
|
||||
|
||||
/* Returns a file descriptor for the serial port. */
|
||||
ParcelFileDescriptor openSerialPort(String name);
|
||||
}
|
||||
88
core/java/android/hardware/SerialManager.java
Normal file
88
core/java/android/hardware/SerialManager.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
package android.hardware;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public class SerialManager {
|
||||
private static final String TAG = "SerialManager";
|
||||
|
||||
private final Context mContext;
|
||||
private final ISerialManager mService;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public SerialManager(Context context, ISerialManager service) {
|
||||
mContext = context;
|
||||
mService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string array containing the names of available serial ports
|
||||
*
|
||||
* @return names of available serial ports
|
||||
*/
|
||||
public String[] getSerialPorts() {
|
||||
try {
|
||||
return mService.getSerialPorts();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException in getSerialPorts", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens and returns the {@link android.hardware.SerialPort} with the given name.
|
||||
* The speed of the serial port must be one of:
|
||||
* 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600,
|
||||
* 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000,
|
||||
* 1500000, 2000000, 2500000, 3000000, 3500000 or 4000000
|
||||
*
|
||||
* @param name of the serial port
|
||||
* @param speed at which to open the serial port
|
||||
* @return the serial port
|
||||
*/
|
||||
public SerialPort openSerialPort(String name, int speed) throws IOException {
|
||||
try {
|
||||
ParcelFileDescriptor pfd = mService.openSerialPort(name);
|
||||
if (pfd != null) {
|
||||
SerialPort port = new SerialPort(name);
|
||||
port.open(pfd, speed);
|
||||
return port;
|
||||
} else {
|
||||
throw new IOException("Could not open serial port " + name);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "exception in UsbManager.openDevice", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
122
core/java/android/hardware/SerialPort.java
Normal file
122
core/java/android/hardware/SerialPort.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package android.hardware;
|
||||
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public class SerialPort {
|
||||
|
||||
private static final String TAG = "SerialPort";
|
||||
|
||||
// used by the JNI code
|
||||
private int mNativeContext;
|
||||
private final String mName;
|
||||
private ParcelFileDescriptor mFileDescriptor;
|
||||
|
||||
/**
|
||||
* SerialPort should only be instantiated by SerialManager
|
||||
* @hide
|
||||
*/
|
||||
public SerialPort(String name) {
|
||||
mName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* SerialPort should only be instantiated by SerialManager
|
||||
* Speed must be one of 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600,
|
||||
* 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000,
|
||||
* 1500000, 2000000, 2500000, 3000000, 3500000, 4000000
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void open(ParcelFileDescriptor pfd, int speed) throws IOException {
|
||||
native_open(pfd.getFileDescriptor(), speed);
|
||||
mFileDescriptor = pfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the serial port
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (mFileDescriptor != null) {
|
||||
mFileDescriptor.close();
|
||||
mFileDescriptor = null;
|
||||
}
|
||||
native_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the serial port
|
||||
*
|
||||
* @return the serial port's name
|
||||
*/
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data into the provided buffer
|
||||
*
|
||||
* @param buffer to read into
|
||||
* @return number of bytes read
|
||||
*/
|
||||
public int read(ByteBuffer buffer) throws IOException {
|
||||
if (buffer.isDirect()) {
|
||||
return native_read_direct(buffer, buffer.remaining());
|
||||
} else if (buffer.hasArray()) {
|
||||
return native_read_array(buffer.array(), buffer.remaining());
|
||||
} else {
|
||||
throw new IllegalArgumentException("buffer is not direct and has no array");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data from provided buffer
|
||||
*
|
||||
* @param buffer to write
|
||||
* @param length number of bytes to write
|
||||
*/
|
||||
public void write(ByteBuffer buffer, int length) throws IOException {
|
||||
if (buffer.isDirect()) {
|
||||
native_write_direct(buffer, length);
|
||||
} else if (buffer.hasArray()) {
|
||||
native_write_array(buffer.array(), length);
|
||||
} else {
|
||||
throw new IllegalArgumentException("buffer is not direct and has no array");
|
||||
}
|
||||
}
|
||||
|
||||
private native void native_open(FileDescriptor pfd, int speed) throws IOException;
|
||||
private native void native_close();
|
||||
private native int native_read_array(byte[] buffer, int length) throws IOException;
|
||||
private native int native_read_direct(ByteBuffer buffer, int length) throws IOException;
|
||||
private native void native_write_array(byte[] buffer, int length) throws IOException;
|
||||
private native void native_write_direct(ByteBuffer buffer, int length) throws IOException;
|
||||
}
|
||||
@@ -126,6 +126,7 @@ LOCAL_SRC_FILES:= \
|
||||
android_media_ToneGenerator.cpp \
|
||||
android_hardware_Camera.cpp \
|
||||
android_hardware_SensorManager.cpp \
|
||||
android_hardware_SerialPort.cpp \
|
||||
android_hardware_UsbDevice.cpp \
|
||||
android_hardware_UsbDeviceConnection.cpp \
|
||||
android_hardware_UsbRequest.cpp \
|
||||
|
||||
@@ -76,6 +76,7 @@ extern int register_android_opengl_jni_GLES20(JNIEnv* env);
|
||||
|
||||
extern int register_android_hardware_Camera(JNIEnv *env);
|
||||
extern int register_android_hardware_SensorManager(JNIEnv *env);
|
||||
extern int register_android_hardware_SerialPort(JNIEnv *env);
|
||||
extern int register_android_hardware_UsbDevice(JNIEnv *env);
|
||||
extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
|
||||
extern int register_android_hardware_UsbRequest(JNIEnv *env);
|
||||
@@ -1157,6 +1158,7 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_com_android_internal_os_ZygoteInit),
|
||||
REG_JNI(register_android_hardware_Camera),
|
||||
REG_JNI(register_android_hardware_SensorManager),
|
||||
REG_JNI(register_android_hardware_SerialPort),
|
||||
REG_JNI(register_android_hardware_UsbDevice),
|
||||
REG_JNI(register_android_hardware_UsbDeviceConnection),
|
||||
REG_JNI(register_android_hardware_UsbRequest),
|
||||
|
||||
266
core/jni/android_hardware_SerialPort.cpp
Normal file
266
core/jni/android_hardware_SerialPort.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SerialPortJNI"
|
||||
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
static jfieldID field_context;
|
||||
|
||||
static void
|
||||
android_hardware_SerialPort_open(JNIEnv *env, jobject thiz, jobject fileDescriptor, jint speed)
|
||||
{
|
||||
switch (speed) {
|
||||
case 50:
|
||||
speed = B50;
|
||||
break;
|
||||
case 75:
|
||||
speed = B75;
|
||||
break;
|
||||
case 110:
|
||||
speed = B110;
|
||||
break;
|
||||
case 134:
|
||||
speed = B134;
|
||||
break;
|
||||
case 150:
|
||||
speed = B150;
|
||||
break;
|
||||
case 200:
|
||||
speed = B200;
|
||||
break;
|
||||
case 300:
|
||||
speed = B300;
|
||||
break;
|
||||
case 600:
|
||||
speed = B600;
|
||||
break;
|
||||
case 1200:
|
||||
speed = B1200;
|
||||
break;
|
||||
case 1800:
|
||||
speed = B1800;
|
||||
break;
|
||||
case 2400:
|
||||
speed = B2400;
|
||||
break;
|
||||
case 4800:
|
||||
speed = B4800;
|
||||
break;
|
||||
case 9600:
|
||||
speed = B9600;
|
||||
break;
|
||||
case 19200:
|
||||
speed = B19200;
|
||||
break;
|
||||
case 38400:
|
||||
speed = B38400;
|
||||
break;
|
||||
case 57600:
|
||||
speed = B57600;
|
||||
break;
|
||||
case 115200:
|
||||
speed = B115200;
|
||||
break;
|
||||
case 230400:
|
||||
speed = B230400;
|
||||
break;
|
||||
case 460800:
|
||||
speed = B460800;
|
||||
break;
|
||||
case 500000:
|
||||
speed = B500000;
|
||||
break;
|
||||
case 576000:
|
||||
speed = B576000;
|
||||
break;
|
||||
case 921600:
|
||||
speed = B921600;
|
||||
break;
|
||||
case 1000000:
|
||||
speed = B1000000;
|
||||
break;
|
||||
case 1152000:
|
||||
speed = B1152000;
|
||||
break;
|
||||
case 1500000:
|
||||
speed = B1500000;
|
||||
break;
|
||||
case 2000000:
|
||||
speed = B2000000;
|
||||
break;
|
||||
case 2500000:
|
||||
speed = B2500000;
|
||||
break;
|
||||
case 3000000:
|
||||
speed = B3000000;
|
||||
break;
|
||||
case 3500000:
|
||||
speed = B3500000;
|
||||
break;
|
||||
case 4000000:
|
||||
speed = B4000000;
|
||||
break;
|
||||
default:
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException",
|
||||
"Unsupported serial port speed");
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
|
||||
// duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
|
||||
fd = dup(fd);
|
||||
if (fd < 0) {
|
||||
jniThrowException(env, "java/io/IOException", "Could not open serial port");
|
||||
return;
|
||||
}
|
||||
env->SetIntField(thiz, field_context, fd);
|
||||
|
||||
struct termios tio;
|
||||
if (tcgetattr(fd, &tio))
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
|
||||
tio.c_cflag = speed | CS8 | CLOCAL | CREAD;
|
||||
tio.c_iflag = IGNPAR;
|
||||
tio.c_lflag = 0; /* turn of CANON, ECHO*, etc */
|
||||
/* no timeout but request at least one character per read */
|
||||
tio.c_cc[VTIME] = 0;
|
||||
tio.c_cc[VMIN] = 1;
|
||||
tcsetattr(fd, TCSANOW, &tio);
|
||||
tcflush(fd, TCIFLUSH);
|
||||
}
|
||||
|
||||
static void
|
||||
android_hardware_SerialPort_close(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
int fd = env->GetIntField(thiz, field_context);
|
||||
close(fd);
|
||||
env->SetIntField(thiz, field_context, -1);
|
||||
}
|
||||
|
||||
static jint
|
||||
android_hardware_SerialPort_read_array(JNIEnv *env, jobject thiz, jbyteArray buffer, jint length)
|
||||
{
|
||||
int fd = env->GetIntField(thiz, field_context);
|
||||
jbyte* buf = (jbyte *)malloc(length);
|
||||
if (!buf) {
|
||||
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = read(fd, buf, length);
|
||||
if (ret > 0) {
|
||||
// copy data from native buffer to Java buffer
|
||||
env->SetByteArrayRegion(buffer, 0, ret, buf);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
if (ret < 0)
|
||||
jniThrowException(env, "java/io/IOException", NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jint
|
||||
android_hardware_SerialPort_read_direct(JNIEnv *env, jobject thiz, jobject buffer, jint length)
|
||||
{
|
||||
int fd = env->GetIntField(thiz, field_context);
|
||||
|
||||
jbyte* buf = (jbyte *)env->GetDirectBufferAddress(buffer);
|
||||
if (!buf) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", "ByteBuffer not direct");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = read(fd, buf, length);
|
||||
if (ret < 0)
|
||||
jniThrowException(env, "java/io/IOException", NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
android_hardware_SerialPort_write_array(JNIEnv *env, jobject thiz, jbyteArray buffer, jint length)
|
||||
{
|
||||
int fd = env->GetIntField(thiz, field_context);
|
||||
jbyte* buf = (jbyte *)malloc(length);
|
||||
if (!buf) {
|
||||
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
|
||||
return;
|
||||
}
|
||||
env->GetByteArrayRegion(buffer, 0, length, buf);
|
||||
|
||||
jint ret = write(fd, buf, length);
|
||||
free(buf);
|
||||
if (ret < 0)
|
||||
jniThrowException(env, "java/io/IOException", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
android_hardware_SerialPort_write_direct(JNIEnv *env, jobject thiz, jobject buffer, jint length)
|
||||
{
|
||||
int fd = env->GetIntField(thiz, field_context);
|
||||
|
||||
jbyte* buf = (jbyte *)env->GetDirectBufferAddress(buffer);
|
||||
if (!buf) {
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", "ByteBuffer not direct");
|
||||
return;
|
||||
}
|
||||
int ret = write(fd, buf, length);
|
||||
if (ret < 0)
|
||||
jniThrowException(env, "java/io/IOException", NULL);
|
||||
}
|
||||
|
||||
static JNINativeMethod method_table[] = {
|
||||
{"native_open", "(Ljava/io/FileDescriptor;I)V",
|
||||
(void *)android_hardware_SerialPort_open},
|
||||
{"native_close", "()V", (void *)android_hardware_SerialPort_close},
|
||||
{"native_read_array", "([BI)I",
|
||||
(void *)android_hardware_SerialPort_read_array},
|
||||
{"native_read_direct", "(Ljava/nio/ByteBuffer;I)I",
|
||||
(void *)android_hardware_SerialPort_read_direct},
|
||||
{"native_write_array", "([BI)V",
|
||||
(void *)android_hardware_SerialPort_write_array},
|
||||
{"native_write_direct", "(Ljava/nio/ByteBuffer;I)V",
|
||||
(void *)android_hardware_SerialPort_write_direct},
|
||||
};
|
||||
|
||||
int register_android_hardware_SerialPort(JNIEnv *env)
|
||||
{
|
||||
jclass clazz = env->FindClass("android/hardware/SerialPort");
|
||||
if (clazz == NULL) {
|
||||
ALOGE("Can't find android/hardware/SerialPort");
|
||||
return -1;
|
||||
}
|
||||
field_context = env->GetFieldID(clazz, "mNativeContext", "I");
|
||||
if (field_context == NULL) {
|
||||
ALOGE("Can't find SerialPort.mNativeContext");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(env, "android/hardware/SerialPort",
|
||||
method_table, NELEM(method_table));
|
||||
}
|
||||
@@ -1514,6 +1514,13 @@
|
||||
android:description="@string/permdesc_bindPackageVerifier"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- Allows applications to access serial ports via the SerialManager.
|
||||
@hide -->
|
||||
<permission android:name="android.permission.SERIAL_PORT"
|
||||
android:label="@string/permlab_serialPort"
|
||||
android:description="@string/permdesc_serialPort"
|
||||
android:protectionLevel="normal" />
|
||||
|
||||
<!-- The system process is explicitly the only one allowed to launch the
|
||||
confirmation UI for full backup/restore -->
|
||||
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
|
||||
|
||||
@@ -368,6 +368,12 @@
|
||||
<string-array name="config_usbHostBlacklist" translatable="false">
|
||||
</string-array>
|
||||
|
||||
<!-- List of paths to serial ports that are available to the serial manager.
|
||||
for example, /dev/ttyUSB0
|
||||
-->
|
||||
<string-array translatable="false" name="config_serialPorts">
|
||||
</string-array>
|
||||
|
||||
<!-- Vibrator pattern for feedback about a long screen/key press -->
|
||||
<integer-array name="config_longPressVibePattern">
|
||||
<item>0</item>
|
||||
|
||||
@@ -1289,6 +1289,7 @@
|
||||
<java-symbol type="array" name="config_tether_usb_regexs" />
|
||||
<java-symbol type="array" name="config_tether_wifi_regexs" />
|
||||
<java-symbol type="array" name="config_usbHostBlacklist" />
|
||||
<java-symbol type="array" name="config_serialPorts" />
|
||||
<java-symbol type="array" name="radioAttributes" />
|
||||
<java-symbol type="bool" name="config_animateScreenLights" />
|
||||
<java-symbol type="bool" name="config_automatic_brightness_available" />
|
||||
|
||||
@@ -2243,6 +2243,11 @@
|
||||
<string name="permdesc_bindPackageVerifier">Allows the holder to make requests of
|
||||
package verifiers. Should never be needed for normal apps.</string>
|
||||
|
||||
<!-- Title of an application permission which allows the application to access serial ports via the SerialManager. [CHAR LIMIT=40] -->
|
||||
<string name="permlab_serialPort">access serial ports</string>
|
||||
<!-- Description of an application permission which allows the application access serial ports via the SerialManager. [CHAR LIMIT=NONE] -->
|
||||
<string name="permdesc_serialPort">Allows the holder to access serial ports using the SerialManager API.</string>
|
||||
|
||||
<!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Text in the save password dialog, asking if the browser should remember a password. -->
|
||||
<string name="save_password_message">Do you want the browser to remember this password?</string>
|
||||
<!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Button in the save password dialog, saying not to remember this password. -->
|
||||
|
||||
58
services/java/com/android/server/SerialService.java
Normal file
58
services/java/com/android/server/SerialService.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 an
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.ISerialManager;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SerialService extends ISerialManager.Stub {
|
||||
|
||||
private final Context mContext;
|
||||
private final String[] mSerialPorts;
|
||||
|
||||
public SerialService(Context context) {
|
||||
mContext = context;
|
||||
mSerialPorts = context.getResources().getStringArray(
|
||||
com.android.internal.R.array.config_serialPorts);
|
||||
}
|
||||
|
||||
public String[] getSerialPorts() {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
|
||||
|
||||
ArrayList<String> ports = new ArrayList<String>();
|
||||
for (int i = 0; i < mSerialPorts.length; i++) {
|
||||
String path = mSerialPorts[i];
|
||||
if (new File(path).exists()) {
|
||||
ports.add(path);
|
||||
}
|
||||
}
|
||||
String[] result = new String[ports.size()];
|
||||
ports.toArray(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public ParcelFileDescriptor openSerialPort(String path) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
|
||||
return native_open(path);
|
||||
}
|
||||
|
||||
private native ParcelFileDescriptor native_open(String path);
|
||||
}
|
||||
@@ -126,6 +126,7 @@ class ServerThread extends Thread {
|
||||
BluetoothA2dpService bluetoothA2dp = null;
|
||||
DockObserver dock = null;
|
||||
UsbService usb = null;
|
||||
SerialService serial = null;
|
||||
UiModeManagerService uiMode = null;
|
||||
RecognitionManagerService recognition = null;
|
||||
ThrottleService throttle = null;
|
||||
@@ -496,6 +497,15 @@ class ServerThread extends Thread {
|
||||
reportWtf("starting UsbService", e);
|
||||
}
|
||||
|
||||
try {
|
||||
Slog.i(TAG, "Serial Service");
|
||||
// Serial port support
|
||||
serial = new SerialService(context);
|
||||
ServiceManager.addService(Context.SERIAL_SERVICE, serial);
|
||||
} catch (Throwable e) {
|
||||
Slog.e(TAG, "Failure starting SerialService", e);
|
||||
}
|
||||
|
||||
try {
|
||||
Slog.i(TAG, "UI Mode Manager Service");
|
||||
// Listen for UI mode changes
|
||||
|
||||
@@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \
|
||||
com_android_server_InputWindowHandle.cpp \
|
||||
com_android_server_LightsService.cpp \
|
||||
com_android_server_PowerManagerService.cpp \
|
||||
com_android_server_SerialService.cpp \
|
||||
com_android_server_SystemServer.cpp \
|
||||
com_android_server_UsbDeviceManager.cpp \
|
||||
com_android_server_UsbHostManager.cpp \
|
||||
|
||||
82
services/jni/com_android_server_SerialService.cpp
Normal file
82
services/jni/com_android_server_SerialService.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SerialServiceJNI"
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace android
|
||||
{
|
||||
|
||||
static struct parcel_file_descriptor_offsets_t
|
||||
{
|
||||
jclass mClass;
|
||||
jmethodID mConstructor;
|
||||
} gParcelFileDescriptorOffsets;
|
||||
|
||||
static jobject android_server_SerialService_open(JNIEnv *env, jobject thiz, jstring path)
|
||||
{
|
||||
const char *pathStr = env->GetStringUTFChars(path, NULL);
|
||||
|
||||
int fd = open(pathStr, O_RDWR | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
ALOGE("could not open %s", pathStr);
|
||||
env->ReleaseStringUTFChars(path, pathStr);
|
||||
return NULL;
|
||||
}
|
||||
env->ReleaseStringUTFChars(path, pathStr);
|
||||
|
||||
jobject fileDescriptor = jniCreateFileDescriptor(env, fd);
|
||||
if (fileDescriptor == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return env->NewObject(gParcelFileDescriptorOffsets.mClass,
|
||||
gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
|
||||
}
|
||||
|
||||
|
||||
static JNINativeMethod method_table[] = {
|
||||
{ "native_open", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
|
||||
(void*)android_server_SerialService_open },
|
||||
};
|
||||
|
||||
int register_android_server_SerialService(JNIEnv *env)
|
||||
{
|
||||
jclass clazz = env->FindClass("com/android/server/SerialService");
|
||||
if (clazz == NULL) {
|
||||
ALOGE("Can't find com/android/server/SerialService");
|
||||
return -1;
|
||||
}
|
||||
|
||||
clazz = env->FindClass("android/os/ParcelFileDescriptor");
|
||||
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
|
||||
gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
|
||||
gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
|
||||
LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL,
|
||||
"Unable to find constructor for android.os.ParcelFileDescriptor");
|
||||
|
||||
return jniRegisterNativeMethods(env, "com/android/server/SerialService",
|
||||
method_table, NELEM(method_table));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -27,6 +27,7 @@ int register_android_server_InputWindowHandle(JNIEnv* env);
|
||||
int register_android_server_InputManager(JNIEnv* env);
|
||||
int register_android_server_LightsService(JNIEnv* env);
|
||||
int register_android_server_PowerManagerService(JNIEnv* env);
|
||||
int register_android_server_SerialService(JNIEnv* env);
|
||||
int register_android_server_UsbDeviceManager(JNIEnv* env);
|
||||
int register_android_server_UsbHostManager(JNIEnv* env);
|
||||
int register_android_server_VibratorService(JNIEnv* env);
|
||||
@@ -49,6 +50,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
ALOG_ASSERT(env, "Could not retrieve the env!");
|
||||
|
||||
register_android_server_PowerManagerService(env);
|
||||
register_android_server_SerialService(env);
|
||||
register_android_server_InputApplicationHandle(env);
|
||||
register_android_server_InputWindowHandle(env);
|
||||
register_android_server_InputManager(env);
|
||||
|
||||
Reference in New Issue
Block a user