diff --git a/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp index 292c80e7b6..9224ebcf09 100644 --- a/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp +++ b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp @@ -55,6 +55,31 @@ class MockGrpcClientStub : public WakeupClient::StubInterface { return Status::OK; } + Status ScheduleTask(ClientContext* context, const ScheduleTaskRequest& request, + ScheduleTaskResponse* response) { + return Status::OK; + } + + Status UnscheduleTask(ClientContext* context, const UnscheduleTaskRequest& request, + UnscheduleTaskResponse* response) { + return Status::OK; + } + + Status UnscheduleAllTasks(ClientContext* context, const UnscheduleAllTasksRequest& request, + UnscheduleAllTasksResponse* response) { + return Status::OK; + } + + Status IsTaskScheduled(ClientContext* context, const IsTaskScheduledRequest& request, + IsTaskScheduledResponse* response) { + return Status::OK; + } + + Status GetAllScheduledTasks(ClientContext* context, const GetAllScheduledTasksRequest& request, + GetAllScheduledTasksResponse* response) { + return Status::OK; + } + // Async methods which we do not care. ClientAsyncReaderInterface* AsyncGetRemoteTasksRaw( [[maybe_unused]] ClientContext* context, @@ -83,6 +108,76 @@ class MockGrpcClientStub : public WakeupClient::StubInterface { [[maybe_unused]] CompletionQueue* c) { return nullptr; } + + ClientAsyncResponseReaderInterface* AsyncScheduleTaskRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const ScheduleTaskRequest& request, + [[maybe_unused]] CompletionQueue* cq) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* PrepareAsyncScheduleTaskRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const ScheduleTaskRequest& request, + [[maybe_unused]] CompletionQueue* c) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* AsyncUnscheduleTaskRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const UnscheduleTaskRequest& request, + [[maybe_unused]] CompletionQueue* cq) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* PrepareAsyncUnscheduleTaskRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const UnscheduleTaskRequest& request, + [[maybe_unused]] CompletionQueue* c) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* AsyncUnscheduleAllTasksRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const UnscheduleAllTasksRequest& request, + [[maybe_unused]] CompletionQueue* cq) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* + PrepareAsyncUnscheduleAllTasksRaw([[maybe_unused]] ClientContext* context, + [[maybe_unused]] const UnscheduleAllTasksRequest& request, + [[maybe_unused]] CompletionQueue* c) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* AsyncIsTaskScheduledRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const IsTaskScheduledRequest& request, + [[maybe_unused]] CompletionQueue* cq) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* PrepareAsyncIsTaskScheduledRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const IsTaskScheduledRequest& request, + [[maybe_unused]] CompletionQueue* c) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* AsyncGetAllScheduledTasksRaw( + [[maybe_unused]] ClientContext* context, + [[maybe_unused]] const GetAllScheduledTasksRequest& request, + [[maybe_unused]] CompletionQueue* cq) { + return nullptr; + } + + ClientAsyncResponseReaderInterface* + PrepareAsyncGetAllScheduledTasksRaw([[maybe_unused]] ClientContext* context, + [[maybe_unused]] const GetAllScheduledTasksRequest& request, + [[maybe_unused]] CompletionQueue* c) { + return nullptr; + } }; } // namespace remoteaccess diff --git a/automotive/remoteaccess/hal/default/proto/wakeup_client.proto b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto index 4fe0d0177b..e061016daf 100644 --- a/automotive/remoteaccess/hal/default/proto/wakeup_client.proto +++ b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto @@ -18,6 +18,12 @@ syntax = "proto3"; package android.hardware.automotive.remoteaccess; +enum ErrorCode { + OK = 0; + UNSPECIFIED = 1; + INVALID_ARG = 2; +} + /** * Service provided by a wakeup client running on TCU. */ @@ -50,6 +56,50 @@ service WakeupClient { * to wake up AP. */ rpc NotifyWakeupRequired(NotifyWakeupRequiredRequest) returns (NotifyWakeupRequiredResponse) {} + + /** + * Schedules a task to be executed later even when the vehicle is off. + * + *

This sends a scheduled task message to a device external to Android so that the device + * can wake up Android and deliver the task through {@link IRemoteTaskCallback}. + * + *

Note that the scheduled task execution is on a best-effort basis. Multiple situations + * might cause the task not to execute successfully: + * + *

    + *
  • The vehicle is low on battery and the other device decides not to wake up Android. + *
  • User turns off vehicle while the task is executing. + *
  • The task logic itself fails. + * + *

    Must return a response with error code: {@code INVALID_ARG} if a pending schedule with the + * same {@code scheduleId} for this client exists. + */ + rpc ScheduleTask(ScheduleTaskRequest) returns (ScheduleTaskResponse) {} + + /** + * Unschedules a scheduled task. + * + *

    Does nothing if a pending schedule with {@code clientId} and {@code scheduleId} does not + * exist. + */ + rpc UnscheduleTask(UnscheduleTaskRequest) returns (UnscheduleTaskResponse) {} + + /** + * Unschedules all scheduled tasks for the client. + */ + rpc UnscheduleAllTasks(UnscheduleAllTasksRequest) returns (UnscheduleAllTasksResponse) {} + + /** + * Returns whether the specified task is scheduled. + */ + rpc IsTaskScheduled(IsTaskScheduledRequest) returns (IsTaskScheduledResponse) {} + + /** + * Gets all pending scheduled tasks for the client. + * + *

    The finished scheduled tasks will not be included. + */ + rpc GetAllScheduledTasks(GetAllScheduledTasksRequest) returns (GetAllScheduledTasksResponse) {} } message GetRemoteTasksRequest {} @@ -64,3 +114,50 @@ message NotifyWakeupRequiredRequest { } message NotifyWakeupRequiredResponse {} + +message ScheduleTaskRequest { + GrpcScheduleInfo scheduleInfo = 1; +} + +message ScheduleTaskResponse { + ErrorCode errorCode = 1; +} + +message GrpcScheduleInfo { + string clientId = 1; + string scheduleId = 2; + bytes data = 3; + int32 count = 4; + int64 startTimeInEpochSeconds = 5; + int64 periodicInSeconds = 6; +} + +message UnscheduleTaskRequest { + string clientId = 1; + string scheduleId = 2; +} + +message UnscheduleTaskResponse {} + +message UnscheduleAllTasksRequest { + string clientId = 1; +} + +message UnscheduleAllTasksResponse {} + +message IsTaskScheduledRequest { + string clientId = 1; + string scheduleId = 2; +} + +message IsTaskScheduledResponse { + bool isTaskScheduled = 1; +} + +message GetAllScheduledTasksRequest { + string clientId = 1; +} + +message GetAllScheduledTasksResponse { + repeated GrpcScheduleInfo allScheduledTasks = 1; +} diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp index 7721bf404a..0944d8699d 100644 --- a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp +++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp @@ -314,38 +314,106 @@ ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState) return ScopedAStatus::ok(); } -ScopedAStatus RemoteAccessService::isTaskScheduleSupported([[maybe_unused]] bool* out) { - // TODO(b/297271235): implement this. +ScopedAStatus RemoteAccessService::isTaskScheduleSupported(bool* out) { + *out = true; return ScopedAStatus::ok(); } -ScopedAStatus RemoteAccessService::scheduleTask([[maybe_unused]] const ScheduleInfo& scheduleInfo) { - // TODO(b/297271235): implement this. +ScopedAStatus RemoteAccessService::scheduleTask(const ScheduleInfo& scheduleInfo) { + ClientContext context; + ScheduleTaskRequest request = {}; + ScheduleTaskResponse response = {}; + request.mutable_scheduleinfo()->set_clientid(scheduleInfo.clientId); + request.mutable_scheduleinfo()->set_scheduleid(scheduleInfo.scheduleId); + request.mutable_scheduleinfo()->set_data(scheduleInfo.taskData.data(), + scheduleInfo.taskData.size()); + request.mutable_scheduleinfo()->set_count(scheduleInfo.count); + request.mutable_scheduleinfo()->set_starttimeinepochseconds( + scheduleInfo.startTimeInEpochSeconds); + request.mutable_scheduleinfo()->set_periodicinseconds(scheduleInfo.periodicInSeconds); + Status status = mGrpcStub->ScheduleTask(&context, request, &response); + if (!status.ok()) { + return rpcStatusToScopedAStatus(status, "Failed to call ScheduleTask"); + } + int errorCode = response.errorcode(); + switch (errorCode) { + case ErrorCode::OK: + return ScopedAStatus::ok(); + case ErrorCode::INVALID_ARG: + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + default: + // Should not happen. + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + -1, ("Got unknown error code: " + ErrorCode_Name(errorCode) + + " from remote access HAL") + .c_str()); + } +} + +ScopedAStatus RemoteAccessService::unscheduleTask(const std::string& clientId, + const std::string& scheduleId) { + ClientContext context; + UnscheduleTaskRequest request = {}; + UnscheduleTaskResponse response = {}; + request.set_clientid(clientId); + request.set_scheduleid(scheduleId); + Status status = mGrpcStub->UnscheduleTask(&context, request, &response); + if (!status.ok()) { + return rpcStatusToScopedAStatus(status, "Failed to call UnscheduleTask"); + } return ScopedAStatus::ok(); } -ScopedAStatus RemoteAccessService::unscheduleTask([[maybe_unused]] const std::string& clientId, - [[maybe_unused]] const std::string& scheduleId) { - // TODO(b/297271235): implement this. +ScopedAStatus RemoteAccessService::unscheduleAllTasks(const std::string& clientId) { + ClientContext context; + UnscheduleAllTasksRequest request = {}; + UnscheduleAllTasksResponse response = {}; + request.set_clientid(clientId); + Status status = mGrpcStub->UnscheduleAllTasks(&context, request, &response); + if (!status.ok()) { + return rpcStatusToScopedAStatus(status, "Failed to call UnscheduleAllTasks"); + } return ScopedAStatus::ok(); } -ScopedAStatus RemoteAccessService::unscheduleAllTasks( - [[maybe_unused]] const std::string& clientId) { - // TODO(b/297271235): implement this. - return ScopedAStatus::ok(); -} - -ScopedAStatus RemoteAccessService::isTaskScheduled([[maybe_unused]] const std::string& clientId, - [[maybe_unused]] const std::string& scheduleId, - [[maybe_unused]] bool* out) { - // TODO(b/297271235): implement this. +ScopedAStatus RemoteAccessService::isTaskScheduled(const std::string& clientId, + const std::string& scheduleId, bool* out) { + ClientContext context; + IsTaskScheduledRequest request = {}; + IsTaskScheduledResponse response = {}; + request.set_clientid(clientId); + request.set_scheduleid(scheduleId); + Status status = mGrpcStub->IsTaskScheduled(&context, request, &response); + if (!status.ok()) { + return rpcStatusToScopedAStatus(status, "Failed to call isTaskScheduled"); + } + *out = response.istaskscheduled(); return ScopedAStatus::ok(); } ScopedAStatus RemoteAccessService::getAllScheduledTasks(const std::string& clientId, std::vector* out) { - // TODO(b/297271235): implement this. + ClientContext context; + GetAllScheduledTasksRequest request = {}; + GetAllScheduledTasksResponse response = {}; + request.set_clientid(clientId); + Status status = mGrpcStub->GetAllScheduledTasks(&context, request, &response); + if (!status.ok()) { + return rpcStatusToScopedAStatus(status, "Failed to call isTaskScheduled"); + } + out->clear(); + for (int i = 0; i < response.allscheduledtasks_size(); i++) { + const GrpcScheduleInfo& rpcScheduleInfo = response.allscheduledtasks(i); + ScheduleInfo scheduleInfo = { + .clientId = rpcScheduleInfo.clientid(), + .scheduleId = rpcScheduleInfo.scheduleid(), + .taskData = stringToBytes(rpcScheduleInfo.data()), + .count = rpcScheduleInfo.count(), + .startTimeInEpochSeconds = rpcScheduleInfo.starttimeinepochseconds(), + .periodicInSeconds = rpcScheduleInfo.periodicinseconds(), + }; + out->push_back(std::move(scheduleInfo)); + } return ScopedAStatus::ok(); } diff --git a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp index c5afd6300f..c0038c270b 100644 --- a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp +++ b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,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::vehicle::VehiclePropValue; using ::grpc::ClientAsyncReaderInterface; @@ -63,6 +65,12 @@ using ::testing::Return; using ::testing::SetArgPointee; constexpr char kTestVin[] = "test_VIN"; +const std::string kTestClientId = "test client id"; +const std::string kTestScheduleId = "test schedule id"; +const std::vector kTestData = {0xde, 0xad, 0xbe, 0xef}; +constexpr int32_t kTestCount = 1234; +constexpr int64_t kTestStartTimeInEpochSeconds = 2345; +constexpr int64_t kTestPeriodicInSeconds = 123; } // namespace @@ -73,6 +81,21 @@ class MockGrpcClientStub : public WakeupClient::StubInterface { MOCK_METHOD(Status, NotifyWakeupRequired, (ClientContext * context, const NotifyWakeupRequiredRequest& request, NotifyWakeupRequiredResponse* response)); + MOCK_METHOD(Status, ScheduleTask, + (ClientContext * context, const ScheduleTaskRequest& request, + ScheduleTaskResponse* response)); + MOCK_METHOD(Status, UnscheduleTask, + (ClientContext * context, const UnscheduleTaskRequest& request, + UnscheduleTaskResponse* response)); + MOCK_METHOD(Status, UnscheduleAllTasks, + (ClientContext * context, const UnscheduleAllTasksRequest& request, + UnscheduleAllTasksResponse* response)); + MOCK_METHOD(Status, IsTaskScheduled, + (ClientContext * context, const IsTaskScheduledRequest& request, + IsTaskScheduledResponse* response)); + MOCK_METHOD(Status, GetAllScheduledTasks, + (ClientContext * context, const GetAllScheduledTasksRequest& request, + GetAllScheduledTasksResponse* response)); // Async methods which we do not care. MOCK_METHOD(ClientAsyncReaderInterface*, AsyncGetRemoteTasksRaw, (ClientContext * context, const GetRemoteTasksRequest& request, CompletionQueue* cq, @@ -88,6 +111,42 @@ class MockGrpcClientStub : public WakeupClient::StubInterface { PrepareAsyncNotifyWakeupRequiredRaw, (ClientContext * context, const NotifyWakeupRequiredRequest& request, CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, AsyncScheduleTaskRaw, + (ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + PrepareAsyncScheduleTaskRaw, + (ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, AsyncUnscheduleTaskRaw, + (ClientContext * context, const UnscheduleTaskRequest& request, + CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + PrepareAsyncUnscheduleTaskRaw, + (ClientContext * context, const UnscheduleTaskRequest& request, + CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + AsyncUnscheduleAllTasksRaw, + (ClientContext * context, const UnscheduleAllTasksRequest& request, + CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + PrepareAsyncUnscheduleAllTasksRaw, + (ClientContext * context, const UnscheduleAllTasksRequest& request, + CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + AsyncIsTaskScheduledRaw, + (ClientContext * context, const IsTaskScheduledRequest& request, + CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + PrepareAsyncIsTaskScheduledRaw, + (ClientContext * context, const IsTaskScheduledRequest& request, + CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + AsyncGetAllScheduledTasksRaw, + (ClientContext * context, const GetAllScheduledTasksRequest& request, + CompletionQueue* cq)); + MOCK_METHOD(ClientAsyncResponseReaderInterface*, + PrepareAsyncGetAllScheduledTasksRaw, + (ClientContext * context, const GetAllScheduledTasksRequest& request, + CompletionQueue* cq)); }; class FakeVhalClient final : public android::frameworks::automotive::vhal::IVhalClient { @@ -367,6 +426,174 @@ TEST_F(RemoteAccessServiceUnitTest, testGetVehicleId) { ASSERT_EQ(vehicleId, kTestVin); } +TEST_F(RemoteAccessServiceUnitTest, TestIsTaskScheduleSupported) { + bool out = false; + ScopedAStatus status = getService()->isTaskScheduleSupported(&out); + + EXPECT_TRUE(status.isOk()); + EXPECT_TRUE(out); +} + +TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask) { + ScheduleTaskRequest grpcRequest = {}; + EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask) + .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context, + const ScheduleTaskRequest& request, + [[maybe_unused]] ScheduleTaskResponse* response) { + grpcRequest = request; + return Status(); + }); + ScheduleInfo scheduleInfo = { + .clientId = kTestClientId, + .scheduleId = kTestScheduleId, + .taskData = kTestData, + .count = kTestCount, + .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds, + .periodicInSeconds = kTestPeriodicInSeconds, + }; + + ScopedAStatus status = getService()->scheduleTask(scheduleInfo); + + ASSERT_TRUE(status.isOk()); + EXPECT_EQ(grpcRequest.scheduleinfo().clientid(), kTestClientId); + EXPECT_EQ(grpcRequest.scheduleinfo().scheduleid(), kTestScheduleId); + EXPECT_EQ(grpcRequest.scheduleinfo().data(), std::string(kTestData.begin(), kTestData.end())); + EXPECT_EQ(grpcRequest.scheduleinfo().count(), kTestCount); + EXPECT_EQ(grpcRequest.scheduleinfo().starttimeinepochseconds(), kTestStartTimeInEpochSeconds); + EXPECT_EQ(grpcRequest.scheduleinfo().periodicinseconds(), kTestPeriodicInSeconds); +} + +TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_InvalidArg) { + EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask) + .WillOnce([]([[maybe_unused]] ClientContext* context, + [[maybe_unused]] const ScheduleTaskRequest& request, + ScheduleTaskResponse* response) { + response->set_errorcode(ErrorCode::INVALID_ARG); + return Status(); + }); + ScheduleInfo scheduleInfo = { + .clientId = kTestClientId, + .scheduleId = kTestScheduleId, + .taskData = kTestData, + .count = kTestCount, + .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds, + .periodicInSeconds = kTestPeriodicInSeconds, + }; + + ScopedAStatus status = getService()->scheduleTask(scheduleInfo); + + ASSERT_FALSE(status.isOk()); + ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT); +} + +TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_UnspecifiedError) { + EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask) + .WillOnce([]([[maybe_unused]] ClientContext* context, + [[maybe_unused]] const ScheduleTaskRequest& request, + ScheduleTaskResponse* response) { + response->set_errorcode(ErrorCode::UNSPECIFIED); + return Status(); + }); + ScheduleInfo scheduleInfo = { + .clientId = kTestClientId, + .scheduleId = kTestScheduleId, + .taskData = kTestData, + .count = kTestCount, + .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds, + .periodicInSeconds = kTestPeriodicInSeconds, + }; + + ScopedAStatus status = getService()->scheduleTask(scheduleInfo); + + ASSERT_FALSE(status.isOk()); + ASSERT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC); +} + +TEST_F(RemoteAccessServiceUnitTest, TestUnscheduleTask) { + UnscheduleTaskRequest grpcRequest = {}; + EXPECT_CALL(*getGrpcWakeupClientStub(), UnscheduleTask) + .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context, + const UnscheduleTaskRequest& request, + [[maybe_unused]] UnscheduleTaskResponse* response) { + grpcRequest = request; + return Status(); + }); + + ScopedAStatus status = getService()->unscheduleTask(kTestClientId, kTestScheduleId); + + ASSERT_TRUE(status.isOk()); + EXPECT_EQ(grpcRequest.clientid(), kTestClientId); + EXPECT_EQ(grpcRequest.scheduleid(), kTestScheduleId); +} + +TEST_F(RemoteAccessServiceUnitTest, TestUnscheduleAllTasks) { + UnscheduleAllTasksRequest grpcRequest = {}; + EXPECT_CALL(*getGrpcWakeupClientStub(), UnscheduleAllTasks) + .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context, + const UnscheduleAllTasksRequest& request, + [[maybe_unused]] UnscheduleAllTasksResponse* response) { + grpcRequest = request; + return Status(); + }); + + ScopedAStatus status = getService()->unscheduleAllTasks(kTestClientId); + + ASSERT_TRUE(status.isOk()); + EXPECT_EQ(grpcRequest.clientid(), kTestClientId); +} + +TEST_F(RemoteAccessServiceUnitTest, TestIsTaskScheduled) { + bool isTaskScheduled = false; + IsTaskScheduledRequest grpcRequest = {}; + EXPECT_CALL(*getGrpcWakeupClientStub(), IsTaskScheduled) + .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context, + const IsTaskScheduledRequest& request, + IsTaskScheduledResponse* response) { + grpcRequest = request; + response->set_istaskscheduled(true); + return Status(); + }); + + ScopedAStatus status = + getService()->isTaskScheduled(kTestClientId, kTestScheduleId, &isTaskScheduled); + + ASSERT_TRUE(status.isOk()); + EXPECT_TRUE(isTaskScheduled); + EXPECT_EQ(grpcRequest.clientid(), kTestClientId); + EXPECT_EQ(grpcRequest.scheduleid(), kTestScheduleId); +} + +TEST_F(RemoteAccessServiceUnitTest, testGetAllScheduledTasks) { + std::vector result; + GetAllScheduledTasksRequest grpcRequest = {}; + EXPECT_CALL(*getGrpcWakeupClientStub(), GetAllScheduledTasks) + .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context, + const GetAllScheduledTasksRequest& request, + GetAllScheduledTasksResponse* response) { + grpcRequest = request; + GrpcScheduleInfo* newInfo = response->add_allscheduledtasks(); + newInfo->set_clientid(kTestClientId); + newInfo->set_scheduleid(kTestScheduleId); + newInfo->set_data(kTestData.data(), kTestData.size()); + newInfo->set_count(kTestCount); + newInfo->set_starttimeinepochseconds(kTestStartTimeInEpochSeconds); + newInfo->set_periodicinseconds(kTestPeriodicInSeconds); + return Status(); + }); + + ScopedAStatus status = getService()->getAllScheduledTasks(kTestClientId, &result); + + ASSERT_TRUE(status.isOk()); + EXPECT_EQ(grpcRequest.clientid(), kTestClientId); + ASSERT_EQ(result.size(), 1u); + ASSERT_EQ(result[0].clientId, kTestClientId); + ASSERT_EQ(result[0].scheduleId, kTestScheduleId); + ASSERT_EQ(result[0].taskData, kTestData); + ASSERT_EQ(result[0].count, kTestCount); + ASSERT_EQ(result[0].startTimeInEpochSeconds, kTestStartTimeInEpochSeconds); + ASSERT_EQ(result[0].periodicInSeconds, kTestPeriodicInSeconds); +} + } // namespace remoteaccess } // namespace automotive } // namespace hardware diff --git a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h index 4159e83366..d0e076d999 100644 --- a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h +++ b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h @@ -117,22 +117,27 @@ class TestWakeupClientServiceImpl : public WakeupClient::Service { * to the client every 5s. */ void startGeneratingFakeTask(const std::string& clientId); + /** * stops generating fake tasks. */ void stopGeneratingFakeTask(); + /** * Returns whether we need to wakeup the target device to send remote tasks. */ bool isWakeupRequired(); + /** * Returns whether we have an active connection with the target device. */ bool isRemoteTaskConnectionAlive(); + /** * Injects a fake task with taskData to be sent to the specific client. */ void injectTask(const std::string& taskData, const std::string& clientId); + /** * Wakes up the target device. *