目录
- 概述
- Ims注册时序图
- PhoneApp的启动过程
- Ims注册主要代码
- 总结
- 概述
IMS(IP Multimedia Subsystem)是IP多媒体系统, 是一种新的多媒体业务形式,ims service 结构主要包括 ImsService、ImsManager、MmTelFeatureConnection、ImsCallSession。其中:
- ImsService:ims的Service,实现了所有的ImsFeature(MmTelFeature和RcsFeature)和ims协议行为。通过ImsResolver绑定。由ImsServiceController来负责管理其生命周期及这个service所支持的ImsFeatures。其主要操作可以通过IImsServiceController来调用。
- ImsManager:单例类。提供了与IMS services交互的API,如创建ims call。这个类是所有ims相关操作的起点。
- MmTelFeatureConnection:IImsServiceController binder的容器类。
- ImsCallSession:负责ImsCall的发起和终止,以及两个ims端点间的媒体交换。它和ImsService直接交互。
- Ims注册时序图
时序图从开机后PhoneApp启动开始到最终发出请求
PhoneApp是如何开机启动的呢,下面我们简要说明一下。
三、PhoneApp的启动过程
首先PhoneApp的主要功能是什么呢?
- 负责实例化创建Telephony应用框架层(phone),且和phone一起运行在com.android.phone进程中。
- 管理(CallManager),控制通话相关的UI、功能操作、业务逻辑实现
这里我们需要知道,Android系统中多个应用程序(Apk)是可以运行在同一个进程中的,PhoneApp就是这样,连同Stk、SMSProvider、TelephonyProvider等模块都运行在com.android.phone进程中(简称phone进程)。
<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的路径是:packages\services\Telephony,我们来看看它的AndroidManifest.xml内容:
- persistent属性的作用:开机时被系统自动初始化;该模块所在的进程(com.android.phone)由于任何原因被kill掉之后,都会自动重启(这种情况只针对系统内置app,第三方安装的app不会被重启)
- directBootAware属性的作用:该属性使得用户在加密状态(未解锁)下能够正常使用一些手机功能,如闹钟、接电话等,但不允许访问私有应用数据
系统在启动时会先启动SystemService,SystemService会启动各种系统服务,包括AMS:
private void startBootstrapServices() {
.....
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
......
}
而ActivityManagerService的SystemReady方法中就有一个启动PersistentApps的方法,且该应用还需要MATCH_DIRECT_BOOT_AWARE,而PhoneApp正满足此需求:
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
......
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
......
}
由此可见,PhoneApp会在系统启动起来的时候由系统自动启动
四、Ims注册主要代码
PhoneApp启动后会先执行onCreate()方法
packages\services\Telephony\src\com\android\phone\PhoneApp.java
public class PhoneApp extends Application {
PhoneGlobals mPhoneGlobals;
TelephonyGlobals mTelephonyGlobals;
public 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);// 创建PhoneGlobals,即Phone的全局状态
mPhoneGlobals.onCreate();
mTelephonyGlobals = new TelephonyGlobals(this);
mTelephonyGlobals.onCreate();
}
}
PhoenApp的onCreate()方法主要创建了mPhoneGlobals对象和mTelephonyGlobals对象,并执行了两个对象的onCreate()方法,接下来的流程也将围绕mPhoneGlobals对象的onCreate展开:
packages\services\Telephony\src\com\android\phone\PhoneGlobals.java
public void onCreate() {
......
if (mCM == null) {
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);
}
......
}
首先通过PhoneFactory makeDefaultPhones,下面看一下makeDefaultPhones方法主要执行的动作
frameworks\opt\telephony\src\java\com\android\internal\telephony\PhoneFactory.java
public static void makeDefaultPhone(Context context) {
......
for (int i = 0; i < numPhones; i++) {
Phone phone = null;
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
phone = telephonyComponentFactory.makePhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_GSM,
telephonyComponentFactory);
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
phone = telephonyComponentFactory.makePhone(context,
sCommandsInterfaces[i], sPhoneNotifier, i,
PhoneConstants.PHONE_TYPE_CDMA_LTE,
telephonyComponentFactory);
}
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();
}
}
主要贴了创建GSMPhone和CDMAPhone的方法。
总结一下makeDefaultPhone()方法:
- 初始化各种控制接口SubscriptionController,UiccController,主要负责SIM卡状态信息的控制监听
- 根据SIM卡数量创建Phone和RIL实例,并且设置默认Phone和RIL,Phone分为GSM和CDMA两大种类
- 启动ImsResolver并绑定到ImsServices
Android中有三种PhoneFactory:
1.PhoneFactory.java ——–>用于创建GsmCdmaPhone对象
2.ImsPhoneFactory.java ——–>用于创建ImsPhone对象
3.SipPhoneFactory.java ——–>用于创建SipPhone对象
下面跟进startMonitoringImsService方法
frameworks\opt\telephony\src\java\com\android\internal\telephony\Phone.java
public void startMonitoringImsService() {
if (getPhoneType() == PhoneConstants.PHONE_TYPE_SIP) {
return;
}
synchronized(Phone.lockForRadioTechnologyChange) {
IntentFilter filter = new IntentFilter();
ImsManager imsManager = ImsManager.getInstance(mContext, getPhoneId());
// Don't listen to deprecated intents using the new dynamic binding.
if (imsManager != null && !imsManager.isDynamicBinding()) {
filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP);
filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN);
}
mContext.registerReceiver(mImsIntentReceiver, filter);
if (imsManager != null) {
if (imsManager.isDynamicBinding() || imsManager.isServiceAvailable()) {
mImsServiceReady = true;
updateImsPhone();
}
}
}
}
从上面的代码中可以看到,startMonitoringImsService() 做了如下动作:
- 初始化ImsManager
- 注册ImsService的UP/DOWN两个广播
- 更新ImsPhone.
当接收到UP广播后
private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
......
synchronized (Phone.lockForRadioTechnologyChange) {
if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
mImsServiceReady = true;
updateImsPhone();
ImsManager.getInstance(mContext, mPhoneId).updateImsServiceConfig(false);
} else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) {
mImsServiceReady = false;
updateImsPhone();
}
}
}
通过ImsManager更新ImsService的配置
frameworks\opt\net\ims\src\java\com\android\ims\ImsManager.java
public void updateImsServiceConfig(boolean force) {
......
if (!mConfigUpdated || force) {
try {
boolean isImsUsed = updateVolteFeatureValue();
isImsUsed |= updateWfcFeatureAndProvisionedValues();
isImsUsed |= updateVideoCallFeatureValue();
if (isImsUsed || !isTurnOffImsAllowedByPlatform()) {
log("updateImsServiceConfig: turnOnIms");
turnOnIms();
} else {
// Turn off IMS if it is not used AND turning off is allowed for carrier.
log("updateImsServiceConfig: turnOffIms");
turnOffIms();
}
mConfigUpdated = true;
} catch (ImsException e) {
loge("updateImsServiceConfig: ", e);
mConfigUpdated = false;
}
}
}
此处turnOnIms()会经过TelephonyManager、ImsResolver、ImsServiceController等类的实现、重写等。最终在高通私有类ImsService中实现。
下面是高通私有类的流程
vendor\qcom\proprietary\commonsys\telephony-apps\ims\src\org\codeaurora\ims\ ImsService.java
@Override
public void enableIms(int slotId) {
Log.i(this, "enableIms :: slotId=" + slotId);
if (slotId > INVALID_SLOT_ID && slotId < getNumSlots()) {
mServiceSubs[slotId].turnOnIms();
} else {
Log.e(this, "enableIms :: Invalid slotId " + slotId);
}
}
vendor\qcom\proprietary\commonsys\telephony-apps\ims\src\org\codeaurora\ims\ ImsServiceSub.java
public void turnOnIms() {
mCi.sendImsRegistrationState(ImsRegistrationInfo.REGISTERED,
mHandler.obtainMessage(EVENT_SET_IMS_STATE));
}
vendor\qcom\proprietary\commonsys\telephony-apps\ims\src\org\codeaurora\ims\ ImsSenderRxr.java
public void sendImsRegistrationState(int imsRegState, Message result) {
……
queueRequest(rr);
try {
……
imsRadioV10().requestRegistrationChange(rr.mSerial,
ImsRadioUtils.regStateToHal(imsRegState));
} catch (Exception ex) {
removeFromQueueAndSendResponse(rr.mSerial);
Log.e(this, msgIdString + "request to IImsRadio: Exception: " + ex);
}
}
最后通过ImsSenderRxr把请求发出去。
上述就是ims从开机到注册的主要流程,关于时序图中的ImsPhone那块,就不在详细说明了。
五、总结
Ims的概念很大,上述只是介绍了它很小的一部分。IMS是一个在分组域(PS)上的多媒体控制/呼叫控制平台,IMS使得PS具有电路域(CS)的部分功能,支持会话类和非会话类的多媒体业务。IMS为未来的多媒体应用提供了一个通用的业务平台。