详细解读android6.0SerialPort服务

简介: 详细解读android6.0SerialPort服务

上一篇博客描述了一个简单的串口应用程序和驱动程序,了解了应用程序访问串口的基本操作,如

打开串口,设置串口,写串口,读串口,关闭串口等。和Linux串口驱动的基本框架。这里将了解Android

下的串口系统框架,仍然使用上一篇博客中的tiny_serial.c作为本例的驱动,本例实现的功能不变,无

论应用程序写任何数据到串口,都能从该串口中读回。

关于Android系统服务基本框架,可以参考博客,

Android串口(serial port)服务框架与该例子十分类似,这里作简单描述。当然也有些不同的地方,后面会分析。

(A) 串口服务的基本框架

1. 注册驱动

2. 注册hal

3. 注册JNI

4. 注册和添加SerialService

5. 串口管理SerialManager

(B) 打开串口

(C) 设置权限

(D) 测试串口

(A) 串口服务的基本框架

1. 注册驱动

通过加载kernel/driver/tty/serial/tiny_serial.c驱动,生成/dev/ttytiny0节点,应用通过访问

该节点,实现的对串口的open、read、write、close等操作。

2. 注册hal

在Android串口服务中,省略了hal层,即通过JNI直接访问驱动。

3. 注册JNI

通过frameworks/base/services/core/jni/com_android_server_SerialService.cpp和

frameworks/base/core/jni/android_hardware_SerialPort.cpp两个JNI文件对驱动访问,

为JAVA提供底层驱动访问的接口,如:

private native ParcelFileDescriptor native_open(String path);

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;

private native void native_send_break();

4. 注册和添加SerialService

frameworks/base/services/core/java/com/android/server/SerialService.java的SerialService类

中提供了服务端通过JNI放问驱动的接口,如:

public String【】 getSerialPorts()

public ParcelFileDescriptor openSerialPort(String path)

通过向frameworks/base/services//java/com/android/server/SystemServer.java的服务管理器ServiceManager

添加服务:

serial = new SerialService(context);

ServiceManager.addService(Context.SERIAL_SERVICE, serial);

并且,通过frameworks/base/core/java/android/app/SystemServiceRegistry.java

1 registerService(Context.SERIAL_SERVICE, SerialManager.class,

2 new CachedServiceFetcher() {

3 @Override

4 public SerialManager createService(ContextImpl ctx) {

5 IBinder b = ServiceManager.getService(Context.SERIAL_SERVICE);

6 return new SerialManager(ctx, ISerialManager.Stub.asInterface(b));

7 }}//代码效果参考:http://www.ezhiqi.com/bx/art_3713.html);

可以访问串口服务SerialService,客户端通过获得SerialService,就能远程调用getSerialPorts()和

openSerialPort(String path)接口

5. 串口管理SerialManager

frameworks/base/core/java/android/hardware/SerialManager.java中SerialManager对串口操作进一步管理,

客户端只要实例化一个SerialManager对象,使用该对象的方法访问串口。不过,该对象只对

openSerialPort(String name, int speed)管理。

(B) 打开串口

通过以上简单分析Android串口服务框架之后,这里进一步分析串口的打开open操作流程。

博客中,只有服务端调用JNI访问底层驱动,而在串口服务中,客户端也调用JNI直接访问底层驱动。服务端

只负责对串口的open操作,在frameworks/base/services/core/jni/com_android_server_SerialService.cpp中

1 static jobject android_server_SerialService_open(JNIEnv env, jobject / thiz /, jstring path)

2 {

3 const char pathStr = env->GetStringUTFChars(path, NULL);

4 //打开/dev/tty节点

5 int fd = open(pathStr, O_RDWR | O_NOCTTY);

6 if (fd < 0) {

7 ALOGE("could not open %s", pathStr);

8 env->ReleaseStringUTFChars(path, pathStr);

9 return NULL;

10 }

11 env->ReleaseStringUTFChars(path, pathStr);

12

13 jobject fileDescriptor = jniCreateFileDescriptor(env, fd);

14 if (fileDescriptor == NULL) {

15 return NULL;

16 }

17 //返回文件描述符,用于跨进程访问文件

18 return env->NewObject(gParcelFileDescriptorOffsets.mClass,

19 gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);

20 }

而read、write、close等相关操作在frameworks/base/core/jni/android_hardware_SerialPort.cpp中,

其中android_hardware_SerialPort_open只对串口进行相关设置,如波特,数据位等。由此看出

frameworks/base/services/core/jni/com_android_server_SerialService.cpp和

frameworks/base/core/jni/android_hardware_SerialPort.cpp可能处于两个不同的线程中,这两个不

同的线程对同一个文件进行访问,需要对文件描述符进行转换。

在frameworks/base/core/jni/android_hardware_SerialPort.cpp中

1 static void android_hardware_SerialPort_open(JNIEnv env, jobject thiz, jobject fileDescriptor, jint speed)

2 {

3 ......

4 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);

5 // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy

6 fd = dup(fd);

7 if (fd < 0) {

8 jniThrowException(env, "java/io/IOException", "Could not open serial port");

9 return;

10 }

11 ......

12 }

(C) 设置权限

device/sprd/scx35l/common/rootdir/root/ueventd.sc8830.rc

1 ......

2 /dev/ttytiny0 0660 system system

3 ......

device/sprd/scx35l/common/sepolicy/file_contexts

1 ......

2 /dev/ttytiny0 u:object_r:serial_device:s0

3 ......

device/sprd/scx35l/common/sepolicy/system_app.te

......

allow system_app serial_device:chr_file { open read write ioctl};

......

(D) 测试串口

这里引用Android6.0源码目录下的一个串口测试app,还要添加一些权限等设置才能正常使用。

串口测试APP源码:frameworks/base/tests/SerialChat

1. 设置权限:

frameworks/base/tests/SerialChat/Android.mk

1 ......

2 LOCAL_CERTIFICATE := platform

3 ......

frameworks/base/tests/SerialChat/AndroidManifest.xml

1 ......

2

3 package="com.android.serialchat"

4 android:sharedUserId="android.uid.system"

5 ......

2. 添加串口节点名称

应用程序根据这个名称来打开对应的串口。

frameworks/base/core/res/res/values/config.xml

1 ......

2 [span style="color: rgba(0, 0, 255, 1)">string-array translatable="false" name="config_serialPorts"

3 "/dev/ttytiny0"

4

5 ......

用mmm frameworks/base/tests/SerialChat -B 编译出的SerialChat.apk push到机器之后,就可以

进行测试了。

a.点击打开SerialChat.apk:

b.输入要发送的内容

c.点击确定(打钩的位置)发送,并且接收显示在上方。

相关文章
|
2月前
|
Android开发
Android 11 添加Service服务SELinux问题
Android 11 添加Service服务SELinux问题
106 1
|
2月前
|
Java API 调度
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
82 0
|
8月前
|
开发工具 数据库 Android开发
0001Java安卓程序设计-基于Android多餐厅点餐桌号后厨前台服务设计与开发2
0001Java安卓程序设计-基于Android多餐厅点餐桌号后厨前台服务设计与开发
36 0
|
10月前
|
编解码 物联网 开发工具
Android平台内网RTSP网关和轻量级RTSP服务的区别和联系
我们在对接轻量级RTSP服务的时候,遇到客户这样的使用场景:客户是用于车载自组网环境,确保多辆车之间可以相互看到对方的实时视频,以期可以了解到前方路况等关注的信息。
115 0
|
10月前
|
编解码 监控 开发工具
如何同时启动Android平台GB28181设备接入模块和轻量级RTSP服务模块?
为什么要设计GB28181设备接入模块?GB28181接入SDK,实现不具备国标音视频能力的 Android终端,通过平台注册接入到现有的GB/T28181—2016服务,可用于如智能监控、智慧零售、智慧教育、远程办公、生产运输、智慧交通、车载或执法记录仪等场景。Android终端除支持常规的音视频数据接入外,还可以支持移动设备位置(MobilePosition)订阅和通知、语音广播和语音对讲、云台控制和预置位查询等。
|
2月前
|
XML Java Android开发
Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)
Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)
369 0
|
28天前
|
调度 Android开发
43. 【Android教程】服务:Service
43. 【Android教程】服务:Service
22 2
|
15天前
|
存储 监控 调度
Android系统服务:WMS、AMS相关知识
参考文献 Android窗口管理服务WindowManagerService计算Activity窗口大小的过程分析 Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析 Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析 Android窗口管理服务WindowManagerService显示窗口动画的原理分析
|
2月前
|
安全 网络安全 Android开发
云端防御策略:融合云服务与网络安全的未来构建高效的Android应用:从内存优化到电池寿命
【4月更文挑战第30天】 随着企业加速向云计算环境转移,数据和服务的云端托管成为常态。本文探讨了在动态且复杂的云服务场景下,如何构建和实施有效的网络安全措施来保障信息资产的安全。我们将分析云计算中存在的安全挑战,并展示通过多层次、多维度的安全框架来提升整体防护能力的方法。重点关注包括数据加密、身份认证、访问控制以及威胁检测与响应等关键技术的实践应用,旨在为读者提供一种结合最新技术进展的网络安全策略视角。 【4月更文挑战第30天】 在竞争激烈的移动市场中,Android应用的性能和资源管理已成为区分优秀与平庸的关键因素。本文深入探讨了提升Android应用效率的多个方面,包括内存优化策略、电池
|
10月前
|
安全 网络协议 Linux
在安卓Termux上搭建apache服务创建个人站点并且结合cpolar内网穿透
在安卓Termux上搭建apache服务创建个人站点并且结合cpolar内网穿透工具实现公网访问。
在安卓Termux上搭建apache服务创建个人站点并且结合cpolar内网穿透