结合代码分析过程,我们可以看出整个telephony的初始化流程如下,鉴于下面已经有分析过程,这里就不再对流程图做文字描述了。
需要注意的是,在每个类模块下面,类之间的上下关系表示初始化的前后顺序。
Phone就象个后台进程一样,开机即运行并一直存在(如果异常退出,它会自动重启)。
在系统开机启动时,由ActivityManagerService启动的。Phone的源码位于packages\apps\Phone。在Phone的AndroidManifest.xml文件配置了如下属性:
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 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(); } } 如上,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:通话过程中的按钮功能以及来电接听时的滑动接听功能。 PhoneGlobalsBroadcastReceiver、MediaButtonReceiver的注册。 其他的处理: AudioManager等创建。 SimAssociateHandler创建并加载数据。 cellConnMgr、SIMInfoWrapper、CallHistoryDatabaseHelper、PhoneNumberUtil等相关类创建和初始化。 在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(); 通过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)); 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); 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")); } 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而来,后面分析其初始化过程。 在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。 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发送通知给当前客户端。 上面提到了两种service,这里简单比较一下。 TelephonyManager所属的service通过在context 创建, 通过registerService存放在一个hashMap里面,通过context.getSystemService获取到实例,是一个普通类。 TelephonyRegistry所属的service通过在ServiceManager创建,通过ServiceManager.addService存放在hashMap里,通过ServiceManager.getService获取到实例,用IBinder方式使用。 对比Phone应用的启动方式,查看MMS的manifest文件,发现并没有persistent的属性, 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, 然后定义一个receiver,继承自BroadcastReceiver,接收到事件BOOT_COMPLETED后,启动相关服务。在6572,有三个这样的receiver, 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); IccPhoneBookInterfaceManagerProxy在PhoneProxy里面创建,之后通过IccPhoneBookInterfaceManager的对象进行实际操作 public PhoneProxy(PhoneBase phone) { 。。。 mIccPhoneBookInterfaceManagerProxy = new IccPhoneBookInterfaceManagerProxy( phone.getIccPhoneBookInterfaceManager(), simId); PhoneSubInfoProxy在PhoneProxy里面创建,之后通过PhoneSubInfo的对象进行实际操作 public PhoneProxy(PhoneBase phone) { 。。。 mPhoneSubInfoProxy = new PhoneSubInfoProxy(phone.getPhoneSubInfo(), simId); 1.1.1 PhoneGlobals创建
ManageConferenceUtils:管理多方通话的工具,包括部分UI元素。借助PhoneUtils实现其功能。
DTMFTwelveKeyDialer:通话状态时的拨号盘,用于发送DTMF。
DTMFTwelveKeyDialerView:DTMF拨号视图布局类。
InCallControlState:维护着一些状态信息,诸如是否Enable了Speaker声音免提、是否可以添加新的一路通话等等。它是MVC模式的数据部分。
InCallMenu:通话状态菜单,里面包含各个菜单项 1.1.1 PhoneFactory创建
1.1.2 Phone创建
1.1.3 SIMRecords初始化
1.1.4 PhoneNotifier初始化
1.1.5 ITelephonyRegistry
1.1.6 TelephonyRegistry向ServiceManager注册
1.1.7 TelephonyManager
1.1.8 Service
1.1.9 Message加载
1.1.10 Isms
1.1.1 Contact加载
1.1.2 PhoneSubInfo