Android 14 引入了新的远程访问功能,使合作伙伴能够远程唤醒车辆中的 Android 以执行特定任务。例如,隔夜执行车库模式以应用软件更新。端到端工作流需要多个非 Android 组件。Android 未定义或提供非 Android 组件的实现(此责任由您承担)。
要了解详情,请参阅以下部分
工作流。客户端注册和任务交付的示例架构中多个组件之间工作流。
编写远程任务客户端。使用远程访问并学习如何编写远程任务客户端。
供应商实现。示例架构中用于支持远程访问的供应商组件。
恢复出厂设置和所有权转移。了解如何处理恢复出厂设置和车辆所有权转移。
测试远程访问客户端。了解如何测试远程访问功能。
架构
以下内容假定使用以下示例架构,该架构是假设性的,可能无法反映实际架构。OEM 应使实际实现适应其车辆和服务器架构。
图 1. 示例架构。
示例架构包含以下硬件组件
硬件组件 | 说明 |
---|---|
应用处理器 | 运行 Android 的处理器。Android 可能在此处理器上的虚拟机 (VM)(而不是实际硬件)上运行。 |
车辆处理器 | 负责控制应用处理器电源的处理器。 |
远程信息处理控制单元 (TCU) | 车辆中始终能够从云端接收远程消息的处理器。TCU 假定始终处于开启状态或低功耗模式。使用远程消息唤醒 TCU。 |
唤醒服务器 | 在云端运行的远程服务器,负责与车辆中的 TCU 通信以发出唤醒命令。 |
远程任务服务器 | 远程任务服务器在云端运行,与人员互动并管理远程任务。 |
示例架构包含以下软件组件,所有组件都在 Android 上运行
Android 上软件组件 | 说明 |
---|---|
Car Service | 提供远程访问 API 的 AAOS 框架服务。 |
远程任务客户端 | 供应商编写的 Service 类,用于执行远程任务。一个 Android 系统可以运行多个远程任务客户端。 |
远程访问 HAL | 必须为远程访问实现。 用于 AAOS 和非 Android 组件(如 TCU)之间通信的抽象层。 |
非 Android 软件组件如下所述
非 Android 软件组件 | 说明 |
---|---|
唤醒客户端 | 在 TCU 上运行的软件,用于维护与唤醒服务器的长期连接。它还维护与远程访问 HAL 的连接,以将远程任务交付到 Car Service。 |
唤醒服务器实现 | 与在 TCU 上运行的唤醒客户端通信的服务器。可以向唤醒客户端发送唤醒请求。 |
远程任务服务器实现 | 管理远程任务的服务器。用户与此服务器互动以发出和监控远程任务。 |
工作流
本节列出了示例工作流中的步骤。
示例工作流
详细的工作流可能类似于以下步骤
用户将车辆停在车库中。
合作伙伴希望在车辆互动不太可能的情况下,在夜间更新车辆。
合作伙伴云服务器向车辆发送更新系统远程任务。具体而言,是远程信息处理控制单元 (TCU)。
车辆的 TCU 唤醒 Android 电子控制单元 (ECU),OEM 服务触发车库模式。
Android 运行车库模式以通过 Google Play 下载和安装更新。
应用更新后,Android 将任务标记为已完成,并结束连接或达到指定的超时。
详细工作流
远程访问需要两个重要步骤。第一个是注册客户端,即将特定用户链接到在特定车辆上运行的特定远程任务客户端。另一个是交付任务,即将特定用户的远程任务交付到在特定车辆上运行的特定远程任务客户端。
注册客户端
要使用远程访问功能,用户必须至少打开一次远程任务客户端应用并完成客户端注册流程(粗体文本表示由 AAOS 实现的任务)
启动时,Car Service 从远程访问 HAL 获取车辆信息。
启动时,Car Service 基于 intent-filter 和权限启动所有远程任务客户端。
在远程任务客户端启动时,远程任务客户端向 Car Service 注册自身。
Car Service 将注册信息(包括车辆 ID 和客户端 ID)通知远程任务客户端。客户端 ID 是唯一的,由 Car Service 分配给此客户端。保证在同一车辆上的所有远程任务客户端中是唯一的。
用户通过远程任务客户端登录远程任务服务器,并为此车辆启用远程访问功能。此步骤通常涉及通过远程任务服务器进行身份验证。
远程任务客户端将用户的信息连同车辆 ID 和客户端 ID 上传到远程任务服务器,并请求其将用户与此特定客户端和此特定车辆关联起来。
可选地,此步骤可能涉及来自用户的额外双重身份验证。
远程任务服务器必须验证请求中提供的车辆 ID 是否与发送者的车辆 ID 匹配,这可以通过车辆证明来完成。
除非执行恢复出厂设置,否则每个用户每辆车需要进行一次客户端注册流程。客户端 ID 本地存储在 Car Service 中,对于同一客户端保持不变。
图 2. 注册客户端。
取消注册客户端
用户可以从车辆或远程任务服务器取消车辆与其帐号的关联
在车辆上,用户可以打开远程任务客户端应用并发出取消关联请求,以取消此车辆与其先前关联的用户帐号的关联。
在远程任务服务器上,用户可以登录其帐号并取消先前关联的车辆与此帐号的关联。
如果用户取消车辆与其帐号的关联,则远程任务服务器必须删除特定用户的存储映射。
交付任务
在云端
用户使用远程任务服务器向特定车辆发送远程任务。
远程任务服务器将用户 ID 映射到车辆 ID 和客户端 ID。它将任务数据、车辆 ID 和客户端 ID 发送到唤醒服务器。
唤醒服务器查找车辆 ID 的特定 TCU(假设 TCU 注册已完成),并将任务数据和客户端 ID 发送到 TCU。
在车辆上(粗体文本表示由 AAOS 执行的任务)
TCU 从远程服务器接收远程任务。
如果运行 AAOS 的应用处理器 (AP) 关闭,则 TCU 使用车辆处理器 (VP) 唤醒 AP。
Car Service 从 TCU 接收任务。
Car Service 将任务分发到相应的远程任务客户端。
远程任务客户端接收并执行任务。
(可选)远程任务客户端联系任务服务器以获取更多任务详情并执行任务。
(可选)远程任务客户端服务向任务服务器报告任务结果。
远程任务客户端在任务完成时通知 Car Service。
如果需要,Car Service 恢复车辆的电源状态。
图 3. 交付任务。
编写远程任务客户端
CarRemoteAccessManager
提供远程访问功能的 API。要了解详情,请参阅 CarRemoteAccessManager。远程任务客户端是执行远程任务并使用 CarRemoteAccessManager
的 Android 服务。这需要 PERMISSION_USE_REMOTE_ACCESS
和 PERMISSION_CONTROL_REMOTE_ACCESS
,并且必须为 RemoteTaskClientService
声明 intent 过滤器,例如
<service android:name=".remoteaccess.RemoteTaskClientService"
android:directBootAware="true"
android:exported="true">
<intent-filter>
<action android:name="android.car.remoteaccess.RemoteTaskClientService" />
</intent-filter>
</service>
远程任务客户端应在创建期间向 Car Service 注册自身
public final class RemoteTaskClientService extends Service {
@Override
public void onCreate() {
// mCar = Car.createCar()...
mRemoteAccessManager = (CarRemoteAccessManager)
mcar.getCarManager(Car.CAR_REMOTE_ACCESS_SERVICE);
if (mRemoteAccessManager == null) {
// Remote access feature is not supported.
return;
}
mRemoteAccessManager.setRemoteTaskClient(executor, mRemoteTaskClient);
}
}
它必须替换 onBind 函数以返回 null。
@Override
public IBinder onBind(Intent intent) {
return null;
}
Car Service 管理其生命周期。Car Service 在启动期间和远程任务到达时绑定到此服务。任务完成时,Car Service 解除与此服务的绑定。要了解详情,请参阅 管理服务的生命周期。
远程任务客户端作为系统用户运行,因此它无权访问任何用户特定数据。
以下示例展示了如何处理已注册的回调
private final class RemoteTaskClient
implements CarRemoteAccessManager.RemoteTaskClientCallback {
@Override
public void onRegistrationUpdated(
RemoteTaskClientRegistrationInfo info) {
// Register to remote task server using info.
}
@Override
public void onRemoteTaskRequested(String taskId,
byte[] data, int remainingTimeSec) {
// Parses the data and execute the task.
// Report task result to remote task server.
mRemoteAccessManager.reportRemoteTaskDone(taskId);
}
@Override
public void onShutdownStarting(CompleteableRemoteTaskFuture future) {
// Stop the executing task.
// Clear the pending task queue.
future.complete();
}
}
供应商实现
远程访问功能是可选的,默认情况下处于停用状态。要启用该功能,请添加 RRO,例如以下内容
// res/xml/overlays.xml
<?xml version="1.0" encoding="utf-8"?>
<overlay>
<item target="array/config_allowed_optional_car_features" value="@array/config_allowed_optional_car_features" />
</overlay>
// res/values/config.xml
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array translatable="false" name="config_allowed_optional_car_features">
<item>car_remote_access_service</item>
</string-array>
</resources>
// Android.bp
runtime_resource_overlay {
name: "RemoteAccessOverlay",
resource_dirs: ["res"],
manifest: "AndroidManifest.xml",
sdk_version: "current",
product_specific: true
}
或在 userdebug/eng 构建上使用以下 adb 命令
adb shell cmd car_service enable-feature car_remote_access_service
Android 上要求
远程访问 HAL
远程访问硬件抽象层 (HAL) 是供应商实现的抽象层,用于 AAOS 和另一个 ECU(例如 TCU)之间的通信。它对于支持远程访问功能是强制性的。如果未实现远程访问功能,则无需实现它。
该接口在 IRemoteAccess.aidl 中定义,包括以下方法
类 | 说明 |
---|---|
String getVehicleId() |
获取可被唤醒服务器识别的唯一车辆 ID。 |
String getWakeupServiceName() |
获取远程唤醒服务器的名称。 |
String getProcessorId() |
获取可被唤醒客户端识别的唯一处理器 ID。 |
void setRemoteTaskCallback(IRemoteTaskCallback callback)
设置在请求远程任务时要调用的回调。 |
|
void clearRemoteTaskCallback() |
清除先前设置的远程任务回调。 |
void notifyApStateChange(in ApState state)
检测应用处理器是否准备好接收远程任务。 |
回调接口在 IRemoteTaskCallback.aid
中定义。
类 | 说明 |
---|---|
oneway void onRemoteTaskRequested(String clientId, in byte[] data)
在请求远程任务时调用的回调。 |
请参阅带有外部 TCU 的参考实现。该实现使用长期读取流来接收远程任务,并支持以下 debug
命令
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default
车辆 HAL
为了支持远程访问功能,VHAL 必须支持以下属性
类 | 说明 |
---|---|
SHUTDOWN_REQUEST |
请求关闭信息娱乐系统。 |
VEHICLE_IN_USE |
|
要了解详情,请参阅支持的系统属性。
静默模式
远程访问功能必须支持静默模式,以便车辆可以在静默模式下启动以在没有用户在场时执行远程任务。使用静默模式,AAOS 设备启动时显示屏和音频关闭。
静默模式通过两个 Linux 内核 sysfs
文件控制。
类 | 说明 |
---|---|
/sys/kernel/silent_boot/pm_silentmode_kernel_state
表示当前静默模式。 |
|
/sys/kernel/silent_boot/pm_silentmode_hw_state
表示用于设置新静默模式的硬件信号。 |
车辆处理器发送 HW 信号到 Android SoC 以开启/关闭静默模式。信号(0 或 1)写入 /sys/kernel/silent_boot/pm_silentmode_hw_state
。然后,AAOS 框架相应地更新 /sys/kernel/silent_boot/pm_silentmode_kernel_state
,表示当前静默模式。AAOS 模块检查 /sys/kernel/silent_boot/pm_silentmode_kernel_state
以了解系统是否处于静默模式。
当收到远程任务并且 AAOS 启动时,车辆处理器设置静默模式并启动 AAOS,以便系统在显示屏/音频关闭的情况下启动。
车载非 Android 组件
车辆处理器
车辆处理器是车辆中可以控制运行 Android 的应用处理器的电源的处理器。在示例架构中,TCU 通过向车辆处理器发送信号来唤醒应用处理器。
车载非 Android 组件
车辆 TCU 始终可以接收远程消息。
唤醒客户端在 TCU 上运行,以确保与远程唤醒服务器的长期连接。
在 AP 上运行的 AAOS 可以通过远程访问 HAL 与在 TCU 上运行的唤醒客户端通信。
图 4. TCU(唤醒客户端)。
云端组件
唤醒服务器
唤醒服务器与 TCU 上的唤醒客户端通信,以
- 维护与车辆 TCU 的长期连接。
- 根据车辆 ID 查找特定 TCU。
- 报告车辆状态。例如,在线或离线,或上次在线时间到远程任务服务器。
在实际实现中,唤醒服务器可以与远程任务服务器合并。
远程任务服务器
远程任务服务器管理这些远程任务。
用户与服务器互动以启动新的远程任务并监控远程任务。
使用远程唤醒服务器唤醒车辆中的应用处理器。
与在车辆上运行的远程任务客户端互动。
存储客户端注册信息。这会将特定用户与特定车辆上的特定远程任务客户端关联起来。
通常,通过远程任务服务器发送到唤醒服务器、车辆 TCU 以及最终发送到远程任务客户端的任务数据只是一个任务 ID。远程任务客户端使用任务 ID 从远程任务服务器获取详细信息。
隐私和安全要求
任务 | 条件 | 要求 |
---|---|---|
TCU(唤醒客户端) | 必须 |
|
唤醒服务器 | 必须 |
|
远程任务客户端 | 必须 |
|
远程任务服务器 | 必须 |
|
恢复出厂设置和所有权转移
如果用户执行恢复出厂设置,则存储在 Car Service 中的客户端 ID 将被擦除。但是,服务器(远程任务服务器和远程唤醒服务器)不会收到通知。服务器保留从现在已过期的客户端 ID 到车辆的映射。因此,如果用户为车辆启动新的远程任务,它将使用过期的客户端 ID。车辆被唤醒,但远程任务无法执行,因为远程任务客户端具有不同的客户端 ID,该 ID 不匹配。
以下描述了恢复出厂设置的一种可能的实现。
当用户发出恢复出厂设置时,如果用户之前已关联车辆,则供应商会提示用户登录远程任务服务器并取消车辆与其帐号的关联。设备不保证在恢复出厂设置时具有网络访问权限。因此,在恢复出厂设置时从设备发出取消关联请求可能不可行。
每当车辆的所有权转移时,都应执行一些操作,以确保以前的所有者无法再向车辆发出远程任务。例如,可能会要求新所有者
执行恢复出厂设置。这确保了客户端 ID 被重新生成。在此步骤之后,以前的所有者仍然可以唤醒车辆,但无法再执行远程任务。
打开远程任务客户端应用并按照取消注册客户端流程操作,以取消车辆与以前所有者帐号的关联。新所有者可以按照注册客户端流程操作,以将车辆与其帐号关联并替换先前关联的帐号。
新所有者可以使用注册客户端流程,将车辆与其帐号关联并替换先前关联的帐号。
测试远程任务客户端
我们提供参考远程访问 HAL default
目录来测试远程任务客户端。您可以使用以下 debug
命令向 HAL 注入伪造的远程任务,如果您提供正确的客户端 ID,该任务将转发到您的远程任务客户端。您可以通过记录远程任务客户端实现中的注册信息来获取客户端 ID。
adb root && adb shell dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --inject-task [clientID] [taskData]