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

来源:互联网 发布:壁纸自动更换软件 编辑:程序博客网 时间:2024/05/06 17:39

首先在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.javapublic 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)                                && (phoneId < TelephonyManager.getDefault().getPhoneCount()))                        ? sProxyPhones[phoneId] : null);            }            if (DBG) {                Rlog.d(LOG_TAG, "getPhone:- " + dbgInfo + " phoneId=" + phoneId +                        " phone=" + phone);            }            return phone;        }    }
PhoneProxy.java@Override    public String getDeviceId() {        return mActivePhone.getDeviceId();    }
而mActivePhone是PhoneBase对象,具体实现在PhoneFactory的makeDefaultPhone中实现,应该是GSMPhone或者CDMALTEPhone对象

继续看TelephonyManager中的其他方法

/**     * Returns the unique device ID of a subscription, 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}     *     * @param slotId of which deviceID is returned     */    public String getDeviceId(int slotId) {        // FIXME this assumes phoneId == slotId        try {            IPhoneSubInfo info = getSubscriberInfo();            if (info == null)                return null;            return info.getDeviceIdForPhone(slotId, mContext.getOpPackageName());        } catch (RemoteException ex) {            return null;        } catch (NullPointerException ex) {            return null;        }    }
这个是调用了PhoneSubInfoProxy的getDeviceIdForPhone方法,获取设备ID,IMEI或者MEID号

/**     * Returns the IMEI. Return null if IMEI is not available.     *     * <p>Requires Permission:     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}     */    /** {@hide} */    public String getImei() {        return getImei(getDefaultSim());    }
/**     * Returns the IMEI. Return null if IMEI 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 getImei(int slotId) {        int[] subId = SubscriptionManager.getSubId(slotId);        try {            IPhoneSubInfo info = getSubscriberInfo();            if (info == null)                return null;            return info.getImeiForSubscriber(subId[0], mContext.getOpPackageName());        } catch (RemoteException ex) {            return null;        } catch (NullPointerException ex) {            return null;        }    }

获取IMEI号

/**     * Returns the NAI. Return null if NAI is not available.     *     */    /** {@hide}*/    public String getNai() {        return getNai(getDefaultSim());    }
/**     * Returns the NAI. Return null if NAI is not available.     *     *  @param slotId of which Nai is returned     */    /** {@hide}*/    public String getNai(int slotId) {        int[] subId = SubscriptionManager.getSubId(slotId);        try {            IPhoneSubInfo info = getSubscriberInfo();            if (info == null)                return null;            String nai = info.getNaiForSubscriber(subId[0], mContext.getOpPackageName());            if (Log.isLoggable(TAG, Log.VERBOSE)) {                Rlog.v(TAG, "Nai = " + nai);            }            return nai;        } catch (RemoteException ex) {            return null;        } catch (NullPointerException ex) {            return null;        }    }
获取NAI

/**     * Returns the current location of the device.     *<p>     * If there is only one radio in the device and that radio has an LTE connection,     * this method will return null. The implementation must not to try add LTE     * identifiers into the existing cdma/gsm classes.     *<p>     * In the future this call will be deprecated.     *<p>     * @return Current location of the device or null if not available.     *     * <p>Requires Permission:     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.     */    public CellLocation getCellLocation() {        try {            ITelephony telephony = getITelephony();            if (telephony == null) {                Rlog.d(TAG, "getCellLocation returning null because telephony is null");                return null;            }            Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName());            if (bundle.isEmpty()) {                Rlog.d(TAG, "getCellLocation returning null because bundle is empty");                return null;            }            CellLocation cl = CellLocation.newFromBundle(bundle);            if (cl.isEmpty()) {                Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty");                return null;            }            return cl;        } catch (RemoteException ex) {            Rlog.d(TAG, "getCellLocation returning null due to RemoteException " + ex);            return null;        } catch (NullPointerException ex) {            Rlog.d(TAG, "getCellLocation returning null due to NullPointerException " + ex);            return null;        }    }
获取设备的位置信息

/**     * Enables location update notifications.  {@link PhoneStateListener#onCellLocationChanged     * PhoneStateListener.onCellLocationChanged} will be called on location updates.     *     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES     * CONTROL_LOCATION_UPDATES}     *     * @hide     */    public void enableLocationUpdates() {            enableLocationUpdates(getDefaultSubscription());    }
/**     * Enables location update notifications for a subscription.     * {@link PhoneStateListener#onCellLocationChanged     * PhoneStateListener.onCellLocationChanged} will be called on location updates.     *     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES     * CONTROL_LOCATION_UPDATES}     *     * @param subId for which the location updates are enabled     */    /** @hide */    public void enableLocationUpdates(int subId) {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                telephony.enableLocationUpdatesForSubscriber(subId);        } catch (RemoteException ex) {        } catch (NullPointerException ex) {        }    }
启动设备位置信息更新通知

/**     * Disables location update notifications.  {@link PhoneStateListener#onCellLocationChanged     * PhoneStateListener.onCellLocationChanged} will be called on location updates.     *     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES     * CONTROL_LOCATION_UPDATES}     *     * @hide     */    public void disableLocationUpdates() {            disableLocationUpdates(getDefaultSubscription());    }    /** @hide */    public void disableLocationUpdates(int subId) {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                telephony.disableLocationUpdatesForSubscriber(subId);        } catch (RemoteException ex) {        } catch (NullPointerException ex) {        }    }
关闭设备位置更新通知

/**     * Returns the neighboring cell information of the device.     *     * @return List of NeighboringCellInfo or null if info unavailable.     *     * <p>Requires Permission:     * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}     *     * @deprecated Use (@link getAllCellInfo} which returns a superset of the information     *             from NeighboringCellInfo.     */    @Deprecated    public List<NeighboringCellInfo> getNeighboringCellInfo() {        try {            ITelephony telephony = getITelephony();            if (telephony == null)                return null;            return telephony.getNeighboringCellInfo(mContext.getOpPackageName());        } catch (RemoteException ex) {            return null;        } catch (NullPointerException ex) {            return null;        }    }
/**     * Returns all observed cell information from all radios on the     * device including the primary and neighboring cells. This does     * not cause or change the rate of PhoneStateListener#onCellInfoChanged.     *<p>     * The list can include one or more of {@link android.telephony.CellInfoGsm CellInfoGsm},     * {@link android.telephony.CellInfoCdma CellInfoCdma},     * {@link android.telephony.CellInfoLte CellInfoLte} and     * {@link android.telephony.CellInfoWcdma CellInfoWcdma} in any combination.     * Specifically on devices with multiple radios it is typical to see instances of     * one or more of any these in the list. In addition 0, 1 or more CellInfo     * objects may return isRegistered() true.     *<p>     * This is preferred over using getCellLocation although for older     * devices this may return null in which case getCellLocation should     * be called.     *<p>     * This API will return valid data for registered cells on devices with     * {@link android.content.pm.PackageManager#FEATURE_TELEPHONY}     *<p>     * @return List of CellInfo or null if info unavailable.     *     * <p>Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}     */    public List<CellInfo> getAllCellInfo() {        try {            ITelephony telephony = getITelephony();            if (telephony == null)                return null;            return telephony.getAllCellInfo(getOpPackageName());        } catch (RemoteException ex) {            return null;        } catch (NullPointerException ex) {            return null;        }    }
获取附近小区信息

/**     * Returns the current phone type.     * TODO: This is a last minute change and hence hidden.     *     * @see #PHONE_TYPE_NONE     * @see #PHONE_TYPE_GSM     * @see #PHONE_TYPE_CDMA     * @see #PHONE_TYPE_SIP     *     * {@hide}     */    @SystemApi    public int getCurrentPhoneType() {        return getCurrentPhoneType(getDefaultSubscription());    }
/**     * Returns a constant indicating the device phone type for a subscription.     *     * @see #PHONE_TYPE_NONE     * @see #PHONE_TYPE_GSM     * @see #PHONE_TYPE_CDMA     *     * @param subId for which phone type is returned     */    /** {@hide} */    @SystemApi    public int getCurrentPhoneType(int subId) {        int phoneId;        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {            // if we don't have any sims, we don't have subscriptions, but we            // still may want to know what type of phone we've got.            phoneId = 0;        } else {            phoneId = SubscriptionManager.getPhoneId(subId);        }        try{            ITelephony telephony = getITelephony();            if (telephony != null && subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {                return telephony.getActivePhoneTypeForSubscriber(subId);            } else {                // This can happen when the ITelephony interface is not up yet.                return getPhoneTypeFromProperty(phoneId);            }        } catch (RemoteException ex) {            // This shouldn't happen in the normal case, as a backup we            // read from the system property.            return getPhoneTypeFromProperty(phoneId);        } catch (NullPointerException ex) {            // This shouldn't happen in the normal case, as a backup we            // read from the system property.            return getPhoneTypeFromProperty(phoneId);        }    }获取当前Phone的类型,这个地方获取的是默认的SubId

/**     * Returns a constant indicating the device phone type.  This     * indicates the type of radio used to transmit voice calls.     *     * @see #PHONE_TYPE_NONE     * @see #PHONE_TYPE_GSM     * @see #PHONE_TYPE_CDMA     * @see #PHONE_TYPE_SIP     */    public int getPhoneType() {        if (!isVoiceCapable()) {            return PHONE_TYPE_NONE;        }        return getCurrentPhoneType();    }

private int getPhoneTypeFromProperty() {        return getPhoneTypeFromProperty(getDefaultPhone());    }    /** {@hide} */    private int getPhoneTypeFromProperty(int phoneId) {        String type = getTelephonyProperty(phoneId,                TelephonyProperties.CURRENT_ACTIVE_PHONE, null);        if (type == null || type.equals("")) {            return getPhoneTypeFromNetworkType(phoneId);        }        return Integer.parseInt(type);    }    private int getPhoneTypeFromNetworkType() {        return getPhoneTypeFromNetworkType(getDefaultPhone());    }    /** {@hide} */    private int getPhoneTypeFromNetworkType(int phoneId) {        // When the system property CURRENT_ACTIVE_PHONE, has not been set,        // use the system property for default network type.        // This is a fail safe, and can only happen at first boot.        String mode = getTelephonyProperty(phoneId, "ro.telephony.default_network", null);        if (mode != null) {            return TelephonyManager.getPhoneType(Integer.parseInt(mode));        }        return TelephonyManager.PHONE_TYPE_NONE;    }

这些方法全部是获取当前PHone的类型的,还有上述getPhoneType(int networkMode)方法

/**     * The contents of the /proc/cmdline file     */    private static String getProcCmdLine()    {        String cmdline = "";        FileInputStream is = null;        try {            is = new FileInputStream("/proc/cmdline");            byte [] buffer = new byte[2048];            int count = is.read(buffer);            if (count > 0) {                cmdline = new String(buffer, 0, count);            }        } catch (IOException e) {            Rlog.d(TAG, "No /proc/cmdline exception=" + e);        } finally {            if (is != null) {                try {                    is.close();                } catch (IOException e) {                }            }        }        Rlog.d(TAG, "/proc/cmdline=" + cmdline);        return cmdline;    }
获取当前/proc/cmdline中的数据

/**     * Returns the alphabetic name of current registered operator.     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     */    public String getNetworkOperatorName() {        return getNetworkOperatorName(getDefaultSubscription());    }
/**     * Returns the alphabetic name of current registered operator     * for a particular subscription.     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     * @param subId     */    /** {@hide} */    public String getNetworkOperatorName(int subId) {        int phoneId = SubscriptionManager.getPhoneId(subId);        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, "");    }
/**     * Gets the telephony property.     *     * @hide     */    public static String getTelephonyProperty(int phoneId, String property, String defaultVal) {        String propVal = null;        String prop = SystemProperties.get(property);        if ((prop != null) && (prop.length() > 0)) {            String values[] = prop.split(",");            if ((phoneId >= 0) && (phoneId < values.length) && (values[phoneId] != null)) {                propVal = values[phoneId];            }        }        return propVal == null ? defaultVal : propVal;    }
获取运营商的名称

/**     * Returns the numeric name (MCC+MNC) of current registered operator.     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     */    public String getNetworkOperator() {        return getNetworkOperatorForPhone(getDefaultPhone());    }
/**     * Returns the numeric name (MCC+MNC) of current registered operator     * for a particular subscription.     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     *     * @param subId     */    /** {@hide} */   public String getNetworkOperatorForSubscription(int subId) {        int phoneId = SubscriptionManager.getPhoneId(subId);        return getNetworkOperatorForPhone(phoneId);     }
/**     * Returns the numeric name (MCC+MNC) of current registered operator     * for a particular subscription.     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     *     * @param phoneId     * @hide     **/   public String getNetworkOperatorForPhone(int phoneId) {        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");     }
获取MCC+MNC

/**     * Returns true if the device is considered roaming on the current     * network, for GSM purposes.     * <p>     * Availability: Only when user registered to a network.     */    public boolean isNetworkRoaming() {        return isNetworkRoaming(getDefaultSubscription());    }
/**     * Returns true if the device is considered roaming on the current     * network for a subscription.     * <p>     * Availability: Only when user registered to a network.     *     * @param subId     */    /** {@hide} */    public boolean isNetworkRoaming(int subId) {        int phoneId = SubscriptionManager.getPhoneId(subId);        return Boolean.parseBoolean(getTelephonyProperty(phoneId,                TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null));    }
是否漫游

/**     * Returns the ISO country code equivalent of the current registered     * operator's MCC (Mobile Country Code).     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     */    public String getNetworkCountryIso() {        return getNetworkCountryIsoForPhone(getDefaultPhone());    }
/**     * Returns the ISO country code equivalent of the current registered     * operator's MCC (Mobile Country Code) of a subscription.     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     *     * @param subId for which Network CountryIso is returned     */    /** {@hide} */    public String getNetworkCountryIsoForSubscription(int subId) {        int phoneId = SubscriptionManager.getPhoneId(subId);        return getNetworkCountryIsoForPhone(phoneId);    }
/**     * Returns the ISO country code equivalent of the current registered     * operator's MCC (Mobile Country Code) of a subscription.     * <p>     * Availability: Only when user is registered to a network. Result may be     * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if     * on a CDMA network).     *     * @param phoneId for which Network CountryIso is returned     */    /** {@hide} */    public String getNetworkCountryIsoForPhone(int phoneId) {        return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");    }
获取ISO国家信息

/**     * @return the NETWORK_TYPE_xxxx for current data connection.     */    public int getNetworkType() {       try {           ITelephony telephony = getITelephony();           if (telephony != null) {               return telephony.getNetworkType();            } else {                // This can happen when the ITelephony interface is not up yet.                return NETWORK_TYPE_UNKNOWN;            }        } catch(RemoteException ex) {            // This shouldn't happen in the normal case            return NETWORK_TYPE_UNKNOWN;        } catch (NullPointerException ex) {            // This could happen before phone restarts due to crashing            return NETWORK_TYPE_UNKNOWN;        }    }
/**     * Returns a constant indicating the radio technology (network type)     * currently in use on the device for a subscription.     * @return the network type     *     * @param subId for which network type is returned     *     * @see #NETWORK_TYPE_UNKNOWN     * @see #NETWORK_TYPE_GPRS     * @see #NETWORK_TYPE_EDGE     * @see #NETWORK_TYPE_UMTS     * @see #NETWORK_TYPE_HSDPA     * @see #NETWORK_TYPE_HSUPA     * @see #NETWORK_TYPE_HSPA     * @see #NETWORK_TYPE_CDMA     * @see #NETWORK_TYPE_EVDO_0     * @see #NETWORK_TYPE_EVDO_A     * @see #NETWORK_TYPE_EVDO_B     * @see #NETWORK_TYPE_1xRTT     * @see #NETWORK_TYPE_IDEN     * @see #NETWORK_TYPE_LTE     * @see #NETWORK_TYPE_EHRPD     * @see #NETWORK_TYPE_HSPAP     *     * <p>     * Requires Permission:     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}     */    /** {@hide} */   public int getNetworkType(int subId) {       try {           ITelephony telephony = getITelephony();           if (telephony != null) {               return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());           } else {               // This can happen when the ITelephony interface is not up yet.               return NETWORK_TYPE_UNKNOWN;           }       } catch(RemoteException ex) {           // This shouldn't happen in the normal case           return NETWORK_TYPE_UNKNOWN;       } catch (NullPointerException ex) {           // This could happen before phone restarts due to crashing           return NETWORK_TYPE_UNKNOWN;       }   }

获取数据连接网络类型,调用的是PhoneInterfaceManager的getNetworkType方法

/**     * Return general class of network type, such as "3G" or "4G". In cases     * where classification is contentious, this method is conservative.     *     * @hide     */    public static int getNetworkClass(int networkType) {        switch (networkType) {            case NETWORK_TYPE_GPRS:            case NETWORK_TYPE_GSM:            case NETWORK_TYPE_EDGE:            case NETWORK_TYPE_CDMA:            case NETWORK_TYPE_1xRTT:            case NETWORK_TYPE_IDEN:                return NETWORK_CLASS_2_G;            case NETWORK_TYPE_UMTS:            case NETWORK_TYPE_EVDO_0:            case NETWORK_TYPE_EVDO_A:            case NETWORK_TYPE_HSDPA:            case NETWORK_TYPE_HSUPA:            case NETWORK_TYPE_HSPA:            case NETWORK_TYPE_EVDO_B:            case NETWORK_TYPE_EHRPD:            case NETWORK_TYPE_HSPAP:            case NETWORK_TYPE_TD_SCDMA:                return NETWORK_CLASS_3_G;            case NETWORK_TYPE_LTE:            case NETWORK_TYPE_IWLAN:                return NETWORK_CLASS_4_G;            default:                return NETWORK_CLASS_UNKNOWN;        }    }

根据网络类型,获取网络数据等级,2G/3G/4G

/**     * Returns a string representation of the radio technology (network type)     * currently in use on the device.     * @return the name of the radio technology     *     * @hide pending API council review     */    public String getNetworkTypeName() {        return getNetworkTypeName(getNetworkType());    }
获取网络类型名称

/**     * @return true if a ICC card is present     */    public boolean hasIccCard() {        return hasIccCard(getDefaultSim());    }
/**     * @return true if a ICC card is present for a subscription     *     * @param slotId for which icc card presence is checked     */    /** {@hide} */    // FIXME Input argument slotId should be of type int    public boolean hasIccCard(int slotId) {        try {            ITelephony telephony = getITelephony();            if (telephony == null)                return false;            return telephony.hasIccCardUsingSlotId(slotId);        } catch (RemoteException ex) {            // Assume no ICC card if remote exception which shouldn't happen            return false;        } catch (NullPointerException ex) {            // This could happen before phone restarts due to crashing            return false;        }    }
判断是否有IccCard,即SIM卡

/**     * Returns a constant indicating the state of the default SIM card.     *     * @see #SIM_STATE_UNKNOWN     * @see #SIM_STATE_ABSENT     * @see #SIM_STATE_PIN_REQUIRED     * @see #SIM_STATE_PUK_REQUIRED     * @see #SIM_STATE_NETWORK_LOCKED     * @see #SIM_STATE_READY     * @see #SIM_STATE_NOT_READY     * @see #SIM_STATE_PERM_DISABLED     * @see #SIM_STATE_CARD_IO_ERROR     */    public int getSimState() {        int slotIdx = getDefaultSim();        // slotIdx may be invalid due to sim being absent. In that case query all slots to get        // sim state        if (slotIdx < 0) {            // query for all slots and return absent if all sim states are absent, otherwise            // return unknown            for (int i = 0; i < getPhoneCount(); i++) {                int simState = getSimState(i);                if (simState != SIM_STATE_ABSENT) {                    Rlog.d(TAG, "getSimState: default sim:" + slotIdx + ", sim state for " +                            "slotIdx=" + i + " is " + simState + ", return state as unknown");                    return SIM_STATE_UNKNOWN;                }            }            Rlog.d(TAG, "getSimState: default sim:" + slotIdx + ", all SIMs absent, return " +                    "state as absent");            return SIM_STATE_ABSENT;        }        return getSimState(slotIdx);    }
/** {@hide} */    public int getSimState(int slotIdx) {        int simState = SubscriptionManager.getSimStateForSlotIdx(slotIdx);        return simState;    }
获取SIM卡状态

/**     * Returns the MCC+MNC (mobile country code + mobile network code) of the     * provider of the SIM. 5 or 6 decimal digits.     * <p>     * Availability: SIM state must be {@link #SIM_STATE_READY}     *     * @see #getSimState     */    public String getSimOperator() {        return getSimOperatorNumeric();    }
public String getSimOperator(int subId) {        return getSimOperatorNumericForSubscription(subId);    }
public String getSimOperatorNumeric() {        int subId = SubscriptionManager.getDefaultDataSubId();        if (!SubscriptionManager.isUsableSubIdValue(subId)) {            subId = SubscriptionManager.getDefaultSmsSubId();            if (!SubscriptionManager.isUsableSubIdValue(subId)) {                subId = SubscriptionManager.getDefaultVoiceSubId();                if (!SubscriptionManager.isUsableSubIdValue(subId)) {                    subId = SubscriptionManager.getDefaultSubId();                }            }        }        return getSimOperatorNumericForSubscription(subId);    }
public String getSimOperatorNumericForSubscription(int subId) {        int phoneId = SubscriptionManager.getPhoneId(subId);        return getSimOperatorNumericForPhone(phoneId);    }
public String getSimOperatorNumericForPhone(int phoneId) {        return getTelephonyProperty(phoneId,                TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");    }
返回IccCard的MCCMNC

public String getSimOperatorName() {        return getSimOperatorNameForPhone(getDefaultPhone());    }
public String getSimOperatorNameForSubscription(int subId) {        int phoneId = SubscriptionManager.getPhoneId(subId);        return getSimOperatorNameForPhone(phoneId);    }
public String getSimOperatorNameForPhone(int phoneId) {         return getTelephonyProperty(phoneId,                TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "");    }
返回SIM卡的SPN

public String getSimCountryIso() {        return getSimCountryIsoForPhone(getDefaultPhone());    }
返回SIM卡的ISO城市代码

/**     * Returns the serial number of the SIM, if applicable. Return null if it is     * unavailable.     * <p>     * Requires Permission:     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}     */    public String getSimSerialNumber() {         return getSimSerialNumber(getDefaultSubscription());    }
返回SIM卡的Serial Number

public String getMsisdn() {        return getMsisdn(getDefaultSubscription());    }
返回MSISDN

public String getVoiceMailNumber() {        return getVoiceMailNumber(getDefaultSubscription());    }
返回VoiceMail Number

public boolean setVoiceMailNumber(String alphaTag, String number) {        return setVoiceMailNumber(getDefaultSubscription(), alphaTag, number);    }
设置VoiceMail Number

public int getVoiceMessageCount() {        return getVoiceMessageCount(getDefaultSubscription());    }
获取VoiceMail消息数量

public int getCallState() {        try {            ITelecomService telecom = getTelecomService();            if (telecom != null) {                return telecom.getCallState();            }        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelecomService#getCallState", e);        }        return CALL_STATE_IDLE;    }
获取当前的通话状态

public int getDataActivity() {        try {            ITelephony telephony = getITelephony();            if (telephony == null)                return DATA_ACTIVITY_NONE;            return telephony.getDataActivity();        } catch (RemoteException ex) {            // the phone process is restarting.            return DATA_ACTIVITY_NONE;        } catch (NullPointerException ex) {          // the phone process is restarting.          return DATA_ACTIVITY_NONE;      }    }
获取数据连接的上下行状态

public int getDataState() {        try {            ITelephony telephony = getITelephony();            if (telephony == null)                return DATA_DISCONNECTED;            return telephony.getDataState();        } catch (RemoteException ex) {            // the phone process is restarting.            return DATA_DISCONNECTED;        } catch (NullPointerException ex) {            return DATA_DISCONNECTED;        }    }
获取数据链接的状态

public void listen(PhoneStateListener listener, int events) {        if (mContext == null) return;        try {            Boolean notifyNow = (getITelephony() != null);            sRegistry.listenForSubscriber(listener.mSubId, getOpPackageName(),                    listener.callback, events, notifyNow);        } catch (RemoteException ex) {            // system process dead        } catch (NullPointerException ex) {            // system process dead        }    }
注册监听,监听手机Telephony的状态变化

private static int getDefaultSubscription() {        return SubscriptionManager.getDefaultSubId();    }
获取默认的subId

private static int getDefaultPhone() {        return SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubId());    }
获取默认的PhoneId,这个代表的是哪一个卡槽

/** {@hide} */    public int getDefaultSim() {        return SubscriptionManager.getSlotId(SubscriptionManager.getDefaultSubId());    }
获取默认的SIM卡

/** @hide */    public int getSimCount() {        // FIXME Need to get it from Telephony Dev Controller when that gets implemented!        // and then this method shouldn't be used at all!        if(isMultiSimEnabled()) {            return 2;        } else {            return 1;        }    }
获取当前SIM卡数量

public int getPreferredNetworkType(int subId) {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                return telephony.getPreferredNetworkType(subId);        } catch (RemoteException ex) {            Rlog.e(TAG, "getPreferredNetworkType RemoteException", ex);        } catch (NullPointerException ex) {            Rlog.e(TAG, "getPreferredNetworkType NPE", ex);        }        return -1;    }
根据subId获取PreferredNetworkType

public boolean setPreferredNetworkType(int subId, int networkType) {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                return telephony.setPreferredNetworkType(subId, networkType);        } catch (RemoteException ex) {            Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex);        } catch (NullPointerException ex) {            Rlog.e(TAG, "setPreferredNetworkType NPE", ex);        }        return false;    }
设置subId对应的SIM卡的PreferredNetworkType

 public void dial(String number) {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                telephony.dial(number);        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#dial", e);        }    }
public void call(String callingPackage, String number) {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                telephony.call(callingPackage, number);        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#call", e);        }    }
实现拨号

public boolean endCall() {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                return telephony.endCall();        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#endCall", e);        }        return false;    }
实现挂断电话

public void answerRingingCall() {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                telephony.answerRingingCall();        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#answerRingingCall", e);        }    }
实现接听通话

public void silenceRinger() {        try {            getTelecomService().silenceRinger(getOpPackageName());        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelecomService#silenceRinger", e);        }    }
实现来电静音

public boolean enableDataConnectivity() {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                return telephony.enableDataConnectivity();        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#enableDataConnectivity", e);        }        return false;    }
实现打开数据链接

public boolean disableDataConnectivity() {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                return telephony.disableDataConnectivity();        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#disableDataConnectivity", e);        }        return false;    }
实现关闭数据链接

public boolean isDataConnectivityPossible() {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                return telephony.isDataConnectivityPossible();        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#isDataConnectivityPossible", e);        }        return false;    }
判断数据链接使用可用

public void setDataEnabled(boolean enable) {        setDataEnabled(SubscriptionManager.getDefaultDataSubId(), enable);    }
打开数据连接

public boolean getDataEnabled() {        return getDataEnabled(SubscriptionManager.getDefaultDataSubId());    }
获取数据链接是否打开状态

public void enableVideoCalling(boolean enable) {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                telephony.enableVideoCalling(enable);        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#enableVideoCalling", e);        }    }
开启视频通话

public boolean isVideoCallingEnabled() {        try {            ITelephony telephony = getITelephony();            if (telephony != null)                return telephony.isVideoCallingEnabled(getOpPackageName());        } catch (RemoteException e) {            Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e);        }        return false;    }
视频通话是否开启










0 0
原创粉丝点击