Android_FM分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
FM Document
李耀宗1. Start FM
根据FM的AndroidManifest.xml的定义,FmServiceManager作为application被首先启动,它初始化过程中先去register FmReceiver,如:
registerService(FmReceiver.SERVICE_NAME, new
FmReceiverService(mSystemContext));
这里只提供了这一个local Android service,由FMServiceConfig配置。
FmReceiverService初始化之后被包装成FmServiceWrapper类型放在容器中,初始状态为stoped。
同时BTLD library被加载并且FMInitNative被调用,Native被初始化。
(Native初始化过程略)
static {
//System.loadLibrary("btld");
System.loadLibrary("fmservice");
classFmInitNative();
} /* BTLD配置在init.qcom.rc中启动*/
随后FmRadio被初始化,它从系统获取NotificationManager、TelephonyManager、
AudioManager服务,以监听相关的状态或者进行相应的操作。
然后通过getProxy()函数调用初始化FmReceiver,并将FmReceiverEventHandler对象传递给它。
并进行一些其他的初始化工作。
2. FM类基本结构
FmServiceManager --> Application
|--> FmServiceWrapper
|--> FmReceiverService
FmReceiverService --> BaseService --> IbtService(均由FM模块实现)
|--> CallbackList<IfmReceiverCallback>(实现回调机制,本应为Binder跨进程)
|--> Handler (实现Msg处理)
FmReceiver
|--> FmReceiverCallback --> IFmReceiverCallback.Stub(未使用)
|--> LocalFmReceiverCallback --> IfmReceiverCallback (aidl)
|--> Handler (引用,此处使用多线程进行消息处理)
|--> HandlerCreatorImpl --> IhandlerCreator
|--> Handler
|--> IfmReceiverEventHandler (引用指向FmReceiver. mHandler,如此复杂的结构只是为了使用多线程处理message)
|--> IfmReceiverEventHandler (引用来自FmRadio)
|--> LocalFmReceiverServiceStub --> IfmReceiverService (aidl)
|--> FmReceiverService (引用指向FmServiceManager. FmReceiverService,本应为跨进程通信,这里实现为进程内函数调用,通过getProxy函数获取引用)
FmRadio (实现了IbluetoothProxyCallback接口,为获取FmReceiver引用)
|--> FmReceiver (引用从onProxyAvailable()函数中获取)
|--> Handler
|--> FmReceiverEventHandler --> IfmReceiverEventHandler(配合Handler对来自FmReceiver的事件进行处理)
FM的代码中实现了许多原Android框架的基类,如:BaseProxy、BaseService等,都是为了实现本地调用。
FM的代码中还有一些其他的类,例如:FmRadioSettings、FmReceiveView等等。
初始化过程:
set Volume函数调用的逻辑如下:
FmRadio的dispatchKeyEvent()函数接收到KEYCODE_VOLUME_UP事件,调用FmReceiver的setFMVolume()函数,FmReceiverService实现为本地类后,就直接调用它的setFMVolume()函数,再转化为setFMVolumeNative() 的C++调用,再由C库函数经由Socket发给BTLD进程,最终传递到驱动,完成音量调节动作。
FM提供的C库还实现了回调的功能,在Socket send MSG之后会调用
enqueuePendingEvent()函数查找FmReceiverService (Java)中对应的回调函数
onRadioVolumeEvent(),从C++上下文转入Java上下文执行,因为FmReceiverService 实现为本地类,所以在这里又用一次回调来代替进程间通信,代码如下:
private void sendVolumeEventCallback(int status, int volume) {
……
for (int i = 0; i < callbacks; i++) {
……
m_callbacks.getBroadcastItem(i).onVolumeEvent(status, volume);
……
}
……
}
最终回到FmRadio的FmReceiverEventHandler子类,调用其onVolumeEvent()函数,再转入相应的Handler中处理。
3. FM类扩展结构
上面的FM类结构仅在Android应用框架上完成FM的相应功能,要完成FM的完整功能,至少还需要Audio Manager的支持,除此之外,我们还需要Notification Manager、Telephony Manager用于通知显示和监听电话状态。
基本类构建从底到顶的纵向结构,扩展类表象为横向功能交互。
以上分析可知,硬件的功能由驱动提供,由BTLD守护进程操作。
驱动以上、Android SDK 以下,又分三层,分别是BTLD守护进程、专用C库、FmReceiverService。
FmReceiver 是Fm模块提供的SDK,供上层应用FmRadio调用。
整个框架的实现跟Android的架构类似,只是移除了IPC部分。
4. 一些问题
可能某些功能游离于以上结构之外,还有待调查
有许多重复无用代码存在,可删除
大部分代码没有仔细研究过,还有一些对象不熟悉其用途
没有比较此处的本地实现与Android原生的进程间调用的实现方法
不熟悉Android的多线程
5. 提升效率
Tab转换为空格
在SourceInsight中选中代码,然后选择Edit -> Special Edit -> Tabs to Spaces
显示tab键
在SourceInsight中选择Options -> Document Options 选择File Type,将Visible tabs复选框打勾。
(有乱码,不好用)
在BeyondCompare的工具栏点击>> 按钮。
查看Android.mk文件
在SourceInsight中选择Options -> Document Options 选择File Type为Make File,添加*.mk后缀。
在Notepad++中选择setting -> Style configuartor… -> Makefile -> User ext 添加mk 后缀。
操作源代码
在baseline上做过修改之后,记住路径,将修改文件及其目录结构全部导出,然后delete baseline中的目录,运行svn up获取baseline代码,比较导出目录和baseline,
(beyondcompare加载慢可以点*停止比较),移除无用的改动,查看tab键,没有问题就可以合并入baseline进行commit了。
工具TotalCmd
TotalCmd功能十分强大,可以在它里面配置经常使用的其他工具,如:
BeyondCompare,配置参数:%X%P %T 即可比较TotalCmd左右两侧的内容。
powerCmd,配置参数:/P=”work path”或者/P=%X%P 以左侧路径打开Cmd。
Putty,配置参数:[user]@192.168.3.168–pw [password]可直接登录Ubuntu server。
其他所有应用程序也可配置在它上面。
6. (完)。