IMS
开机初始化流程图请见如下附件,流程图较大,文档中显示不清晰。
IMS开机初始化流程图
1.1 监控IMS Service
PhoneApp进程是在系统开机时启动的,Phone进程初始化的时候(步骤1~6),在创建GSMPhone或者CDMAPhone之后,会执行监控IMS Service的流程,也就是流程图上的步骤7,在PhoneFactory.Java的makeDefaultPhone()方法中:
/**
* FIXME replace this with
some other way of making these
* instances
*/
public static void
makeDefaultPhone(Context context) {
......
//先根据phoneType创建GSMPhone或者CDMAPhone
for (int i = 0; i <
numPhones; i++) {
PhoneBase phone =
null;
int phoneType =
TelephonyManager.getPhoneType(Modes[i]);
if (phoneType ==
PhoneConstants.PHONE_TYPE_GSM) {
phone =
TelephonyPluginDelegate.getInstance().makeGSMPhone(context,
sss[i], sPhoneNotifier, i);
} else if
(phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
phone =
TelephonyPluginDelegate.getInstance().makeCDMALTEPhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i);
}
Rlog.i(LOG_TAG,
"Creating Phone with type = " + phoneType + " sub = " + i);
sProxyPhones[i] =
TelephonyPluginDelegate.getInstance().makePhoneProxy(phone);
}
......
//在makeDefaultPhone()方法的最后,等所有要初始化的操作
//(如创建RIL,Default Phone等)都执行完之后。
for (int i = 0; i <
numPhones; i++) {
//开始执行监控IMS Service的流程
sProxyPhones[i].startMonitoringImsService();
}
}
接着来到PhoneProxy.java的startMonitoringImsService()方法中,可以看到在监控IMS service之前必须先创建Default Phone。
public void
startMonitoringImsService() {
//必须先创建Default Phone
if (mActivePhone !=
null) {
mActivePhone.startMonitoringImsService();
}
}
接着来到PhoneBase.java的startMonitoringImsService()方法中,来到这里,主要是为了注册上监听IMS SERVICE UP或者DOWN的广播。等到ImsService onCreate()的时候,会发出ACTION_IMS_SERVICE_UP的广播,然后PhoneBase接收到广播之后就可以执行创建IMSPhone对象(1.3小节会详细讲)和通知modem turn on IMS的流程(1.4小节会详细讲)。
@Override
public void
startMonitoringImsService() {
if (getPhoneType() ==
PhoneConstants.PHONE_TYPE_SIP) {
return;
}
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
IntentFilter
filter = new IntentFilter();
filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP);
filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN);
//注册监听IMS SERVICE UP或者DOWN的广播
mContext.registerReceiver(mImsIntentReceiver, filter);
mImsIntentReceiverRegistered = true;
// Monitor IMS
service - but first poll to see if already up (could miss
//
intent)
//初始化ImsManager对象
ImsManager imsManager =
ImsManager.getInstance(mContext, getPhoneId());
//IMS
service目前还不可用
if (imsManager !=
null && imsManager.isServiceAvailable()) {
mImsServiceReady = true;
ImsPhone();
ImsManager.updateImsServiceConfig(mContext, mPhoneId, false);
}
}
}
1.2 IMS Service的启动
备注:这部分内容是Qualcomm的实现。
步骤11:ImsServiceAutoboot.java监听了ACTION_BOOT_COMPLETED和ACTION_SIM_STATE_CHANGED广播,在开机的时候,ImsServiceAutoboot会先收到ACTION_SIM_STATE_CHANGED广播。
//ClassName是ImsService,所以下面启动的Service就是Ims Service
private final static
String mClassName = ImsService.class.getName();
public void
onReceive(Context context, Intent intent) {
String intentAction =
intent.getAction();
//在开机的时候,会先收到ACTION_SIM_STATE_CHANGED广播
if
((Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) ||
(ACTION_SIM_STATE_CHANGED.equals(intentAction))) {
//如果这时候Service还没有启动
if
(!isServiceRunning(context)) {
Log.d(TAG,
"Starting " + mClassName + " : " + intentAction + " received. ");
//启动Service
startService(context);
} else
{
Log.d(TAG,
mClassName + " is already running. " +
intentAction + " ignored. ");
}
} else {
Log.e(TAG,
"Received Intent: " + intent.toString());
}
}
private void
startService(Context context) {
ComponentName comp =
new ComponentName(context.getName(), mClassName);
//启动Ims Service
ComponentName service
= context.startService(new Intent().setComponent(comp));
if (service == null)
{
Log.e(TAG, "Could
Not Start Service " + comp.toString());
} else {
Log.e(TAG,
mClassName + " service Started Successfully");
}
}
在ImsService.java的onCreate()方法中
public void onCreate() {
super.onCreate();
Log.d (LOG_TAG,
"ImsService created!");
mServiceSub = new
ImsServiceSub[getNumSubscriptions()];
for (int i = 0; i <
getNumSubscriptions(); i++) {
//在这里初始化ImsServiceSub对象,在ImsServiceSub的
//构造方法中进而会初始化ImsSenderRxr、ImsServiceSubHandler
//等对象并且监听IMS、Call等的状态变化;
//(ImsSenderRxr跟RILJ作用类似,可以跟Qcril交互,
// IMS的流程会走ImsSenderRxr而不会走RIL.java)
mServiceSub[i] = new ImsServiceSub(i +
1, this);
}
ServiceManager.addService("ims", mBinder);
//配置mImsPhoneId为DEFAULT_PHONE_ID,发送ACTION_IMS_SERVICE_UP广播
switchImsPhoneByPhoneId(DEFAULT_PHONE_ID);
final int defaultSub =
1;
ImsVideoGlobals.init(mServiceSub[defaultSub-1], this);
/* Check if any change
in socket communication is required */
initSubscriptionStatus();
/* Initialize Call
Deflect support to not supported */
initCallDeflectStatus();
}
/* Method to re-initialize
the Ims Phone instances */
private void
switchImsPhoneByPhoneId(int phoneId) {
if (mImsPhoneId ==
phoneId) {
Log.d(LOG_TAG,
"switchImsPhone: ImsPhoneId: " + mImsPhoneId + " UNchanged");
return;
}
Log.d(LOG_TAG,
"switchImsPhone: ImsPhoneId:" + mImsPhoneId + " changed to " +
phoneId);
mImsPhoneId =
phoneId;
/* Change the socket
communication */
final int defaultSub =
1;
mServiceSub[defaultSub-1].registerForPhoneId(mImsPhoneId);
/* Shut-down the
existing ims phone */
int mNumPhones =
TelephonyManager.getDefault().getPhoneCount();
for (int i = 0; i <
mNumPhones; i++) {
if(mImsPhoneId !=
i) {
Intent intent
= new Intent(ImsManager.ACTION_IMS_SERVICE_DOWN);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(ImsManager.EXTRA_PHONE_ID, i);
this.sendStickyBroadcast(new Intent(intent));
}
}
/* Create the new IMS
phone */
Intent intent = new
Intent(ImsManager.ACTION_IMS_SERVICE_UP);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
//添加ImsPhoneId,发送广播,通知PhoneBase
intent.putExtra(ImsManager.EXTRA_PHONE_ID, mImsPhoneId);
this.sendStickyBroadcast(new Intent(intent));
}
在IMS Service启动之后,回到PhoneBase.java的mImsIntentReceiver广播接收器中
private BroadcastReceiver
mImsIntentReceiver = new BroadcastReceiver() {
@Override
public void
onReceive(Context context, Intent intent) {
Rlog.d(LOG_TAG,
"mImsIntentReceiver: action " + intent.getAction());
//先判断intent中是否包含Phone Id
if
(intent.hasExtra(ImsManager.EXTRA_PHONE_ID)) {
int
extraPhoneId = intent.getIntExtra(ImsManager.EXTRA_PHONE_ID,
SubscriptionManager.INVALID_PHONE_INDEX);
Rlog.d(LOG_TAG, "mImsIntentReceiver: extraPhoneId = " +
extraPhoneId);
//如果获取到的Phone Id等于-1或者Phone Id跟当前get到的
//phone
Id不一样,说明有误,所以直接return
if
(extraPhoneId == SubscriptionManager.INVALID_PHONE_INDEX ||
extraPhoneId != getPhoneId()) {
return;
}
}
synchronized
(PhoneProxy.lockForRadioTechnologyChange) {
//如果ACTION是IMS_SERVICE_UP,说明IMS Service已启动
if
(intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
//将标志设置成true,在更新ImsPhone时会用到
mImsServiceReady = true;
//创建或者更新ImsPhone(1.3小节会详细讲)
updateImsPhone();
//更新配置信息,通知Modem turn On/Off IMS(1.4小节会详细讲)
ImsManager.updateImsServiceConfig(mContext, mPhoneId, false);
} else if
(intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)){
mImsServiceReady = false;
updateImsPhone();
}
}
}
};
1.3 创建ImsPhone
protected void
updateImsPhone() {
Rlog.d(LOG_TAG,
"updateImsPhone"
+ "
mImsServiceReady=" + mImsServiceReady);
//如果ImsService已启动并且ImsPhone还没有被创建
if (mImsServiceReady
&& (mImsPhone == null)) {
//通过PhoneFactory创建ImsPhone,这里的this就是default Phone
mImsPhone =
PhoneFactory.makeImsPhone(mNotifier, this);
//registerPhone的作用是把新创建的ImsPhone对象添加到CallManager
//的Phone list中,并且为ImsPhone注册监听各种Phone States
CallManager.getInstance().registerPhone(mImsPhone);
mImsPhone.registerForSilentRedial(
this,
EVENT_INITIATE_SILENT_REDIAL, null);
} else if
(!mImsServiceReady && (mImsPhone != null)) {
CallManager.getInstance().unregisterPhone(mImsPhone);
mImsPhone.unregisterForSilentRedial(this);
mImsPhone.dispose();
// Potential GC
issue if someone keeps a reference to ImsPhone.
// However: this
change will make sure that such a reference does
// not access
functions through NULL pointer.
//mImsPhone.removeReferences();
mImsPhone =
null;
}
}
接着PhoneFactory还是调了ImsPhoneFactory的makePhone()方法
/**
* Makes a {@link
ImsPhone} object.
* @return the {@code
ImsPhone} object or null if the exception occured
*/
public static ImsPhone
makeImsPhone(PhoneNotifier phoneNotifier, Phone defaultPhone) {
return
ImsPhoneFactory.makePhone(sContext, phoneNotifier, defaultPhone);
}
而ImsPhoneFactory中只有一个方法,也就是
public static ImsPhone
makePhone(Context context,
PhoneNotifier
phoneNotifier, Phone defaultPhone) {
try {
//直接new ImsPhone,在ImsPhone的构造方法中又
//会new ImsPhoneCallTracker,在ImsPhoneCallTracker的
//构造方法中,会执行获取IMS注册状态的流程(第二节会详细讲)
return new
ImsPhone(context, phoneNotifier, defaultPhone);
} catch (Exception e)
{
Rlog.e("VoltePhoneFactory", "makePhone", e);
return
null;
}
}
到这里,ImsPhone被创建完成。
1.4 通知Modem turn On IMS
在PhoneBase.java的mImsIntentReceiver广播接收器中,除了创建ImsPhone对象,还调了ImsManager.java的updateImsServiceConfig()方法更新配置信息。
public static void
updateImsServiceConfig(Context context, int phoneId, boolean force) {
final ImsManager
imsManager = ImsManager.getInstance(context, phoneId);
//此时imsManager.mConfigUpdated的值还是false,说明还没有更新过
if (imsManager != null
&& (!imsManager.mConfigUpdated || force)) {
try {
//如果Volte、VideoCall、WfC(Wifi Calling)任意一项可用且enable的话,那么就要turn On IMS
boolean turnOn
= imsManager.updateVolteFeatureValue();
turnOn |=
imsManager.updateVideoCallFeatureValue();
turnOn |=
imsManager.updateWfcFeatureAndProvisionedValues();
if (turnOn)
{
//通知modem turn On IMS
imsManager.turnOnIms();
} else if
(getBooleanCarrierConfig(context,
CarrierConfigManager.KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL)) {
imsManager.turnOffIms();
}
//把标志位设成true,除非强制更新,否则不会再进来这里
imsManager.mConfigUpdated =
true;
} catch
(ImsException e) {
loge("updateImsServiceConfig: " + e);
imsManager.mConfigUpdated = false;
}
}
}