安卓电话补充业务 SS
1. 一些概念知识
补充业务(Supplementary service)简称SS,包括呼叫等待、呼叫转移、呼叫限制、三方通话、USSD等,补充业务可以在VoLTE网络中使用,也可以在3G网络中使用。
XCAP协议(XML Configuration Access Protocol,XML配置访问协议):是一种应用层协议,它允许一个客户端来读,写,修改和删除应用程序配置数据存储在服务器上的XML格式。XCAP映射XML文件子树和元素属性到HTTP URIs,使这些组件可以直接使用HTTP协议的客户端访问。
具体应用:在很多通信应用程序中,如VoIP,IM和presence,需要网络服务器去获取个性化用户信息给服务请求的进程。这些个性化用户信息存在于网络中,但由终端用户自己管理。这些管理可通过各种获取终端完成,包括web,无线手机,或pc应用程序。个性化用户信息的例子包括presence,授权策略和presence lists。
详细可以查看
UT:3GPP中规定的IMS UE 与VoLTE AS之间的接口,双方使用XCAP协议来交互。
VoLTE AS:VoLTE Application Server,VoLTE应用服务器,提供各种VoLTE业务。
USSD:(Unstructured Supplementary Service Data)即非结构化补充数据业务,是一种新型基于GSM网络的交互式数据业务。 当你使用手机键盘输入一些网络已预先制定的数字或者符号比如*#等,再按send也就是拨号键就可以向网络发送一条指令,网络根据你的指令选择你需要的服务提供给你。
呼叫等待(Call Waiting):当用户电话正在通话,遇第三用户呼入时,可保留一方,与另一方通话的功能。当接到新的入呼叫时收到提醒,从而避免漏接重要人士的来电。
如具有此功能的甲用户与乙用户正在通话,如遇两用户呼入时,甲、乙两用户耳机中会听到“等待音”,丙用户可听到“回铃音”,此时甲用户可以有以下三种选择:①拒绝丙用户呼入,此时不需任何操作,过一定时间后丙与甲的接续中断,“等待音”消失,“回铃音”转为“忙音”;②保留原通话用户乙,改与呼入用户丙通话,并能轮流与乙、丙用户通话;③结束与乙用户通话,改与用户通话
呼叫限制(Call Barring):呼叫限制是在不同的条件下,判断是否允许用户进行出呼叫,以及是否允许用户接入一个呼叫的过程。客户可以灵活地控制手机的服务权限,防止被人误打、盗打电话,特别是国际长途电话,以避免不必要的经济损失。呼叫限制是指您可按一定条件设定密码,限制电话打入及手机打出的业务。如:1.BAOC(Barring of All Outgoing Calls,限制所有的出呼叫)设置此项功能后,该移动电话只能接听来话呼叫,而不能拨打电话。2.BOIC(Barring of Outgoing International Calls,限制所有的国际出呼叫)签约此业务的情况下,用户将不能呼出任何国际号码,可以发短信和接收短信。3. 限制除归属PLMN外的国际出呼叫(Barring of Outgoing International calls except those directed to the Home PLMN country)漫游分为国内漫游和国际漫游。
呼叫转移(Call Fowarding):呼叫转移是指您的电话无法接听或您不愿接电话,可以将来电转移到其它电话号码上。分为:1、无条件转移;2、遇忙转移;3、无应答转移;4、不可及(无信号或关机)转移
固定拨号(Fixed Dialing Number):
固定拨号(Fixed Dialing Number, FDN) 这个功能是为了在手机借给第三方的时候防止非授权使用的。即A用户把手机借给B用户,只限定B用户拨打A用户指定的号码,非指定的号码不能拨出,这个功能同时也适用于在集体条件下(比如放在集体宿舍充电)防止别人使用,而且不耽误来话,但是经过使用发现,SIM中的存储固定号码的空间太小了,普通的32K SIM卡只能存一个电话号码,动感地带32K SIM卡只能存两个号码,64K 大容量SIM卡也只能存两个。当启动固定拨号的时候,SIM卡电话簿被禁止访问,同时在电话簿里出现“FDN电话簿”,FDN里显示你设定的固定拨号的号码。这时,你无法拨出FDN以外的电话号码。
在启用(取消)这个功能和添加(更改、删除)FDN号码的时候需要用到PIN2
2. IMS 补充业务流程
UE发起IMS补充业务过程为,
- UE 向DNS网关查询xcap服务器的地址;
- UE向DNS 网关查询bsf 服务器的地址;
- UE在BSF服务器的引导下完成GBA认证;
- UE向NAF发起业务认证;
- UE查询、设置补充业务。
GBA两次认证
GBA架构流程包括两个步骤。第一步是UE的BSF引导认证,第二步是UE补充业务访问的认证。类似于第一步完成鉴权,获得密钥、BTID,第二步是业务执行过程中的二次认证,看UE是否合法、是否在有效生命周期内。
UE 与 BSF 完成引导认证流程
- UE 向BSF 发起HTTP请求(不带AUTH),携带MPI (用户标识);
- BSF 向HSS 请求用户认证向量五元组(RAND/AUTN/XRES/CK/IK);
- HSS 返回用户认证向量组给BSF;
- BSF 向UE 发送401 认证请求,携带RAND/AUTN;
- UE通过AUTN 计算得到RES和Ks;
- UE 发送HTTP请求给BSF ,携带RES;
- BSF 计算RES 和Ks,与UE发过来的RES 对比;
- 计算B-TID,BSF 向UE发送HTTP 200 OK,携带btid和lifetime。
PS:B-TID是本次引导认证成功后产生的标识,用于此次会话中后续与BSF交互。
UE 与 AP/NAF 完成业务访问流程
- UE通过 Ks 派生出业务访问标识 Ks_NAF ,向NAF 发起业务访问请求,携带B-TID(http get/put);
- NAF 向 BSF 发起认证请求,携带B-TID;
- BSF 认证通过,则返回prof、有效周期等给NAF;
- NAF 处理补充业务请求,然后向UE 发送应答(http 200ok)。
UT整体流程
wireshark抓包中的UT 过程
下图是一次补充业务查询和设置的http过程:
Ut接口参数
3. 安卓中ss的核心代码
补充业务(Supplementary Service) MMI Code的核心代码都在frameworks/opt/telephony仓库下的GsmMmiCode.java文件中。
// See TS 22.030 6.5.2 "Structure of the MMI"static Pattern sPatternSuppService = Pattern.compile("((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
/* 1 2 3 4 5 6 7 8 9 10 11 121 = Full string up to and including #2 = action (activation/interrogation/registration/erasure)3 = service code5 = SIA7 = SIB9 = SIC10 = dialing number
*/
首先,使用"(\\*|#|\\*#|\\*\\*|##)",匹配以"*" "#" "*#" "**" 或 "##" 开头的字符串(其中,"\"为转义字符,"|"代表"或")。
第二步,使用"(\\d{2,3})",匹配一个2位或者3位的数字(其中,"\d"用来匹配数字,{2,3}表示最少匹配2次,至多匹配3次)。
第三步,使用(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#,匹配最多连续四组以*开头,其余部分为除了*或#以外的字符串。这一部分的结尾匹配一个"#"。
这里有一点儿不太容易看明白,但其实,可以观察到,这里其实是由好几个"\\*([^*#]*)"嵌套在一起组成的,拆分来说明一下:
"\\*",不用多说,用来匹配一个"*"字符。
([^*#]*),其中前半部分的"[^*#]"用来匹配除了*或#以外的任意单个字符;最后面的"*"表示,对前面的[^*#]匹配零次或多次。
由此,我们可知,当"[^*#]"匹配了3次时,"\\*([^*#]*)"匹配到的字符串诸如"*XYZ";而当且仅当"[^*#]"匹配零次时,"\\*([^*#]*)"匹配到的字符串为"*"。
而每一组后面的"?",则表示,前面的匹配可以出现零次或一次。
第四步,使用(.*),匹配一个除了"\r\n"外,任意长度的字符串(字符串长度可以为0)。
按照3GPP协议,正则表达式所匹配出来的每一部分,都有一个名字,我们来按照名字来写一下:
**SERVICE_CODE*SIA*SIB*SIC*PWD_CONFIRM#DIALING_NUMBER
其中,最前面的部分叫做ACTION,为了体现出格式,我们用"**"表示(也可以是"*" "#" "*#" 或 "##"中的任意一种)。
而上面我们第三步中所讲的,即这里的"*SIA*SIB*SIC*PWD_CONFIRM#",我们也说了,后面的"?"表示,他们可以出现零次或一次,所以,其实这里可以是如下的任意一种形式:
- *SIA*SIB*SIC*PWD_CONFIRM#
- *SIA*SIB*SIC#
- *SIA*SIB**PWD_CONFIRM#
- *SIA**SIC*PWD_CONFIRM#
- **SIB*SIC*PWD_CONFIRM#
- *SIA*SIB#
- *SIA**SIC#
- **SIB*SIC#
- ***SIC*PWD_CONFIRM#
- **SIB**PWD_CONFIRM#
- *SIA***PWD_CONFIRM#
- *SIA#
- **SIB#
- ***SIC#
- ****PWD_CONFIRM#
之所以这样设计,是因为,并不是所有的MMI Code中都会同时使用到SIA、SIB、SIC和PWD_CONFIRM这四个值,有可能只需要其中的一个或者两个。
关于正则表达式的匹配,我们就说到这里,这里确实比较乱,如果对正则表达式不是特别熟悉,可以先去看看最基本的正则表达式规则(注意: Java中的正则表达式与其他地方用的正则表达式略有不同,学习的时候不要混淆),而后在纸上或者Notepad中将正则表达式分成一小块一小块来进行解析,慢慢阅读其含义。
好,那么我们回到主题,如何使用MMI Code来设置/取消/查询呼叫转移呢?
首先我们查看代码中的一些定义:
// From TS 22.030 6.5.2
static final String ACTION_ACTIVATE = "*"; // 激活呼叫转移业务
static final String ACTION_DEACTIVATE = "#"; // 去激活呼叫转移业务
static final String ACTION_INTERROGATE = "*#"; // 查询呼叫转移
static final String ACTION_REGISTER = "**"; // 注册呼叫转移
static final String ACTION_ERASURE = "##"; // 取消呼叫转移// Call Forwarding
static final String SC_CFU = "21"; // 无条件转移
static final String SC_CFB = "67"; // 遇忙转移
static final String SC_CFNRy = "61"; // 不可及转移
static final String SC_CFNR = "62"; // 无应答转移static final String SC_CF_All = "002"; // 所有呼叫转移
static final String SC_CF_All_Conditional = "004"; // 所有条件呼叫转移(不包含无条件转移)
我们一般在使用电话设置的UI向运营商注册呼叫转移时,所使用的是ACTION_REGISTER,即"**";取消时所使用的是ACTION_ERASURE,即"##";而查询时,则是ACTION_INTERROGATE,即"*#"。
我们查看GsmMmiCode.java中processCode()方法对CF的处理:
1. 匹配到的ServiceCode:"**"代表注册呼叫转移,"##"代表取消呼叫转移,"*#"代表查询呼叫转移
2. 匹配到的SIA:要转移给哪个号码
3. 匹配到的SIB:对哪个ServiceClass设置呼叫转移
4. 匹配到的SIC:在何种情况下进行呼叫转移(即无条件转移、遇忙转移等)
/** Process a MMI code or short code...anything that isn't a dialing number */
public void
processCode() throws CallStateException {try {......// 使用匹配到的Service Code,判断是否为上面所列出的呼叫转移相关的值} else if (isServiceCodeCallForwarding(mSc)) {Rlog.d(LOG_TAG, "processCode: is CF");// 匹配到的SIA,是要转移给哪一个号码String dialingNumber = mSia;// 匹配到的SIB,是ServiceClassint serviceClass = siToServiceClass(mSib);// 匹配到的SIC,为何种情况下进行转移(即无条件转移、遇忙转移等)int reason = scToCallForwardReason(mSc);int time = siToTime(mSic);if (isInterrogate()) {mPhone.mCi.queryCallForwardStatus(reason, serviceClass, dialingNumber,obtainMessage(EVENT_QUERY_CF_COMPLETE, this));} else {int cfAction;if (isActivate()) {// 3GPP TS 22.030 6.5.2// a call forwarding request with a single * would be// interpreted as registration if containing a forwarded-to// number, or an activation if notif (isEmptyOrNull(dialingNumber)) {cfAction = CommandsInterface.CF_ACTION_ENABLE;mIsCallFwdReg = false;} else {cfAction = CommandsInterface.CF_ACTION_REGISTRATION;mIsCallFwdReg = true;}} else if (isDeactivate()) {cfAction = CommandsInterface.CF_ACTION_DISABLE;} else if (isRegister()) {cfAction = CommandsInterface.CF_ACTION_REGISTRATION;} else if (isErasure()) {cfAction = CommandsInterface.CF_ACTION_ERASURE;} else {throw new RuntimeException ("invalid action");}int isEnableDesired =((cfAction == CommandsInterface.CF_ACTION_ENABLE) ||(cfAction == CommandsInterface.CF_ACTION_REGISTRATION)) ? 1 : 0;Rlog.d(LOG_TAG, "processCode: is CF setCallForward");mPhone.mCi.setCallForward(cfAction, reason, serviceClass,dialingNumber, time, obtainMessage(EVENT_SET_CFF_COMPLETE,isVoiceUnconditionalForwarding(reason, serviceClass) ? 1 : 0,isEnableDesired, this));}}......} catch (RuntimeException exc) {mState = State.FAILED;mMessage = mContext.getText(com.android.internal.R.string.mmiError);Rlog.d(LOG_TAG, "processCode: RuntimeException=" + exc);mPhone.onMMIDone(this);}
}
我们在电话设置的UI中,是无法指定serviceClass的,只能使用默认的SERVICE_CLASS_VOICE。但是,我们可以在这里通过SIB选择不同的serviceClass。在上述问题中,由于用户的Sim卡设置了SERVICE_CLASS_DATA_SYNC下的无条件呼叫转移,所以,根据以下代码,我们可以在MMI Code中,设置SIB的值为24(注意,SIB的值与CommandsInterface.java中定义的serviceClass的值并不一致),从而取消该呼叫转移的设置。
private static int
siToServiceClass(String si) {if (si == null || si.length() == 0) {return SERVICE_CLASS_NONE;} else {// NumberFormatException should cause MMI failint serviceCode = Integer.parseInt(si, 10);switch (serviceCode) {......case 24: return SERVICE_CLASS_DATA_SYNC;......default:throw new RuntimeException("unsupported MMI service code " + si);}}
}
参考博客
安卓电话补充业务 SS相关推荐
- 安卓电话和网络开发全解:电话硬件检测、电话服务信息、sim信息、网络服务信息、数据连接和数据传输信息、电话状态监听
全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓电话和网络开发全解,包括电话硬件检测.电话服务信息.sim信息.网络服务信息.数据连接和数据传输信息.通过phone state listener ...
- 安卓电话交互桥梁 Telecom【System进程】
1. Telecom所处位置 由下图,Telecom的作用是起到交互桥梁,与IncallUI 和 Telephony[Phone进程.TeleService]交互 路径 统称 进程 packages/ ...
- 微软从安卓那里获取的盈利比重WinPhone 7还多
为什么80%的码农都做不了架构师?>>> Microsoft Earns More from Android than Windows Phone 7 微软从安卓那里获取的盈利比重W ...
- 安卓开发大全、系列文章、精品教程
全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓Intent的Action中的常值变量:窗口action常量(android.intent.action.+xxx),广播action常量(and ...
- 李彦宏清华经管学院演讲:11年创业心路历程与人生感悟
李彦宏清华经管学院演讲:11年创业心路历程与人生感悟 浏览次数: 425次 2011年10月22日 腾讯科技 字号: 大 中 小 分享到: QQ空间 新浪微博 腾讯微博 人人网 豆瓣网 开心网 更多 ...
- wi-fi测试软件正确吗,几款Wi-Fi信号测试小工具
原标题:几款Wi-Fi信号测试小工具 今天就为大家介绍几种测试WiFi信号强度方法,有了它们的帮助,还愁没有好WiFi吗? 方法一:小白都会用的Wi-Fi信号强度测量法 无论是智能手机,还是PAD,抑 ...
- 我的asterisk 接入电信ims之旅【把电信座机提取到手机上,实现手机不插卡也用打电话】
第一步.配置光猫. 注意事项:登录光猫用超级管理员的账号密码,光猫后面的那个是普通用户的,创建不了网络连接. 1.进入光猫提取voip[就是座机的配置信息] 上图的主服务器地址.主用端口.outbou ...
- android wear 中文键盘,不用 鼠标和键盘用AndroidWear手表控制PC
[导读]最新版本的Unified Remote(远程遥控器)增加了对Android Wear的支持,让你能够从手表上操纵PC的鼠标光标,同时能够通过语音命令控制具体应用程序及网站. 如果你连鼠标和键盘 ...
- 手表控android+wear,鼠标和键盘都不用 用Android Wear手表控制PC
智东西(公众号:zhidxcom) 文|大禾 如果你连鼠标和键盘都懒得碰,现在有了新的方法,你可以通过Android Wear智能手表控制你的PC. 最新版本的Unified Remote(远程遥控器 ...
最新文章
- 业余时间用哪里,哪里就有发展的可能
- android 导入开源项目代码常见问题
- Ubuntu 下最简明的翻译词典(调用GoogleAPI,运行在终端)
- Spring Cache抽象-缓存注解
- LSQL Developer连接Oracle11g 64位数据库配置详解
- StringBuilder详解
- python生成requirements.txt的两种方法
- Angular 6+ 之新版service
- 思考:日期类型的数据应该用什么样的具体形式存储到数据库?
- java 执行查询_在单个语句中用Java执行多个查询
- pcfg 自然语言处理_自然语言处理:原理简明教程09-句法分析,语义分析和篇章分析...
- android 车牌输入键盘
- centos 搭建 SVN
- 【ARM】嵌入式 ARM Linux 下移植 USB 蓝牙、交叉编译 bluez 各种版本
- Sql查询某个字段是否包含小写字母或小写
- JAVA中Object类中的equal方法
- 共阴极和共阳极数码管显示的十六进制代码
- 超级推荐:网工必备模拟器PNETLab,附下载链接,全球第一篇最优质的帖子
- 费曼 计算机科学 讲义,《费曼物理讲义》3 物理学与其他科学的关系
- Python字典操作大全