Phone的追溯
在Android中我们可以查看后台的进程,会发现存在常驻phone进程。进程名一般是该app的包名,搜索package=”com.android.phone”
在/packages/services/Telephony/AndroidManifest.xml发现如下定义
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.phone"
coreApp="true"
android:sharedUserId="android.uid.phone"
android:sharedUserLabel="@string/phoneAppLabel"
>
继续查看该XML文件的其他定义,
<application android:name="PhoneApp"
android:persistent="true"//开机启动
android:label="@string/phoneAppLabel"
android:icon="@mipmap/ic_launcher_phone"
android:allowBackup="false"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
看到其应用名是PhoneApp,可知启动该线程的是PhoneApp应用
1.跟进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();
}
}
看到该类主要的实现是onCreate方法,而其onCreate方法主要是创建并调用PhoneGlobals和TelephonyGlobals的onCreate方法。
追踪到PhoneGlobals.java和telephonyGlobals.java,我们根据注释可以得知:
PhoneGlobals:监听进程运行时的状态
telephonyGlobals:初始化相关系统,并且只有一个实例,而且需要确保后台存在,一旦挂掉就要重新生成那么我们继续跟进对应的onCreate方法看其是如何实现的。
2.跟进mPhoneGlobals.onCreate
public void onCreate() {
...
if (mCM == null) {
//Initialize the telephony framework创建phone实例
PhoneFactory.makeDefaultPhones(this);
// Start TelephonyDebugService After the default phone is created.
Intent intent = new Intent(this, TelephonyDebugService.class);
startService(intent);
//CallManager获取及注册phone
mCM = CallManager.getInstance();
for (Phone phone : PhoneFactory.getPhones()) {
mCM.registerPhone(phone);
}
// Create the NotificationMgr singleton, which is used to display
// status bar icons and control other status bar behavior.
notificationMgr = NotificationMgr.init(this);
// If PhoneGlobals has crashed and is being restarted, then restart.
mHandler.sendEmptyMessage(EVENT_RESTART_SIP);
// 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 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.)
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);
phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone());
configLoader = CarrierConfigLoader.init(this);
// Create the CallNotifer singleton, which handles
// asynchronous events from the telephony layer (like
// launching the incoming-call UI when an incoming call comes
// in.)初始化notifier以监听来电消息
notifier = CallNotifier.init(this);
PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);
// 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(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);
mCarrierVvmPackageInstalledReceiver.register(this);
//set the default values for the preferences in the phone.
PreferenceManager.setDefaultValues(this, R.xml.network_setting_fragment, 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);
}
// XXX pre-load the SimProvider so that it's ready
resolver.getType(Uri.parse("content://icc/adn"));
// 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);
}
}
这段代码的很多功能都通过注释说明了,这里我们主要关注PhoneFactory.makeDefaultPhones(this)创建phone实例
3.继续跟进makeDefaultPhones方法
/**
* FIXME replace this with some other way of making these
* instances
*/
public static void makeDefaultPhone(Context context) {
synchronized (sLockProxyPhones) {
if (!sMadeDefaults) {
...
sPhoneNotifier = new DefaultPhoneNotifier();
...
int[] networkModes = new int[numPhones];
sPhones = new Phone[numPhones];
sCommandsInterfaces = new RIL[numPhones];
sTelephonyNetworkFactories = new TelephonyNetworkFactory[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()
sUiccController = UiccController.make(context, sCommandsInterfaces);
//创建具体的phone
for (int i = 0; i < numPhones; i++) {
Phone phone = null;
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
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());
}
Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);
sPhones[i] = phone;
}
// 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.
sPhone = sPhones[0];
sCommandsInterface = sCommandsInterfaces[0];
...
// Start monitoring after defaults have been made.
// Default phone must be ready before ImsPhone is created because ImsService might
// need it when it is being opened. This should initialize multiple ImsPhones for
// ImsResolver implementations of ImsService.
for (int i = 0; i < numPhones; i++) {
sPhones[i].startMonitoringImsService();
}
ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(
ServiceManager.getService("telephony.registry"));
SubscriptionController sc = SubscriptionController.getInstance();
...
}
}
}
makeDefaultPhones主要对DefaultPhoneNotifier,sCommandsInterfaces进行了初始化,之后创建具体的GsmCdmaPhone实例。DefaultPhoneNotifier实现了PhoneNotifier接口,PhoneNotifier接口中定义了很多notifyXXX的接口,DefaultPhoneNotifier主要的作用就是发送通知的消息,具体可以查看DefaultPhoneNotifier,其本质是使用ITelephonyRegistry的实例去通知状态。
4.继续跟进GsmCdmaPhone类
public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode, int phoneId, int precisePhoneType,
TelephonyComponentFactory telephonyComponentFactory) {
super(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA",
notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory);
// phone type needs to be set before other initialization as other objects rely on it
mPrecisePhoneType = precisePhoneType;
initOnce(ci);
initRatSpecific(precisePhoneType);
mSST = mTelephonyComponentFactory.makeServiceStateTracker(this, this.mCi);
// DcTracker uses SST so needs to be created after it is instantiated
mDcTracker = mTelephonyComponentFactory.makeDcTracker(this);
mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
mDeviceStateMonitor = mTelephonyComponentFactory.makeDeviceStateMonitor(this);
logd("GsmCdmaPhone: constructor: sub = " + mPhoneId);
}
发现其调用了父类phone的构造方法,其次调用了initOnce进行了初始化,后续又对其他几个Tracker进行了初始化。
5.继续跟进initOnce方法
private void initOnce(CommandsInterface ci) {
if (ci instanceof SimulatedRadioControl) {
mSimulatedRadioControl = (SimulatedRadioControl) ci;
}
mCT = mTelephonyComponentFactory.makeGsmCdmaCallTracker(this);
mIccPhoneBookIntManager = mTelephonyComponentFactory.makeIccPhoneBookInterfaceManager(this);
PowerManager pm
= (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
mIccSmsInterfaceManager = mTelephonyComponentFactory.makeIccSmsInterfaceManager(this);
mIccCardProxy = mTelephonyComponentFactory.makeIccCardProxy(mContext, mCi, mPhoneId);
mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCi.registerForOn(this, EVENT_RADIO_ON, null);
mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
//GSM
mCi.setOnUSSD(this, EVENT_USSD, null);
mCi.setOnSs(this, EVENT_SS, null);
//CDMA
mCdmaSSM = mTelephonyComponentFactory.getCdmaSubscriptionSourceManagerInstance(mContext,
mCi, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
mEriManager = mTelephonyComponentFactory.makeEriManager(this, mContext,
EriManager.ERI_FROM_XML);
mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE,
null);
// get the string that specifies the carrier OTA Sp number
mCarrierOtaSpNumSchema = TelephonyManager.from(mContext).getOtaSpNumberSchemaForPhone(
getPhoneId(), "");
mResetModemOnRadioTechnologyChange = SystemProperties.getBoolean(
TelephonyProperties.PROPERTY_RESET_ON_RADIO_TECH_CHANGE, false);
mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
}
init方法主要是对GsmCdmaCallTracker及RIL接口进行了初始化,并且注册监听了一些消息。
因此,Phone实例就间接地拥有了跟modem交互的能力和上报消息的能力,再加上Phone实例自身就有监听事件的能力,所以Phone的作用就是:
1.注册监听事件,及时上报消息(Call状态变化、Service状态变化、新来电等等)
2.间接地为其他类提供跟modem交互的服务。
其实总结起来phone中比较重要的就是以下三类对象
1.RIL接口
2.Tracker相关类
3.Notifiy相关类
具体的后续会更新博客补充分析此三类对象