Android7.0 数据拨号前的准备工作

背景
在介绍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

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值