(M)SIM卡开机流程分析之TelephonyManager类分析

本文分析了Android系统中SIM卡开机流程,重点关注TelephonyManager类的使用。在PhoneFactory的makeDefaultPhone方法启动过程中,通过TelephonyManager.getDefault获取该对象。TelephonyManager提供了多种方法,如获取IMEI号、手机类型和数据连接网络类型,其内部会调用PhoneInterfaceManager来获取网络类型,并据此判断网络数据等级。
摘要由CSDN通过智能技术生成

首先在PhoneFactory的makeDefaultPhone方法中,调用了TelephonyManager.getDefault方法

int numPhones = TelephonyManager.getDefault().getPhoneCount();
查看TelephonyManager的getDefault方法

// Leo, 全局变量
    private static TelephonyManager sInstance = new TelephonyManager();

    /** @hide
    /* @deprecated - use getSystemService as described above */
    public static TelephonyManager getDefault() {
        return sInstance;
    }
可以看到,就是返回了一个全局TelephonyManager对象

/**
     * Returns the number of phones available.
     * Returns 1 for Single standby mode (Single SIM functionality)
     * Returns 2 for Dual standby mode.(Dual SIM functionality)
     */
    public int getPhoneCount() {
        int phoneCount = 1;
        switch (getMultiSimConfiguration()) {
            case UNKNOWN:
                phoneCount = 1;
                break;
            case DSDS:
            case DSDA:
                phoneCount = PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
                break;
            case TSTS:
                phoneCount = PhoneConstants.MAX_PHONE_COUNT_TRI_SIM;
                break;
        }
        return phoneCount;
    }
/**
     * Returns the multi SIM variant
     * Returns DSDS for Dual SIM Dual Standby
     * Returns DSDA for Dual SIM Dual Active
     * Returns TSTS for Triple SIM Triple Standby
     * Returns UNKNOWN for others
     */
    /** {@hide} */
    public MultiSimVariants getMultiSimConfiguration() {
        String mSimConfig =
            SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
        if (mSimConfig.equals("dsds")) {
            return MultiSimVariants.DSDS;
        } else if (mSimConfig.equals("dsda")) {
            return MultiSimVariants.DSDA;
        } else if (mSimConfig.equals("tsts")) {
            return MultiSimVariants.TSTS;
        } else {
            return MultiSimVariants.UNKNOWN;
        }
    }
所以,

int numPhones = TelephonyManager.getDefault().getPhoneCount();
这个语句就是根据用户预设定的persist.radio.multisim.config值,来确定当前是单卡项目还是多卡项目,返回的是手机所支持的卡槽数量。

我们通常看到的获取TelephonyManager对象的方法,都是通过调用

TelephonyManager.from(context)
方法,而且看到上述无参构造函数中注释中说明,获取其对象一般需要使用getSystemService方法来获取,来看看TelephonyManager的from方法

/** {@hide} */
    public static TelephonyManager from(Context context) {
        return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    }
可以看到,如google原始注释,需要使用getSystemService方法来获取其对象,而从之前对于getSystemService方法分析,可以知道,其就是通过TelephonyManager(context)构造函数来生成TelephonyManager对象的

/** @hide */
    public TelephonyManager(Context context) {
        Context appContext = context.getApplicationContext();
        if (appContext != null) {
            mContext = appContext;
        } else {
            mContext = context;
        }
        mSubscriptionManager = SubscriptionManager.from(mContext);

        if (sRegistry == null) {
            sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                    "telephony.registry"));
        }
    }
同样地,SubscriptionManager的from方法

/**
     * Get an instance of the SubscriptionManager from the Context.
     * This invokes {@link android.content.Context#getSystemService
     * Context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)}.
     *
     * @param context to use.
     * @return SubscriptionManager instance
     */
    public static SubscriptionManager from(Context context) {
        return (SubscriptionManager) context.getSystemService(
                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
    }
通过查看SystemServiceRegistry.java的方法
registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
                new CachedServiceFetcher<SubscriptionManager>() {
            @Override
            public SubscriptionManager createService(ContextImpl ctx) {
                return new SubscriptionManager(ctx.getOuterContext());
            }});
其调用的是SubscriptionManager类中的SubscriptionManager(Context)构造函数

因此,mSubscriptionManager就是SubscriptionManager对象,而sRegistry就是TelephonyRegistry对象,这个不多说。

int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
这个方法不多说,获取当前卡槽的PhoneType

再来看看TelephonyManager类中的其他方法

/**
    * @hide
    */
    private ITelephony getITelephony() {
        return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
    }
这个方法是AIDL的应用,我还没搞明白,等后续分析后,再来记录下吧,其返回的是PhoneInterfaceManager对象

/**
    * @hide
    */
    private ITelecomService getTelecomService() {
        return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));
    }
不多说,这个ITelephonyService应该是在TelecomServiceImpl类中实现的

/**
    * @hide
    */
    private IPhoneSubInfo getSubscriberInfo() {
        // get it each time because that process crashes a lot
        return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
    }
在PhoneSubInfoProxy类中实现

/** {@hide} */
    public boolean isMultiSimEnabled() {
        return (multiSimConfig.equals("dsds") || multiSimConfig.equals("dsda") ||
            multiSimConfig.equals("tsts"));
    }
判断是否是多卡项目

/**
     * Returns the software version number for the device, for example,
     * the IMEI/SV for GSM phones. Return null if the software version is
     * not available.
     *
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     */
    public String getDeviceSoftwareVersion() {
        return getDeviceSoftwareVersion(getDefaultSim());
    }
/**
     * Returns the software version number for the device, for example,
     * the IMEI/SV for GSM phones. Return null if the software version is
     * not available.
     *
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     *
     * @param slotId of which deviceID is returned
     */
    /** {@hide} */
    public String getDeviceSoftwareVersion(int slotId) {
        // FIXME methods taking slot id should not use subscription, instead us Uicc directly
        int[] subId = SubscriptionManager.getSubId(slotId);
        if (subId == null || subId.length == 0) {
            return null;
        }
        try {
            IPhoneSubInfo info = getSubscriberInfo();
            if (info == null)
                return null;
            return info.getDeviceSvnUsingSubId(subId[0], mContext.getOpPackageName());
        } catch (RemoteException ex) {
            return null;
        } catch (NullPointerException ex) {
            return null;
        }
    }
获取软件版本,调用的是PhoneSubInfoProxy类中的getDeviceSvnUsingSubId方法

/**
     * Returns the unique device ID, for example, the IMEI for GSM and the MEID
     * or ESN for CDMA phones. Return null if device ID is not available.
     *
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     */
    public String getDeviceId() {
        try {
            ITelephony telephony = getITelephony();
            if (telephony == null)
                return null;
            return telephony.getDeviceId(mContext.getOpPackageName());
        } catch (RemoteException ex) {
            return null;
        } catch (NullPointerException ex) {
            return null;
        }
    }
获取设备ID,IMEI或者MEID号,调用PhoneInterfaceManager类中的getDeviceId方法,如下:

/**
     * Returns the unique device ID of phone, for example, the IMEI for
     * GSM and the MEID for CDMA phones. Return null if device ID is not available.
     *
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     */
    @Override
    public String getDeviceId(String callingPackage) {
        if (!canReadPhoneState(callingPackage, "getDeviceId")) {
            return null;
        }

        final Phone phone = PhoneFactory.getPhone(0);
        if (phone != null) {
            return phone.getDeviceId();
        } else {
            return null;
        }
    }
调用的是Phone的getDeviceId方法,而PhoneFactory的getPhone方法

PhoneFactory.java
public static Phone getPhone(int phoneId) {
        Phone phone;
        String dbgInfo = "";

        synchronized (sLockProxyPhones) {
            if (!sMadeDefaults) {
                throw new IllegalStateException("Default phones haven't been made yet!");
                // CAF_MSIM FIXME need to introduce default phone id ?
            } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
                if (DBG) dbgInfo = "phoneId == DEFAULT_PHONE_ID return sProxyPhone";
                phone = sProxyPhone;
            } else {
                if (DBG) dbgInfo = "phoneId != DEFAULT_PHONE_ID return sProxyPhones[phoneId]";
                phone = (((phoneId >= 0)
                   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值