`
海布里的味道
  • 浏览: 18900 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

基于Phone模块的Service实现

阅读更多

1.1      总体启动框架图

(1) init进程启动

(2) Native服务启动

(3) System Server,Android服务启动

(4) Home启动

 



  

1.2    initial进程(system\core\init)

init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程。

Init进程一起来就根据init.rc和init.xxx.rc脚本文件建立了几个基本的服务:

 servicemanamger

 zygote 。。。。

最后Init并不退出,而是担当起property service的功能。

关于init的详细信息,参考相关文章。

1.3    Zygote

Servicemanager和zygote进程就奠定了Android的基础。Zygote这个进程起来才会建立起真正的Android运行空间,初始化建立的Service都是Navtive service.在.rc脚本文件中zygote的描述:

 

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

所以Zygote从main(…)--frameworks\base\cmds\app_main.cpp开始。

(1) main(…)---frameworks\base\cmds\app_main.cpp

建立Java Runtime

runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);

(2) runtime.start@AndroidRuntime.cpp

建立虚拟机

运行:com.android.internal.os.ZygoteInit:main函数。

(3)main()---com.android.internal.os.ZygoteInit//正真的Zygote。

registerZygoteSocket();//登记Listen端口

startSystemServer();

进入Zygote服务框架。

经过这几个步骤,Zygote就建立好了,利用Socket通讯,接收ActivityManangerService的请求,Fork应用程序。

1.4      System Server

startSystemServer(com.android.internal.os.ZygoteInit)在Zygote上fork了一个进程: com.android.server.SystemServer.于是SystemServer(SystemServer.java)就建立了。Android的所有服务循环框架都是建立SystemServer(SystemServer.java)上。在SystemServer.java中看不到循环结构,只是可以看到建立了init2的实现函数,建立了一大堆服务,并AddService到service Manager。

main() ( com/android/server/SystemServer )

{

 init1();

}

 

Init1()是在Native空间实现的(com_andoird_server_systemServer.cpp)。我们一看这个函数就知道了,init1->system_init() (System_init.cpp)

在system_init()我们看到了循环闭合管理框架。

{

 Call "com/android/server/SystemServer", "init2"

 ProcessState::self()->startThreadPool();

     IPCThreadState::self()->joinThreadPool();

}

init2()@SystemServer.java中建立了Android中所有要用到的服务。

这个init2()建立了一个线程,来New Service和AddService来建立服务

在其上建立了多个android服务,包括我们以后的指纹识别,也会是在这个总的服务框架内实施,需要做到信息的收发处理,可以理解为。与底层JNI如何通信,与上层app如何相互传递信息。

对于如何建立某个功能模块的服务,不需要关注太多底层的东西(包括init,zygote等等)。需要关注如上的第步 System Server

1.5      Home启动

ServerThread(SystemServer.java)后半段,我们可以看到系统在启动完所有的Android服务后,做了这样一些动作:

(1) 使用xxx.systemReady()通知各个服务,系统已经就绪。

(2)  特别对于ActivityManagerService.systemReady(回调)

 

2         Phone模块

为了对android的server如何工作有个大致的了解,以Phone模块电话为例。

流程图

 

 

 

 

2.1      过程分析

Phone服务:是指Phone所能提供的各种服务(来电去电,短信,SIM的锁定,数据连结传输等)与service不是同一个概念。

Phone 中的service是ITelephony和ITelephonyRegistry的实现类,PhoneInterfaceManager.java和TelephonyRegistry.java,后续说明。

GSMPhone 管理了电话服务的内部功能,也对RIL层进行了封装,上层应用不能直接跟RIL本地代码打交道,而是间接通过GSMPhone.但是应用层为了更方便的访问电话服务,需要在GSMPhone之上的TelephonyManager。

TelephonyManager通过两个IBinder接口ITelephony和ITelephonyRegistry来完成这项工作。

ITelephony是电话服务用户(用户层或框架其他部分)主动进行RIL访问的路径,它的服务端实现类不在代码中,而是在Phone应用PhoneInterfaceManager.java(packages/apps/Phone/src/com/android/phone/)中。PhoneInterfaceManager.publish中以”phone”为名注册该服务,提供拨号界面、呼叫、挂机等呼叫相关控制,也提供SIM PIN、开关Radio等操作,他的实现是通过调用Phone接口来操作。

ItelephonyRegistry提供一个通知机制,将底层状态变更通知给电话服务的用户(用户层或框架其他部分),是用户被动通知的路径,通知消息如网络状态、信号强弱更新、电话状态更新等。它的服务端实现在框架代码中TelephonyRegistry.java(frameworks/base/services/java/com/android/server/)。

底层通知的来源,是GSMPhone通过PhoneNotifier的实现者DefaultPhoneNotifier将具体的事件转化为函数调用并且通知到TelephonyRegistry。TelephonyRegistry再通过两种方式通知给用户,其一是广播事件,另外一种是通过服务用户在TelephonyRegistry中注册的IphoneStateListener接口,实现回调。

SystemServer.java实现了电话服务的添加

………

ServiceManager.addService("telephony.registry",new TelephonyRegistry(context));

………

对于在SystemServer.java中添加的Service,SystemServer.java 中的init1()函数保证了Service在后台不断运行,具体的底层实现,需要查看文档和源码。

 

 

2.2      去电流程

不论打电话的方式是何种(拨号盘拨打,通话记录中拨号,联系人中拨号。。),都会触发outgoingCallBroadcastonCreate()函数,获得Action & Number,并对其进行判断,并且广播给outgoingCallReceiver内部类,发送Intent.ACTION_NEW_OUTGOING_CALL消息。

outgoingCallReceiver收到Intent消息,调用onReceiver() -> doReceiver(),启动InCallScreen界面。

进入InCallScreen后,可以分为15个函数调用。

具体的分析如下:

1.进入InCallScreen类中,如果是第一次进入,调用onCreate()函数(1),如果在通话过程再一次的拨打电话,调用onNewIntent()函数(2)。两个函数都会调用IntentResolveIntent()函数(3),在这个函数中调用InCallScreen类中的成员方法placeCall()函数(4)

InCallScreen中的placeCall()函数调用类PhoneUtils.placeCall()函数(5)PhoneUtils.placeCall()函数调用phone.dial()函数,至此app层的函数调用结束,转到frameworks层。

InCallScreen.java PhoneUtils.Javapackages\apps\phone\src\com\android\phone…

(6) PhoneUtils.java

static int placeCall(Phone phone, String number, Uri contactRef)

(7) Connection cn = phone.dial(number); 

GSMPhone.java

phone应用程序中,通过PhoneFactory来获取GSMPhone实例。

 GSMPhone()....

(8)dial(String dialString)

(9)mCT.dial(mmi.dialingNumber, mmi.getCLIRMode()); (PS: GsmCallTracker mCT)

 

GsmCallTracker.java

GsmCallTracker dial (String dialString)...

(10)dial (String dialString, int clirMode) {

...

(11)cm.dial(pendingMO.address, clirMode, obtainCompleteMessage());

(ps: CommandInterface cm = phone.mCM)

...

}

因为 RIL.java (frameworks\base\telephony\java\com\android\internal\telephony):

public final class RIL extends BaseCommands implements CommandsInterface所以 cm.dial

实际上调用的是 RIL.java 中的dial -(12)

 

RIL.java

(12)dial (String address, int clirMode, Message result)

LRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);

(13)send()

(14) msg.sendToTarget();

target.sendMessage(this); (frameworks/base/core/java/android/os/Message.java)

//Handler.java (frameworks\base\core\java\android\os)

boolean sendMessage(Message msg){ 

       return sendMessageDelayed(msg, 0);

}

-->   return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

--->    sent = queue.enqueueMessage(msg, uptimeMillis);

(15) RIL.java

class RILSender extends Handler implements Runnable{

 

//把消息放入到消息队列

public void handleMessage(Message msg)

..

s.getOutputStream().write(dataLength);                    

s.getOutputStream().write(data);

...

 因为在 RIL.java 文件中有 static final String SOCKET_NAME_RIL = "rild";

 run()函数中有:

                    s = new LocalSocket();

                    l = new LocalSocketAddress(SOCKET_NAME_RIL,

                            LocalSocketAddress.Namespace.RESERVED);

                    s.connect(l);

                    ...

                    mSocket = s;}

所以可以确定s.getOutputStream().write(data) 是往 rild socket写数据。

到这里,frameworks 请求结束,通过socket转到RIL层处理 dial请求。

 

2.3      来电流程

1.创建GsmPhone时,mCT = new GsmCallTracker(this);

2.创建GsmCallTracker时:

    cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null); -->   

    mCallStateRegistrants.add(r);

3.RIL中的RILReceiver线程首先读取从rild中传来的数据:processResponse -> processUnsolicited

4.对应于incoming call,RIL收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED 消息,触发mCallStateRegistrants中的所有记录。

5.GsmCallTracker处理EVENT_CALL_STATE_CHANGE,调用pollCallsWhenSafe

6.函数pllCallsWhenSafe 处理:

     lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);

     cm.getCurrentCalls(lastRelevantPoll);

7.RIL::getCurrentCalls

    RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);

    ...

    send(rr);

8.接着RIL调用processSolicited处理RIL_REQUEST_GET_CURRENT_CALLS的返回结果

9.GsmCallTracker的handleMessage被触发,处理事件EVENT_POLL_CALLS_RESULT,调用函数 

    handlePollCalls

10.handlPollCalls 调用

    phone.notifyNewRingingConnection(newRinging);

11.PhoneApp中创建CallNotifier

12.CallNotifier注册:

registerForNewRingingConnection ->

mNewRingingConnectionRegistrants.addUnique(h, what, obj);

 

 

2.4   小结

Phone模块的分析,并对具体的来电、去电流程的跟踪,电话服务的框架式可以确定的,但是具体的实现细节还不清楚,这也是接下来的工作。

对于今后的新模块Service,大体可以这样实现:

1.            Service完成的内容要明确,实现可以按照大多数模块那样编写AIDL文件,产生对应的java文件,通过继承与实现方式,来具体实现Service内容

2.            上层不可以直接的调用Service内的函数,需要通过一个xxxManager.java来方便的操作Service发送的消息。如Phone中的TelephonyManager.java来管理操作,具体的操作又是通过ITelephony ITelephonyRegistry来完成。

3.            Service响应底层的事件,通过Broadcast发送Intent消息,应用层接收到消息事件,进行相应的处理。

4.            Service可以设置监听,等到有反馈时,进行处理

5.            Service启动可以在SystemServer.java 中添加。

  • 大小: 39.2 KB
  • 大小: 25 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics