HSM和AsyncChannel介绍

article/2025/9/23 5:34:00

HSM(hierarchical state machine, 层次状态机)和AsyncChannel是Android Java Framework中两个重要的类。

这两个类的作用如下。

  • HSM在传统状态机对所有状态都一视同仁的基础上做了一些改变,使得状态和状态之间有了层级关系。HSM中的状态层级关系与Java中父子类的派生和继承关系类似,即在父状态中实现generic的功能,而在子状态中实现一些特定的处理。不过,和Java中类派生不同的是,HSM中父子状态对应的是毫无派生关系的两个类,所以使用时需要创建两个对象。而Java中子类则从其父类派生,实际使用时创建一个子类对象即可,该子类对象就能完成父类的工作。
  • AsyncChannel用于两个Handler之间的通信。具体的通信方式为源Handler通过sendMessage向目标Handler发送消息,而目标Handler通过replyToMessage回复源Handler处理结果。注意,这两个Handler可位于同一个进程,也可分属两个不同的进程。

HSM

hierarchical state machine, 层次状态机. 对应的类是StateMachine。下面通过一个例子来介绍其用法。

[HSM示例]// 此例来源于StateMachine.java文件中的注释
// StateMachineTest是StateMachine的子类
class StateMachineTest extends StateMachine {StateMachineTest(String name) {super(name);// 为状态机添加一个状态。代码中一般用缩进的方式表达层级关系addState(mP0);// 添加一个状态mS0,其父状态为mP0addState(mS0, mP0);addState(mP1, mP0);addState(mS1,mP1); // 添加一个状态mS1,其父状态为mP1addState(mS5,mS1)addState(mS2, mP1);addState(mS3, mS2);addState(mS4, mS2);// setInitialState函数用于设置状态机的初始状态,本例中该状态是mS5setInitialState(mS5);}// StateMachineTest构造函数结束

上述代码中StateMachineTest所涉及的状态及层级关系下图所示。

mS5是初始状态,由代码中的setInitialState函数设置。接着来看StateMachineTest的代码。

[HSM示例]// 接上面的代码。P0从State类派生。在HSM中,状态由类State来表达class P0 extends State {/*enter代表一个状态的Entry Action,SM进入此状态时将调用其EA。exit代表一个状态的Exit Action,SM退出某状态时将调用其EXA。*/public void enter() {......// do sth here}public void exit() {......// do sth here}/*除了EA和EXA外,每个State中最重要的函数就是processMessage了。在HSM中,外界和HSM交互的方式就是向其sendMessage。Message由当前State的processMessage函数来处理。如果当前State成功处理此message,则返回HANDLED。否则返回NOT_HANDLED。在Message处理中,如果子状态返回NOT_HANDLED,则其父状态的processMessage将被调用。如果当前状态及祖先状态都不能处理,则HSM的unhandledMessage将被调用。而HSM的派生类可重载unhandledMessage函数以处理这个不能被当前状态及祖先状态处理的消息。*/public boolean processMessage(Message message) {return HANDLED; // P0能处理任何Message}}class P1 extends State {......// 实现P1的enter,exit和processMessage函数}class S0 extends State {......// 实现S0的enter,exit和processMessage函数}......// S1到S4的定义class S5 extends State {public void enter() {......// 实现S5的enter函数}public void exit() { ......// 实现S5的exit函数}public boolean processMessage(Message message) {switch(message.what){case: TRANSITION_CMD:transitionTo(mS4);// 切换状态时,需要调用此函数break;case: TRANSITON_CMD_DEFER_MSG:// deferMessage用于保留某个消息。而被保留的消息将留待到下一个状态中去处理deferMessage(message);transitionTo(mS1);break;default:break;}return HANDLED;}}......// StateMachine其他一些可重载函数。// 定义各个状态对应的对象private P0 mP0 = new P0();private P1 mP1 = new P1();private S0 mS0 = new S0();private S1 mS1 = new S1();private S2 mS2 = new S2();private S3 mS3 = new S4();private S4 mS4 = new S4();private S5 mS5 = new S5();// 定义消息final static int TRANSITION_CMD = 0;final static int TRANSITON_CMD_DEFER_MSG = 1;
}// 主函数
public void main() throws Exception {StateMachineTest smTest = new StateMachineTest("StateMachineTest");smTest.start(); // 启动状态机synchronized (sm5) {// 外界只能通过obtainMessage以及sendMessage发送消息给SM去执行smTest.sendMessage(obtainMessage(TRANSITION_CMD));smTest.sendMessage(obtainMessage(TRANSITON_CMD_DEFER_MSG));......}......
}

上面代码介绍了HSM中一些重要的API。

  • addState:添加一个状态。同时还可指定父状态。
  • enter代表一个状态的Entry Action,SM进入此状态时将调用其EA。
  • exit代表一个状态的Exit Action,SM退出某状态时将调用其EXA。
  • transitionTo:将状态机切换到某个状态。
  • obtainMessage:由于HSM内部是围绕一个Handler来工作的,所以外界只能调用HSM的obtainMessage以获取一个Message
  • sendMessage:发送消息给HSM。HSM中的Handler会处理它。
  • deferMessage:保留某个消息。该消息将留待下一个新状态中去处理。其内部实现就是把这些被deferred的message保存到一个队列中。当HSM切换到新状态后,这些deferred消息将被移到HSM内部Handler所对应消息队列的头部,从而新状态能首先处理这些deferred消息
  • start:启动状态机。
  • 停止状态机可使用quit或quitNow函数。这两个函数均会发送SM_QUIT_CMD消息给HSM内部的Handler,不过效果略有区别。当使用quit时,SM_QUIT_CMD添加在消息队列尾;而使用quitNow时,SM_QUIT_CMD被添加到消息队列头。

HSM中状态和状态之间的层级关系体现在哪些方面呢?以上述代码为例:

  • SM启动后,初始状态的EA将按派生顺序执行。即其祖先状态的EA先执行,子状态的EA后执行。以示例代码中的初始状态mS5为例。当HSM的start调用完毕后,EA调用顺序为mP0、mP1、mS1、mS5
  • 当State发生切换时,旧State的exit先执行,新State的enter后执行,并且新旧State派生树上对应的State也需要执行exit或enter函数。以mS5切换到mS4为例,在此切换过程中,首先执行的是EXA,其顺序是mS5,mS1。注意,EXA执行的终点是离mS4和mS5最近的一个公共(即同时是mS4和mS5的祖先)祖先State(此处是mP1),但公共祖先状态的EXA不会执行。然后执行的是EA,其顺序是mS2、mS4。同理,公共祖先的EA也不会执行。细心的读者可以发现,HSM中EA和EXA执行顺序和C++类构造/析构函数执行顺序类似。EA执行顺序由祖先类开始直至子孙类,而析构函数的执行先从子孙类开始,直到祖先类。
  • State处理Message时,如果子状态不能处理(返回NOT_HANDLED),则交给父状态去处理。这一点也和C++中类的派生函数类似。

2.AsyncChannel

AsyncChannel用于两个Handler之间的通信,其用法包含两种不同的应用模式(usage model)。

  • 简单的request/response模式下,Server端无须维护Client的信息,它只要处理来自Client的请求即可。连接时,Client调用connectSync(同步连接)或connect(异步连接,连接成功后Client会收到CMD_CHANNEL_HALF_CONNECTED消息)即可连接到Server。
  • 与request/response模式相反,AsyncChannel中另外一种应用模式就是Server端维护Client的信息。这样,Server可以向Client发送自己的状态或者其他一些有意义的信息。与这种模式类似的应用场景就是wpa_cli和wpa_supplicant。wpa_cli可以发送命令给WPAS去执行。同时,WPAS也会将自己的状态及其他一些消息通知给wpa_cli。

AsyncChannel中Client和Server端在最开始建立连接关系时,可以采用同步或异步的方式。以异步方式为例介绍第二种应用模式中AsyncChannel的使用步骤。

  1. Client调用AsyncChannel的connect函数。Client的Handler会收到一个名为CMD_CHANNEL_HALF_CONNECTED消息。
  2. Client在处理CMD_CHANNEL_HALF_CONNECTED消息时,需通过sendMessage函数向Server端发送一个名为CMD_CHANNEL_FULL_CONNECTION的消息。
  3. Server端的Handler将收到此CMD_CHANNEL_FULL_CONNECTION消息。成功处理它后,Server端先调用AsyncChannel的connected函数,然后通过sendMessage函数向Client端发送CMD_CHANNEL_FULLY_CONNECTED消息(特别注意)。
  4. Client端收到CMD_CHANNEL_FULLY_CONNECTED消息。至此,Client和server端成功建立连接。
  5. Client和Server端的两个Handler可借助sendMessage和replyToMessge来完成请求消息及回复消息的传递。注意,只有针对那些需要回复的情况,Server端才需调用replyToMessage。
  6. 最后,Client和Server的任意一端都可以调用disconnect函数以结束连接。该函数将导致Client和Server端都会收到CMD_CHANNEL_DISCONNECTED消息。

上述步骤的描述来自AsyncChannel.java文件中的注释。但实际上Server端代码在处理CMD_CHANNEL_FULL_CONNECTION消息时并不能按照上面的描述开展工作。因为AsyncChannel对象一般由客户端创建,而CMD_CHANNEL_FULL_CONNECTION消息无法携带AsyncChannel对象(AsyncChannel对象无法通过Binder进行跨进程传递)。所以,Server端并不能获取客户端创建的这个AsyncChannel对象,它也就没办法调用AsyncChannel的connected函数。

结合WifiManager中的相关代码来介绍AsyncChannel中第二种模式涉及的一些重要函数。

WifiManager的init函数中会创建一个AsyncChannel以和WifiService中的某个Handler建立连接关系,代码如下所示。

[-->WifiManager.java::init]private void init() {/*该函数内部通过Binder机制调用WifiService的getWifiServiceMessgener函数,返回值是一个类型为Messagener的对象。Messgener从Parcelable派生,其内部有一个IMessenger对象用于支持跨进程的Binder通信。WifiService中,getWifiServiceMessgener的代码如下。public Messenger getWifiServiceMessenger() {......// 权限检查return new Messenger(mAsyncServiceHandler);// 通过Messenger封装了目标Handler}*/mWifiServiceMessenger = getWifiServiceMessenger();......// 创建一个HandlerThread。sHandlerThread = new HandlerThread("WifiManager");sHandlerThread.start();// Client中的Handler,它将运行在sHandlerThread线程中// AsyncChannel对Client Handler运行在什么线程没有要求mHandler = new ServiceHandler(sHandlerThread.getLooper());/*connect是AsyncChannel的重要函数。此处使用的connect函数原型如下:connect(Context srcContext, Handler srcHandler, Messenger dstMessenger)srcContext:为Client端的Context对象,AsyncChannel内部将使用它。srcHandler:为Client端的Handler。dstMessgener:是Server端Handler在Client端的代表。*/mAsyncChannel.connect(mContext, mHandler, mWifiServiceMessenger);......
}

connect函数将触发Client端Handler收到一个CMD_CHANNEL_HALF_CONNECTED消息。马上来看WIfiManager中ServiceHandler。

[-->WifiManager.java::ServiceHandler]private class ServiceHandler extends Handler {......// 此处只关注和AsyncChannel相关的内容public void handleMessage(Message message) {......switch (message.what) {case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:// 半连接成功if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {// 向Server端发送CMD_CHANNEL_FULL_CONNECTION消息mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);}......break;case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: // 连接成功break;case AsyncChannel.CMD_CHANNEL_DISCONNECTED:// 连接关闭mAsyncChannel = null;getLooper().quit();// 连接关闭,退出线程break;......}......
}

WifiService中的目标Handler是AsyncServiceHandler,其代码如下所示。

[-->WifiService::AsyncServiceHandler]private class AsyncServiceHandler extends Handler {......// 先看它是如何处理CMD_CHANNEL_FULL_CONNECTION消息的public void handleMessage(Message msg) {switch (msg.what) {case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {// 处理因ac.connect调用而收到的CMD_CHANNEL_HALF_CONNECTED消息// 该消息携带了一个AsyncChannel对象,即acif (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {// 保存这个AsyncChannel对象,用于向Client发送消息mClients.add((AsyncChannel) msg.obj);/*注意,Server端可在此处向Client端发送CMD_CHANNEL_FULLY_CONNECTED消息。例如:AsyncChannel sample = (AsyncChannel) msg.obj;sample.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);*/}break;}case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {mClients.remove((AsyncChannel) msg.obj);break;}case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {// Server端先收到此消息/*新创建一个AsyncChannel对象ac,然后调用它的connect函数。其中:msg.replyTo代表Client端的Handler,也就是WifiManager中ServiceHandler。connect函数将触发CMD_CHANNEL_HALF_CONNECTED消息被发送,而且该消息会携带对应的AsyncChannel对象,即此处的ac。请回到handleMessage的前面去看CMD_CHANNEL_HALF_CONNECTED的处理。*/AsyncChannel ac = new AsyncChannel();// 创建一个新的AsyncChannel对象ac.connect(mContext, this, msg.replyTo);break;}......}}

根据WifiService的代码,由于Server端无法得到Client端的AsyncChannel对象,所以它干脆自己又新创建了一个AsyncChannel,并connect到客户端。这样,Server和Client端实际上有两个不同的AsyncChannel对象,并且都需要调用connect函数。

如果AsyncChannel支持跨进程传递,那么Server端只要获取Client端传递过来的AsyncChannel对象,并调用其connected(注意,不是connect)函数即可。

 


http://chatgpt.dhexx.cn/article/b9MV5MTZ.shtml

相关文章

英飞凌 AURIX 系列单片机的HSM详解(2)——与HSM相关的UCB和寄存器

本系列的其它几篇文章: 《英飞凌 AURIX 系列单片机的HSM详解(1)——何为HSM》 《英飞凌 AURIX 系列单片机的HSM详解(3)——开发方法》 《英飞凌 AURIX 系列单片机的HSM详解(4)——Tricore核与H…

英飞凌 AURIX 系列单片机的HSM详解(3)——开发方法

本系列的其它几篇文章: 《英飞凌 AURIX 系列单片机的HSM详解(1)——何为HSM》 《英飞凌 AURIX 系列单片机的HSM详解(2)——与HSM相关的UCB和寄存器》 《英飞凌 AURIX 系列单片机的HSM详解(4)—…

HSM硬件加密机国密标准解读

HSM全称硬件安全模块,是数据安全领域的关键硬件设备,是公钥基础设施的一部分。本文从国密0054出发,概要分析了HSM也就是通常说的服务器密码机需要遵循的国密相关标准,以及与等保的关系。 一、信息系统密钥应用的基本要求 1、总体…

HSM和TEE

本文摘自牛咖网文章 HSM和TEE HSM为其他应用程序提供密钥管理和加密功能。 TEE还提供让应用程序(或应用程序的安全相关部分)在其隔离环境中执行的功能。 常规执行环境 (REE)是TEE社区中的术语,用于表示设备中特定TEE之外的所有内容。 HSM如何…

满足AUTOSAR基础软件要求的硬件安全模块(HSM)加密运算

随着软件日益复杂,并且车载系统和传感器数量稳步增加,车内系统的通讯成几何增长,必须加强密码保护。这种保护可以通过经典的实时汽车开放系统架构(AUTOSAR)来实现。即便在资源稀缺的情况下,安装合适固件的硬…

硬件安全模块- HSM

目录 一、什么是硬件安全模块 二、HSM是如何工作的 三、HSM的应用 公钥基础设施(Public Key Infrastructure - PKI) 卡支付系统(Card Payment HSM) 安全套接字协议(Secure Sockets Layer - SSL) 车载…

鉴源实验室丨HSM技术浅述

作者 | 徐奕华 上海控安可信软件创新研究院汽车网络安全组 来源 | 鉴源实验室 引言:2023年5月初,工业和信息化部装备工业一司组织全国汽车标准化技术委员会开展《汽车整车信息安全技术要求》等四项强制性国家标准的制修订[1]。这意味着车辆信息安全管理…

英飞凌 AURIX 系列单片机的HSM详解(1)——何为HSM

本系列的其它几篇文章: 《英飞凌 AURIX 系列单片机的HSM详解(2)——与HSM相关的UCB和寄存器》 《英飞凌 AURIX 系列单片机的HSM详解(3)——开发方法》 《英飞凌 AURIX 系列单片机的HSM详解(4)—…

硬件安全模块(HSM)

一、什么是HSM 说起信息安全和加解密,我们很容易会在脑海中浮现出锁和钥匙。那我们来想象一个场景: 假设一位父亲有三个儿子,他给每个儿子各买了一台掌上游戏机。为避免他们沉迷游戏,父亲把每台游戏机都锁到一个小盒子里。盒子归…

什么是WSDL?

WSDL(Web Service Description Language)Web服务器描述语言是用XML文档来描述Web服务的标准,是Web服务的接口定义语言,由Ariba、Intel、IBM、MS等共同提出,通过WSDL,可描述Web服务的三个基本属性&#xff1…

已有wsdl,怎么去调用他的方法

1,在浏览器验证该wsdl地址是否可以打开,显示为该模式 2,新建一个项目,右击该项目,other,webservice,webservice clent , 讲该wsdl地址输入,finish 3,新建一个类,实例化impl,调用一个…

WSDL的文件结构(WSDL 1.1规范

为能将一个WebService描述清楚&#xff0c;WSDL从三个层面对一个服务进行了描述&#xff1a; 一&#xff1a;描述服务的接口(<wsdl:portType/>部分)&#xff0c;也就是服务有哪些操作(<wsdl:operation/>部分)以及每个操作的输入输出参数(<wsdl:message/>部分…

WSDL阅读方法

我们以天气预报WebService服务为例&#xff0c;来看看怎么阅读一个wsdl文档。 打开一个wsdl文档后&#xff0c;先看底部。 binding在这里&#xff1a; portType在这里&#xff1a; 好了&#xff0c;看了上面的&#xff0c;我们来说说wsdl说明书的整体结构吧&#xff1a; 1.&l…

IDEA wsdl教程

这篇文章教你如何利用IDEA发布WSDL 博主大学复习周精心制作,共推出几个模块供大家利用, ####今天我们先来学习一下如何利用IDEA发布WSDL 首先打开IDEA 新建一个Java项目 OK了基本的项目已经创建完成! 创建一个新的类命名为Java6WB代码如下所示: package com.company; im…

【WebService】wsdl配置详解以及使用注解修改wsdl配置

欢迎关注我新搭建的博客&#xff1a;http://www.itcodai.com/ WebService系列文章&#xff1a; 【WebService】带你走进webservice的世界 【WebService】自定义WebService服务及其调用 【WebService】CXF处理javaBean等复合类型以及Map等复杂类型的数据 【WebService】CXF拦…

WSDL实例解析

WSDL的主要文档元素 WSDL文档可以分为两部分。顶部分由抽象定义组成&#xff0c;而底部分则由具体描述组成。抽象部分以独立于平台和语言的方式定义SOAP消息&#xff0c;它们并不包含任何随 机器或语言而变的元素。这就定义了一系列服务&#xff0c;截然不同的应用都可以实现。…

WSDL、详解

WebService中的WSDL详解 有人在WebService开发的时候&#xff0c;特别是和第三方有接口的时候&#xff0c;走的是SOAP协议&#xff0c;然后用户&#xff08;或后台&#xff09;给你一个WSDL文件&#xff08;或网址&#xff09;&#xff0c;说按照上面的进行适配&#xff0c; 这…

wsdl和wadl区别

1、Java开发WebService最重要的两个规范&#xff1a; JSR-224 (JAX-WS&#xff1a;Java API for XML-Based Web Services ) &#xff0c;主要使用soap协议&#xff0c;使用wsdl来描述&#xff1b;JSR-311 (JAX-RS&#xff1a;The Java API for RESTful Web Services)&#xff…

WebService中的WSDL详细解析

WebService中的WSDL详解 有人在WebService开发的时候&#xff0c;特别是和第三方有接口的时候&#xff0c;走的是SOAP协议&#xff0c;然后用户&#xff08;或后台&#xff09;给你一个WSDL文件&#xff08;或网址&#xff09;&#xff0c;说按照上面的进行适配&#xff0c; 这…

WSDL详解

原文链接&#xff1a;WebService中的WSDL详解 有人在WebService开发的时候&#xff0c;特别是和第三方有接口的时候&#xff0c;走的是SOAP协议&#xff0c;然后用户&#xff08;或后台&#xff09;给你一个WSDL文件&#xff08;或网址&#xff09;&#xff0c;说按照上面的进…