本文仅为工作中对AAOS电源管理的学习笔记，不作为教程或其他用途，存在对官方文档的大量摘抄和个人理解，如有错误烦请指出。前注：本文由notion创作，由于Markdown对某些效果的实现略繁琐，因此如有需要请移步至原文，系列地址：Notion Share 车库模式是为AAOS提供空闲时间，以完成受空闲限制的任务调度器（JobScheduler）中的任务（即满足public JobInfo.Builder setRequiresDeviceIdle (boolean requiresDeviceIdle)中requiresDeviceIdle值为真的任务）一般，在手机中，Android提供一个闲时窗口状态，当用户一段时间没有对手机进行操作时（一般为60分钟或更长时间），手机将会被认为进入了空闲状态，在空闲状态下系统将会进行基础的维护、更新以及优化等任务。然而与手机不同，汽车不使用时，将会挂起或关闭，所以汽车将没有空闲状态。为了解决这个问题，AAOS引入了车库模式，确保系统存在空闲时间。一般，当车辆关闭时，会先进入车库模式，在车库模式下，电源会被打开，显示屏不会亮起，并自动执行JobScheduler中的任务。车库模式的使用如果想进入车库模式，则汽车关闭时，VHAL必须发送AP_POWER_STATE_REQ信号，且状态参数（参数1）为SHUTDOWN_PREPARE，同时，附加参数（参数2）需要为SHUTDOWN_ONLY或CAN_SLEEP。具体状态转换流程见《AAOS电源（1）：概览与电源系统》的状态转换图。连接到Android框架构建运行方法//通过继承JobService编写任务 public class MyGarageModeJob extends JobService { ... } Context context = ...; int jobId = ...; //通过任务服务类创建ComponentName（组件名，用于启动服务或活动） ComponentName myGarageModeJobName = new componentName(context, MyGarageModeJob.class); //创建任务状态描述 JobInfo.Builder infoBuilder = new JobInfo.Builder(jobId, myGarageModeJobName) .setRequiresDeviceIdle(true); // 设置任务状态描述，下行为一个演示demo，即任务需要网络状态为免费网络 infoBuilder.setRequiredNetworkType(NetworkType.NETWORK_TYPE_UNMETERED); //创建任务实例 JobScheduler jobScheduler = (JobScheduler) context .getSystemService(Context.JOB_SCHEDULER_SERVICE); //通过任务调度设置任务 jobScheduler.schedule(infoBuilder.build());调试车库模式启动车库模式的日志记录adb shell stop adb shell setprop log.tag.GarageMode VERBOSE adb shell setprop log.tag.Finsky VERBOSE adb shell setprop log.tag.CAR.POWER VERBOSE adb shell setprop log.tag.JobScheduler.Connectivity VERBOSE adb shell start车库模式正在启动的日志GarageMode: [Controller]: CPM state changed to SHUTDOWN_PREPARE GarageMode: [GarageMode]: Entering GarageMode GarageMode: [Controller]: Sending broadcast with action: com.android.server.jobscheduler.GARAGE_MODE_ON车库模式启动完成的日志[GarageMode]: GarageMode was canceled或[GarageMode]: GarageMode completed normally电源状态日志CAR.POWER: starting shutdown prepare without Garage Mode GarageMode: [Controller]: CPM state changed to SHUTDOWN_PREPARE GarageMode: [GarageMode]: Entering GarageMode CAR.POWER: send shutdown prepare CAR.POWER: setPowerState=SHUTDOWN_PREPARE(7) param=0注：以上仅为输出日志，是否进入车库模式取决于车辆的电源状态迁移流程。 2022-07-26 22:57 UtopiaXC 于大连
本文仅为工作中对AAOS电源管理的学习笔记，不作为教程或其他用途，存在对官方文档的大量摘抄和个人理解，如有错误烦请指出。前注：本文由notion创作，由于Markdown对某些效果的实现略繁琐，因此如有需要请移步至原文，系列地址：Notion Share电源管理CPM提供的编码接口CPM为系统应用程序和服务提供了相关编码接口，我们可以通过这些API对以下方面进行操作：在AP中监控电源状态机变化应用电源策略通过以下步骤进行API的调用：通过Car API获取CPM实例通过CPM实例调用CPM API创建CPM对象//通过上下文创建Car API Car car = Car.createCar(this); //通过Car API获取CPM对象 CarPowerManager powerManager = (CarPowerManager) car.getCarManager(android.car.Car.POWER_SERVICE);CarPowerStateListener与其注册系统允许应用和服务通过CarPowerManager.CarPowerStateListener获取电源变化状态，该接口定义了方法onStateChanged()，该方法是CPMS电源状态改变时的回调函数java//通过匿名类实现一个电源状态监听器 private final CarPowerManager.CarPowerStateListener powerListener = new CarPowerManager.CarPowerStateListener () { @Override public void onStateChanged(int state) { //TODO: 电源状态改变时执行的业务 Log.i(TAG, "onStateChanged() state = " + state); } };如果要对上述状态监听器进行注册，需要创建一条新的线程并将该监听器与线程注册到CPM中：executor = new ThreadPerTaskExecutor(); powerManager.setListener(powerListener, executor);当注册完成后，监听器的onStateChanged()方法将在电源状态改变时被调用，同时，存在一个整型state来表示新的电源状态， CarPowerManager 中定义了实际值和电源状态之间的关联，如下表所示：状态名状态描述STATE_ON进入开启状态，系统已全面运行STATE_SHUTDOWN_CANCELLED关机动作被取消，同时电源状态回到正常状态STATE_POST_SHUTDOWN_ENTER关机准备工作已经完成，同时VMCU已经做好关机准备，进入关机状态STATE_PRE_SHUTDOWN_PREPARE已经提交了关机请求，但是CPMS还没有开始进行关机，此时屏幕和声音依旧开启。STATE_SHUTDOWN_PREPARE车库模式可以在此状态下运行STATE_SUSPEND_ENTER应用程序应该在此时被清理并准备好挂起到内存。STATE_POST_SUSPEND_ENTER挂起到内存的准备工作已经完成，VMCU已经准备好挂起到内存，进入挂起状态。STATE_SUSPEND_EXIT从挂起状态唤醒或取消挂起操作。STATE_HIBERNATION_ENTER应用程序应该在此时被清理并准备好休眠（挂起到硬盘）STATE_POST_HIBERNATION_ENTER休眠的住被已经完成，VMCU已经准备好进入休眠状态，然后进入休眠。STATE_HIBERNATION_EXIT从休眠状态唤醒或取消休眠操作。STATE_WAIT_FOR_VHAL系统正在启动，但是在进入ON状态之前需要等待VHAL回应通信。CarPowerStateListener注销通过CPM实例对监听器进行注销：powerManager.clearListener();在安卓实现上集成系统系统集成需要对以下内容进行实现：实现内核接口以挂起系统实现VHAL功能，包括：从汽车硬件将挂起与关闭初始化指令传递至安卓系统从安卓系统传递关闭准备指令到汽车硬件通过Linux内核接口初始化安卓的挂起和关闭当设备挂起时，确保所有的唤醒源被禁用确保应用程序可以迅速关闭以避免无限期地延长关闭过程确保BSP根据电源策略打开或关闭组件，防止挂起和休眠被阻塞内核接口：/sys/power/state当应用程序或服务将用于挂起到RAM的内存或用于挂起到磁盘的磁盘写入位于/sys/power/state的文件时，AAOS会将设备置于挂起模式。开发者必须提供一个功能来监控这个文件并将Linux置于挂起电源状态。该功能可以向VMCU发送一个GPIO以通知VMCU设备已完全关闭。开发者还应负责消除VHAL将最终消息发送到VMCU与系统进入挂起或关闭模式之间的任何冲突条件。VHAL的任务VHAL应提供一个介于安卓系统层和车载网络层之间的交互接口层，其应满足上述VHAL功能。当CPMS通知VHAL准备好关机时，VHAL将关机准备完成的消息发送给VMCU，一般情况下，通过例如UART，SPI或USB等片上外围设备发送消息。一旦发送了消息，CPMS就会调用内核命令来挂起或关闭设备。在此之前，VHAL 或BSP可能会切换GPIO以指示VMCU可以安全地从设备中移除电源。VHAL需要实现以下属性，以用来控制CPM：属性名描述AP_POWER_STATE_REPORT安卓通过VehicleApPowerStateReport枚举值来向VMCU报告电源状态的转换。AP_POWER_STATE_REQVMCU使用此属性来指示安卓通过VehicleApPowerStateReport枚举值转换到不同的状态。AP_POWER_STATE_REPORT本属性具有两个整型参数：int32Values[0]：通过VehicleApPowerStateReport枚举表示的当前电源状态。int32Values[1]：延迟或关机或休眠的时间（单位毫秒），具体含义由参数1决定。参数1可以选择的值如下：值描述参数2是否必须WAIT_FOR_VHALAP正在启动并需要与VHAL建立通信。否DEEP_SLEEP_ENTRYAP正在进入深度睡眠模式，通过第二个参数设置VMCU唤醒AP的时间。是DEEP_SLEEP_EXITAP正在结束深度睡眠。否HIBERNATION_ENTRYAP正在进入休眠模式，通过第二个参数设置VMCU唤醒AP的时间。是HIBERNATION_EXITAP正在结束休眠。否SHUTDOWN_POSTPONE安卓尚未准备好关闭，通过第二个参数设置VMCU等待的时间，同时，安卓可能会再次发出SHUTDOWN_POSTPONE来增加延迟关闭的时间。是SHUTDOWN_PREPARE安卓已经准备好进入关闭状态。是SHUTDOWN_STARTAP已经准备好关闭，通过第二个参数设置VMCU唤醒AP的时间（VMCU不需要支持定时启动的功能）。是SHUTDOWN_CANCELLED安卓将停止准备关闭并进入WAIT_FOR_VHAL状态否ON安卓处于正常运行状态否注：更加具体的描述包含在VehicleApPowerStateReport.aidl，存储在hardware/interfaces/automotive/vehicle/aidl/android/hardware/automotive/vehicle该状态可以自行设置或通过以响应VMCU请求的方式设置。AP_POWER_STATE_REQ本属性具有两个整型参数：int32Values[0]：通过VehicleApPowerStateReport枚举表示将要转换到的新状态。int32Values[1]：VehicleApPowerStateShutdownParam**枚举值，仅在参数1为SHUTDOWN_PREPARE的情况下将其选项传递给安卓。参数1可以选择的值如下：值描述ONAP应处于全功能状态。SHUTDOWN_PREPAREAP应该已经准备好进行关闭，第二个值表示是否允许AP推迟关闭，以及AP是否应该关闭电源或进入深度睡眠。CANCEL_SHUTDOWNAP应该取消准备关闭并进入准备进入全功能。FINISHEDAP已进入挂起或关闭。参数2即VehicleApPowerStateShutdownParam可选值如下：值描述CAN_SLEEPAP可以进入深度睡眠模式而非彻底关闭，可以被延迟。CAN_HIBERNATEAP可以进入休眠而非彻底关闭，可以被延迟。SHUTDOWN_ONLYAP只可以彻底关闭，可以被延迟。SLEEP_IMMEDIATELYAP必须立刻进入深度睡眠模式。HIBERNATE_IMMEDIATELYAP必须立刻进入休眠模式。SHUTDOWN_IMMEDIATELYAP必须立刻彻底关闭。唤醒源当设备处于挂起状态时，开发者应适当禁用唤醒源。一般来说，心跳包，调制解调器，Wi-Fi与蓝牙等均属于唤醒源。挂起时，唯一有效的唤醒源应为由VMCU发往SoC的打断。当然，VMCU需要可以监听远程唤醒事件，如果此功能由AP实现，则需要添加另一个专为此服务的唤醒源作为调制解调器。应用程序OEM开发者应小心地开发对应的应用程序以保证当电源状态发生改变时迅速关闭或启动而非无限期地延迟指令顺序。 2022-07-23 20:51 UtopiaXC 于大连
本文仅为工作中对AAOS电源管理的学习笔记，不作为教程或其他用途，存在对官方文档的大量摘抄和个人理解，如有错误烦请指出。前注：本文由notion创作，由于Markdown对某些效果的实现略繁琐，因此如有需要请移步至原文，系列地址：Notion Share概览电源要求耗电要求：车辆停放时耗电几乎为0，保证即使在数月后车辆电池依旧有足够电量启动发动机。硬件启动：后视摄像头，音频与启动画面等需要在安卓系统启动前迅速响应并启动。系统启动：在短时间内快速启动安卓主屏幕以便用户交互使用。系统状态：类似于挂起，重启后需要维持原本系统状态。电源解决方案电源政策：确保根据需要选择性地开启和关闭硬件和软件组件。电源管理：AAOS的电源状态机，给予相关HAL属性。车库模式：车辆于停放时的低功耗状态，同时保证系统执行必要维护操作。管理启动时间：启动时间优化提示以及启动序列说明。术语表名称简称作用系统芯片（片上系统）SoCSystem On a Chip，和手机芯片类似，在单颗芯片上集成了完整的嵌入式系统。应用处理器AP物联网领域中使用的低功耗多功能处理器，一般是在低功耗CPU的基础上拓展音视频能力和专用接口的超大规模集成电路。是片上系统SoC的一部分。介质（媒体）处理器MPMedia Processor，SoC的一部分控制器区域网络CAN一种功能丰富的车用总线标准。被设计为无需主机的情况下允许总线网络上的单片机与仪器进行通信。（ISO 11898）通用 I/OGPIOGeneral-purpose input/output，一种具有引脚的微型处理芯片，可以实现高低电平的写入与读出。串行外设接口SPISerial Peripheral Interface Bus，一种用于芯片通信的同步串口规范。车载主控微控制器单元VMCUMCU，即Microcontroller Unit，微控制器单元，VMCU即Vehicle MCU，车载控制器单元，具体作用如下列表所示。汽车电源管理CPM车载电源管理API，用于向应用暴露操作接口来操作电源状态。汽车电源管理服务CPMS车载电源管理服务，实现车载电源状态机，提供VHAL接口，同时执行对挂起和关机的最终调用。汽车电源政策守护进程CPPD暴露原生AIDL接口以注册电源管理策略监听器挂起Suspend也称为挂起到内存（S2R/STR）。SoC将进入S3电源模式，CPU断电但内存RAM依旧通电。指Storage to RAM。休眠Hibernate也称为挂起到磁盘（S2D/S4）。SoC将进入S4电源模式即休眠，同时将RAM内存写入硬盘等非易失介质，同时系统断电。S2D指Storage to Disk，S4为电源模式。硬件抽象层HALHardware Abstraction Layer，位于操作系统与硬件之间，用于对其二者提供交互接口。板级支持处理器BSPBSP是介于硬件与操作系统之间的支撑层，用于初始化硬件并加载系统引导。电源管理集成电路PMIC用于管理主机系统的电源需求的芯片。车载 HALVHALHAL层即硬件抽象层，介于硬件（驱动）层与应用层之间，为应用提供硬件操作接口。V指Vehicle，即车。车载接口处理器VIPVehicle Interface Processor硬件架构VMCU与车辆原生接口连接，如CAN总线等。控制AP电源。通过GPIO与AP通信以通知状态转换活动。AP车辆关闭与AP状态车辆熄火后，AP需要进入如下状态之一：睡眠（Sleep）：当VMCU决定保留AP主电源的时候AP进入此状态，一般，唤醒信号会通过GPIO通知AP。休眠（Hibernation）：当VMCU决定切断AP主电源的同时保留内存内容的时候进入此状态，当下次开机时AP会载入内存内容。关闭（Shutdown）：当VMCU决定保留电池电量的时候进入此状态，AP将在下次开机时进入冷启动。VMCU-AP总线结构必须为SPI等双向接口，且必须在车载HAL中公开。用于发送事件：AP屏幕显示关闭或开启AP唤醒（通过GPIO）AP后视摄像头显示画面的关闭或开启AP完整关闭（返回状态给VMCU）其他电源管理电源系统电源状态转换挂起到RAM（Suspend-to-RAM）：车辆和SoC断电。停止代码执行。内存仍然通电保证挂起状态。等待VHAL（Wait for VHAL）：当司机与车辆交互时（比如打开车门），VMCU向SoC通电，AAOS从挂起状态恢复并进入等待HAVL状态。开启（On）：VHAL启动完毕并向AAOS通知后，AAOS启动并进入开启状态，此时，司机与AAOS完全可交互。关闭准备（Shutdown Prepare）：当司机结束驾驶后（熄火），VHAL通知AAOS进入准备关闭状态，此时，显示屏和音频关闭，系统不与司机互动，但仍可更新应用与系统。当一切操作完成准备就绪时，进入等待VHAL结束状态。等待 VHAL 完成/结束（Wait for VHAL Finish）：当一切操作完成后，AAOS通知VHAL已经做好关闭准备，VMCU进入深度睡眠状态，并切断AP电源，同时，AAOS进入挂起状态。电源管理模块电源管理模块由以下部分构成：CarPowerManager：车载电源管理，用于提供Java/C++的API。CarPowerManagementService：车载电源管理服务，用于协调电源状态转换。CarPowerPolicyDaemon：车载电源政策守护进程，用于和原生电源政策客户端进行通信。VHAL：车载硬件抽象层，用于连接到VMCU。libsuspend：用于进入挂起模式的本地库文件。Kernel：内核，用于实现对挂起与休眠的实现。其中，内核对睡眠sleep与休眠（挂起到RAM）进行了实现，位于/sys/power/state，AAOS通过内存或硬盘写入此文件进行挂起。CPMS与其他Service和HAL协调电源状态，CPMS实现状态机，并在电源状态发生变化的时候向每个观察者发送消息。某些属性定义在VHAL中，为了和VMCU进行通信，CPMS会读取并写入这些数据，应用程序可以在CPM中定义的接口来获取并监控电源状态的改变。同时，应用还能通过此接口注册电源政策监听器。在CPM中的 API 可通过 Java 进行调用，并且带有 @hide/@System API 注解，这意味着它仅供特权应用使用。CPPD用于管理电源政策，直到CPMS接管控制权为止。此外，还会向原生监听器发送电源政策更改通知。电源状态机AAOS使用电源状态机（Car power state machine）对AP电源状态进行表示，状态机转移如下图所示：由CpmsState类实现，同时在CPMS中以类属性形式保存，即public final int mState;其中，定义了六个状态参数：参数名参数值参数用途WAIT_FOR_VHAL0等待VAHL。当车俩从关闭或挂起状态下激活时，状态机由OFF或STR状态进入等待VHAL状态，同时状态机置于WAIT_FOR_VHAL并等待VHAL返回信号。除此之外，当状态机处于SHUTDOWN_PREPARE时，如果VHAL通知取消关机，也会重新进入WAIT_FOR_VHAL此状态。ON1当VHAL返回On信号时，即硬件启动成功，状态机进入ON 状态完成电源启动。SHUTDOWN_PREPARE21、当等待VHAL失败，即硬件启动失败时，直接进入关机准备状态。2、当VHAL返回关机准备时，状态机进入SHUTDOWN_PREPARE。3、当AAOS还有应用正在运行时，CMPS通知应用进行关闭，同时状态机一直处于SHUTDOWN_PREPARE状态直至不再有应用等待关闭。注1：当处于车库模式下，关闭准备状态允许执行闲置任务（idle jobs）。注2：当VHAL取消关闭时，状态迁移至WAIT_FOR_VHAL状态注3：此状态下，VHAL会返回SLEEP_IMMEDIATELY与SHUTDOWN_IMMEDIATELY信号，状态机应立即发生状态改变。WAIT_FOR_FINISH3当所有应用关闭完成后，状态由SHUTDOWN_PREPARE迁移至WAIT_FOR_FINISH，同时通知VHAL已经做好关闭准备，等待VHAL返回完成信号。SUSPEND4挂起到内存（STR）状态：1、当状态机为WAIT_FOR_FINISH状态时，VHAL返回关闭完成（Finished）信号，状态机迁移至SUSPEND2、当状态机处于SHUTDOWN_PREPARE状态时，VHAL返回立即睡眠信号（SLEEP_IMMEDIATELY），状态应立即迁移至SUSPENDSIMULATE_SLEEP5模拟睡眠模式，用于对睡眠模式进行测试的状态，实际不会进行使用。在CPMS中，存在*endPowerManagerEvent函数用于发送CPM状态迁移事件，在其中，通过notifyListeners方法中的listener.onStateChanged(newState);向所有监听这发送状态迁移广播，通过传递CpmsState的status code进行状态迁移目标通知。深度睡眠模式与电源消息序列只有 VMCU 可以启动深度睡眠。启动深度睡眠后，VMCU 会通过 VHAL 向 CPMS 发送通知。同时CPM会提供一个新的状态ID，然后CPMS通过上述方式向所有监听者发送该状态来实现状态迁移。状态迁移消息序列如下图所示：注：Garage Modes ends为等待车库模式结束，正常下电流程中，会进行车库模式的流程，但是如果VHAL返回SLEEP_IMMEDIATELY与SHUTDOWN_IMMEDIATELY信号时，即要求立刻下电，则跳过车库模式。 2022-07-21 11:40 UtopiaXC 于大连