深入理解Android Telephony之PhoneApp的初始化

PhoneApp即phone进程的初始化应该在系统启动时尽早进行,而这取决于PhoneApp代码包中AndroidManifest.xml是如何配置的,这会在另一篇文章介绍。
先看看PhoneApp.java是什么样子。

public class PhoneApp extends Application {
    PhoneGlobals mPhoneGlobals;
    TelephonyGlobals mTelephonyGlobals;

    public PhoneApp() {
    }

    @Override
    public void onCreate() {
        if (UserHandle.myUserId() == 0) {
            mPhoneGlobals = new PhoneGlobals(this);
            mPhoneGlobals.onCreate();
            //TelephonyGlobals在整个工程中没看到使用的地方,类中只是创建个实例和初始化TtyMananger,看解释是与PSTN call相关
            mTelephonyGlobals = new TelephonyGlobals(this);
            mTelephonyGlobals.onCreate();
        }
    }
}

public void onCreate() {
        ContentResolver resolver = getContentResolver();

        sVoiceCapable =
                getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
        // ...but this might eventually become a PackageManager "system
        // feature" instead, in which case we'd do something like:
        // sVoiceCapable =
        //   getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);

        if (mCM == null) {
            //初始化telephony framework部分
            PhoneFactory.makeDefaultPhones(this);
            //实例化通话管理类CallManager,并把phone注册进去
            mCM = CallManager.getInstance();
            for (Phone phone : PhoneFactory.getPhones()) {
                mCM.registerPhone(phone);
            }
            //实例化通知栏管理类NotificationMgr,用来管理通知栏图标显示及其它行为
            // Create the NotificationMgr singleton, which is used to display
            // status bar icons and control other status bar behavior.
            notificationMgr = NotificationMgr.init(this);

            //走到这里已经存在phone进程,mHandler在处理EVENT_RESTART_SIP消息时,会从UserManager中查找当前用户的状态,如果处于unlocked状态,才调用startSipService
            mHandler.sendEmptyMessage(EVENT_RESTART_SIP);

            //实例化通话状态类CdmaPhoneCallState并初始化成IDLE,通话状态包括IDLE/SINGLE_ACTIVE/THRWAY_ACTIVE/CONF_CALL
            cdmaPhoneCallState = new CdmaPhoneCallState();
            cdmaPhoneCallState.CdmaPhoneCallStateInit();

            //获取电源管理器、唤醒锁、锁屏管理器
            mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
            mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
            mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
                    | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
            mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
            //为了屏蔽在通话过程中提示系统更新相关事件,创建UpdateLock对象
            mUpdateLock = new UpdateLock("phone");
            //实例化通话路由管理器
            callGatewayManager = CallGatewayManager.getInstance();

            //实例化通话控制类CallController,这是telephony层的用户接口,比如可以通过调用PhoneGlobals.getInstance().callController.placeCall(intent)拨打电话,注意这个类没有getInstance()方法,只能通过PhoneGlobals来使用,而callController的修饰域是默认的friendly,因此callController只能在包内使用
            callController = CallController.init(this, callLogger, callGatewayManager);

            //实例化通话信息缓存类
            callerInfoCache = CallerInfoCache.init(this);
            //实例化phone接口管理类,这个类可用于访问/修改phone的状态,比如通话状态/数据连接/网络状态等等
            phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
            phoneMgrEx = PhoneInterfaceManagerEx.init(this, PhoneFactory.getDefaultPhone());
            //实例化运营商配置加载类
            configLoader = CarrierConfigLoader.init(this);

            //实例化通话通知类,用于处理从telephony层发来的异步事件,比如来电时调起来电界面
            notifier = CallNotifier.init(this);

            //注册ICC的EVENT_SIM_NETWORK_LOCKED状态监听处理
            PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);

            //注册MMI/USSD事件的监听处理
            mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);

            //注册连接事件的监听处理,ConnectionHandler处理PHONE_STATE_CHANGED事件
            PhoneUtils.initializeConnectionHandler(mCM);

            //注册一些广播事件处理
            IntentFilter intentFilter =
                    new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
            intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
            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);
            intentFilter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
            intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
            intentFilter.addAction(Intent.ACTION_MSIM_MODE_CHANGED);
            intentFilter.addAction(ACTION_SHUTDOWN_IPO);
            intentFilter.addAction(ACTION_PREBOOT_IPO);

            registerReceiver(mReceiver, intentFilter);

            //注册subscriptions监听器
            SubscriptionManager.from(this)
                    .addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
            mSubscriptionInfos = PhoneUtils.getActiveSubInfoList();

            //初始化音频模式
            PhoneUtils.setAudioMode(mCM);
        }
        //OTASP相关
        cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData();
        cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData();
        cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState();
        cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState();
        //SimActivationManager用于SIM卡的激活请求并执行激活动作
        simActivationManager = new SimActivationManager();

        //尝试访问SimProvider来初始化它
        resolver.getType(Uri.parse(ADNList.ICC_ADN_URI));

        //audio相关
        if (TelephonyUtils.isHacSupport()) {
            int hac = android.provider.Settings.System.getInt(
                    getPhone().getContext().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);
        }

       /// add for OP01 plugin roaming auto test @{
       ExtensionManager.getSsRoamingServiceExt().registerSsRoamingReceiver(this);
       ///@}
    }

看看makeDefaultPhone具体做了什么

public static void makeDefaultPhone(Context context) {
        synchronized (sLockProxyPhones) {
            if (!sMadeDefaults) {
                sContext = context;

                //实例化telephony硬件资源控制接口,这里的硬件资源包括SIM/MODEM/RIL
                TelephonyDevController.create();
                //这里通过尝试创建地址为"com.android.internal.telephony"的LocalServerSocket来中断循环
                int retryCount = 0;
                for(;;) {
                    boolean hasException = false;
                    retryCount ++;

                    try {
                        // use UNIX domain socket to
                        // prevent subsequent initialization
                        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) {
                        }
                    }
                }
                //phone的状态通知器,对外发出通知,包括通话状态/网络服务状态/信号强度/SS(运营商补充服务--呼叫转移等)/网络小区信息/数据连接等等,DefaultPhoneNotifier其实就是个中转站,本质上各接口都是通过ITelephonyRegistry代理来访问"telephony.registry"服务
                sPhoneNotifier = new DefaultPhoneNotifier();

                //CDMA subscription状态管理
                int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);

                //单卡还是多卡,初始化默认网络模式/Phone/RIL
                int numPhones = TelephonyManager.getDefault().getPhoneCount();
                int[] networkModes = new int[numPhones];
                sPhones = new Phone[numPhones];
                sCommandsInterfaces = new RIL[numPhones];
                //TelephonyNetworkFactory是创建网络代理的工厂,默认网络代理的评判根据分数和能力来进行,也可以通过重载来实现更复杂的计算来评判
                sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];

                for (int i = 0; i < numPhones; i++) {
                    //初始化网络模式和RIL,支持几张卡就初始化几个RIL
                    networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE;
                    sCommandsInterfaces[i] = new RIL(context, networkModes[i],
                            cdmaSubscription, i);
                }
                //SubscriptionController提供访问SubscriptionInfo的IPC接口,SubscriptionInfo是framework层对sim卡信息的抽象表示,数据都存储在数据库中,比如设置SIM卡的icon/名称/号码,读取plmn/mccmnc等等
                SubscriptionController.init(context, sCommandsInterfaces);
                //实例化上层的射频管理类,用于诸如开关SIM卡/飞行模式/modem的开关重启等等
                RadioManager.init(context, numPhones, sCommandsInterfaces);

                //实例化UiccController,用于访问UICC卡的相关信息,通过在RIL中注册事件监听来实现
                sUiccController = UiccController.make(context, sCommandsInterfaces);

                for (int i = 0; i < numPhones; i++) {
                    Phone phone = null;
                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
                    //7.0开始没有CDMAPhone类,把之前的GSMPhone和CDMAPhone合并成了GsmCdmaPhone,同样的就有了GsmCdmaCallTracker/GsmCdmaConnection
                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
                        phone = new GsmCdmaPhone(context,
                                sCommandsInterfaces[i], sPhoneNotifier, i,
                                PhoneConstants.PHONE_TYPE_GSM,
                                TelephonyComponentFactory.getInstance());
                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                        phone = new GsmCdmaPhone(context,
                                sCommandsInterfaces[i], sPhoneNotifier, i,
                                PhoneConstants.PHONE_TYPE_CDMA_LTE,
                                TelephonyComponentFactory.getInstance());
                    }

                    sPhones[i] = phone;
                }

                sPhone = sPhones[0];
                sCommandsInterface = sCommandsInterfaces[0];

                //默认短信应用
                ComponentName componentName =
                        SmsApplication.getDefaultSmsApplication(context, true /* updateIfNeeded */);
                String packageName = "NONE";
                if (componentName != null) {
                    packageName = componentName.getPackageName();
                }
                //短信包的监听器
                SmsApplication.initSmsPackageMonitor(context);

                sMadeDefaults = true;
                //顾名思义,SubscriptionInfoUpdater主要监听sim卡的插入/拔出/上锁/加载等情况
                sSubInfoRecordUpdater = new SubscriptionInfoUpdater(context,
                        sPhones, sCommandsInterfaces);
                SubscriptionController.getInstance().updatePhonesAvailability(sPhones);

                //DataSubSelector用于管理默认数据卡
                sDataSubSelector = new DataSubSelector(context, numPhones);

                //phone创建完成之后,可以启动监听ImsService
                for (int i = 0; i < numPhones; i++) {
                    sPhones[i].startMonitoringImsService();
                }
                //ITelephonyRegistry提供了访问通话状态/网络服务状态/信号强度/SS(运营商补充服务--呼叫转移等)/网络小区信息/数据连接等等的接口
                ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(
                        ServiceManager.getService("telephony.registry"));
                SubscriptionController sc = SubscriptionController.getInstance();

                sSubscriptionMonitor = new SubscriptionMonitor(tr, sContext, sc, numPhones);

                //PhoneSwitcher监听subscription的变化和网络请求来决定启用哪个phone
                sPhoneSwitcher = new PhoneSwitcher(MAX_ACTIVE_PHONES, numPhones,
                        sContext, sc, Looper.myLooper(), tr, sCommandsInterfaces,
                        sPhones);
                //ProxyController类用于get/set radio相关的操作
                sProxyController = ProxyController.getInstance(context, sPhones,
                        sUiccController, sCommandsInterfaces, sPhoneSwitcher);

                sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];
                for (int i = 0; i < numPhones; i++) {
                    sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
                            sPhoneSwitcher, sc, sSubscriptionMonitor, Looper.myLooper(),
                            sContext, i, sPhones[i].mDcTracker);
                }

                //数据连接辅助类
                DataConnectionHelper.makeDataConnectionHelper(context, sPhones, sPhoneSwitcher);

                //WorldMode相关
                if (WorldPhoneUtil.isWorldModeSupport() && WorldPhoneUtil.isWorldPhoneSupport()) {
                    Rlog.i(LOG_TAG, "World mode support");
                    WorldMode.init();
                } else if (WorldPhoneUtil.isWorldPhoneSupport()) {
                    Rlog.i(LOG_TAG, "World phone support");
                    sWorldPhone = WorldPhoneWrapper.getWorldPhoneInstance();
                } else {
                    Rlog.i(LOG_TAG, "World phone not support");
                }

            }
        }
    }

PhoneInterfaceManager类值得关注的是往ServiceManager中add了“phone“服务

    /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
        synchronized (PhoneInterfaceManager.class) {
            if (sInstance == null) {
                sInstance = new PhoneInterfaceManager(app, phone);
            } else {
                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
            }
            return sInstance;
        }
    }

    /** Private constructor; @see init() */
    private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
        mApp = app;
        mPhone = phone;
        mCM = PhoneGlobals.getInstance().mCM;
        mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
        mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
        mMainThreadHandler = new MainThreadHandler();
        mTelephonySharedPreferences =
                PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
        mSubscriptionController = SubscriptionController.getInstance();

        publish();
    }

    private void publish() {
        if (DBG) log("publish: " + this);

        ServiceManager.addService("phone", this);
    }

看PhoneApp的初始化,其实就是根据支持卡的张数来创建phone以及与RILD沟通的RILJ,并往系统服务管理注册phone服务和telephony.registry服务,经过RILJ的信息,有通话/SIM卡/网络服务/数据连接,对应的定义一些类来监听处理这些信息:
DefaultPhoneNotifier—-通过实现ITelephonyRegistry接口向上通知phone信息的状态变化,向下通过Binder访问telephony.registry服务;
CdmaSubscriptionSourceManager—-用来管理CDMA 卡的抽象数据;
SubscriptionController—-通用的监听/访问卡的抽象数据接口;
UiccController—-监听/访问uicc的通用接口;
RadioManager—-管理sim卡开关/飞行模式/modem重启等radio相关功能;
DataSubSelector—-用来处理数据连接卡的设置;

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值