首先在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)