数据业务建立流程之APN参数的激活_apn激活信令-程序员宅基地

技术标签: 数据连接  

APN参数在前面《 数据业务建立流程之常规APN参数的创建》一文中已经都被创建完毕并存入mAllApnSettings的数组中,但是这些APN参数默认都是没有被Enable的, 只有当APN被Enable之后,该APN才可以被使用,下面我们就来看如何将一个APN参数激活。
        APN的Enable是通过TelephonyNetworkFactory中的needNetworkFor()方法触发的,我们在《 网络连接评分机制之NetworkFactory》文章中介绍过,当当前网络的评分比其他网络高时,就会通过needNetworkFor()方法触发当前网络的建立。比如当前WIFI断开时,如果发现数据网络是打开的,此时就会通过该方法激活数据流量,从而实现从WIFI到数据的转换过程。
        而当needNetworkFor()被触发时,就会引发APN的Enable过程:
  1. protected void needNetworkFor(NetworkRequest networkRequest, int score) {  
  2.     //根据网络需求寻找合适APN  
  3.     ApnContext apnContext = apnContextForNetworkRequest(networkRequest);  
  4.     //Enable上网用的APN  
  5.     if (apnContext != null) apnContext.incRefCount();  
  6. }  
        由于不同网络需求可能需要不同的APN参数,因此先要经过apnContextForNetworkRequest()来寻找合适的APN,对于上网来说,其寻找到的APN类型为TYPE_MOBILE,然后通过incRefCount()来Enable当前的APN:
  1. @ApnContext.java  
  2. public void incRefCount() {  
  3.     synchronized (mRefCountLock) {  
  4.         if (mRefCount++ == 0) {  
  5.             //设置Enable  
  6.             mDcTracker.setEnabled(mDcTracker.apnTypeToId(mApnType), true);  
  7.         }  
  8.     }  
  9. }  
        这里需要用到DcTracker父类DcTrackerBase中的setEnabled()方法来将APN打开:
  1. @DcTrackerBase.java  
  2. protected void setEnabled(int id, boolean enable) {  
  3.     Message msg = obtainMessage(DctConstants.EVENT_ENABLE_NEW_APN);  
  4.     msg.arg1 = id;  
  5.     msg.arg2 = (enable ? DctConstants.ENABLED : DctConstants.DISABLED);  
  6.     sendMessage(msg);  
  7. }  
        这里发送了一条EVENT_ENABLE_NEW_APN的消息,该消息将会在DcTrackerBase中handleMessage()中被处理:
  1. @DcTrackerBase.java  
  2. public void handleMessage(Message msg) {  
  3.     switch (msg.what) {  
  4.         case DctConstants.EVENT_ENABLE_NEW_APN:  
  5.             onEnableApn(msg.arg1, msg.arg2);  
  6.             break;  
  7.     }  
  8. }  
        这里的onEnableApn()在子类DcTracker中被覆盖:
  1. @DcTracker.java  
  2. protected void onEnableApn(int apnId, int enabled) {  
  3.     ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));  
  4.     if (apnContext == null) {  
  5.         loge("onEnableApn(" + apnId + ", " + enabled + "): NO ApnContext");  
  6.         return;  
  7.     }  
  8.     //打开APN  
  9.     applyNewState(apnContext, enabled == DctConstants.ENABLED, apnContext.getDependencyMet());  
  10. }  
        继续看applyNewState()过程,这里传递的第二个参数为true,第二个参数是从networkAttributes数组中读取的,默认都为true。
  1. private void applyNewState(ApnContext apnContext, boolean enabled, boolean met) {  
  2.     boolean cleanup = false;  
  3.     boolean trySetup = false;  
  4.     if (apnContext.isReady()) {  
  5.         //APN如果已经被Enable  
  6.     } else {  
  7.         if (enabled && met) {  
  8.             //APN需要被Enable  
  9.             if (apnContext.isEnabled()) {  
  10.                 apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_MET);  
  11.             } else {  
  12.                 //设置reason为REASON_DATA_ENABLED  
  13.                 apnContext.setReason(Phone.REASON_DATA_ENABLED);  
  14.             }  
  15.             if (apnContext.getState() == DctConstants.State.FAILED) {  
  16.                 apnContext.setState(DctConstants.State.IDLE);  
  17.             }  
  18.             trySetup = true;  
  19.         }  
  20.     }  
  21.     //Enable当前APN  
  22.     apnContext.setEnabled(enabled);  
  23.     //设置其mDependencyMet属性也为true  
  24.     apnContext.setDependencyMet(met);  
  25.     //清除当前连接  
  26.     if (cleanup) cleanUpConnection(true, apnContext);  
  27.     //建立数据连接  
  28.     if (trySetup) trySetupData(apnContext);  
  29. }  
        由于enabled、met两个参数此时都为true,因此将会设置APN的Reason为REASON_DATA_ENABLED,并且其mDataEnabled和mDependencyMet属性都为true:
  1. public void setEnabled(boolean enabled) {  
  2.     mDataEnabled.set(enabled);  
  3. }  
  4. public void setDependencyMet(boolean met) {  
  5.     mDependencyMet.set(met);  
  6. }  
        再来看一下该APN参数isReady的判断:
  1. public boolean isReady() {  
  2.     return mDataEnabled.get() && mDependencyMet.get();  
  3. }  
        由此可知,以后当判断该APN是否isReady()时,将会得到true的状态,也就是说,当前APN已经准备就绪。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014386544/article/details/52594508

智能推荐

VirtualBox在CentOS中安装VBOXADDITIONS_centos virtualbox addition-程序员宅基地

文章浏览阅读588次。VirtualBox在CentOS中安装VBOXADDITIONS_centos virtualbox addition

s3c2416 U-Boot移植笔记-程序员宅基地

文章浏览阅读4.1k次。首先说,今天是一个值得高兴的日子,因为经过四天的努力,终于把U-Boot1.3.4成功移植到了s3c2416上.板子要求是SD卡启动,以下具体的移植步聚:一、SD起动首先要修改/include/configs/smdk2416.h头文件: 在365行左右,按如下修改: //#define CONFIG_BOOT_NAND #define CONFIG_BOOT_M_s3c2416 u-boot移植

java线程池的四种拒绝策略_rejectedpolicy-程序员宅基地

文章浏览阅读5.3k次,点赞12次,收藏24次。本文主要介绍了java juc包中提供的四种拒绝策略。先是接受了部分java线程池ThreadPoolExecutor的构造方法,然后以源码和程序示例的方式介绍了四种拒绝策AbortPolicy,CallerRunsPolicy,DiscardPolicy,DiscardOldestPolicy的不同。_rejectedpolicy

相机相关知识学习笔记_照相机基础知识笔记-程序员宅基地

文章浏览阅读231次。留空,要学_照相机基础知识笔记

InputStream读取数据问题_event check_return:"java.io.inputstream.read(byte[-程序员宅基地

文章浏览阅读3.8k次。1. 关于InputStream.read() 在从数据流里读取数据时,为图简单,经常用InputStream.read()方法。这个方法是从流里每次只读取读取一个字节,效率会非常低。 更好的方法是用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,一次读取多个字节。2._event check_return:"java.io.inputstream.read(byte[])" returns the number of

Ubuntu 14.04 更换阿里云源_ubuntu14.04更换阿里云-程序员宅基地

文章浏览阅读2.8k次。Ubuntu 14.04 更换阿里云源查看Ubuntu信息:root@llf-virtual-machine:/etc/apt# lsb_release -aNo LSB modules are available.Distributor ID: UbuntuDescription: Ubuntu 14.04.5 LTSRelease: 14.04Codena..._ubuntu14.04更换阿里云

随便推点

Solr是如何工作的?_solr 是如何工作的-程序员宅基地

文章浏览阅读45次。solr是基于Lucence开发的企业级搜索引擎技术,而lucence的原理是倒排索引。倒排索引:Demo1:A在吃饭Demo2:B在睡觉记录就变成了这样关键词 段落号(出现频率) 出现位置吃饭 1(1) 3在 1(1) 22(1) 2A 1(1) 1睡觉 2(1_solr 是如何工作的

Linux 学习路线图_linux学习路径-程序员宅基地

文章浏览阅读2.4w次,点赞60次,收藏551次。1.应用场景更加高效地学习并达到运用Linux 2.学习/操作 linux运维学习需要分为四个阶段:初级入门、中级进阶、高级提升、资深方向细化。 第一阶段:初级入门 初级阶段需要把linux学习路线搞清楚,任何学习都是循序渐进的,所以学linux也是需要有一定的路线。 初级入门: Linux基础知识、基本命令(起源、组成、常用命令如cp、ls、fi..._linux学习路径

kafka在zookeeper中对应目录_kafka在zookeeper上的目录-程序员宅基地

文章浏览阅读1.4k次。Zookeeper DirectoriesThe following gives the zookeeper structures and algorithms used for co-ordination between consumers and brokers.NotationWhen an element in a path is denoted [xyz], that m_kafka在zookeeper上的目录

Exchange 常见问题(转自微软论坛)_微软exchanger批量修改邮箱密码-程序员宅基地

文章浏览阅读4.7k次。来自望兄的总结。这些文档都是最基础的了。如果你有类似的不清楚的问题,这里都是比较权威的回答了。1.什么是邮件中继? 邮件中继是指将邮件转发到你所在域以外的域的能力。更具体地说,当使用与您的 SMTP 服务器的入站连接来向外部域发送电子邮件时,便发生了中继。 2.在Exchange 2003中,如何知道哪些SMTP域是你的权威域?打开Exchange Se_微软exchanger批量修改邮箱密码

vue3.0中setup如何使用_vue3 setup函数 可以用在配置项组件内吗-程序员宅基地

文章浏览阅读745次。组件中所有用到的:数据、方法、计算属性、监视属性、生命周期钩子都可以配置在setup中_vue3 setup函数 可以用在配置项组件内吗

C语言---单链表(详解)---数据结构_单链表c语言-程序员宅基地

文章浏览阅读3.1k次,点赞5次,收藏43次。单链表所需要的头文件重命名类型的意义在于以后还需要用到单链表时,存入的类型不一定时int类型,需要更改类型时,要一个个更改,非常麻烦,我们可以直接在这里修改,更加方便(这里的解释我上一篇也有提到)单链表用到的结构体这里我们把结构体重命名为ST单链表需要实现的功能有 1.申请一个新节点的内存空间 2.单链表的头部,尾部的插入和删除 3.单链表的查找 4.单链表查找后的插入和删除 5.单链表的打印 6.单链表的释放1.单链表的节点申请内存空间申请内存空间并不是直接使用,._单链表c语言

推荐文章

热门文章

相关标签