背景
在介绍PhoneApp的创建过程时,我们知道为了支持双卡手机,PhoneFactory创建了两个Phone对象。
然而由于通信制式、功耗等的限制,目前底层的芯片厂商规定modem工作于DSDS模式下,于是同一时间内只有一个Phone具有上网的能力。
本文旨在揭示激活Phone拨号能力的过程,即讲述数据拨号前的准备工作。
版本
android 7.0
1 TelephonyProvider的启动
数据业务在建立之前,必须有可用的APN,因此我们首先看看Android 7.0中APN加载的过程。
之前分析PhoneApp启动过程时,我们知道PhoneApp的onCreate函数是靠ActivityThread.java中的handleBindApplication函数调用的。
private void handleBindApplication(AppBindData data) {
........
try {
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
//加载App中的provider
installContentProviders(app, data.providers);
...........
}
}
try {
mInstrumentation.onCreate(data.instrumentationArgs);
} catch (Exception e) {
.........
}
try {
//调用App的onCreate函数
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
..............
}
} finally {
.............
}
}
从上面的代码,我们知道在PhoneApp的onCreate被调用前,先加载了PhoneApp中的ContentProvider(PM解析xml得到这种包含关系)。
private void installContentProviders(Context context, List<ProviderInfo> providers) {
........
for (ProviderInfo cpi : providers) {
..........
//依次安装provider
IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
............
}
try {
//发布provider
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
从TelephonyProvider的AndroidManifest.xml,我们知道TelephonyProvider就是运行在Phone进程中的,因此结合上面的代码,可以得出结论:
TelephonyProvider将在PhoneApp的onCreate被调用前被加载。
Android7.0 TelephonyProvider启动后的过程,与Android6.0中一致。
之前的blog分析Android6.0中APN加载过程时,已经做过描述了,其实就是创建数据库、解析xml文件并存入数据库的过程,此处不再赘述。
2 设定具有拨号能力的Phone
我们回忆一下PhoneApp启动后,利用PhoneFactory的makeDefaultPhone创建对象的代码,其中:
.........
//创建了一个PhoneSwitcher
sPhoneSwitcher = new PhoneSwitcher(MAX_ACTIVE_PHONES, numPhones,
sContext, sc, Looper.myLooper(), tr, sCommandsInterfaces,
sPhones);
.........
sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];
for (int i = 0; i < numPhones; i++) {
//创建了两个TelephonyNetworkFactory,分别与每个Phone关联起来
sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
sPhoneSwitcher, sc, sSubscriptionMonitor, Looper.myLooper(),
sContext, i, sPhones[i].mDcTracker);
}
在刚开机时,不插卡的情况下,上面代码提及的PhoneSwitcher和TelephonyNetworkFactory将决定具有拨号能力的Phone。
我们在这里先分析不插卡情况下的流程,主要原因是:
框架对卡信息有记录,将会根据记录信息改变具有拨号能力的Phone。这个过程是通过调用Phone进程提供的接口完成的,我们以后再做分析。
2.1 PhoneSwitcher
我们先来看看PhoneSwitcher:
//PhoneSwitcher继承自Handler
public class PhoneSwitcher extends Handler {
......
public PhoneSwitcher(......) {
........
//创建NetworkCapabilities,为创建NetworkFactory作准备
//NetworkCapabilities决定了NetworkFactory可以处理的Network Request种类
NetworkCapabilities netCap = new NetworkCapabilities();
netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
netCap.setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
//创建了一个NetworkFactory对象
NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
netCap, this);
//每个NetworkFactory仅能处理分数比自己低的NetworkRequest
//这里设置分数为101,将能够处理所有的request
networkFactory.setScoreFilter(101);
//注册该NetworkFactory对象
networkFactory.register();
}
}
上面的代码涉及到了很多内容,以后有机会再分析,此时我们仅需要有一个映像就是:
PhoneSwitcher创建了一个能够处理所有Network Request的NetworkFactory(实际上是子类),并调用了register方法。
我们来看看NetworkFactory的register方法:
//NetworkFactory继承Handler
public class NetworkFactory extends Handler {
........
public void register() {
if (DBG) log("Registering NetworkFactory");
if (mMessenger == null) {
//构造Messenger对象,其中包含Handler
mMessenger = new Messenger(this);
//调用ConnectivityManager的registerNetworkFactory方法
ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
}
}
..........
}
继续跟进ConnectivityManager中的函数:
public static ConnectivityManager from(Context context) {
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
public void registerNetworkFactory(Messenger messenger, String name) {
try {
//可以看到将调用用mService的registerNetworkFactory函数
mService.registerNetworkFactory(messenger, name);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
mService的类型为IConnectivityManager,其实是ConnectivityService的Binder通信的服务端代理,因此上述代码最终将调用到ConnectivityService的registerNetworkFactory函数。
ConnectivityService是开机时,由SystemServer加载的,这里我们不分析ConnectivityService启动的过程,以后有机会单独介绍ConnectivityService。这里我们只需要知道ConnectivityService主要负责管理Android中的各种网络。
我们看看ConnectivityService的registerNetworkFactory函数:
@Override
public void registerNetworkFactory(Messenger messenger, String name) {
//权限检查
enforceConnectivityInternalPermission();
//构造NetworkFactoryInfo, 该变量用于在ConnectivityService中代表注册的NetworkFactory
//注意Messager中,包含注册NetworkFactory内部的Handler
NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
//发送消息给给内部的Handler处理,将并行的接口调用变为串行的消息处理
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
}
ConnectivityService内部的handler将调用handleRegisterNetworkFactory处理EVENT_REGISTER_NETWORK_FACTORY消息:
............
case EVENT_REGISTER_NETWORK_FACTORY: {
handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
break;
}
...........
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
//以键值对的方式,存储NetworkFactory的messenger和对应的NetworkFactoryInfo
mNetworkFactoryInfos.put(nfi.messenger, nfi);
//调用AsyncChannel的connect方法,将ConnectivityService的TrackerHandler与NetworkFactory的Messenger联系起来
nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
}
我们看看AsyncChannel的connect方法:
//此处传递的srcHandler是ConnectivityService的mTrackerHandler
//dstMessenger为NetworkFactory内部的Messenger
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connect srcHandler to the dstMessenger E");
// We are connected
connected(srcContext, srcHandler, dstMessenger);
// Tell source we are half connected
replyHalfConnected(STATUS_SUCCESSFUL);
if (DBG) log("connect srcHandler to the dstMessenger X");
}
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connected srcHandler to the dstMessenger E");
// Initialize source fields
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(mSrcHandler);
// Initialize destination fields
mDstMessenger = dstMessenger;
//监听目的端断开
linkToDeathMonitor();
if (DBG) log("connected srcHandler to the dstMessenger X");
}
看到connnected函数,我们知道每个NetworkFactory注册后,ConnectivityService将维护对应的NetworkFactoryInfo,对应的键值为NetworkFactory中的Messenger对象。
每个NetworkFactoryInfo中有一个AsyncChannel对象,该对象的源端Messenger包裹着Connectivit