Implement ScheduleTask API using grpc.

Implement the ScheduleTask APIs in reference remote access
HAL by using grpc to communicate with an external grpc server.

Test: atest RemoteAccessServiceUnitTest
Bug: 297271235
Change-Id: I2d363aa244c842cea5be0c35f4f3a7961eb3cc0b
This commit is contained in:
Yu Shan
2023-08-30 11:44:13 -07:00
parent e5bdf5aa64
commit 72d6f8944d
5 changed files with 510 additions and 18 deletions

View File

@@ -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<GetRemoteTasksResponse>* AsyncGetRemoteTasksRaw(
[[maybe_unused]] ClientContext* context,
@@ -83,6 +108,76 @@ class MockGrpcClientStub : public WakeupClient::StubInterface {
[[maybe_unused]] CompletionQueue* c) {
return nullptr;
}
ClientAsyncResponseReaderInterface<ScheduleTaskResponse>* AsyncScheduleTaskRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const ScheduleTaskRequest& request,
[[maybe_unused]] CompletionQueue* cq) {
return nullptr;
}
ClientAsyncResponseReaderInterface<ScheduleTaskResponse>* PrepareAsyncScheduleTaskRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const ScheduleTaskRequest& request,
[[maybe_unused]] CompletionQueue* c) {
return nullptr;
}
ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>* AsyncUnscheduleTaskRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const UnscheduleTaskRequest& request,
[[maybe_unused]] CompletionQueue* cq) {
return nullptr;
}
ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>* PrepareAsyncUnscheduleTaskRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const UnscheduleTaskRequest& request,
[[maybe_unused]] CompletionQueue* c) {
return nullptr;
}
ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>* AsyncUnscheduleAllTasksRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const UnscheduleAllTasksRequest& request,
[[maybe_unused]] CompletionQueue* cq) {
return nullptr;
}
ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*
PrepareAsyncUnscheduleAllTasksRaw([[maybe_unused]] ClientContext* context,
[[maybe_unused]] const UnscheduleAllTasksRequest& request,
[[maybe_unused]] CompletionQueue* c) {
return nullptr;
}
ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>* AsyncIsTaskScheduledRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const IsTaskScheduledRequest& request,
[[maybe_unused]] CompletionQueue* cq) {
return nullptr;
}
ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>* PrepareAsyncIsTaskScheduledRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const IsTaskScheduledRequest& request,
[[maybe_unused]] CompletionQueue* c) {
return nullptr;
}
ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>* AsyncGetAllScheduledTasksRaw(
[[maybe_unused]] ClientContext* context,
[[maybe_unused]] const GetAllScheduledTasksRequest& request,
[[maybe_unused]] CompletionQueue* cq) {
return nullptr;
}
ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*
PrepareAsyncGetAllScheduledTasksRaw([[maybe_unused]] ClientContext* context,
[[maybe_unused]] const GetAllScheduledTasksRequest& request,
[[maybe_unused]] CompletionQueue* c) {
return nullptr;
}
};
} // namespace remoteaccess

View File

@@ -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.
*
* <p>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}.
*
* <p>Note that the scheduled task execution is on a best-effort basis. Multiple situations
* might cause the task not to execute successfully:
*
* <ul>
* <li>The vehicle is low on battery and the other device decides not to wake up Android.
* <li>User turns off vehicle while the task is executing.
* <li>The task logic itself fails.
*
* <p>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.
*
* <p>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.
*
* <p>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;
}

View File

@@ -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<ScheduleInfo>* 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();
}

View File

@@ -21,6 +21,7 @@
#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
#include <aidl/android/hardware/automotive/vehicle/VehiclePropValue.h>
#include <android/binder_status.h>
#include <gmock/gmock.h>
#include <grpcpp/test/mock_stream.h>
#include <gtest/gtest.h>
@@ -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<uint8_t> 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<GetRemoteTasksResponse>*, 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<ScheduleTaskResponse>*, AsyncScheduleTaskRaw,
(ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<ScheduleTaskResponse>*,
PrepareAsyncScheduleTaskRaw,
(ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>*, AsyncUnscheduleTaskRaw,
(ClientContext * context, const UnscheduleTaskRequest& request,
CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>*,
PrepareAsyncUnscheduleTaskRaw,
(ClientContext * context, const UnscheduleTaskRequest& request,
CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*,
AsyncUnscheduleAllTasksRaw,
(ClientContext * context, const UnscheduleAllTasksRequest& request,
CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*,
PrepareAsyncUnscheduleAllTasksRaw,
(ClientContext * context, const UnscheduleAllTasksRequest& request,
CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>*,
AsyncIsTaskScheduledRaw,
(ClientContext * context, const IsTaskScheduledRequest& request,
CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>*,
PrepareAsyncIsTaskScheduledRaw,
(ClientContext * context, const IsTaskScheduledRequest& request,
CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*,
AsyncGetAllScheduledTasksRaw,
(ClientContext * context, const GetAllScheduledTasksRequest& request,
CompletionQueue* cq));
MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*,
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<ScheduleInfo> 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

View File

@@ -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.
*