2 TelePhony启动代码分析:
1.1 Telephony启动流程图
结合代码分析过程,我们可以看出整个telephony的初始化流程如下,鉴于下面已经有分析过程,这里就不再对流程图做文字描述了。
需要注意的是,在每个类模块下面,类之间的上下关系表示初始化的前后顺序。
2.1 Telephony关键类初始化
2.1.1 Phone进程启动
Phone就象个后台进程一样,开机即运行并一直存在(如果异常退出,它会自动重启)。
在系统开机启动时,由ActivityManagerService启动的。Phone的源码位于packages\apps\Phone。在Phone的AndroidManifest.xml文件配置了如下属性:
<application android:name="PhoneApp"
1. android:persistent="true"
2. android:label="@string/dialerIconLabel"
3. android:icon="@drawable/ic_launcher_phone">
对于android:persistent="true" 的应用是在Android开机时启动的,在Android服务启动中,有三种启动方式(init.rc, persistent,BOOT_COMPLETED?),其中一种是在启动完成时通过调用systemReady函数来完成并通知服务启动。ActivityManagerService服务正是采用这种启动方式,对于属性android:persistent为true的应用是在ActivityManagerService服务启动完成后启动的:
1. public void systemReady(final Runnable goingCallback){
2. ......
3. if (goingCallback != null) goingCallback.run();
4. synchronized (this) {
5. if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6. try {
7. //通过PackageManager查询到所有android:persistent属性为true的应用
8. List apps = AppGlobals.getPackageManager().getPersistentApplications(STOCK_PM_FLAGS);
9. if (apps != null) {
10. int N = apps.size();
11. int i;
12. //遍历所有应用,并启动
13. for (i=0; i<N; i++) {
14. //得到每个应用的相关信息
15. ApplicationInfo info= (ApplicationInfo)apps.get(i);
16. //启动应用
17. if (info != null &&!info.packageName.equals("android")) {
18. addAppLocked(info);
19. }
20. }
21. }
22. } catch (RemoteException ex) {
23. // pm is in same process, this will never happen.
24. }
25. }
26. ........
27. mMainStack.resumeTopActivityLocked(null);
28. }
29. }
其中addAppLocked启动该应用,在调用startProcessLocked启动进程,PhoneAPP继承自Application,启动时调用它的onCreate函数,在里面则新建一个PhoneGlobals并调用它的onCreate函数。
public PhoneApp() {
}
@Override
public void onCreate() {
if (UserHandle.myUserId() == 0) {
// We are running as the primary user, so should bring up the
// global phone state.
mPhoneGlobals = new PhoneGlobals(this);
mPhoneGlobals.onCreate();
}
}
1.1.1 PhoneGlobals创建
如上,PhoneGlobals是在PhoneAPP创建,并调用它的onCreate函数,这里有一些重要的工作要做,如下,
Phone相关:
Phone实例没有创建的时候,对其进行相关的初始化,如果PhoneApp重启,因为之前phone实例已经创建过,则不需要再初始化,避免Telephony重新初始化,耗费资源和时间。
创建Phone实例,
PhoneFactory.makeDefaultPhones(this);
启动TelephonyDebugService
Intent intent = new Intent(this, TelephonyDebugService.class);
startService(intent);
registerPhone,主要工作是创建一个CallManager,并根据多卡支持,将Phone实例和其中的方法RingingCall、BackgroundCall、ForegroundCall添加到CallManager里面,然后通过registerForPhoneStates,向Phone注册相关事件。
private void registerPhone() {
mCM = CallManager.getInstance();
if (GeminiUtils.isGeminiSupport()) {
mCMGemini = MTKCallManager.getInstance();
mCMGemini.registerPhoneGemini(phone);
} else {
mCM.registerPhone(phone);
}
}
public boolean registerPhone(Phone phone) {
registerOnePhone()
。。。
registerForPhoneStates() //向phone注册
}
private boolean registerOnePhone(Phone phone) {
boolean result = false;
Phone basePhone = getPhoneBase(phone);
if (basePhone != null && !mPhones.contains(basePhone)) {
if (DBG) {
Log.d(LOG_TAG, "[BSPPackage]registerPhone(" + phone.getPhoneName() + " " + phone + ")");
}
mPhones.add(basePhone);
mRingingCalls.add(basePhone.getRingingCall());
mBackgroundCalls.add(basePhone.getBackgroundCall());
mForegroundCalls.add(basePhone.getForegroundCall());
result = true;
}
return result;
}
NotificationMgr、PhoneInterfaceManager、PhoneInterfaceManagerEx的实例获取,如不存在则需要创建实例。
BluetoothPhoneService、Ringer、PowerManager、KeyguardManager、IPowerManager、InCallUiState、CallerInfoCache、CallNotifier、PhoneUtils等类初始化。
CallNotifier是一个Handler,它为PhoneApp处理各个主动上报来的一些消息。它监听来自Telephony层phone状态变化和其它各种事件,从而作出反应 如各种UI行为:启动铃音播放和来电显示UI、播放正在通话时的来电提示、更新状态栏提示(通过NotificationMgr)、通话记录添加等。在PhoneBase中提供了一些RegistrantList,CallNotifier可以将自己作为一个感兴趣者注册进去,这样,当状态变化时,CallNotifier将得到通知,然后在线程中对其处理,作出UI方面的响应。
NotificationMgr以静态成员函数的方式为PhoneApp用于Phone进程在状态栏中通知用户消息的功能,诸如:有未接电话、正在通话、是否静音等信息。它使用系统提供的API类NotificationManager和StatusBarManager完成通知功能。每项通知对应着通知、更新通知和取消通知的函数。当收到Message时,PhoneApp的Handler的handleMessage会使用NotificationMgr更新状态栏信息。
InCallScreen它是手机正在通话时的Activity。当有来电、开始拨号或正在通话时,运行的是该Activity,InCallScreen需要处理来电时跳过键盘锁直接可以接听电话、是否有耳机插入的情况、是否用蓝牙接听电话、需要监听并维护更新通话状态并显示给用户、需要支持通话过程中的某些功能(如发送DTMF、电话会议、分离一路通话)操作、OTA Call等。CallCard是InCallScreen中的一个call(可能是当前的Call或保持的Call或来电Call)。当需要接听电话或拨打电话时,上层发来intent,然后InCallScreen收到intent时它的InCallScreen.onNewIntent函数被调用,解析intent,要么调用placeCall拨打电话,要么调用internalAnswerCall接听电话。InCallTouchUi:通话过程中的按钮功能以及来电接听时的滑动接听功能。
ManageConferenceUtils:管理多方通话的工具,包括部分UI元素。借助PhoneUtils实现其功能。
DTMFTwelveKeyDialer:通话状态时的拨号盘,用于发送DTMF。
DTMFTwelveKeyDialerView:DTMF拨号视图布局类。
InCallControlState:维护着一些状态信息,诸如是否Enable了Speaker声音免提、是否可以添加新的一路通话等等。它是MVC模式的数据部分。
InCallMenu:通话状态菜单,里面包含各个菜单项
PhoneGlobalsBroadcastReceiver、MediaButtonReceiver的注册。
其他的处理:
AudioManager等创建。
SimAssociateHandler创建并加载数据。
cellConnMgr、SIMInfoWrapper、CallHistoryDatabaseHelper、PhoneNumberUtil等相关类创建和初始化。
1.1.1 PhoneFactory创建
在PhoneGlobals.java (packages\services\telephony\src\com\android\phone)文件的onCreate()方法中,调用PhoneFactory.makeDefaultPhones来创建Phone相关实例,通过getDefaultPhone获取实例引用。
if (phone == null) {
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);
// Get the default phone
phone = PhoneFactory.getDefaultPhone();
1.1.2 Phone创建
通过PhoneFactory.makeDefaultPhones就创建了Phone实例,创建中主要完成的工作有:
(MTK代码有封装,参考googl原生代码。)
public static void makeDefaultPhone(Context context) {
sLooper = Looper.myLooper(); //创建一个looper
sContext = context; // 赋值context
new LocalServerSocket("com.android.internal.telephony"); //新建一个socket,用for语句保证socket一定能分配,否则phone实例不能创建
sPhoneNotifier = new DefaultPhoneNotifier(); //创建notifier实例
//reads the system properties and makes commandsinterface
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);//ril接口
UiccController.make(context, sCommandsInterface); //卡操作实例
// 新建phone示例,实际就是PhoneProxy实例,同时新建一个GSMPhone做参数
sProxyPhone = new PhoneProxy(new GSMPhone(context,
sCommandsInterface, sPhoneNotifier));
1.1.3 SIMRecords初始化
SIMRecords实例由UiccCardApplication创建:
UiccCardApplication.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)
private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) {
if(DBG) log("createIccRecords, AppType = " + type);
if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) {
return new SIMRecords(this, c, ci);
。。。
UiccCardApplication实例由UiccCard创建:
UiccCard.java (frameworks\opt\telephony\src\java\com\android\internal\telephony):
mUiccApplications[i] = new UiccCardApplication(this,
ics.mApplications[i], mContext, mCi);
UiccCard实例由UiccController创建:
UiccController.java (frameworks\opt\telephony\src\java\com\android\internal\telephony\uicc)
private synchronized void onGetIccCardStatusDone(AsyncResult ar) {
if (mUiccCard == null) {
//Create new card
mUiccCard = new UiccCard(mContext, mCi, status, mSimId);
} else {
//Update already existing card
mUiccCard.update(mContext, mCi , status);
}
。。。
UiccController实例由UiccController.make()创建,UiccController.make()在PhoneFactory里被调用:
PhoneFactory.java (frameworks\opt\telephony\src\java\com\android\internal\telephony):
public static void makeDefaultPhone(Context context) {
。。。
// Instantiate UiccController so that all other classes can just call getInstance()
UiccController.make(context, sCommandsInterface);
1.1.4 PhoneNotifier初始化
PhoneNotifier也是在PhoneFactory里创建的,实际是创建的DefaultPhoneNotifier的实例。
。。。
sPhoneNotifier = new DefaultPhoneNotifier();
。。。
int phoneType = TelephonyManager.getPhoneType(networkMode);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
Log.i(LOG_TAG, "Creating GSMPhone");
sProxyPhone = new PhoneProxy(new GSMPhone(context,
sCommandsInterface, sPhoneNotifier));
}
。。。
在DefaultPhoneNotifier的构造函数里,获取了ItelephonyRegistry的服务,将Phone底层的消息通过ItelephonyRegistry上报。
public DefaultPhoneNotifier() {
mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
}
1.1.5 ITelephonyRegistry
ItelephonyRegistry是一个接口,继承自IInterface,它有一个static类型的抽象内部类Stub,继承自Binder并实现了它本身,通过Stub的asInterface能够获取接口实例。接口里方法的实现最终是通过Stub的子类Proxy实现的,
public static com.android.internal.telephony.ITelephonyRegistry asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.android.internal.telephony.ITelephonyRegistry))) {
return ((com.android.internal.telephony.ITelephonyRegistry)iin);
}
return new com.android.internal.telephony.ITelephonyRegistry.Stub.Proxy(obj);
}
可以看出,ItelephonyRegistry对应的实例是从Binder而来,后面分析其初始化过程。
1.1.6 TelephonyRegistry向ServiceManager注册
在SystemServer.java文件,在ServerThread.run()里面,为每张卡向ServiceManager注册了一个telephonyRegistry,这个注册过程实际上就是绑定了一个Ibinder。
Slog.i(TAG, "Telephony Registry Phone1");
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
Slog.i(TAG, "Telephony Registry Phone2");
telephonyRegistry2 = new TelephonyRegistry(context, PhoneConstants.GEMINI_SIM_2);
ServiceManager.addService("telephony.registry2", telephonyRegistry2);
///M: We create phone registry for each SIM card. ex: registry 1~3 for 3SIM_SUPPORT, registry 1~4 for 4SIM_SUPPORT
if(FeatureOption.MTK_GEMINI_3SIM_SUPPORT || FeatureOption.MTK_GEMINI_4SIM_SUPPORT){
Slog.i(TAG, "Telephony Registry Phone3");
telephonyRegistry3 = new TelephonyRegistry(context, PhoneConstants.GEMINI_SIM_3);
ServiceManager.addService("telephony.registry3", telephonyRegistry3);
///M: Support up to 4 SIM cards
if(FeatureOption.MTK_GEMINI_4SIM_SUPPORT){
Slog.i(TAG, "Telephony Registry Phone4");
telephonyRegistry4 = new TelephonyRegistry(context, PhoneConstants.GEMINI_SIM_4);
ServiceManager.addService("telephony.registry4", telephonyRegistry4);
}
}
其中,TelephonyRegistry是继承自ITelephonyRegistry.Stub,ITelephonyRegistry.Stub是继承自Ibinder,所以TelephonyRegistry实际是一个Ibinder。
TelephonyRegistry是一个服务,就需要去向ServiceManager先注册自己。再作为一个服务为客户提供注册,注册的过程其实就是把客户端添加到一个叫做mRecords的列表中,当Phone状态改变后,TelephonyRegistry会遍历mRecords中的客户端,分别调用他们当初注册的回调函数。mRecords是TelephonyRegistry核心维护的列表,其中每一项元素都是一个Record型的数据结构,代表着一个客户端。
根据Record的数据结构,客户端注册监听器时,需要提供一个IPhoneStateListener类型的对象,IPhoneStateListener接口定义了有关Phone各个状态的监听器的回调函数。
private static class Record {
String pkgForDebug;
IBinder binder;
IPhoneStateListener callback;
int callerUid;
int events;
}
客户端指定了自己所关注的状态,同时提供自己对该状态的回调函数,当相应的事件发生时,TelephonyRegistry就会去调用客户端的回调函数IPhoneStateListener。
1.1.7 TelephonyManager
TelephonyManager的创建比较特殊,有两种实例创建,
其一是在ContextImpl里面,创建TelephonyManager实例,并向context注册,方便后面能够通过context.getSystemService获取到实例。
registerService(TELEPHONY_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new TelephonyManager(ctx.getOuterContext());
}});
还一种是在TelephonyManager类文件里,new一个实例,其他一些应用中,使用getDefault获得引用,进行方法调用。
private static TelephonyManager sInstance = new TelephonyManager();
/** @hide
/* @deprecated - use getSystemService as described above */
public static TelephonyManager getDefault() {
return sInstance;
}
至于为什么new出两个实例,具体是如何分别使用的,尚不清楚。
在TelephonyManager通过getITelephony获取服务实例,
private ITelephony getITelephony() {
return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
}
通过listen为客户提供向getITelephony注册的服务。也就是说,客户端 如果想要实现对TelephonyRegistry的监听,可以先得到TelephonyManager的服务,然后通过这个服务调用其listen方法 把当前客户端注册给TelephonyRegistry,当Phone状态改变时,再由TelephonyRegistry发送通知给当前客户端。
1.1.8 Service
上面提到了两种service,这里简单比较一下。
TelephonyManager所属的service通过在context 创建, 通过registerService存放在一个hashMap里面,通过context.getSystemService获取到实例,是一个普通类。
TelephonyRegistry所属的service通过在ServiceManager创建,通过ServiceManager.addService存放在hashMap里,通过ServiceManager.getService获取到实例,用IBinder方式使用。
1.1.9 Message加载
对比Phone应用的启动方式,查看MMS的manifest文件,发现并没有persistent的属性,
<application android:name="MmsApp"
android:label="@string/app_label"
android:icon="@mipmap/ic_launcher_smsmms"
android:taskAffinity="android.task.mms"
android:allowTaskReparenting="true"
android:supportsRtl="true">
显然它不是用和Phone相同方式启动的。
应用启动还有一种方式,就是在manifest文件里注册RECEIVE_BOOT_COMPLETED,
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
然后定义一个receiver,继承自BroadcastReceiver,接收到事件BOOT_COMPLETED后,启动相关服务。在6572,有三个这样的receiver,
<receiver android:name=".transaction.MmsSystemEventReceiver">
<receiver android:name=".transaction.SmsReceiver">
<receiver android:name=".transaction.WapPushReceiver">
1.1.10 Isms
Isms | 接口,继承自IInterface,它有一个static类型的抽象内部类Stub,继承自Binder,并通过proxy实现了它本身。 |
IccSmsInterfaceManager | 抽象类,继承自ISms.Stub,实现了stub的方法。实现发送短信、操作SIM卡上短信相关数据等功能。 |
SimSmsInterfaceManager | 类,继承自IccSmsInterfaceManager,是实例创建的真正对象。内有handler处理事件。 |
IccSmsInterfaceManagerProxy | 类,继承自ISms.Stub,实现了stub的方法。方法的实现实际是对IccSmsInterfaceManager的一层封装,给上层提供了统一的借口,实际的功能还是通过IccSmsInterfaceManager来完成的。 |
Isms相关的类有IccSmsInterfaceManager,SimSmsInterfaceManager,IccSmsInterfaceManagerProxy,以及SMSDispatcher。在这些类中关系如下,
我们IccSmsInterfaceManagerProxy负责向上层的接口,SimSmsInterfaceManager本层功能实现,SMSDispatcher提供下一层的功能支撑。
这些对象的实例化过程如下:
SimSmsInterfaceManager的实例是在GsmPhone里面创建的,
GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int simId) {
mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
IccSmsInterfaceManagerProxy在PhoneProxy里面创建,之后通过IccSmsInterfaceManager的实例进行实际操作,
public PhoneProxy(PhoneBase phone) {
。。。
mIccSmsInterfaceManagerProxy = new IccSmsInterfaceManagerProxy(
phone.getIccSmsInterfaceManager(), simId);
1.1.1 Contact加载
IccPhoneBookInterfaceManagerProxy在PhoneProxy里面创建,之后通过IccPhoneBookInterfaceManager的对象进行实际操作
public PhoneProxy(PhoneBase phone) {
。。。
mIccPhoneBookInterfaceManagerProxy = new IccPhoneBookInterfaceManagerProxy(
phone.getIccPhoneBookInterfaceManager(), simId);
1.1.2 PhoneSubInfo
PhoneSubInfoProxy在PhoneProxy里面创建,之后通过PhoneSubInfo的对象进行实际操作
public PhoneProxy(PhoneBase phone) {
。。。
mPhoneSubInfoProxy = new PhoneSubInfoProxy(phone.getPhoneSubInfo(), simId);