目录

  1. 概述
  2. Ims注册时序图
  3. PhoneApp的启动过程
  4. Ims注册主要代码
  5. 总结
  • 概述

IMS(IP Multimedia Subsystem)是IP多媒体系统, 是一种新的多媒体业务形式,ims service 结构主要包括 ImsService、ImsManager、MmTelFeatureConnection、ImsCallSession。其中:

  1. ImsService:ims的Service,实现了所有的ImsFeature(MmTelFeature和RcsFeature)和ims协议行为。通过ImsResolver绑定。由ImsServiceController来负责管理其生命周期及这个service所支持的ImsFeatures。其主要操作可以通过IImsServiceController来调用。
  2. ImsManager:单例类。提供了与IMS services交互的API,如创建ims call。这个类是所有ims相关操作的起点。
  3. MmTelFeatureConnection:IImsServiceController binder的容器类。
  4. ImsCallSession:负责ImsCall的发起和终止,以及两个ims端点间的媒体交换。它和ImsService直接交互。
  • Ims注册时序图

android ims 框架中怎么判断是否注册上ims网络 打开ims注册_高通平台


  时序图从开机后PhoneApp启动开始到最终发出请求

PhoneApp是如何开机启动的呢,下面我们简要说明一下。

三、PhoneApp的启动过程

首先PhoneApp的主要功能是什么呢?

  1. 负责实例化创建Telephony应用框架层(phone),且和phone一起运行在com.android.phone进程中。
  2. 管理(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内容:

  1. persistent属性的作用:开机时被系统自动初始化;该模块所在的进程(com.android.phone)由于任何原因被kill掉之后,都会自动重启(这种情况只针对系统内置app,第三方安装的app不会被重启)
  2. 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()方法:

  1. 初始化各种控制接口SubscriptionController,UiccController,主要负责SIM卡状态信息的控制监听
  2. 根据SIM卡数量创建Phone和RIL实例,并且设置默认Phone和RIL,Phone分为GSM和CDMA两大种类
  3. 启动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() 做了如下动作:

  1. 初始化ImsManager
  2. 注册ImsService的UP/DOWN两个广播
  3. 更新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为未来的多媒体应用提供了一个通用的业务平台。