diff --git a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl index ccfa22de4e..e6f480856b 100644 --- a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl +++ b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl @@ -41,6 +41,7 @@ interface IRemoteAccess { void clearRemoteTaskCallback(); void notifyApStateChange(in android.hardware.automotive.remoteaccess.ApState state); boolean isTaskScheduleSupported(); + android.hardware.automotive.remoteaccess.TaskType[] getSupportedTaskTypesForScheduling(); void scheduleTask(in android.hardware.automotive.remoteaccess.ScheduleInfo scheduleInfo); void unscheduleTask(String clientId, String scheduleId); void unscheduleAllTasks(String clientId); diff --git a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl index a929e10827..a5d81cf9fc 100644 --- a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl +++ b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl @@ -36,6 +36,7 @@ package android.hardware.automotive.remoteaccess; parcelable ScheduleInfo { String clientId; String scheduleId; + android.hardware.automotive.remoteaccess.TaskType taskType; byte[] taskData; int count; long startTimeInEpochSeconds; diff --git a/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/TaskType.aidl b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/TaskType.aidl new file mode 100644 index 0000000000..da706269f0 --- /dev/null +++ b/automotive/remoteaccess/aidl_api/android.hardware.automotive.remoteaccess/current/android/hardware/automotive/remoteaccess/TaskType.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.automotive.remoteaccess; +@Backing(type="int") @VintfStability +enum TaskType { + CUSTOM = 0, + ENTER_GARAGE_MODE = 1, +} diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl index 4912651294..9863ed728d 100644 --- a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl +++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteAccess.aidl @@ -19,12 +19,39 @@ package android.hardware.automotive.remoteaccess; import android.hardware.automotive.remoteaccess.ApState; import android.hardware.automotive.remoteaccess.IRemoteTaskCallback; import android.hardware.automotive.remoteaccess.ScheduleInfo; +import android.hardware.automotive.remoteaccess.TaskType; /** - * Interface representing a remote wakeup client. + * The remote access HAL. * - * A wakeup client is a binary outside Android framework that communicates with - * a wakeup server and receives wake up command. + *

This HAL represents an external system that is always on even when Android + * is powered off. It is capable of wakeing up and notifying Android when a + * remote task arrives. + * + *

For cloud-based remote access, a cloud server will issue the remote task + * to the external system, which will then be forwarded to Android. The client + * is expected to call {@code setRemoteTaskCallback} to register the remote + * task callback and uses the information returned from {@code getVehicleId}, + * {@code getWakeupServiceName} and {@code getProcessorId} to register with + * a remote server. + * + *

For serverless remote access, the remote task comes from the external + * system alone and no server is involved. The external system may support + * scheduling a remote task to executed later through {@code scheduleTask}. + * + *

For both cloud-based and serverless remote access, the ideal use case + * is to wake up Android when the vehicle is not in use and then shutdown + * Android after the task is complete. However, user may access the vehicle + * during this period, and Android must not be shutdown if this happens. + * + *

If this interface is implemented, then VHAL property + * {@code VEHICLE_IN_USE} must be supported to represent whether the vehicle is + * currently in use. Android will check this before sending the shutdown + * request. + * + *

The external power controller system must also check whether vehicle is + * in use upon receiving the shutdown request and makes sure that an + * user-unexpected shutdown must not happen. */ @VintfStability interface IRemoteAccess { @@ -109,6 +136,17 @@ interface IRemoteAccess { */ boolean isTaskScheduleSupported(); + /** + * Returns the supported task types for scheduling. + * + *

If task scheduling is not supported, this returns an empty array. + * + *

Otherwise, at least {@code TaskType.CUSTOM} must be supported. + * + * @return An array of supported task types. + */ + TaskType[] getSupportedTaskTypesForScheduling(); + /** * Schedules a task to be executed later even when the vehicle is off. * @@ -127,6 +165,8 @@ interface IRemoteAccess { * *

Must return {@code EX_ILLEGAL_ARGUMENT} if a pending schedule with the same * {@code scheduleId} for this client exists. + * + *

Must return {@code EX_ILLEGAL_ARGUMENT} if the task type is not supported. */ void scheduleTask(in ScheduleInfo scheduleInfo); diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl index 2cd7a5db6b..ee6f900525 100644 --- a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl +++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.aidl @@ -22,7 +22,7 @@ package android.hardware.automotive.remoteaccess; @VintfStability interface IRemoteTaskCallback { /** - * A callback that is called when a remote task is requested. + * A callback that is called when a custom type remote task is requested. * * The data is passed down from the remote server to the remote task client * which is an Android application, and is not interpreted/parsed by the diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl index cf1437bf1b..40fba6f2a3 100644 --- a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl +++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/ScheduleInfo.aidl @@ -16,6 +16,8 @@ package android.hardware.automotive.remoteaccess; +import android.hardware.automotive.remoteaccess.TaskType; + @VintfStability @JavaDerive(equals=true, toString=true) parcelable ScheduleInfo { @@ -30,9 +32,15 @@ parcelable ScheduleInfo { * scheduleId will return {@code EX_ILLEGAL_ARGUMENT}. */ String scheduleId; + /** + * The type for the task. + */ + TaskType taskType; /** * The opaque task data that will be sent back to the remote task client app when the task is * executed. It is not interpreted/parsed by the Android system. + * + *

This is only used for {@code TaskType.CUSTOM}. */ byte[] taskData; /** diff --git a/automotive/remoteaccess/android/hardware/automotive/remoteaccess/TaskType.aidl b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/TaskType.aidl new file mode 100644 index 0000000000..761eb1515b --- /dev/null +++ b/automotive/remoteaccess/android/hardware/automotive/remoteaccess/TaskType.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.automotive.remoteaccess; + +@VintfStability +@Backing(type="int") +enum TaskType { + /** + * A custom task that is opaque to anyone other than the remote task client app. + * + *

The opaque task data in the {@code ScheduleInfo} will be sent back to the app when the + * task is to be executed. + */ + CUSTOM = 0, + /** + * Enters the garage mode if allowed. + * + *

Make the Android system enters garage mode if vehicle is currently not in use and + * entering garage mode is allowed (e.g. battery level is high enough). + * + *

This is based on best-effort and it is not guaranteed. + * + *

If allowed, the external system should set {@code AP_POWER_BOOTUP_REASON} to + * {@code SYSTEM_ENTER_GARAGE_MODE} and then boot up (or resume) the head unit. + */ + ENTER_GARAGE_MODE = 1, +} diff --git a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h index 1fc4037ae2..23b4ebe505 100644 --- a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h +++ b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h @@ -81,6 +81,9 @@ class RemoteAccessService ndk::ScopedAStatus isTaskScheduleSupported(bool* out) override; + ndk::ScopedAStatus getSupportedTaskTypesForScheduling( + std::vector* out) override; + ndk::ScopedAStatus scheduleTask( const aidl::android::hardware::automotive::remoteaccess::ScheduleInfo& scheduleInfo) override; diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp index 0944d8699d..55211345b9 100644 --- a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp +++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp @@ -40,6 +40,7 @@ namespace { using ::aidl::android::hardware::automotive::remoteaccess::ApState; using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback; using ::aidl::android::hardware::automotive::remoteaccess::ScheduleInfo; +using ::aidl::android::hardware::automotive::remoteaccess::TaskType; using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; using ::android::base::Error; using ::android::base::ParseInt; @@ -319,6 +320,13 @@ ScopedAStatus RemoteAccessService::isTaskScheduleSupported(bool* out) { return ScopedAStatus::ok(); } +ndk::ScopedAStatus RemoteAccessService::getSupportedTaskTypesForScheduling( + std::vector* out) { + // TODO(b/316233421): support ENTER_GARAGE_MODE type. + out->push_back(TaskType::CUSTOM); + return ScopedAStatus::ok(); +} + ScopedAStatus RemoteAccessService::scheduleTask(const ScheduleInfo& scheduleInfo) { ClientContext context; ScheduleTaskRequest request = {}; diff --git a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp index c0038c270b..4af0003920 100644 --- a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp +++ b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp @@ -48,6 +48,7 @@ using ::android::frameworks::automotive::vhal::VhalClientResult; using ::aidl::android::hardware::automotive::remoteaccess::ApState; using ::aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback; using ::aidl::android::hardware::automotive::remoteaccess::ScheduleInfo; +using ::aidl::android::hardware::automotive::remoteaccess::TaskType; using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; using ::grpc::ClientAsyncReaderInterface; @@ -61,6 +62,7 @@ using ::grpc::testing::MockClientReader; using ::ndk::ScopedAStatus; using ::testing::_; using ::testing::DoAll; +using ::testing::ElementsAre; using ::testing::Return; using ::testing::SetArgPointee; @@ -434,6 +436,14 @@ TEST_F(RemoteAccessServiceUnitTest, TestIsTaskScheduleSupported) { EXPECT_TRUE(out); } +TEST_F(RemoteAccessServiceUnitTest, TestGetSupportedTaskTypesForScheduling) { + std::vector out; + ScopedAStatus status = getService()->getSupportedTaskTypesForScheduling(&out); + + EXPECT_TRUE(status.isOk()); + EXPECT_THAT(out, ElementsAre(TaskType::CUSTOM)); +} + TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask) { ScheduleTaskRequest grpcRequest = {}; EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask) diff --git a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl index 9720aca787..55af2ab0fa 100644 --- a/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl +++ b/automotive/vehicle/aidl_property/aidl_api/android.hardware.automotive.vehicle.property/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl @@ -37,4 +37,5 @@ enum VehicleApPowerBootupReason { USER_POWER_ON = 0, SYSTEM_USER_DETECTION = 1, SYSTEM_REMOTE_ACCESS = 2, + SYSTEM_ENTER_GARAGE_MODE = 3, } diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl index e325b380b7..8c8c2daefb 100644 --- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl +++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl @@ -34,7 +34,24 @@ enum VehicleApPowerBootupReason { SYSTEM_USER_DETECTION = 1, /** * Automatic power on to execute a remote task. This is triggered by - * receiving a wakeup message from TCU wakeup client. + * receiving a wakeup message from an external system in the vehicle. */ SYSTEM_REMOTE_ACCESS = 2, + /** + * Automatic power on to enter garage mode. This is triggered by + * receiving a wakeup message from an external system in the vehicle. + * + * Note that this does not necessarily mean Android will enter + * the garage mode since user may enter the vehicle after this is set. + * The system will only enter garage mode if VEHICLE_IN_USE is not true + * upon check. + * + * To consider the Time-Of-Check-Time-Of-Use issue, there is a slight chance + * that the vehicle become in-use after car service does the VEHICLE_IN_USE + * check. The external power controller must also check whether the vehicle + * is in use upon receiving the SHUTDOWN_REQUEST, before sending out + * SHUTDOWN_PREPARE, to make sure the system does not enter garage mode or + * shutdown if the vehicle is currently in use. + */ + SYSTEM_ENTER_GARAGE_MODE = 3, } diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl index 88c8733bb9..fb8f730398 100644 --- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl +++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl @@ -4732,12 +4732,22 @@ enum VehicleProperty { /** * Request the head unit to be shutdown. * + *

This is required for executing a task when the head unit is powered off (remote task + * feature). After the head unit is powered-on to execute the task, the head unit should + * be shutdown. The head unit will send this message once the task is finished. + * + *

This is not for the case when a user wants to shutdown the head unit. + * *

This usually involves telling a separate system outside the head unit (e.g. a power * controller) to prepare shutting down the head unit. * - *

This does not mean the head unit will shutdown immediately. + *

Note that the external system must validate whether this request is valid by checking + * whether the vehicle is currently in use. If a user enters the vehicle after a + * SHUTDOWN_REQUEST is sent, then the system must ignore this request. It + * is recommended to store a VehicleInUse property in the power controller and exposes it + * through VEHICLE_IN_USE property. A shutdown request must be ignored if VehicleInUse is true. * - *

This means that another system will start sending a shutdown signal to the head unit, + *

If allowed, the external system will start sending a shutdown signal to the head unit, * which will cause VHAL to send SHUTDOWN_PREPARE message to Android. Android will then start * the shut down process by handling the message. *