由于Android几乎所有的代码都是公开的,如果要对Framework层分析就必需先拿到Framework层的代码,我在前面已经搭建好了ubuntu14.04的环境,下载好了Android4.0的源码,其中也包括了Framework层和Package的代码,导出到宿主机Windows XP中用Source Insight 3.5工具来查看源码,Package中的代码可以导入到Eclipse下查看,我是把frameworks\base整个目录都导入到Source Insight 3.5工程中,可以选择我们需要的目录导入,如frameworks\base\media\tests\contents\media_api目录下有很多音、视频文件,可以只导入frameworks\base\core、frameworks\base\telephony、frameworks\base\services、frameworks\base\include等目录。需要代码的可以到这下载:http://pan.baidu.com/s/1i3KczeX在PhoneApp初始化时,有以下代码
@Override
public void onCreate() {
//...........
if (phone == null) {
// 初始化phone frameworks层
PhoneFactory.makeDefaultPhones(this);
// 获取默认的phone对象
phone = PhoneFactory.getDefaultPhone();
mCM = CallManager.getInstance();
mCM.registerPhone(phone);
//.............
}
//...............
}
在应用层的PhoneApp中调用PhoneFactory的静态方法makeDefaultPhones创建一个默认的Phone对象,而framework中采用的是代理模式和工厂模式实现,在makedefaultPhone中
//***** Class Methods
public static void makeDefaultPhones(Context context) {
makeDefaultPhone(context);
}
/**
* FIXME replace this with some other way of making these
* instances
*/
public static void makeDefaultPhone(Context context) {
synchronized(Phone.class) {
if (!sMadeDefaults) {
sLooper = Looper.myLooper();
sContext = context;
if (sLooper == null) {
throw new RuntimeException(
"PhoneFactory.makeDefaultPhone must be called from Looper thread");
}
int retryCount = 0;
for(;;) {
boolean hasException = false;
retryCount ++;
try {
// use UNIX domain socket to
// prevent subsequent initialization
new LocalServerSocket("com.android.internal.telephony");
} catch (java.io.IOException ex) {
hasException = true;
}
if ( !hasException ) {
break;
} else if (retryCount > SOCKET_OPEN_MAX_RETRY) {
throw new RuntimeException("PhoneFactory probably already running");
} else {
try {
Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
} catch (InterruptedException er) {
}
}
}
sPhoneNotifier = new DefaultPhoneNotifier();
// Get preferred network mode
int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
preferredNetworkMode = Phone.NT_MODE_GLOBAL;
}
int networkMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode);
Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
// Get cdmaSubscription
// TODO: Change when the ril will provides a way to know at runtime
// the configuration, bug 4202572. And the ril issues the
// RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, bug 4295439.
int cdmaSubscription;
int lteOnCdma = BaseCommands.getLteOnCdmaModeStatic();
switch (lteOnCdma) {
case Phone.LTE_ON_CDMA_FALSE:
cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_NV;
Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV");
break;
case Phone.LTE_ON_CDMA_TRUE:
cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_RUIM;
Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM");
break;
case Phone.LTE_ON_CDMA_UNKNOWN:
default:
//Get cdmaSubscription mode from Settings.System
cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION,
preferredCdmaSubscription);