【笔记】KaiOS OTA APN 方案(OMADM)

这篇具有很好参考价值的文章主要介绍了【笔记】KaiOS OTA APN 方案(OMADM)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、【需求】功能逻辑

OMADM 机制根据节点信息修改对应的APN,因此代码也通过Node消息管控实现。

  1. _listenOpApnSettings
  2. opCheckIsInProgressAndSaveNodeValue
  3. saveAndUpdateApnValue
    1. this.operatorVariantHandlers[simslot.index].applySettings(mcc, mnc/*, false*/, apnEnabledStateChange)
  4. applySettings(mcc, mnc, updateAPN)
  5. applyOperatorVariantSettings(result)
  6. buildApnSettings(allApnList)
    1. 初始化APN数组 var apnSettings = [] 和tmpApnSettings
    2. 根据APN_TYPES.length长度遍历赋值tmpApnSettings,
    3. 再将数组拷贝给apnSettings 保存 apnSettings = this.convertApnSettings(tmpApnSettings); this.buildPreferredApnSettings(apnSettings);
  7. buildPreferredApnSettings(apnSettings) 
  8. navigator.b2g.engmodeManager.setDataProfileByType(JSON.stringify(apnSettings[index]), 1);

二、【设计】接口说明 

总体接口流程

Interface Module Comment
_listenOpApnSettings(simslot)  operator_variant_manager.js
opCheckIsInProgressAndSaveNodeValue(node, value, simslot) operator_variant_manager.js
saveAndUpdateApnValue(node, value, simslot) operator_variant_manager.js
applySettings(mcc, mnc, updateAPN) operator_variant_handler.js updateAPN是OMADM对应的APN class 类型
applyOperatorVariantSettings(result) operator_variant_handler.js
buildApnSettings(allApnList) operator_variant_handler.js
buildPreferredApnSettings(apnSettings) operator_variant_handler.js 此接口只会被调用一次,因此在manager里面循环传参updateAPN调用applySettings()执行卡的时候,不能下发全部类型的全部APN。(存疑)
setDataProfileByType EngmodeManager.jsm

Manager通过发消息触发服务执行:

1.Services.cpmm.sendAsyncMessage("Engmode:setDataProfileByType",

2.内部收到消息在receiveMessage(aMessage)匹配case 执行

case "Engmode:setDataProfileByType:Return":
    request = this.requestMsgHdl(msg);

3.

_setDataProfileByType EngmodeService.jsm

在 buildPreferredApnSettings定制的类型会触发dataprofile下发MD,在engmode中实现。

(一)System模块-运营商管理OperatorVariantHandler (gaia)

Manager中update创建OperatorVariantHelper,Handler start创建OperatorVariantHelper。

  • OperatorVariantHandler
    • 在operator_variant_manager.js创建,在operator_variant_handler.js实现自身功能逻辑。
    • OperatorVariantHandler 是一个管理运营商变体的对象,用于存储和处理与运营商变体相关的信息。
  • OperatorVariantHelper
    • 在OperatorVariantHandler  start 时new OperatorVariantHelper,创建对象并使用helper进行mccmnc的变化监听
    • this._operatorVariantHelper.listen();

代码路径

  • gaia/apps/system/js/operator_variant_handler.js 具体APN数据处理者
  • gaia/apps/system/js/operator_variant_manager.js 运营商初始化管理
  • gaia/apps/system/js/operator_variant_handler.js 处理加载和应用不同的运营商信息
operator_variant_manager.js 
Manager的代码结构说明
(function() {
  var OperatorVariantManager = function(core) {
    /** Array of OperatorVariantHandler objects. */
    if (core) {
      this.mobileConnections = core.mobileConnections;
    }
    this.operatorVariantHandlers = [];
  };

  OperatorVariantManager.IMPORTS = [
    'js/operator_variant_handler.js'
  ];

  //定义事件,在BaseModule监听到时执行对应逻辑
  OperatorVariantManager.EVENTS = [
    'simslot-updated',
    'simslot-iccinfochange',
    'logohidden'
  ];

  BaseModule.create(OperatorVariantManager, {});//具体功能实现
})();

1、在 KaiOS 的 JavaScript 中,BaseModule 是一个基础模块,用于封装应用程序中的通用功能,例如管理应用程序状态、处理事件、创建通用UI等。BaseModule.create() 是一个用于创建模块实例的静态方法,第一个参数为模块构造函数,第二个参数为模块的配置对象,用于指定模块的名称、版本、依赖关系等信息。

2、logohidden 是一个自定义的事件名称(在OperatorVariantManager.EVENTS定义),用于在 KaiOS 中指示系统已经完成启动过程并准备好显示应用程序。当系统启动时,会显示 KaiOS 的 Logo,一旦logohidden!=null,就会触发 logohidden 事件,表明系统已经启动完毕并准备好显示应用程序。

(1)在下面init代码片段中,注册 logohidden 事件的监听器,在事件触发时调用 updateSavedIccIds() 方法,该方法用于更新保存的 ICCID 列表。这个事件监听器只会在 logohidden 后执行一次,因为 { once: true } 参数指定了事件只会触发一次,确保 updateSavedIccIds() 方法不会被重复调用。

(2)_handle_logohidden 方法是一个事件监听器,它会在 logohidden 事件触发时被调用。在这个方法中,会遍历所有的移动连接对象,并检查是否有对应的 operatorVariantHandlers 对象。如果没有,就将该对象的值设置为 null。

- 正常日志参考:

01-17 10:47:30.019 690 690 I GeckoDump: operator_variant_manager gid =544d
01-17 10:47:30.019 690 690 I GeckoDump: operator_variant_manager simslot.index = 0
01-17 10:47:34.093 690 690 I GeckoDump: _handle_logohidden operatorVariantHandlers[0] : [object Object]

- 异常情况:(在下方案例根据代码详细说明)

01-17 10:44:05.244 712 712 I GeckoDump: operator_variant_manager gid  = null

01-17 10:44:05.245 712 712 I GeckoDump: operator_variant_manager persist gid =[object Promise]

01-17 10:44:49.532 712 712 I GeckoDump: _handle_logohidden  operatorVariantHandlers[0] set to value null // logohidden 发现未初始化,设为'null'

PIN解锁后,不再更新operatorVariantHandlers

01-17 10:44:54.232 712 712 I GeckoDump: operator_variant_manager gid =544d
01-17 10:44:54.232 712 712 I GeckoDump: operatorVariantHandlers[0] : null

  BaseModule.create(OperatorVariantManager, {
    name: 'OperatorVariantManager',
    _start: function() {},
    _stop: function() {},

    //监听到simslot-updated事件,会更新OperatorVariantHandler
    '_handle_simslot-updated': function(evt) {
        var simslot = evt.detail;
        this._updateOperatorVariantHandler(simslot);
    },

    //监听到logohidden事件。会影响APN的加载,如operatorVariantHandlers[index]被初始化成null。
    '_handle_logohidden': function() {
      navigator.b2g.mobileConnections.forEach((conn, index) => {
        if (!this.operatorVariantHandlers[index]) {
          //如果指定SIM 卡槽还没有准备好,就需要将对应的 operatorVariantHandlers 对象的值设置为 null
            dump('_handle_logohidden operatorVariantHandlers[' + index + '] set to value null ')
            this.operatorVariantHandlers[index] = 'null';
        }
      });
    },

    //监听到simslot-iccinfochange事件时执行。
    '_handle_simslot-iccinfochange': function(evt) {
      var simslot = evt.detail;
      this._updateOperatorVariantHandler(simslot);
    },

    //在SIM状态变化的时候会执行,如果存在客制化return了可能会导致operatorVariantHandlers=nnull因此出现APN加载中断问题。
    //【关键逻辑】this.operatorVariantHandlers[simslot.index]只会在这里赋值
    _updateOperatorVariantHandler: function(simslot) {
      if (!this._isVariantReady(simslot)) {
         return;
      }
      if (!this.operatorVariantHandlers[simslot.index]) {
        this.operatorVariantHandlers[simslot.index] =
          new OperatorVariantHandler(simslot.simCard.iccInfo.iccid,
            simslot.index, this);
        this.operatorVariantHandlers[simslot.index].start();
      }
    },

    //SIM卡槽状态
    _isVariantReady: function(simslot) {
        //sim不存在 || SIM没有iccInfo || SIM iccInfo没有iccid = SIM 没有ready
        if (!simslot.simCard ||
          !simslot.simCard.iccInfo ||
          !simslot.simCard.iccInfo.iccid) {
            if (this.operatorVariantHandlers[simslot.index]) {
                this.operatorVariantHandlers[simslot.index] = 'removed';
            } else {
                this.operatorVariantHandlers[simslot.index] = null;
            }
            return false;
        } else if (!this.deviceInfoOs) {
            return false;
        }
        return true;
    },

    updateSavedIccIds: function() {},

    //初始化,会调用_updateOperatorVariantHandler,并监听logohidden和拔卡
    //OperatorVariantManager 对象被创建时被调用,用于初始化该对象并注册必要的事件监听器
    init: function() {
      if (this.deviceInfoOs) {
        SettingsObserver.unobserve('deviceinfo.os', this.updateDeviceInfoOs);
        SIMSlotManager.getSlots().forEach(function(slot) {
          this._updateOperatorVariantHandler(slot);
        }, this);
      }

      window.addEventListener('logohidden', () => {
        this.updateSavedIccIds();
      }, { once: true });  //只执行一次

      window.addEventListener('simslot-removed', () => {
        this.updateSavedIccIds();
      });
    },


    updateDeviceInfoOs: function(value) {},

    nsureValueUnderKeyIsArray: function(key) {}
  });

正常逻辑:

  1. new OperatorVariantHandler =>
  2. OperatorVariantHandler start() =>
  3. 监听'cardstatechange' & 'iccinfochange' =>
  4. 收到以上事件且 cardstate 是 'ready' 时,匹配APN。
异常代码案例 

如果在 _updateOperatorVariantHandler 中添加GID等参数校验的时候考虑不全,实现代码时 return,则在插入有PIN码的卡时,可能会导致SIM卡相应index的operatorVariantHandlers一直为null,不会进行APN加载。

iccManager及其内gid判断代码return造成 logohidden 监听发现未初始化,设为'null。因为KaiOS逻辑,PIN lock情况下只能得到iccid, 得不到mcc/mnc/gid等信息。

  • PIN lock 时 gid1=null
  • SIM ready 时默认 'ff'

解决方案:

  1. 删除GID=null 时直接return 的逻辑,即gid1=null不return,可正常初始化。
  2. 新开发PIN unlock后的逻辑,重新触发初始化APN,执行加载。
    _updateOperatorVariantHandler: function(simslot) {
      if (!this._isVariantReady(simslot)) {
         return;
      }

      //非kaios原生存在缺陷的代码片段
      var iccManager = navigator.b2g.iccManager;
      if (iccManager) {
        var icc = iccManager.getIccById(simslot.simCard.iccInfo.iccid);
        if (icc) {
          var iccInfo = icc.iccInfo;
          if (iccInfo) {
            var gid = iccInfo.gid1;
            dump('operator_variant_manager: gid = ' + gid);
            if (gid === undefined || gid === null || gid === '') {
              //从persist.gsm.sim.gid获取,此值不用手动写入,根据卡。
              var gid1 = navigator.b2g.engmodeManager.getPropertyValue("persist.gsm.sim.gid");
              dump('operator_variant_manager: persist gid1 = ' + gid1);
              return;  //若PIN lock会直接return导致OperatorVariantHandler一直为null。
            }//gid
          }//iccInfo
        }//icc
      }//iccManager

      //最终卡状态ready后,唯一正常初始化operatorVariantHandlers的地方
      if (!this.operatorVariantHandlers[simslot.index]) {
        this.operatorVariantHandlers[simslot.index] =
          new OperatorVariantHandler(simslot.simCard.iccInfo.iccid,
            simslot.index, this);
        this.operatorVariantHandlers[simslot.index].start();
      }

    }//updateOperatorVariantHandler 私有方法

(二)APN 模块

operatorVariantHandlers正常加载后,根据卡匹配apn.json的APN 配置,

1、从配置加载到系统数据库:apn.json→ril.data.apnSettings.sim

  1. start()->
  2. getDMApnProtocol()->
  3. ObserveDMApnSettings()->
  4. combineApn(apnSettings, key)->
  5. this.cloneApn(apn)

2、从数据库到业务使用:ril.data.apnSettings.sim→DataCall

  1. observeSetting(aSettingInfo)
  2. ->this.handleSettingChanged(name, result);
  3. ->this.handleApnSettingChanged(clientId, resultApnObj)
  4. ->handler.updateApnSettings(aApnList);

(三)Engmode 模块(gecko)

  • gecko/koost/engmode/EngmodeService.jsm

在engmode实现同步APN到MD的接口,定义上层和底层APN Type的映射关系,用于同步dataProfile到Modem。

js/module Interface Comment
EngmodeManager.jsm setDataProfileByType(strApnSetting, type) 管理通过消息调起服务。
EngmodeService.jsm _setDataProfileByType(networkType, profileId, apn, protocol, roamingProtocol, authType, user, password, type, maxConnsTime, maxConns, waitTime, enabled, inactivityTimer, callback)  定义服务

三、【开发】调试 Debug

源码编译到软件分区路径的说明,在设备中可以查看编译产物,使用adb pull/push 调试,webapps对应应用内的application.zip 和系统omini.ja  都是压缩包的形式。

Note:若编译调试,单编应用的产物路径在 gaia\profile\webapps\settings(应用名)

相关文件 adb 设备路径 代码模块路径

operator_variant_manager.js

operator_variant_handler.js

system/b2g/webapps/system/ gaia\apps\system
DatacallManager.jsm system/b2g/omni.ja gecko/dom/system/gonk/radio
EngmodeService.jsm
EngmodeManager.jsm
system/b2g/omni.ja gecko/koost/engmode

四、业务知识

SIM

在KaiOS中,是operator_variant_handler.js文件管理着OperatorVariantHandler对象中运营商的信息,包括初始化和切换卡变更。

iccid

mcc

mnc

OMADM 

OMA-DM(Open Mobile Alliance Device Management)是一种用于远程管理移动设备的协议,通过OMA-DM协议,运营商可以向设备推送各种配置、更新、命令等。

在OMA-DM协议中,消息体是指通过协议传输的消息数据。

在OMA-DM协议中,更新APN配置时,需要通过指定一个APN配置模板来实现。

一般通过服务器推送消息到设备,用户终端收到后根据信息修改对应的APN。有的运营商通过class匹配不同类型的APN,而上层修改APN后也需要同步到MD,同样需要建立映射关系。

举例如下:文章来源地址https://www.toymoban.com/news/detail-799439.html

APN Type AP class MD profile_Id Comment/eg
ims 1 5 const NETWORK_TYPE_MOBILE_IMS = 5;
fota 2 7 const NETWORK_TYPE_MOBILE_FOTA = 7;
default 3 0 const NETWORK_TYPE_MOBILE = 1;
mms 4 2 const NETWORK_TYPE_MOBILE_MMS = 2;
  • MD ProfileId 可以自定义的,AP  Class应该运营商有要求。
  • apn.json中配置"profile_id"字段

到了这里,关于【笔记】KaiOS OTA APN 方案(OMADM)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入理解 ECMAScript modules:提升你的 JavaScript 技能(六)

    🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_ CSDN 博客专家、23年度博客之星前端领域TOP1 🕠 牛客 高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课 签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你

    2024年02月21日
    浏览(51)
  • 深入理解 ECMAScript modules:提升你的 JavaScript 技能(一)

    🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_ CSDN 博客专家、23年度博客之星前端领域TOP1 🕠 牛客 高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课 签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你

    2024年02月20日
    浏览(42)
  • BCSP-玄子前端开发之JavaScript+jQuery入门CH07_ECMAScript 6基础

    4.7.1 ECMAScript 6 简介 ECMAScript 6.0(简称 ES6) 是JavaScript语言的下一代标准 正式发布于2015年6月 目标 使JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言 版本升级 ECMAScript 2015 ECMAScript 2016 ECMAScript 2017 ECMAScript和JavaScript 的关系 前者是后者的规格,后者是前者的

    2023年04月27日
    浏览(51)
  • OTA实现设备升级方案

    引言 空中下载技术 (Over-the-Air Technology, OTA) 是通过移动通信的空中接口实现对移动终端设备进行远程管理的技术。 该技术在 IOT 行业非常的重要,当随着市场上的产品越来越多,保有量也越来越多,随着时间的推移,很多设备的功能比较老旧,逐渐落伍。为了能远程帮助

    2024年02月05日
    浏览(48)
  • 【行业方案】ABUP艾拉比物联网OTA解决方案

    随着物联网技术的不断推进,互联设备数量呈几何级增长。物联网将渗透到各个产业领域广泛的联网设备,面临着规模化部署和产品需求多变等众多挑战,这些挑战催生出对无线(OTA)固件升级的需求。OTA固件升级将是物联网应用加速器,成为物联网系统必不可缺的一个重要组

    2024年01月24日
    浏览(39)
  • Android 系统级APP 升级方案 OTA全流程

    支持原创,请关注专栏: 高质量文章导航 一.Android ota固件编译 OTA 介绍 OTA ( over the air )升级是 Android 系统提供的标准软件升级方式。它功能强大,提供了 完全升级(完整包)、增量升级模式(差异包),可以通过本地升级,也可以通过网络升级 1.完整包 完整包所包含内容

    2024年02月02日
    浏览(80)
  • OTA升级学习笔记

    记录下近期学习的OTA升级相关内容 OTA(Over-the-Air Technology)简单来说就是一种无线升级的技术 整编完成后使用make otapackage会生成target_files压缩包(包含完整的image数据)和可用于升级的ota update压缩包。如果不想在编译的时候生成升级包,可以将TARGET_SKIP_OTA_PACKAGE置成false(编

    2024年02月15日
    浏览(50)
  • 【ECMAScript】ES6-ES11学习笔记

    注意事项 代码中的注释有笔记如 有一些错误示范代码,为了代码整体可运行,将其注释如 当代码有输出是,通常将输出放在对应代码下一行,并注释如下 1.声明变量 2.定义常量 3.解构赋值 4.模板字符串 5.简化对象写法 6.箭头函数 箭头函数适合与this无关的回调,定时器,数

    2024年02月13日
    浏览(40)
  • 第二章 FPGA OTA升级方案的分析及简单用例测试

    FPGA程序运行的方式有两种方式: (1)加载到本地RAM(掉电不保存) (2)将程序固化到FLASH中(掉电保存),FPGA上电后自动从地址0加载固件 Xilinx 7系列有Multiboot设计,这种设计允许在应用现场支持FPGA在线加载多种不同应用,并可支持回退。但是需要说明的一点,Virtex®-7

    2024年02月08日
    浏览(43)
  • 调试笔记-stm32的OTA/IAP 通过485升级固件

    背景:最近需要在stm32上实现通过rs485升级固件功能。经过几天搜索和调试,实现了功能。 目标:使用cubeIDE实现stm32F407VGT6,通过RS485升级固件 调试记录: 步骤1. 在keil环境下的rs485升级固件(含源码):STM32 OTA应用开发——通过串口/RS485实现OTA升级(方式2)_stm32串口升级_柒壹漆

    2024年02月11日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包