一篇博客描述了一个简单的串口应用程序和驱动程序,了解了应用程序访问串口的基本操作,如
打开串口,设置串口,写串口,读串口,关闭串口等。和Linux串口驱动的基本框架。这里将了解Android
下的串口系统框架,仍然使用上一篇博客中的tiny_serial.c作为本例的驱动,本例实现的功能不变,无
论应用程序写任何数据到串口,都能从该串口中读回。
    关于Android系统服务基本框架,可以参考http://www.cnblogs.com/hackfun/p/7612617.html博客,
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

 registerService(Context.SERIAL_SERVICE, SerialManager.class,
new CachedServiceFetcher<SerialManager>() {
@Override
public SerialManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.SERIAL_SERVICE);
return new SerialManager(ctx, ISerialManager.Stub.asInterface(b));
}});

可以访问串口服务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操作流程。
    在http://www.cnblogs.com/hackfun/p/7612617.html
博客中,只有服务端调用JNI访问底层驱动,而在串口服务中,客户端也调用JNI直接访问底层驱动。服务端
只负责对串口的open操作,在frameworks/base/services/core/jni/com_android_server_SerialService.cpp中

 static jobject android_server_SerialService_open(JNIEnv *env, jobject /* thiz */, jstring path)
{
const char *pathStr = env->GetStringUTFChars(path, NULL);
//打开/dev/tty*节点
int fd = open(pathStr, O_RDWR | O_NOCTTY);
if (fd < ) {
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);
}

而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中

 static void android_hardware_SerialPort_open(JNIEnv *env, jobject thiz, jobject fileDescriptor, jint speed)
{
......
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
// duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
fd = dup(fd);
if (fd < ) {
jniThrowException(env, "java/io/IOException", "Could not open serial port");
return;
}
......
}

(C) 设置权限

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

 ......
/dev/ttytiny0 system system
......

device/sprd/scx35l/common/sepolicy/file_contexts

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

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

 ......
LOCAL_CERTIFICATE := platform
......

frameworks/base/tests/SerialChat/AndroidManifest.xml

 ......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.serialchat"
android:sharedUserId="android.uid.system">
......

2. 添加串口节点名称
    应用程序根据这个名称来打开对应的串口。

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

 ......
<string-array translatable="false" name="config_serialPorts">
<item>"/dev/ttytiny0"</item>
</string-array>
......

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

a.点击打开SerialChat.apk:

b.输入要发送的内容

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

android6.0 SerialPort 服务的更多相关文章

  1. Android6.0获取权限

    照着<第一行代码>打代码,然并卵,感叹技术进步的神速.最后提醒一点:IT类的书籍一定要注意出版时间!出版时间!出版时间!重要的事情说三遍 问题出在android6.0的权限获取问题上,以前 ...

  2. Android6.0中的权限

    Android6.0相比之前的Android版本有一个很大的不同点,就是动态的获取权限.之前我们需要什么权限只需要在Manifest文件中声明即可,在6.0中,又新增了运行时权限的动态检测. Andr ...

  3. Android6.0权限大全和权限分类

    本文转载至: https://blog.csdn.net/qq_26440221/article/details/53097868 自从出了Android6.0权限管理之后,再也不能像以前那样粘贴复制 ...

  4. android6.0系统Healthd分析及低电量自动关机流程

    系统平台:android6.0概述Healthd是android4.4之后提出来的一种中介模型,该模型向下监听来自底层的电池事件,向上传递电池数据信息给Framework层的BatteryServic ...

  5. imx6 Android6.0.1 init.rc解析

    1. 概述 1.1 概述 之前分析过android5的init.rc,不过还是不够仔细,现在来看看android6的,多的就不写了,只写关键点 忘记一些基本概念可以先看看之前的笔记: Android5 ...

  6. Android6.0之后的权限机制对App开发的影响

    随着Android系统的更新换代,每次重大更新的方面也逐步扩展,从4.*主要是增强功能,到5.*主要是美化界面,到6.*主要提高系统安全性,再到7.*和8.*主要支撑各种大屏设备,因此开发者需要对每个 ...

  7. android6.0获取通讯录权限

    android6.0中,获取通讯录的权限是    <uses-permission android:name="android.permission.GET_ACCOUNTS" ...

  8. android6.0、7.0、8.0新特性总结之开发应用时加以考虑的一些主要变更。

    android6.0 参考一:简书Android 6.0 新特性详解 参考二:关于Android6.0以上系统的权限问题 参考三:值得你关注的Android6.0上的重要变化(一) 参考四:值得你关注 ...

  9. Android6.0获取运行时权限

    照着<第一行代码>打代码,然并卵,感叹技术进步的神速.最后提醒一点:IT类的书籍一定要注意出版时间!出版时间!出版时间!重要的事情说三遍 问题出在android6.0的权限获取问题上,以前 ...

随机推荐

  1. 个人作业2 — 英语学习APP的案例分析

    一.调研准备:   1.软件:必应词典   2.平台:安卓   3.bug定义:(引用自<构建之法>13.1节)    Bug:软件的缺陷    Bug可以分解为:症状(Symptom). ...

  2. 姑娘你大胆地往前走——答大二学生XCL之八问

    姑娘你大胆地往前走--答大二学生XCL之八问 以下问题的答案写给我家正在读大二的XCL. 写于 2017-9-13 晚 请问您是为什么选择了IT行业的? 与其说是我选择了行业,不如说是行业选择了我. ...

  3. 【Alpha阶段】第六次scrum meeting

    一.会议照片 二.会议内容 姓名 学号 负责模块 昨日任务完成度 今日任务 杨爱清 099 界面设计和交互功能 完成 设计界面 杨立鑫 100 数据库搭建和其他 完成 将数据库与其他模块连接 林 钊 ...

  4. 201521123101 《Java程序设计》第5周学习总结

    1. 本周学习总结 2. 书面作业 1. 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 不能 ...

  5. 201521123075 《Java程序设计》第10周学习总结

    1. 本周学习总结 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中finally中捕获异常需要注意什么? fin ...

  6. 一、React Native 搭建开发环境(1)(Mac OS - IOS项目)

    React Native是Facebook推出的一个开发IOS和安卓APP的技术.至于更多的详情,这里不再描述,大家可以自行百度它的定义. 目的: 由于我想在一台电脑上同时开发IOS和Android两 ...

  7. Selenium+Python自动化测试实战(2)元素定位

    1.Selenium2 的原理 第一篇分享简单介绍了基于Python开发的Selenium2的环境配置,这篇主要讲一下基本用法.首先讲一下Selenium2的基本原理.基本上知道了这个东西是怎么回事, ...

  8. 05浏览器-02-操作DOM

    1.DOM操作梗概 本篇内容实际上在另一篇笔记<从JS和jQuery浅谈DOM操作>已经提到了重点的地方,可以戳链接另外进行阅读. 以前提到过,实际上HTML在被浏览器加载以后,会变成 & ...

  9. 鸟哥Linux学习笔记06

    Linux 系统常用的压缩命令 1,*.Z compress程序压缩的文件,这个已经很老了,几乎不再使用,因此不再介绍. 2,gzip应用最广泛的压缩命令.目前gzip可以解开compress.zip ...

  10. 定时器(setTimeout和setInterval)调用带参函数失效解决方法

    方法1:用匿名函数包裹  function test(str){  alert(str);  }  var a = "abcde"  setTimeout(function(){  ...