Android L Phone 启动流程

来源:互联网 发布:知彼而知己 打不开 编辑:程序博客网 时间:2024/05/01 15:28

1、在ActivityManagerService 的SystemReady中启动所有persist属性的应用 ,其中就包含TeleService,且在Launcher前启动!


        synchronized (this) {            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {                try {                    List apps = AppGlobals.getPackageManager().                        getPersistentApplications(STOCK_PM_FLAGS);                    if (apps != null) {                        int N = apps.size();                        int i;                        for (i=0; i<N; i++) {                            ApplicationInfo info                                = (ApplicationInfo)apps.get(i);                            if (info != null &&                                    !info.packageName.equals("android")) {                                addAppLocked(info, false, null /* ABI override */);                            }                        }                    }                } catch (RemoteException ex) {                    // pm is in same process, this will never happen.                }            }            // Start up initial activity.            mBooting = true;            startHomeActivityLocked(mCurrentUserId);            try {                if (AppGlobals.getPackageManager().hasSystemUidErrors()) {                    Message msg = Message.obtain();                    msg.what = SHOW_UID_ERROR_MSG;                    mHandler.sendMessage(msg);                }            } catch (RemoteException e) {            }


2 、于是会启动Telephony中的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();            mTelephonyGlobals = new TelephonyGlobals(this);            mTelephonyGlobals.onCreate();        }    }

它的主要工作便是启动PhoneGlobals,这是一个非常重要的类:

在这里初始化了Phone的framework层的东西,是的,就是这样上上下下来回调,起到承上启下的作用。

而且PhoneGlobals还采用了单例模式!来看重要的onCreate方法:

  public void onCreate() {        if (VDBG) Log.v(LOG_TAG, "onCreate()...");        ContentResolver resolver = getContentResolver();        // Cache the "voice capable" flag.        // This flag currently comes from a resource (which is        // overrideable on a per-product basis):        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 (phone == null) {            // Initialize the telephony framework            <span style="background-color: rgb(255, 255, 102);">PhoneFactory.makeDefaultPhones(this);</span>            int numPhones = TelephonyManager.getDefault().getPhoneCount();            if(numPhones > 1) PrimarySubSelectionController.init(this);            // Get the default phone           <span style="background-color: rgb(255, 255, 51);"> phone = PhoneFactory.getDefaultPhone();</span>            // Start TelephonyDebugService After the default phone is created.            Intent intent = new Intent(this, TelephonyDebugService.class);            startService(intent);            mPhones = new PhoneProxy[numPhones];            mPhones = PhoneFactory.getPhones();            <span style="background-color: rgb(255, 255, 102);">mCM = CallManager.getInstance();</span>            for (Phone ph : mPhones) {                <span style="background-color: rgb(255, 255, 51);">mCM.registerPhone(ph);</span>            }            // Create the NotificationMgr singleton, which is used to display            // status bar icons and control other status bar behavior.            notificationMgr = NotificationMgr.init(this);            mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE);            int phoneType = phone.getPhoneType();            if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {                // Create an instance of CdmaPhoneCallState and initialize it to IDLE                cdmaPhoneCallState = new CdmaPhoneCallState();                cdmaPhoneCallState.CdmaPhoneCallStateInit();            }            // before registering for phone state changes            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);            // get a handle to the service so that we can use it later when we            // want to set the poke lock.            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();            // Create the CallController singleton, which is the interface            // to the telephony layer for user-initiated telephony functionality            // (like making outgoing calls.)            <span style="background-color: rgb(255, 255, 102);">callController = CallController.init(this, callLogger, callGatewayManager);</span>            // 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);            // Monitors call activity from the telephony layer            callStateMonitor = new CallStateMonitor(mCM);            // Bluetooth manager            bluetoothManager = new BluetoothManager();            phoneMgr = PhoneInterfaceManager.init(this, phone);            // Create the CallNotifer singleton, which handles            // asynchronous events from the telephony layer (like            // launching the incoming-call UI when an incoming call comes            // in.)           <span style="background-color: rgb(255, 255, 102);"> notifier = CallNotifier.init(this, phone, callLogger, callStateMonitor,                    bluetoothManager);</span>            // register for ICC status            IccCard sim = phone.getIccCard();            if (sim != null) {                if (VDBG) Log.v(LOG_TAG, "register for ICC status");                sim.registerForPersoLocked(mHandler, EVENT_PERSO_LOCKED, null);            }            // register for MMI/USSD            mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);            // register connection tracking to PhoneUtils            PhoneUtils.initializeConnectionHandler(mCM);            // Register for misc other intent broadcasts.            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);            intentFilter.addAction(TelephonyIntents.ACTION_MANAGED_ROAMING_IND);            <span style="background-color: rgb(255, 255, 102);">registerReceiver(mReceiver, intentFilter);</span>            //set the default values for the preferences in the phone.            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();        // XXX pre-load the SimProvider so that it's ready        resolver.getType(Uri.parse("content://icc/adn"));        // start with the default value to set the mute state.        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(phone.getContext().getContentResolver(),                                                              android.provider.Settings.System.HEARING_AID,                                                              0);            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);            audioManager.setParameter(CallFeaturesSetting.HAC_KEY, hac != 0 ?                                      CallFeaturesSetting.HAC_VAL_ON :                                      CallFeaturesSetting.HAC_VAL_OFF);        }    }


PhoneFactory.makeDefaultPhones(this); 对framework进行初始化,在frameworks/opt下

    public static void makeDefaultPhone(Context context) {        synchronized (sLockProxyPhones) {            if (!sMadeDefaults) {                sContext = context;                // create the telephony device controller.                TelephonyDevController.create();                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) {                        }                    }                }                sPhoneNotifier = new DefaultPhoneNotifier();                // Get preferred network mode                int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;                if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {                    preferredNetworkMode = Phone.NT_MODE_GLOBAL;                }                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];                sCommandsInterfaces = new RIL[numPhones];                for (int i = 0; i < numPhones; i++) {                    //reads the system properties and makes commandsinterface                    try {//                        // Get preferred network type.//                        TODO: Sishir added this code to but we need a new technique for MSim//                        int networkType = calculatePreferredNetworkType(context);//                        Rlog.i(LOG_TAG, "Network Type set to " + Integer.toString(networkType));                        networkModes[i]  = TelephonyManager.getIntAtIndex(                                context.getContentResolver(),                                Settings.Global.PREFERRED_NETWORK_MODE, i);                    } catch (SettingNotFoundException snfe) {                        Rlog.e(LOG_TAG, "Settings Exception Reading Value At Index for"+                                " Settings.Global.PREFERRED_NETWORK_MODE");                        networkModes[i] = preferredNetworkMode;                    }                    if (sContext.getResources().getBoolean(                            com.android.internal.R.bool.config_global_phone_enabled) &&                            i == PhoneConstants.PHONE_ID1) {                        networkModes[i] = Phone.NT_MODE_LTE_CDMA_EVDO_GSM_WCDMA;                        TelephonyManager.putIntAtIndex( context.getContentResolver(),                                Settings.Global.PREFERRED_NETWORK_MODE, i, networkModes[i]);                    }                    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);                sModemStackController = ModemStackController.make(context,                        mUiccController, sCommandsInterfaces);                sModemBindingPolicyHandler = ModemBindingPolicyHandler.make(context,                        mUiccController, sCommandsInterfaces);                for (int i = 0; i < numPhones; i++) {                    PhoneBase phone = null;                    <span style="background-color: rgb(255, 255, 102);">int phoneType = TelephonyManager.getPhoneType(networkModes[i]);</span>                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {                        phone = new GSMPhone(context,                                sCommandsInterfaces[i], sPhoneNotifier, i);                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {                        phone = new CDMALTEPhone(context,                                sCommandsInterfaces[i], sPhoneNotifier, i);                    }                    Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);                   <span style="background-color: rgb(255, 255, 102);"> sProxyPhones[i] = new PhoneProxy(phone)</span>;                }                mProxyController = ProxyController.getInstance(context, sProxyPhones,                        mUiccController, sCommandsInterfaces);                // Set the default phone in base class.                // FIXME: This is a first best guess at what the defaults will be. It                // FIXME: needs to be done in a more controlled manner in the future.                sProxyPhone = sProxyPhones[0];                sCommandsInterface = sCommandsInterfaces[0];                // Ensure that we have a default SMS app. Requesting the app with                // updateIfNeeded set to true is enough to configure a default SMS app.                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;                Rlog.i(LOG_TAG, "Creating SubInfoRecordUpdater ");                sSubInfoRecordUpdater = new SubInfoRecordUpdater(context,                        sProxyPhones, sCommandsInterfaces);                SubscriptionController.getInstance().updatePhonesAvailability(sProxyPhones);            }        }    }

这是一个非常重要的方法,创建套接字 通过socket与底层交互,获得卡类型例如当前为GSM,则创建GSMPhone对象

并生成代理对象.存入数组,此方法内对Phone的framework层初始化完毕

3.

<span style="background-color: rgb(255, 255, 51);">phone = PhoneFactory.getDefaultPhone();</span>
<span style="background-color: rgb(255, 255, 51);"></span>
<span style="background-color: rgb(255, 255, 51);"></span><pre name="code" class="java">    public static Phone getDefaultPhone() {        synchronized (sLockProxyPhones) {            if (!sMadeDefaults) {                throw new IllegalStateException("Default phones haven't been made yet!");            }            return sProxyPhone;        }    }


sProxyPhone为Phone对象数组中的第0个元素。
4、初始化CallManager (在frameworks/opt下),上下层交互的通道,采用单例模式,非常重要的一个类。
<pre name="code" class="html">            mCM = CallManager.getInstance();            for (Phone ph : mPhones) {                mCM.registerPhone(ph);            }


CallManager的registerPhone是一个非常重要的方法:


    /**     * Register phone to CallManager     * @param phone to be registered     * @return true if register successfully     */    public boolean registerPhone(Phone phone) {        Phone basePhone = getPhoneBase(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);            mRingingCalls.add(basePhone.getRingingCall());            mBackgroundCalls.add(basePhone.getBackgroundCall());            mForegroundCalls.add(basePhone.getForegroundCall());            registerForPhoneStates(basePhone);            return true;        }        return false;    

将当前Phone对应的三个Call对象保存到CallManager的三个对应的数组结构中,并调用私有方法
registerForPhoneStates(basePhone),来注册监听Phone的状态。注意此处传入的是真Phone
<pre name="code" class="java"> 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.        // See b/17414427.        CallManagerHandler handler = mHandlerMap.get(phone);        if (handler != null) {            Rlog.d(LOG_TAG, "This phone has already been registered.");            return;        }        // New registration, create a new handler instance and register the phone.        handler = new CallManagerHandler();        mHandlerMap.put(phone, handler);        // for common events supported by all phones        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);        // for events supported only by GSM, CDMA and IMS phone        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);        }        // for events supported only by CDMA phone        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);        }        // for events supported only by IMS phone        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {            phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null);        }    }

剩下的就是初始化一些非常重要的类,和注册广播接收器,就没什么特别的了。

未完待续

0 0
原创粉丝点击