佛山做网站的/百度如何注册公司网站
一、参数说明
(一)APN配置结构对比
平台 | Android | KaiOS |
---|---|---|
文件类型 | xml | json |
结构 | 每个<apn>标签是一条APN,包含完成的信息 | 层级数组结构,使用JSON格式的数据。最外层是mcc,其次mnc,最后APN用数组形式配置(每个APN都是一个对象,不含mccmnc属性)。 |
Android: apns-conf.xml
<!-- Android: apns-conf.xml -->
<?xml version="1.0" encoding="utf-8"?>
<apns version="8"><apn carrier="T-Mobile US" mcc="001" mnc="01" apn="fast.t-mobile.com" user="" password="" server="" proxy="" port="" mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" mmsproxy="" mmsport="" type="default,mms,supl,hipri,xcap,rcs" protocol="IPV6" roaming_protocol="IP" bearer_bitmask="" mvno_type="ecid" mvno_match_data="[4]4310260" class="" user_visible="true" user_editable="true" authtype="0"/>
</apns>
KaiOS: apns.json
特别需要注意格式(很容易出错),数组最后不用加逗号,注意大/中括号的首位一致性。
{
"202": {"10": [{"carrier":"Wind Internet","apn":"gint.b-online.gr","type":["default","supl"]},{"voicemail":"122","type":["operatorvariant"]},{"carrier":"Wind MMS","apn":"mnet.b-online.gr","mmsc":"http://192.168.200.95/servlets/mms","mmsproxy":"192.168.200.11","mmsport":"9401","type":["mms"]}],"01": [{"carrier":"Cosmote Wireless Internet","apn":"","type":["ia"]},{"voicemail":"123","type":["operatorvariant"]},{"carrier":"Cosmote Wireless Internet","apn":"internet","type":["default","supl"]},{"carrier":"Cosmote Mms","apn":"mms","mmsc":"http://mmsc.cosmote.gr:8002","mmsproxy":"10.10.10.20","mmsport":"8080","type":["mms"]}],"09": [{"carrier":"Q Internet","apn":"myq","type":["default","supl"]},{"voicemail":"122","type":["operatorvariant"]},{"carrier":"Q-Telecom MMS GPRS","apn":"q-mms.myq.gr","mmsc":"http://mms.myq.gr","mmsproxy":"192.168.80.134","mmsport":"8080","type":["mms"]}]
},
"001": {"01": [{"carrier":"Testing SIM default","apn":"test","type":["default"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true"},{"carrier":"IMS","apn":"ims","type":["ims"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true"},{"carrier":"XCAP","apn":"xcap","type":["xcap"],"protocol":"IPV4V6","roaming_protocol":"IPV4V6","user_visible":"true","authtype":"0"}]
}
}
(二)bearer配置值对比
- 1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20 (The original bearer value in Android,位运算)
- 1048575(The original bearer value in KaiOS using decimalism)
二、代码解析
(一)Android
待完善
(二)KaiOS
- DataCallManager.jsm
- apn_editor_const.js
1、bitmask的进制转换
可以参考PDN建立逻辑,gecko/dom/system/gonk/radio/DataCallManager.jsm
//DataCallManager.jsm//检查对应的rat是否包含在此APN bearer 配置中
// Check rat value include in the bit map or not.
function bitmaskHasTech(aBearerBitmask, aRadioTech) {if (aBearerBitmask == 0) {return true;} else if (aRadioTech > 0) {return (aBearerBitmask & (1 << (aRadioTech - 1))) != 0;}return false;
}//bearer十进制转成二进制
// Show the detail rat type.
function bitmaskToString(aBearerBitmask) {if (aBearerBitmask == 0 || aBearerBitmask === undefined) {return 0;}let val = "";for (let i = 1; i < RIL.GECKO_RADIO_TECH.length; i++) {if ((aBearerBitmask & (1 << (i - 1))) != 0) {val = val.concat(i + "|");}}return val;
}function bearerBitmapHasCdma(aBearerBitmask) {return (RIL_RADIO_CDMA_TECHNOLOGY_BITMASK & aBearerBitmask) != 0;
}
在bitmaskToString接口中,将bitmask转化成String时,循环RIL.GECKO_RADIO_TECH的长度次,经过位运算转换成与Android原始配置的bearer_bitmask相同格式的bearer位符,用“|”间隔rat类型位。
是如何通过RIL调用ril_consts.js内的GECKO_RADIO_TECH?
在DataCallManager.jsm 中定义RIL对象,并使用XPCOMUtils.defineLazyGetter()方法来实现懒加载,即在要使用时才加载和初始化对象(只有在第一次访问该对象时才会进行初始化和加载),避免不必要的性能开销和资源浪费。
RIL对象是通过ChromeUtils.import 方法从ril_consts.js文件中导入的,该对象由ril_consts.js文件中的代码创建和初始化的。
//DataCallManaer.jsm"use strict";//XPCOM 是一个用于 实现跨语言组件的技术框架。
//导入XPCOMUtils对象(工具库),简化和封装XPCOM组件的开发和使用。
//使用常量const来定义 XPCOMUtils 对象,以确保在运行时不会发生对象被重新赋值的情况。
const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"
);//定义RIL对象,后续调用 RIL.GECKO_RADIO_TECH
XPCOMUtils.defineLazyGetter(this, "RIL", function() {return ChromeUtils.import("resource://gre/modules/ril_consts.js");
});//ref RIL.GECKO_RADIO_TECH
const TCP_BUFFER_SIZES = [null,"4092,8760,48000,4096,8760,48000", // gprs"4093,26280,70800,4096,16384,70800", // edge"58254,349525,1048576,58254,349525,1048576", // umts"16384,32768,131072,4096,16384,102400", // is95a = 1xrtt"16384,32768,131072,4096,16384,102400", // is95b = 1xrtt"16384,32768,131072,4096,16384,102400", // 1xrtt"4094,87380,262144,4096,16384,262144", // evdo0"4094,87380,262144,4096,16384,262144", // evdoa"61167,367002,1101005,8738,52429,262114", // hsdpa"40778,244668,734003,16777,100663,301990", // hsupa = hspa"40778,244668,734003,16777,100663,301990", // hspa"4094,87380,262144,4096,16384,262144", // evdob"131072,262144,1048576,4096,16384,524288", // ehrpd"524288,1048576,2097152,262144,524288,1048576", // lte"122334,734003,2202010,32040,192239,576717", // hspa+"4096,87380,110208,4096,16384,110208", // gsm (using default value)"4096,87380,110208,4096,16384,110208", // tdscdma (using default value)"122334,734003,2202010,32040,192239,576717", // iwlan"122334,734003,2202010,32040,192239,576717", // ca
];//定义了一个常量RIL_RADIO_CDMA_TECHNOLOGY_BITMASK,用于表示CDMA射频技术类型的掩码值。
//RIL.GECKO_RADIO_TECH.indexOf 查找各个CDMA技术类型在GECKO_RADIO_TECH数组中的下标值,
//-1 的目的是得到对应的掩码位数,并将此转换成掩码值,
//使用按位左移(<<)运算符得到掩码值,
//各个掩码值按位或(|)操作得到最终的掩码值。
const RIL_RADIO_CDMA_TECHNOLOGY_BITMASK =(1 << (RIL.GECKO_RADIO_TECH.indexOf("is95a") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("is95b") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("1xrtt") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("evdo0") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("evdoa") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("evdob") - 1)) |(1 << (RIL.GECKO_RADIO_TECH.indexOf("ehrpd") - 1));// set to true in ril_consts.js to see debug messages
var DEBUG = RIL_DEBUG.DEBUG_RIL; //调试用的log打印标识符
如上代码,CDMA技术类型对应的掩码值RIL_RADIO_CDMA_TECHNO如下:
is95a: 1 << (5-1) = 0x10
is95b: 1 << (6-1) = 0x20
1xrtt: 1 << (7-1) = 0x40
evdo0: 1 << (8-1) = 0x80
evdoa: 1 << (9-1) = 0x100
evdob: 1 << (14-1) = 0x2000
ehrpd: 1 << (15-1) = 0x4000
2、GECKO_RADIO_TECH 定义网络制式 (ril_consts.js)
在KaiOS中,RIL.GECKO_RADIO_TECH数组是在Gecko内核的代码中定义的,其实现位于Gecko代码库的"gecko/dom/system/gonk/radio/ril_consts.js"文件中。该文件定义了一系列RIL层的常量,包括射频技术类型、消息ID等。在该文件中,可以找到以下代码片段,其中定义了RIL.GECKO_RADIO_TECH数组的元素和顺序:
//GECKO_RADIO_TECH 数组定义射频技术(网络连接)
this.GECKO_RADIO_TECH = [null,"gprs", //1 GPRS"edge", //2 EDGE"umts", //3 UMTS"is95a", //4 IS-95A"is95b", //5 IS-95B"1xrtt", //6 cdma1x?一种CDMA2000射频技术,是CDMAOne技术的升级版(1x Radio Transmission Technology)"evdo0", //7 EVDO-0"evdoa", //8 EVDO-A"hsdpa", //9"hsupa", //10"hspa", //11"evdob", //12 EVDO-B"ehrpd", //13 EVDO-D"lte", //14 LTE"hspa+", //15 HSPA+"gsm", //16 GSM"tdscdma", //17 TD-SCDMA"iwlan", //18 iWLAN(wifi)"lte_ca", //19 LTE_CA
];//定义遵循的协议类型
this.GECKO_PROFILE_INFO_TYPE_COMMON = 0;
this.GECKO_PROFILE_INFO_TYPE_3GPP = 1;
this.GECKO_PROFILE_INFO_TYPE_3GPP2 = 2;
3、DataCall 对 rat 的使用案例
dataRegistrationChanged(aRadioTech) {let targetBearer;if (this.apnSetting.bearer === undefined) {targetBearer = 0;} else {targetBearer = this.apnSetting.bearer;}if (DEBUG) {this.debug("dataRegistrationChanged: targetBearer: " +bitmaskToString(targetBearer));}if (bitmaskHasTech(targetBearer, aRadioTech)) {// Ignore same rat type. Let handler process the retry.} else {if (DEBUG) {this.debug("dataRegistrationChanged: current APN do not support this rat reset DC. APN:" +JSON.stringify(this.apnSetting));// Clean the requestedNetworkInterfaces due to current DC can not support this rat under DC retrying state.// Let handler process the retry.let targetRequestedNetworkInterfaces = this.requestedNetworkInterfaces.slice();for (let networkInterface of targetRequestedNetworkInterfaces) {this.disconnect(networkInterface);}}},
gecko/koost/telephony/TelephonyBinderService.h
// Cover the GECKO_RADIO_TECH to NETWORK_TYPE_*
int32_t convertRadioTech(const nsAString& rat);
4、apn_editor_const.js 原始数据和 UI显示转换
KaiOS 基线提供了VALUE_CONVERTERS 常量对象,包含两个属性:TO_STRING和TO_DATA,每个属性包含了转换方法。
- TO_STRING:将一个字符串数组转换成一个用逗号分隔的字符串
- apn_editor.js 界面显示用
- TO_DATA :将一个用逗号分隔的字符串转换为一个字符串数组
- apn_editor_session.js 保存数据库用
源码如下,可参考APN Type显示的内容,对数组进行显示和配置数据存储。
/*** The apn editor const*/define([],() => {const APN_PROPERTY_DEFAULTS = {//省略大部分原生属性apn: '',types: ['default'],roaming_protocol: 'notDefined',//自定义mvno_type: 'notDefined',mvno_match_data: '',bearer:['unspecified']};const APN_PROPERTIES = Object.keys(APN_PROPERTY_DEFAULTS);//数据转换工具接口const VALUE_CONVERTERS = {TO_STRING: { //TO_STRING属性types(types) {//判断 types参数存在、是一个数组、且数组非空,就将字符串数组转换成用逗号分隔的字符串// types :参数是否存在// Array.isArray(types):是否为一个数组// types.length:数组是否非空if (types && Array.isArray(types) && types.length) {return types.join(', ');}return 'default'; //默认返回“default”}},TO_DATA: { //TO_DATA属性types(string) {//将用逗号分隔的字符串转换为字符串数组return string.split(',').map(str => str.trim());}}};//在apn_editor.js中定义了常量调用方法,APN_PROPERTIES、APN_PROPERTY_DEFAULTS、VALUE_CONVERTERSreturn { //一个对象,三个只读get属性?外部访问但不能修改他们的值?get APN_PROPERTIES() {return APN_PROPERTIES;},get APN_PROPERTY_DEFAULTS() {return APN_PROPERTY_DEFAULTS;},get VALUE_CONVERTERS() {return VALUE_CONVERTERS;}};
});
(1)测试代码
对以上接口VALUE_CONVERTERS的测试代码和解析,输出案例 :
const types = ['gprs', 'edge', 'umts'];
const str = VALUE_CONVERTERS.TO_STRING.types(types);
console.log(str); // 输出 'gprs, edge, umts'const str = 'gprs, edge, umts';
const types = VALUE_CONVERTERS.TO_DATA.types(str);
console.log(types); // 输出 ['gprs', 'edge', 'umts']
(2)apn_editor.js 调用TO_STRING 界面显示
外部模块调用源码实现
/*** The apn editor module*/
'use strict';
define(function(require) { //eslint-disable-lineconst ApnEditorConst = require('panels/apn_editor/apn_editor_const');const ApnEditorSession = require('panels/apn_editor/apn_editor_session');//引用apn_editor_const.js 定义常量const { APN_PROPERTIES } = ApnEditorConst;const { APN_PROPERTY_DEFAULTS } = ApnEditorConst;const { VALUE_CONVERTERS } = ApnEditorConst;ApnEditor.prototype = {convertValue(value, converter) {if (converter) {return converter(value);}return value;},fillInputElements(inputElements, apn) {APN_PROPERTIES.forEach(function input(name) {const inputElement = inputElements[name];if (inputElement) {//数据处理,调用VALUE_CONVERTERS 转成字符串inputElement.value = this.convertValue(value,VALUE_CONVERTERS.TO_STRING[name]);} //if inputElement}, this);},});
(3)apn_editor_session.js 保存信息到APN数据库
在commit 中保存APN到,通过apn manager执行addApn或 updateApn
/*** The apn editor session module*/
define(['require','modules/apn/apn_settings_manager','panels/apn_editor/apn_editor_const','modules/apn/apn_utils'],function(require) { //eslint-disable-lineconst ApnSettingsManager = require('modules/apn/apn_settings_manager');const ApnEditorConst = require('panels/apn_editor/apn_editor_const');const ApnUtils = require('modules/apn/apn_utils');const { APN_PROPERTIES } = ApnEditorConst;const { VALUE_CONVERTERS } = ApnEditorConst;function ApnEditorSession(obj, inputElements, apnItem) {this.serviceId = obj.serviceId;this.apnMode = obj.mode;this.inputElements = inputElements;this.apnItem = apnItem;}ApnEditorSession.prototype = {convertValue(value, converter) {if (converter) {return converter(value);}return value;},exportApnSetting(inputElements) {const newApnSetting = {};APN_PROPERTIES.forEach(function input(name) {const inputElement = inputElements[name];if (inputElement && !inputElement.hidden) {newApnSetting[name.toLowerCase()] = this.convertValue(inputElement.value,VALUE_CONVERTERS.TO_DATA[name]);}}, this);return newApnSetting;},//保存新增APN数据,调用addApncommitNew() {const promises = [];const newApnSetting = this.exportApnSetting(this.inputElements);promises.push(ApnSettingsManager.addApn(this.serviceId, newApnSetting));return Promise.all(promises);},//保存编辑APN数据,调用updateApncommitEdit() {const promises = [];const newApnSetting = this.exportApnSetting(this.inputElements);promises.push(ApnSettingsManager.updateApn(this.serviceId,this.apnItem.id, newApnSetting));return Promise.all(promises);},//在apn_editor.js中传递 new/edit选择执行新增/编辑APNcommit() {switch (this.apnMode) {case 'new':return this.commitNew();case 'edit':return this.commitEdit();default:console.error('invalid mode');return Promise.resolve();}},//取消,不保存任何数据cancel() {APN_PROPERTIES.forEach(function input(name) {this.inputElements[name].value = '';}, this);this.apnItem = null;},//还没找到mode的用法get mode() {return this.apnMode;}};return function apnEditorSession(obj, inputElements, apnItem) {return new ApnEditorSession(obj, inputElements, apnItem);};
});
三、日志分析
追溯在PDN建立过程中,读取apn配置的bearer参数到DataCall使用的radio类型的bearer值变化情况。
四、方案开发
相关介绍:KaiOS 新增APN信息字段的代码实现-CSDN博客
在 APN Editor中实现bearer显示
代码模块:gaia/apps/settings/js/panels/apn_editor/apn_editor.js
/*** The apn editor module*/
'use strict';
define(function(require) { //eslint-disable-lineconst ApnEditorConst = require('panels/apn_editor_tct/apn_editor_const');const ApnEditorSession = require('panels/apn_editor_tct/apn_editor_session');const ApnUtils = require('modules/apn_tct/apn_utils');//以下三个常量都是从ApnEditorConst模块中导入的const { APN_PROPERTIES } = ApnEditorConst;const { APN_PROPERTY_DEFAULTS } = ApnEditorConst;const { VALUE_CONVERTERS } = ApnEditorConst;return function apnEditor(rootElement) {return new ApnEditor(rootElement);};
});
(一)KaiOS
1、十进制bearer -> bitmask位码 & networkType字符
将kaios中十进制的bearer转换同Android原始配置的bitmask及映射网络类型字符串
// 功能:将十进制bearer转换成1-20字符串(同Android)
function bitmaskToString(aBearerBitmask) {if (aBearerBitmask == 0 || aBearerBitmask === undefined) {return 0;}let val = "";for (let i = 1; i < 20; i++) {if ((aBearerBitmask & (1 << (i - 1))) != 0) {val = val.concat(i + "|");}}return val;
}//常量数组,定义rat。
//最后一个数据到底要不要逗号?源码有,参考代码可以不用 —— 兼容性问题,新的会支持 ,
const GECKO_RADIO_TECH = [null,"gprs","edge","umts","is95a","is95b","1xrtt","evdo0","evdoa","hsdpa","hsupa","hspa","evdob","ehrpd","lte","hspa+","gsm","tdscdma","iwlan","lte_ca",
];//将1-20的bitmask转换成对应的网络制式
function bitmaskToRatString(aBitmask) {if (aBitmask == 0 || aBitmask === undefined) {return "unspecified";}let rat = "";let splitResult = aBitmask.split("|");console.log('splitResult = '+ splitResult);rat = splitResult.map(x => GECKO_RADIO_TECH[x]).join(",").slice(0,-1);//slice(startIndex,endIndex) 用于去掉最后一个逗号return rat;
}// 测试代码
let apnBearer = '312312'; //apn.json原始配置值
let targetBearer; //1-20转换目标值
let bearerString = '';if (apnBearer === undefined) {targetBearer = 0;
} else {targetBearer = apnBearer;
}bearerString = bitmaskToString(targetBearer);
let ratString = bitmaskToRatString(bearerString);// 输出结果
console.log('targetBearer = ' + targetBearer);
console.log('bearerString = '+ bearerString);
console.log('ratString = ' + ratString);
存在一个问题 ,在UI显示了rat的字符串,那么 commitEdit() 的时候会保存bearer为字符串,应该需要在apn_editor_session.js 中处理ApnSettings内容。
难点在于如何将gprs,edge,is95b,1xrtt 转换成bearer数值 ( bitmask=1|2|5|6 甚至是 十进制原文)
2、networktype字符 -> bitmask 位码
convertNetworkTypeToBitmask,将networktype字符串转换成bitmask(1|18|20格式)
//映射表,包含了不同的网络类型和对应的数字码。
const networkTypeMap = {"unspecified": "0","gprs": "1","edge": "2","umts": "3","is95a": "4","is95b": "5","1xrtt": "6","evdo0": "7","evdoa": "8","hsdpa": "9","hsupa": "10","hspa": "11","evdob": "12","ehrpd": "13","lte": "14","hspa+": "15","gsm": "16","tdscdma": "17","iwlan": "18","lte_ca": "19"
};//测试代码
//一、简单程序
let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"; //界面显示字符串包含多个网络类型,使用逗号分隔
let networkTypes = bearerString.split(","); //string转换成字符串数组
let bitCode = Array.from(networkTypes, bearerString => networkTypeMap[bearerString]); //将字符串数组转换成数字码数组
let bitmask = bitCode.join("|");console.log("networkTypes = " + networkTypes);
console.log("bitCode = " + bitCode);//二、改善,封装成接口调用
//参数类型:字符串 "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"
//let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+";
function convertNetworkTypeToBitmask(aNetworkTypes) {let bitmask = '0'; //初始化为0和"0"的区别?if (aNetworkTypes == 0 || aNetworkTypes === undefined) {return 0;}//networkTypesArray是一个字符串数组,存储着多个网络类型的字符串,例如 ['gprs', 'edge']let networkTypesArray = aNetworkTypes.split(","); //字符串转成字符串数组//networkTypesBitCode是一个数字码数组,如[ '1', '2', '3' ]//映射函数对每个字符串进行转换,函数参数是每个字符串,它在映射表中对应的值就是所需bit位数字码//映射函数的代码为 aNetworkTypes => networkTypeMap[aNetworkTypes]let networkTypesBitCode = Array.from(networkTypesArray, aNetworkTypes => networkTypeMap[aNetworkTypes]); //字符串数组转换成功数字码 bitmask = networkTypesBitCode.join("|");return bitmask;
}console.log("bitmask(api) = " + convertNetworkTypeToBitmask(bearerString));
//如果传参是数组,就更简单的封装接口了
//接受一个包含网络类型的数组作为参数,并将这个数组中的每种网络类型转换为对应的数字码,
//返回一个由数字码组成的字符串,使用"|"符号分隔,即bitmask//通过map()方法遍历这个数组,将每种网络类型转换为对应的数字码,存在codes数组
//通过join()方法将codes数字码连接成字符串 ,用“|”符号分隔。function convertNetworkTypes(networkTypes) {const codes = networkTypes.map(type => networkTypeMap[type]);return codes.join("|");
}const types = ["gprs", "edge", "is95b", "1xrtt"];
const codeString = convertNetworkTypes(types); // "1|2|5|6"
3、networktype字符 -> 十进制bearer
用如下bitcode数组能便于转换成 bitmask位码和十进制,不能直接通过bitmask转换成十进制,即bitmask 位码 -> 十进制bearer
bitcode = 1,2,3,9,10,11,14,15
const NETWORK_TYPE_MAP = {"unspecified": "0","gprs": "1","edge": "2","umts": "3","is95a": "4","is95b": "5","1xrtt": "6","evdo0": "7","evdoa": "8","hsdpa": "9","hsupa": "10","hspa": "11","evdob": "12","ehrpd": "13","lte": "14","hspa+": "15","gsm": "16","tdscdma": "17","iwlan": "18","lte_ca": "19"
};//参数类型:字符串 "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"
//let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+";
function convertNetworkTypeToBitCode(aNetworkTypes) {console.log("convertBitcodeToBearer: aNetworkTypes = " + aNetworkTypes);let bitcode = '0';if (aNetworkTypes == 0 || aNetworkTypes === undefined) {return 0;}let networkTypesArray = aNetworkTypes.split(","); //字符串转成字符串数组bitcode = Array.from(networkTypesArray, aNetworkTypes => NETWORK_TYPE_MAP[aNetworkTypes]); // console.log("convertNetworkTypeToBitCode: bitcode = " + bitcode);return bitcode;
}function convertBitCodeToBitmask(aBitCode) {let bitmask = aBitCode.join("|");console.log("convertBitCodeToBitmask: bitmask = " + bitmask);return bitmask;
}function convertBitcodeToBearer(aBitCode) {let bearerDec = 0;let bearerBin =0;if (aBitCode == 0 || aBitCode === undefined) {return 0;}//parseInt((code).toString(2)) 是将数字 code转成二进制字符串bearerBin = aBitCode.map(code => parseInt(code).toString(2)).join(""); //转成二进制console.log("convertBitcodeToBearer: bearerBin = " + bearerBin);bearerDec = parseInt(bearerBin,2);//将二进制转换成十进制 。console.log("convertBitcodeToBearer: bearerDec = " + bearerDec);return bearerDec;
}let bearerString = "gprs,edge,umts,hsdpa,hsupa,hspa,lte,hspa+"; //界面显示字符串包含多个网络类型,使用逗号分隔convertBitCodeToBitmask(convertNetworkTypeToBitCode(bearerString));
convertBitcodeToBearer(convertNetworkTypeToBitCode(bearerString));
bearerBin 存在问题,在bitcode 转成20位二进制数的时候,输出的bearerBin 不正确
优化以上代码:
function convertNetworkTypeToBearer(aNetworkTypes) {dump('apn_editor_session: StringToBearer aNetworkTypes = ' + aNetworkTypes);if (aNetworkTypes == 0 || aNetworkTypes === undefined) {return 0;}let bitcode = '0';let bearerBin = "";let bearer = 0;let networkTypesArray = aNetworkTypes.split(",");bitcode = Array.from(networkTypesArray, aNetworkTypes => NETWORK_TYPE_MAP[aNetworkTypes]); //bitcode array like [18,14]bitcode = bitcode.sort(function(a, b) {return a - b;});dump('apn_editor_session: StringToBearer bitcode = ' + bitcode);let bearerArray = new Array(20).fill(0);for (let i = 0; i < bitcode.length; i++) {bearerArray[bitcode[i]-1] = 1;dump('apn_editor: StringToBearer bitcode[i] = ' + bitcode[i]);}dump('apn_editor_session: StringToBearer bearerArray = ' + bearerArray);bearerBin = bearerArray.reverse().join("");bearer = parseInt(bearerBin,2);dump('apn_editor_session: StringToBearer bearer = ' + bearer);return bearer;}
相关文章:

【笔记】【开发方案】APN 配置参数 bitmask 数据转换(Android KaiOS)
一、参数说明 (一)APN配置结构对比 平台AndroidKaiOS文件类型xmljson结构每个<apn>标签是一条APN,包含完成的信息层级数组结构,使用JSON格式的数据。最外层是mcc,其次mnc,最后APN用数组形式配置&am…...

Redis篇之缓存雪崩、击穿、穿透详解
学习材料:https://xiaolincoding.com/redis/cluster/cache_problem.html 缓存雪崩 什么是缓存雪崩 在面对业务量较大的查询场景时,会把数据库中的数据缓存至redis中,避免大量的读写请求同时访问mysql客户端导致系统崩溃。这种情况下&#x…...

【深度学习笔记】3_2线性回归的从零实现
注:本文为《动手学深度学习》开源内容,仅为个人学习记录,无抄袭搬运意图 3.2 线性回归的从零开始实现 在了解了线性回归的背景知识之后,现在我们可以动手实现它了。尽管强大的深度学习框架可以减少大量重复性工作,但若…...

Apache Maven简介
Maven 简介 Apache Maven 是一个用于项目构建、依赖管理和项目信息管理的强大工具。它基于项目对象模型(Project Object Model,POM)进行构建,通过描述项目的结构和依赖关系来管理项目的构建过程。 以下是 Apache Maven 的一些关键原理和工作流程: 项目对象模型(POM)…...
#12解决request中getReader()和getInputStream()只能调用一次的问题
目录 1、背景 2、解决方案 2.1、自定义HttpServletRequestWrapper 2.2、JsonRequestHeaderParamsHelper 2.3、HttpServletRequestReplacedFilter 2.4、使用 1、背景 当前系统Content-Type为application/json,参数接收方式采用RequestBody和RequestParam&#…...

直接插入排序+希尔排序+冒泡排序+快速排序+选择排序+堆排序+归并排序+基于统计的排序
插入排序:直接插入排序、希尔排序 交换排序:冒泡排序、快速排序 选择排序:简单选择排序、堆排序 其他:归并排序、基于统计的排序 一、直接插入排序 #include<stdio.h> #include<stdlib.h> /* 直接插入排序&#…...

Java高级 / 架构师 场景方案 面试题(二)
1.双十一亿级用户日活统计如何用 Redis快速计算 在双十一这种亿级用户日活统计的场景中,使用Redis进行快速计算的关键在于利用Redis的数据结构和原子操作来高效地统计和计算数据。以下是一个基于Redis的日活统计方案: 选择合适的数据结构: …...

C/C++内存管理学习【new】
文章目录 一、C/C内存分布二、C语言中动态内存管理方式:malloc/calloc/realloc/free三、C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型四、operator new与operator delete函数五、new和delete的实现原理5.1 内置类型 六、定位new表达式(pl…...

选择适合你的编程语言
引言 在当今瞬息万变的技术领域中,选择一门合适的编程语言对于个人职业发展和技术成长至关重要。每种语言都拥有独特的设计哲学、应用场景和市场需求,因此,在决定投入时间和精力去学习哪种编程语言时,我们需要综合分析多个因素&a…...

【力扣每日一题】力扣106从中序和后序遍历序列构造二叉树
题目来源 力扣106从中序和后序遍历序列构造二叉树 题目概述 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 思路分析 后序遍历序列的最末尾数…...

logback日志回滚原理
日志输出主要依赖RollingFileAppender、TimeBasedRollingPolicy、SizeAndTimeBasedFNATP。 RollingFileAppender 主要用于生成日志文件,格式化内容再输出到日志文件TimeBasedRollingPolicy 设置回滚策略,如果发现日志输出的时间超过单位时间,…...

[C#]winform基于opencvsharp结合pairlie算法实现低光图像增强黑暗图片变亮变清晰
【低光图像增强介绍】 在图像处理领域,低光图像增强是一个具有挑战性的任务。由于光线不足,这些图像往往呈现出低对比度、高噪声和细节丢失等问题,严重影响了图像的视觉效果和后续分析的准确性。因此,开发有效的低光图像增强方法…...

React18源码: reconcliler启动过程
Reconcliler启动过程 Reconcliler启动过程实际就是React的启动过程位于react-dom包,衔接reconciler运作流程中的输入步骤.在调用入口函数之前,reactElement(<App/>) 和 DOM对象 div#root 之间没有关联,用图片表示如下: 在启…...

【RN】为项目使用React Navigation中的navigator
简言 移动应用基本不会只由一个页面组成。管理多个页面的呈现、跳转的组件就是我们通常所说的导航器(navigator)。 React Navigation 提供了简单易用的跨平台导航方案,在 iOS 和 Android 上都可以进行翻页式、tab 选项卡式和抽屉式的导航布局…...

CS50x 2024 - Lecture 8 - HTML, CSS, JavaScript
00:00:00 - Introduction 关于互联网是怎么工作的,如何在他的基础上构建软件 HTML和CSS是描述性语言 javascript一种编程语言,在浏览器上下文中很有用,使得界面更具交互性,也用于服务器 00:01:01 - Bingo Board 00:01:51 - T…...

C++:派生类的生成过程(构造、析构)
目录 派生类的生成过程 派生类的构造函数与析构函数: 构造函数: 派生类组合类的构造和析构: 构造函数和析构函数调用顺序: 派生类的生成过程 三步骤: 吸收基类(父类)成员:实现代…...

金蝶字段添加过滤条件
金蝶字段加过滤条件 F_PLDE_Date<GetValue(FDate) and F_PLDE_Date1>GetValue(FDate)...

SQLite 知识整理
写在前面: 本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。 目录 SQLite 类型数据…...

0基础JAVA期末复习最终版
啊啊啊啊啊啊啊啊啊啊,根据网上各位大佬的复习资料,看了很多大多讲的是基础但对内容的整体把握上缺乏系统了解。但是很不幸最终挂科了,那个出题套路属实把我整神了,所以我决定痛改前非,酣畅淋漓的写下这篇文章。。。。…...

【办公类-16-07-04】合并版“2023下学期 中班户外游戏(有场地和无场地版,一周一次)”(python 排班表系列)
背景需求: 把 无场地版(贴周计划用) 和 有场地版(贴教室墙壁上用) 组合在一起,一个代码生成两套。 【办公类-16-07-02】“2023下学期 周计划-户外游戏 每班1周五天相同场地,6周一次循环”&…...

chat GPT第一讲
计算机的语言奇迹:探秘ChatGPT的智能回答和写作能力 目前我们这个行业,最火的话题无疑是AI人工智能,类似ChatGPT这样的智能Ai,今天剩下的时间不多,每天一个主题,我给大家讲一下计算机回答问题和写作的能力,…...

JAVA工程师面试专题-Mysql篇
一、基础 1、mysql可以使用多少列创建索引? 16 2、mysql常用的存储引擎有哪些 存储引擎Storage engine:MySQL中的数据、索引以及其他对象是如何存储的,是一套文件系统的实现。常用的存储引擎有以下: Innodb引擎:In…...

vue中使用echarts绘制双Y轴图表时,刻度没有对齐的两种解决方法
文章目录 1、原因2、思路3、解决方法3.1、使用alignTicks解决3.2、结合min和max属性去配置interval属性1、首先固定两边的分隔的段数。2、结合min和max属性去配置interval。 1、原因 刻度在显示时,分割段数不一样,导致左右的刻度线不一致,不…...

编程笔记 Golang基础 022 数组
编程笔记 Golang基础 022 数组 一、数组定义和初始化二、访问数组元素三、遍历数组四、数组作为参数六、特点七、注意事项 在Go语言中,数组是一种基本的数据结构,用于存储相同类型且长度固定的元素序列。 一、数组定义和初始化 // 声明并初始化一个整数…...

【kubernetes】二进制部署k8s集群之,多master节点负载均衡以及高可用(下)
↑↑↑↑接上一篇继续部署↑↑↑↑ 之前已经完成了单master节点的部署,现在需要完成多master节点以及实现k8s集群的高可用 一、完成master02节点的初始化操作 二、在master01节点基础上,完成master02节点部署 步骤一:准备好master节点所需…...

哈希表在Java中的使用和面试常见问题
当谈到哈希表在Java中的使用和面试常见问题时,以下是一些重要的点和常见问题: 哈希表在Java中的使用 HashMap 和 HashTable 的区别: HashMap 和 HashTable 都实现了 Map 接口,但它们有一些重要的区别: HashMap 是非线…...

LeetCode刷题小记 三、【哈希表】
1. 哈希表 文章目录 1. 哈希表写在前面1.1 理论基础1.2 有效的字母异位词1.3 两个数组的交集1.4 快乐数1.5 两数之和1.6 四数相加||1.7 赎金信1.8 三数之和(哈希法梦碎的地方)1.9 四数之和 Reference 写在前面 本系列笔记主要作为笔者刷题的题解&#x…...

Zookeeper选举Leader源码剖析
Zookeeper选举Leader源码剖析 leader选举流程 参数说明 myid: 节点的唯一标识,手动设置zxid: 当前节点中最大(新)的事务idepoch-logic-clock: 同一轮投票过程中的逻辑时钟值相同,每投完一次值会增加 leader选举流程 默认投票给自己,优先选择…...

Redis(十六)缓存预热+缓存雪崩+缓存击穿+缓存穿透
文章目录 面试题缓存预热缓存雪崩解决方案 缓存穿透解决方案 缓存击穿解决方案案例:高并发聚划算业务 总结表格 面试题 缓存预热、雪崩、穿透、击穿分别是什么?你遇到过那几个情况?缓存预热你是怎么做的?如何避免或者减少缓存雪崩?穿透和击穿有什么区别?他两是…...

[已解决]npm淘宝镜像最新官方指引(2023.08.31)
最新的配置淘宝镜像的淘宝官方提供的方法 npm config set registry https://registry.npmmirror.com原来的 registry.npm.taobao.org 已替换为 registry.npmmirror.com ,当点击 registry.npm.taobao.org 会默认跳转到 registry.npmmirror.com 如果你想将npm的下载…...