Android6.0的phone应用源码分析(2)——phone相关进程启动分析

1.1   PhoneApp启动

PhoneApp进程是在系统开机时启动的,和其他的很多服务应用或Activity一样,它是由AMS在SystemReady后启动的。其AndroidManifest.xml文件中有如下配置:

<application android:name="PhoneApp"

                 android:persistent="true"//这里的true表示应用是在ActivityManagerService

                //服务启动完成后启动的

                 android:label="@string/phoneAppLabel"

                 android:icon="@mipmap/ic_launcher_phone"

                 android:allowBackup="false"

                 android:supportsRtl="true">

首先执行的肯定是onCreate(),如下

    public void onCreate() {

        if (UserHandle.myUserId() == 0) {//primary用户

            mPhoneGlobals = new PhoneGlobals(this);

            mPhoneGlobals.onCreate();

 

            mTelephonyGlobals = new TelephonyGlobals(this);//处理PSTN呼叫

            mTelephonyGlobals.onCreate();

        }

    }

可以看到此方法实际上是新建了两个类:PhoneGlobals和TelephoneGlobals,并分别调用了它们的onCreate()方法。phoneApp类似后台服务,当异常退出后,它会自动重启。从上面程序内的注释可以看到最为普遍的Phone入口为mPhoneGlobals.onCreate():

    public void onCreate() {

        if (VDBG) Log.v(LOG_TAG, "onCreate()...");

 

        ContentResolver resolver = getContentResolver();

        sVoiceCapable =              getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);

       

        if (mCM == null) {//和之前的版本不一样,这里检测的是mCM而不是phone

            //初始化Telecom Framwork创建phone

            PhoneFactory.makeDefaultPhones(this);

            // 开启TelephonyDebugService

            Intent intent = new Intent(this, TelephonyDebugService.class);

            startService(intent);

            //②注意mCM的类型为CallManager

            mCM = CallManager.getInstance();//注意这里是个单例

            for (Phone phone : PhoneFactory.getPhones()) {

                mCM.registerPhone(phone); //phone注册到mCM,注意这里管理多个phone

            }

   // 创建NotificationMgr单例, 用来显示状态栏图标和控制其他状态栏

            notificationMgr = NotificationMgr.init(this);

            //开启Sip服务

            mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE);

 

              //6.0现在默认创建cdmaphonecallstate实例并初始化状态为IDLE

            cdmaPhoneCallState = new CdmaPhoneCallState();

            cdmaPhoneCallState.CdmaPhoneCallStateInit();

 

            // 注册之前对电源服务的处理

            mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);

            mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);

            // lock used to keep the processor awake, when we don't care for the display.

            mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK

                    | PowerManager.ON_AFTER_RELEASE, LOG_TAG);

            //锁屏管理

            mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);

 

            //binder相关,获取远程Power服务对象

            mPowerManagerService = IPowerManager.Stub.asInterface(

                    ServiceManager.getService("power"));

 

            // Get UpdateLock to suppress system-update related events (e.g. dialog

            // show-up) during phone calls.

            mUpdateLock = new UpdateLock("phone");

 

            if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock);

 

            CallLogger callLogger = new CallLogger(this, new CallLogAsync());

 

            callGatewayManager = CallGatewayManager.getInstance();

 

            // 创建CallController单例, which is the interface

            // to the telephony layer for user-initiated telephony functionality

            // (like making outgoing calls.)

            callController = CallController.init(this, callLogger, callGatewayManager);

 

            // Create the CallerInfoCache singleton, which remembers custom ring tone

            // and send-to-voicemail settings.

            // The asynchronous caching will start just after this call.

            callerInfoCache = CallerInfoCache.init(this);

 

            // 从电话层监视呼叫活动,这里其实是注册了来电响铃的回调

            callStateMonitor = new CallStateMonitor(mCM);

 

             // 蓝牙,猜测为蓝牙免提

            bluetoothManager = new BluetoothManager();

             //实现对Phone的控制操作。

            phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());

            //6.0新增

            configLoader = CarrierConfigLoader.init(this);

 

           //Callnotifier主要是对电话状态的监听,通知事件比如响铃,是个Handler

            notifier = CallNotifier.init(this, callLogger, callStateMonitor, bluetoothManager);

            // 注册ICC状态

            PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);

 

            // 注册MMI/USSD

            mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);

 

           // 通过PhoneUtils跟踪CallManager

            PhoneUtils.initializeConnectionHandler(mCM);

            // 注册其他意图广播,此类广播将在内部类PhoneAppBroadcastReceiver中被接受

            //注意一下注册类型名字,如ACTION_AIRPLANE_MODE_CHANGED

            IntentFilter intentFilter =

                    new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);

            intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);

            intentFilter.addAction(Intent.ACTION_DOCK_EVENT);

            intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);

            intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);

            intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);

            intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);

            registerReceiver(mReceiver, intentFilter); //绑定事件接收者

 

            //设置在电话中的首选项的默认值

            PreferenceManager.setDefaultValues(this, R.xml.network_setting, false);

 

            PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);

 

            // Make sure the audio mode (along with some

            // audio-mode-related state of our own) is initialized

            // correctly, given the current state of the phone.

            PhoneUtils.setAudioMode(mCM);

        }

 

        cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();

        cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();

        cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();

        cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();

 

        simActivationManager = new SimActivationManager();

 

        // XXX pre-load the SimProvider so that it's ready

        resolver.getType(Uri.parse("content://icc/adn"));

 

        //静音标志,指的是能听到对方声音,自己声音被屏蔽的那种静音

        mShouldRestoreMuteOnInCallResume = false;

 

        // TODO: Register for Cdma Information Records

        // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);

 

        // Read HAC settings and configure audio hardware

        if (getResources().getBoolean(R.bool.hac_enabled)) {

            int hac = android.provider.Settings.System.getInt(

                    getContentResolver(),

                    android.provider.Settings.System.HEARING_AID,

                    0);

            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

            audioManager.setParameter(SettingsConstants.HAC_KEY,

                    hac == SettingsConstants.HAC_ENABLED

                            ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF);

        }

    }

1.2   Phone的创建

入口在上节代码标号的位置,可以看到,phone是通过工厂模式创建的。采用这样的创建方式和phoneApp异常退出然后重启有关,重启时phoneApp的phone不需要重新创建,只需要获得之前的phone就可以了。以下是工厂的相关方法:

    public static void makeDefaultPhone(Context context) {

        synchronized (sLockProxyPhones) {//同步,以避免创建多个phone

            if (!sMadeDefaults) {//判断是否已经创建了phone

                sContext = context;

                // 新建设备控制器

                TelephonyDevController.create();

                int retryCount = 0;

                for(;;) {//采用死循环保证肯定创建

                    boolean hasException = false;

                    retryCount ++;

                    try {

                        //使用UNIX域套接字来防止后续的初始化,这里并没有抽出引用,像是为了//某种同步

                      new LocalServerSocket("com.android.internal.telephony");

                    } catch (java.io.IOException ex) {

                        hasException = true;

                    }

                    if ( !hasException ) {

                        break;

                    } else if (retryCount > SOCKET_OPEN_MAX_RETRY) {

                        throw new RuntimeException("PhoneFactory probably already running");

                    } else {

                        try {

                            Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);

                        } catch (InterruptedException er) {

                        }

                    }

                }

                sPhoneNotifier = new DefaultPhoneNotifier();

 

                // 获取网络制式类型和CdmaSubscription相关描述

                int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);

                Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);

 

                /* In case of multi SIM mode two instances of PhoneProxy, RIL are created,

                   where as in single SIM mode only instance. isMultiSimEnabled() function checks

                   whether it is single SIM or multi SIM mode */

                int numPhones = TelephonyManager.getDefault().getPhoneCount();

                int[] networkModes = new int[numPhones];

                sProxyPhones = new PhoneProxy[numPhones];

                 //新建RIL接口

                sCommandsInterfaces = new RIL[numPhones];

 

                for (int i = 0; i < numPhones; i++) {

                    // reads the system properties and makes commandsinterface

                    // Get preferred network type.

                    networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;

 

                    Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));

                    sCommandsInterfaces[i] = new RIL(context, networkModes[i],

                            cdmaSubscription, i);

                }

                Rlog.i(LOG_TAG, "Creating SubscriptionController");

                SubscriptionController.init(context, sCommandsInterfaces);

 

                // Instantiate UiccController so that all other classes can just

                // call getInstance()

                mUiccController = UiccController.make(context, sCommandsInterfaces);

 

                for (int i = 0; i < numPhones; i++) {

                    PhoneBase phone = null;

                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);

                    // 新建phone实例,根据网络模式,新建一个GSMPhone实例或CDMALTEPhone

                    //实例,做为参数再创建PhoneProxy实例,

                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {

                        phone = new GSMPhone(context,

                                sCommandsInterfaces[i], sPhoneNotifier, i);

phone.startMonitoringImsService();

                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {

                        phone = new CDMALTEPhone(context,

                                sCommandsInterfaces[i], sPhoneNotifier, i);

phone.startMonitoringImsService();

                    }

                    Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);             //以上面的Phone创建相应的phoneProxy

                    sProxyPhones[i] = new PhoneProxy(phone);

                }

                //代理控制器

                mProxyController = ProxyController.getInstance(context, sProxyPhones,

                        mUiccController, sCommandsInterfaces);

 

                //设置默认phone

                sProxyPhone = sProxyPhones[0];

                sCommandsInterface = sCommandsInterfaces[0];

 

                // SMS应用检测

                ComponentName componentName =

                        SmsApplication.getDefaultSmsApplication(context, true /* updateIfNeeded */);

                String packageName = "NONE";

                if (componentName != null) {

                    packageName = componentName.getPackageName();

                }

                Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName);

 

                // Set up monitor to watch for changes to SMS packages

                SmsApplication.initSmsPackageMonitor(context);

 

                sMadeDefaults = true; //phone已创建标志设置

 

                Rlog.i(LOG_TAG, "Creating SubInfoRecordUpdater ");

                sSubInfoRecordUpdater = new SubInfoRecordUpdater(context,

                        sProxyPhones, sCommandsInterfaces);

                SubscriptionController.getInstance().updatePhonesAvailability(sProxyPhones);

            }

        }

    }

从上面的代码可以知道,在phone创建的同时,相应的RIL也被创建,phone和其RIL是一一对应的关系。这里明显的使用了代理模式,并没有返回真正的Phone,而只是返回PhoneProxy。这里一方面当然是出于安全方面的考虑:让App直接获取到phone太危险了,需要加上一层代理以控制权限。另一方面无论是CmdaPhone还是GSMPhone在这里都被统一起来了。phone创建好后可以调用下面的方法获取proxyPhones,在6.0中这一部分稍微有点变化,它把所有的Phone都注册进入了mCM。个人理解是mCM在phone的后面被创建,phone创建好了并不代表mCM也创建好了,而反过来却可以,所以6.0phone的重复性检测并不是检测的phone而是检测mCM。因此才会将5.0的getDefaultPhone()更改为getPhones()返回多个phone的代理,并全注册进mCM。

public static Phone[] getPhones() {

        synchronized (sLockProxyPhones) {

            if (!sMadeDefaults) {

                throw new IllegalStateException("Default phones haven't been made yet!");

            }

            return sProxyPhones;

        }

    }

1.3   CallManager分析

CallManager的实例mCM在的位置被创建,接着将之前已经获得的默认phone注册进这个CallManager。从mCM的创建方式可以猜到它是个单例。以下为其私有的构造方式:

private CallManager() {

        mPhones = new ArrayList<Phone>();//存储所有Phone的数组

        mRingingCalls = new ArrayList<Call>();//存储所有的Calls

        mBackgroundCalls = new ArrayList<Call>();//后景Calls

        mForegroundCalls = new ArrayList<Call>();//前景Calls

        mDefaultPhone = null;

    }

CallManager类提供了一个抽象层,以供phoneApp访问和控制call等操作。它实现了Phone接口。CallManager提供呼叫和连接控制以及Channel能力。CallManager提供三种类型的API:

1,呼叫控制和操作,如dial()和hangup();

2,Channel的能力,如canconference();

3,注册通知。

接着将Phone注册进mCM

public boolean registerPhone(Phone phone) {

        Phone basePhone = getPhoneBase(phone);//得到相应的PhoneBase,其实就是对PhoneProxy

        //解代理,得到Phone对象

        if (basePhone != null && !mPhones.contains(basePhone)) {//存在性和重复性检查

            if (DBG) {

                Rlog.d(LOG_TAG, "registerPhone(" +

                        phone.getPhoneName() + " " + phone + ")");

            }

            if (mPhones.isEmpty()) {

                mDefaultPhone = basePhone;

            }

            mPhones.add(basePhone);//phone加入mPhones队列进行管理

            mRingingCalls.add(basePhone.getRingingCall());//phone添加

            mBackgroundCalls.add(basePhone.getBackgroundCall());//后景call添加

            mForegroundCalls.add(basePhone.getForegroundCall());//前景call添加

            registerForPhoneStates(basePhone);//phone关联CallManagerHandler

            return true;

        }

        return false;

    }

一个Phone可以有多个Call。而每一个Call都对应着9种状态,分别是IDLE,ACTIVE,HOLDING,DIALING,ALERTING,INCOMING,WAITING,DISCONNECTED,DISCONNECTING。一般Phone启动时创建了3个Call,根据状态的不同,3个Call可以成为RingCall,ForegroundCall以及BackgroundCall和IdleCall(本人加的称呼)。其中RingCall,ForegroundCall唯一,BackgroundCall你自己算下就知道最多2个,当一个电话都没有时3个Call都为Idle状态成为IdleCall。每个Call,据查阅百度,最多有5个connections,但同时3个Call合起来不能超过7个connections(资料准确性待定)。

这里就存在着三类状态,Connection的状态、CallState和PhoneState。按本人的理解应该是这样的:Connection的状态更新CallState,而CallState更新PhoneState。CallState有9种,下图为网上搜索到的Call的状态转化图(电话静止时处于IDLE状态:


 图2-1 状态转化图


图2-2 Call的9种状态(网络截图)

从Call的9种状态来看,同一时刻三个Call只能有一个RingCall(INCOMING或WAITING状态),一个ForegroundCall(ACTIVE状态)一个BackgroundCall(HOLDING状态),可以同时有多个IDLE状态。这里需要联想到实际的电话:假设有一个超级大忙人,1)首先,有一通电话Call_1进入,Ring~~Ring,接之,此时这个Call_1由Ring变为Active状态,成为ForegroundCall;2)接Call_1的过程中,又来了一通电话Call_2,接之,此时Call_1状态转化为HOLD成为BackgroundCall,而Call_2由Ring变为Active成为ForegroundCall。此后的处理我也没弄太清楚,以下仅为猜测,希望有经验的人告知一下:3)两通电话同时存在时应该还是可以切换的(我从来没遇到过同时多通电话的情况,只是看到别人好像是这么做的),也就是说ForegroundCall和BackgroundCall可以互相转换,CallManager也确实提供了这样的一个函数;4)此时又来第三通电话,再接之,BackgroundCall数量加1,ForegroundCall变为BackgroundCall。此时一个phone实例的3个Call都被占用。当然可以想到的是,对于存在多个phone实例的智能机,ForegroundCall和BackgroundCall的切换不仅仅局限于一个phone的3个Call内,还可能是不同phone的Call之间切换。并且此时RingCall和BackgroundCall等的限制数量应该和单phone实例的数量有关。

无论怎样,从以上的不确切的分析可以得出一个肯定的结论就是:一台电话有多个Phone,一个Phone对应多个Call。这一点很重要,再看一下类的名字——CallManager,从名字就可以看出这个应该主要是管理Call的(当然,CallManager也维护着一个phone的数组)。

 得到mCM后需要将phone(实际参数是PhoneProxy)注册进mCM。registerForPhoneStates()中注册了关于Phone状态改变的监听事件,Phone状态改变之后InCallUI就能够收到变化消息了。

   private void registerForPhoneStates(Phone phone) {

        // We need to keep a mapping of handler to Phone for proper unregistration.

        // TODO: Clean up this solution as it is just a work around for each Phone instance

        // using the same Handler to register with the RIL. When time permits, we should consider

        // moving the handler (or the reference ot the handler) into the Phone object.

        CallManagerHandler handler = mHandlerMap.get(phone);//重复性检查

        if (handler != null) {

            Rlog.d(LOG_TAG, "This phone has already been registered.");

            return;

        }

        handler = new CallManagerHandler();//新建Handler

        mHandlerMap.put(phone, handler);//绑定起来,当phone状态变化发生变化是,回调handler

 

        // 注册对于所有phones都支持的common events

        phone.registerForPreciseCallStateChanged(handler, EVENT_PRECISE_CALL_STATE_CHANGED, null);

        phone.registerForDisconnect(handler, EVENT_DISCONNECT, null);

        phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION, null);

        phone.registerForUnknownConnection(handler, EVENT_UNKNOWN_CONNECTION, null);

        phone.registerForIncomingRing(handler, EVENT_INCOMING_RING, null);

        phone.registerForRingbackTone(handler, EVENT_RINGBACK_TONE, null);

        phone.registerForInCallVoicePrivacyOn(handler, EVENT_IN_CALL_VOICE_PRIVACY_ON, null);

        phone.registerForInCallVoicePrivacyOff(handler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, null);

        phone.registerForDisplayInfo(handler, EVENT_DISPLAY_INFO, null);

        phone.registerForSignalInfo(handler, EVENT_SIGNAL_INFO, null);

        phone.registerForResendIncallMute(handler, EVENT_RESEND_INCALL_MUTE, null);

        phone.registerForMmiInitiate(handler, EVENT_MMI_INITIATE, null);

        phone.registerForMmiComplete(handler, EVENT_MMI_COMPLETE, null);

        phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, null);

        phone.registerForServiceStateChanged(handler, EVENT_SERVICE_STATE_CHANGED, null);

 

        // 分别注册GSM, CDMA IMS phone特有的event

        //首先是GSMevent

        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||

                phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ||

                phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {

            phone.setOnPostDialCharacter(handler, EVENT_POST_DIAL_CHARACTER, null);

        }

 

        //CDMAevent

        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){

            phone.registerForCdmaOtaStatusChange(handler, EVENT_CDMA_OTA_STATUS_CHANGE, null);

            phone.registerForSubscriptionInfoReady(handler, EVENT_SUBSCRIPTION_INFO_READY, null);

            phone.registerForCallWaiting(handler, EVENT_CALL_WAITING, null);

            phone.registerForEcmTimerReset(handler, EVENT_ECM_TIMER_RESET, null);

        }

 

        // IMSevent

        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {

            phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null);

        }

    }

CallManager的内部类CallManagerHandler继承自Handler,负责处理状态消息,其重写的handleMessage()方法如下:

public void handleMessage(Message msg) {

            switch (msg.what) {

                case EVENT_DISCONNECT:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)");

                    mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_PRECISE_CALL_STATE_CHANGED:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)");

                    mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_NEW_RINGING_CONNECTION:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");

                    Connection c = (Connection) ((AsyncResult) msg.obj).result;

                    long subId = c.getCall().getPhone().getSubId();

                    if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall()) {

                        try {

                            Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall());

                            c.getCall().hangup();

                        } catch (CallStateException e) {

                            Rlog.w(LOG_TAG, "new ringing connection", e);

                        }

                    } else {

                        mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    }

                    break;

                case EVENT_UNKNOWN_CONNECTION:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)");

                    mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_INCOMING_RING:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)");

                    // The event may come from RIL who's not aware of an ongoing fg call

                    if (!hasActiveFgCall()) {

                        mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    }

                    break;

                case EVENT_RINGBACK_TONE:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)");

                    mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_IN_CALL_VOICE_PRIVACY_ON:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)");

                    mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_IN_CALL_VOICE_PRIVACY_OFF:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)");

                    mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_CALL_WAITING:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)");

                    mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_DISPLAY_INFO:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)");

                    mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_SIGNAL_INFO:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)");

                    mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_CDMA_OTA_STATUS_CHANGE:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)");

                    mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_RESEND_INCALL_MUTE:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)");

                    mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_MMI_INITIATE:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)");

                    mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_MMI_COMPLETE:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)");

                    mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_ECM_TIMER_RESET:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)");

                    mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_SUBSCRIPTION_INFO_READY:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)");

                    mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_SUPP_SERVICE_FAILED:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)");

                    mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_SERVICE_STATE_CHANGED:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)");

                    mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

                case EVENT_POST_DIAL_CHARACTER:

                    // we need send the character that is being processed in msg.arg1

                    // so can't use notifyRegistrants()

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)");

                    for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) {

                        Message notifyMsg;

                        notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant();

                        notifyMsg.obj = msg.obj;

                        notifyMsg.arg1 = msg.arg1;

                        notifyMsg.sendToTarget();

                    }

                    break;

                case EVENT_ONHOLD_TONE:

                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ONHOLD_TONE)");

                    mOnHoldToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);

                    break;

            }

        }

    };

1.4   CallNotifier分析

CallNotifier是一个Handler,它为PhoneApp处理各个主动上报来的一些消息。它监听phone状态变化和其它各种事件,从而作出反应 如各种UI行为:启动铃音播放和来电显示UI、播放正在通话时的来电提示、更新状态栏提示(通过NotificationMgr)、通话记录添加等。在PhoneBase中提供了一些RegistrantList,CallNotifier可以将自己作为一个感兴趣者注册进去,这样,当phone的状态变化时,CallNotifier将得到通知,然后在线程中对其处理,作出UI方面的响应。

1.5   NotificationMgr分析

NotificationMgr以静态成员函数的方式为PhoneApp用于Phone进程在状态栏中通知用户消息的功能,诸如:有未接电话、正在通话、是否静音等信息。它使用系统提供的API类NotificationManager和StatusBarManager完成通知功能。每项通知对应着通知、更新通知和取消通知的函数。当收到Message时,PhoneApp的Handler的handleMessage会使用NotificationMgr更新状态栏信息。以下为其构造函数,可以看出它获得了很多系统服务,并且持有一个phone的引用

    private NotificationMgr(PhoneGlobals app) {//特别注意这里获得的四个Mgr

        mApp = app;

        mContext = app;

        mNotificationManager = (NotificationManager)

app.getSystemService(Context.NOTIFICATION_SERVICE);

 

        mStatusBarManager =

                (StatusBarManager) app.getSystemService(Context.STATUS_BAR_SERVICE);

       

        mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);

 

        mPhone = app.mCM.getDefaultPhone();

        statusBarHelper = new StatusBarHelper();

        mSubscriptionManager = SubscriptionManager.from(mContext);

        mTelecomManager = TelecomManager.from(mContext);

 

        mTelephonyManager = (TelephonyManager) app.getSystemService(Context.TELEPHONY_SERVICE);

    }

 

1.6   PhoneNotifier分析

PhoneNotifier是在PhoneFactory里创建的,实际是创建的DefaultPhoneNotifier的实例。首先来看其构造方法:

protected DefaultPhoneNotifier() {

        mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(

                    "telephony.registry"));

    }

很典型的Binder,在DefaultPhoneNotifier的构造函数里,获取了ITelephonyRegistry的服务。而这个PhoneNotifier又在之前的makeDefaultPhone()当做构造参数绑定了Phone,从而可以将Phone底层的消息通过ITelephonyRegistry上报。重新截取代码如下:

for (int i = 0; i < numPhones; i++) {

                    PhoneBase phone = null;

                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);

                    // 新建phone实例,根据网络模式,新建一个GSMPhone实例或CDMALTEPhone

                   //实例,做为参数再创建PhoneProxy实例,

                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {

                        phone = new GSMPhone(context,

                                sCommandsInterfaces[i],sPhoneNotifier, i);

phone.startMonitoringImsService();

                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {

                        phone = new CDMALTEPhone(context,

                                sCommandsInterfaces[i],sPhoneNotifier, i);

phone.startMonitoringImsService();

                    }

                    Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);             //以上面的Phone创建相应的phoneProxy

                    sProxyPhones[i] = new PhoneProxy(phone);

                }

 

1.7   CallStateMonitor分析

从其构造函数的参数可以看出,它与CallManager直接交互。

    public CallStateMonitor(CallManager callManager) {

        this.callManager = callManager;

        registeredHandlers = new ArrayList<Handler>();

 

        registerForNotifications();

    }

它自己是个Handler,并且维护一组Handler。从下面可以看出他只是将msg交给它维护的每一个Handler去处理。

@Override

    public void handleMessage(Message msg) {

        if (DBG) {

            Log.d(LOG_TAG, "handleMessage(" + msg.what + ")");

        }

 

        for (Handler handler : registeredHandlers) {

            handler.handleMessage(msg);

        }

    }

1.8   小结

以下为粗糙的PhoneApp核心类UML结构图。

图2-3 phoneApp核心类图

PhoneApp在SystemReady被启动,在它的onCreate()方法里面新建了两个实例PhoneGlobals和TelePhonyGlobals,并分别调用了它们的onCreate()方法。其中TelePhonyGlobals主要负责PSTN。PhoneGlobals.onCreate()利用工厂模式创建了phones并获取了phones的代理对象PhoneProxy。接着新建CallManager单例mCM,并将这些PhoneProxy全部注册进入mCM。除此之外PhoneGlobals还新建了一系列的管理对象,获取远程服务接口。如power服务等。mCM负责了Call的相关操作管理。如接拨电话,RingCall、ActiveCall的获取,以及ForegroundCall和BackgroundCall管理和切换等。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值