1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "RemoteAccessService.h"
18 
19 #include <AidlHalPropValue.h>
20 #include <IVhalClient.h>
21 #include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
22 #include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
23 #include <aidl/android/hardware/automotive/vehicle/VehiclePropValue.h>
24 #include <android/binder_status.h>
25 #include <gmock/gmock.h>
26 #include <grpcpp/test/mock_stream.h>
27 #include <gtest/gtest.h>
28 #include <wakeup_client.grpc.pb.h>
29 #include <chrono>
30 #include <thread>
31 
32 namespace android {
33 namespace hardware {
34 namespace automotive {
35 namespace remoteaccess {
36 
37 namespace {
38 
39 using ::android::base::ScopedLockAssertion;
40 using ::android::frameworks::automotive::vhal::AidlHalPropValue;
41 using ::android::frameworks::automotive::vhal::IHalPropConfig;
42 using ::android::frameworks::automotive::vhal::IHalPropValue;
43 using ::android::frameworks::automotive::vhal::ISubscriptionCallback;
44 using ::android::frameworks::automotive::vhal::ISubscriptionClient;
45 using ::android::frameworks::automotive::vhal::IVhalClient;
46 using ::android::frameworks::automotive::vhal::VhalClientResult;
47 
48 using ::aidl::android::hardware::automotive::remoteaccess::ApState;
49 using ::aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback;
50 using ::aidl::android::hardware::automotive::remoteaccess::ScheduleInfo;
51 using ::aidl::android::hardware::automotive::remoteaccess::TaskType;
52 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
53 
54 using ::grpc::ClientAsyncReaderInterface;
55 using ::grpc::ClientAsyncResponseReaderInterface;
56 using ::grpc::ClientContext;
57 using ::grpc::ClientReader;
58 using ::grpc::ClientReaderInterface;
59 using ::grpc::CompletionQueue;
60 using ::grpc::Status;
61 using ::grpc::testing::MockClientReader;
62 using ::ndk::ScopedAStatus;
63 using ::testing::_;
64 using ::testing::DoAll;
65 using ::testing::ElementsAre;
66 using ::testing::Return;
67 using ::testing::SetArgPointee;
68 
69 constexpr char kTestVin[] = "test_VIN";
70 const std::string kTestClientId = "test client id";
71 const std::string kTestScheduleId = "test schedule id";
72 const std::vector<uint8_t> kTestData = {0xde, 0xad, 0xbe, 0xef};
73 constexpr int32_t kTestCount = 1234;
74 constexpr int64_t kTestStartTimeInEpochSeconds = 2345;
75 constexpr int64_t kTestPeriodicInSeconds = 123;
76 
77 }  // namespace
78 
79 class MockGrpcClientStub : public WakeupClient::StubInterface {
80   public:
81     MOCK_METHOD(ClientReaderInterface<GetRemoteTasksResponse>*, GetRemoteTasksRaw,
82                 (ClientContext * context, const GetRemoteTasksRequest& request));
83     MOCK_METHOD(Status, NotifyWakeupRequired,
84                 (ClientContext * context, const NotifyWakeupRequiredRequest& request,
85                  NotifyWakeupRequiredResponse* response));
86     MOCK_METHOD(Status, ScheduleTask,
87                 (ClientContext * context, const ScheduleTaskRequest& request,
88                  ScheduleTaskResponse* response));
89     MOCK_METHOD(Status, UnscheduleTask,
90                 (ClientContext * context, const UnscheduleTaskRequest& request,
91                  UnscheduleTaskResponse* response));
92     MOCK_METHOD(Status, UnscheduleAllTasks,
93                 (ClientContext * context, const UnscheduleAllTasksRequest& request,
94                  UnscheduleAllTasksResponse* response));
95     MOCK_METHOD(Status, IsTaskScheduled,
96                 (ClientContext * context, const IsTaskScheduledRequest& request,
97                  IsTaskScheduledResponse* response));
98     MOCK_METHOD(Status, GetAllPendingScheduledTasks,
99                 (ClientContext * context, const GetAllPendingScheduledTasksRequest& request,
100                  GetAllPendingScheduledTasksResponse* response));
101     // Async methods which we do not care.
102     MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, AsyncGetRemoteTasksRaw,
103                 (ClientContext * context, const GetRemoteTasksRequest& request, CompletionQueue* cq,
104                  void* tag));
105     MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, PrepareAsyncGetRemoteTasksRaw,
106                 (ClientContext * context, const GetRemoteTasksRequest& request,
107                  CompletionQueue* cq));
108     MOCK_METHOD(ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*,
109                 AsyncNotifyWakeupRequiredRaw,
110                 (ClientContext * context, const NotifyWakeupRequiredRequest& request,
111                  CompletionQueue* cq));
112     MOCK_METHOD(ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*,
113                 PrepareAsyncNotifyWakeupRequiredRaw,
114                 (ClientContext * context, const NotifyWakeupRequiredRequest& request,
115                  CompletionQueue* cq));
116     MOCK_METHOD(ClientAsyncResponseReaderInterface<ScheduleTaskResponse>*, AsyncScheduleTaskRaw,
117                 (ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq));
118     MOCK_METHOD(ClientAsyncResponseReaderInterface<ScheduleTaskResponse>*,
119                 PrepareAsyncScheduleTaskRaw,
120                 (ClientContext * context, const ScheduleTaskRequest& request, CompletionQueue* cq));
121     MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>*, AsyncUnscheduleTaskRaw,
122                 (ClientContext * context, const UnscheduleTaskRequest& request,
123                  CompletionQueue* cq));
124     MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>*,
125                 PrepareAsyncUnscheduleTaskRaw,
126                 (ClientContext * context, const UnscheduleTaskRequest& request,
127                  CompletionQueue* cq));
128     MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*,
129                 AsyncUnscheduleAllTasksRaw,
130                 (ClientContext * context, const UnscheduleAllTasksRequest& request,
131                  CompletionQueue* cq));
132     MOCK_METHOD(ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*,
133                 PrepareAsyncUnscheduleAllTasksRaw,
134                 (ClientContext * context, const UnscheduleAllTasksRequest& request,
135                  CompletionQueue* cq));
136     MOCK_METHOD(ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>*,
137                 AsyncIsTaskScheduledRaw,
138                 (ClientContext * context, const IsTaskScheduledRequest& request,
139                  CompletionQueue* cq));
140     MOCK_METHOD(ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>*,
141                 PrepareAsyncIsTaskScheduledRaw,
142                 (ClientContext * context, const IsTaskScheduledRequest& request,
143                  CompletionQueue* cq));
144     MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllPendingScheduledTasksResponse>*,
145                 AsyncGetAllPendingScheduledTasksRaw,
146                 (ClientContext * context, const GetAllPendingScheduledTasksRequest& request,
147                  CompletionQueue* cq));
148     MOCK_METHOD(ClientAsyncResponseReaderInterface<GetAllPendingScheduledTasksResponse>*,
149                 PrepareAsyncGetAllPendingScheduledTasksRaw,
150                 (ClientContext * context, const GetAllPendingScheduledTasksRequest& request,
151                  CompletionQueue* cq));
152 };
153 
154 class FakeVhalClient final : public android::frameworks::automotive::vhal::IVhalClient {
155   public:
isAidlVhal()156     inline bool isAidlVhal() { return true; }
157 
getValueSync(const IHalPropValue & requestValue)158     VhalClientResult<std::unique_ptr<IHalPropValue>> getValueSync(
159             const IHalPropValue& requestValue) override {
160         auto propValue = std::make_unique<AidlHalPropValue>(requestValue.getPropId());
161         propValue->setStringValue(kTestVin);
162         return propValue;
163     }
164 
createHalPropValue(int32_t propId)165     std::unique_ptr<IHalPropValue> createHalPropValue(int32_t propId) override {
166         return std::make_unique<AidlHalPropValue>(propId);
167     }
168 
169     // Functions we do not care.
createHalPropValue(int32_t propId,int32_t areaId)170     std::unique_ptr<IHalPropValue> createHalPropValue([[maybe_unused]] int32_t propId,
171                                                       [[maybe_unused]] int32_t areaId) override {
172         return nullptr;
173     }
174 
getValue(const IHalPropValue & requestValue,std::shared_ptr<GetValueCallbackFunc> callback)175     void getValue([[maybe_unused]] const IHalPropValue& requestValue,
176                   [[maybe_unused]] std::shared_ptr<GetValueCallbackFunc> callback) override {}
177 
setValue(const IHalPropValue & requestValue,std::shared_ptr<SetValueCallbackFunc> callback)178     void setValue([[maybe_unused]] const IHalPropValue& requestValue,
179                   [[maybe_unused]] std::shared_ptr<SetValueCallbackFunc> callback) override {}
180 
setValueSync(const IHalPropValue & requestValue)181     VhalClientResult<void> setValueSync([[maybe_unused]] const IHalPropValue& requestValue) {
182         return {};
183     }
184 
addOnBinderDiedCallback(std::shared_ptr<OnBinderDiedCallbackFunc> callback)185     VhalClientResult<void> addOnBinderDiedCallback(
186             [[maybe_unused]] std::shared_ptr<OnBinderDiedCallbackFunc> callback) override {
187         return {};
188     }
189 
removeOnBinderDiedCallback(std::shared_ptr<OnBinderDiedCallbackFunc> callback)190     VhalClientResult<void> removeOnBinderDiedCallback(
191             [[maybe_unused]] std::shared_ptr<OnBinderDiedCallbackFunc> callback) override {
192         return {};
193     }
194 
getAllPropConfigs()195     VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getAllPropConfigs() override {
196         return std::vector<std::unique_ptr<IHalPropConfig>>();
197     }
198 
getPropConfigs(std::vector<int32_t> propIds)199     VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getPropConfigs(
200             [[maybe_unused]] std::vector<int32_t> propIds) override {
201         return std::vector<std::unique_ptr<IHalPropConfig>>();
202     }
203 
getSubscriptionClient(std::shared_ptr<ISubscriptionCallback> callback)204     std::unique_ptr<ISubscriptionClient> getSubscriptionClient(
205             [[maybe_unused]] std::shared_ptr<ISubscriptionCallback> callback) override {
206         return nullptr;
207     }
208 };
209 
210 class FakeRemoteTaskCallback : public BnRemoteTaskCallback {
211   public:
onRemoteTaskRequested(const std::string & clientId,const std::vector<uint8_t> & data)212     ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
213                                         const std::vector<uint8_t>& data) override {
214         std::lock_guard<std::mutex> lockGuard(mLock);
215         mDataByClientId[clientId] = data;
216         mTaskCount++;
217         mCv.notify_all();
218         return ScopedAStatus::ok();
219     }
220 
getData(const std::string & clientId)221     std::vector<uint8_t> getData(const std::string& clientId) { return mDataByClientId[clientId]; }
222 
wait(size_t taskCount,size_t timeoutInSec)223     bool wait(size_t taskCount, size_t timeoutInSec) {
224         std::unique_lock<std::mutex> lock(mLock);
225         return mCv.wait_for(lock, std::chrono::seconds(timeoutInSec), [taskCount, this] {
226             ScopedLockAssertion lockAssertion(mLock);
227             return mTaskCount >= taskCount;
228         });
229     }
230 
231   private:
232     std::mutex mLock;
233     std::unordered_map<std::string, std::vector<uint8_t>> mDataByClientId GUARDED_BY(mLock);
234     size_t mTaskCount GUARDED_BY(mLock) = 0;
235     std::condition_variable mCv;
236 };
237 
238 class RemoteAccessServiceUnitTest : public ::testing::Test {
239   public:
SetUp()240     virtual void SetUp() override {
241         mGrpcWakeupClientStub = std::make_unique<MockGrpcClientStub>();
242         mService = ndk::SharedRefBase::make<RemoteAccessService>(mGrpcWakeupClientStub.get());
243     }
244 
getGrpcWakeupClientStub()245     MockGrpcClientStub* getGrpcWakeupClientStub() { return mGrpcWakeupClientStub.get(); }
246 
getService()247     RemoteAccessService* getService() { return mService.get(); }
248 
setRetryWaitInMs(size_t retryWaitInMs)249     void setRetryWaitInMs(size_t retryWaitInMs) { mService->setRetryWaitInMs(retryWaitInMs); }
250 
getVehicleIdWithClient(IVhalClient & vhalClient,std::string * vehicleId)251     ScopedAStatus getVehicleIdWithClient(IVhalClient& vhalClient, std::string* vehicleId) {
252         return mService->getVehicleIdWithClient(vhalClient, vehicleId);
253     }
254 
255   private:
256     std::unique_ptr<MockGrpcClientStub> mGrpcWakeupClientStub;
257     std::shared_ptr<RemoteAccessService> mService;
258 };
259 
TEST_F(RemoteAccessServiceUnitTest,TestGetWakeupServiceName)260 TEST_F(RemoteAccessServiceUnitTest, TestGetWakeupServiceName) {
261     std::string serviceName;
262 
263     ScopedAStatus status = getService()->getWakeupServiceName(&serviceName);
264 
265     EXPECT_TRUE(status.isOk());
266     EXPECT_EQ(serviceName, "com.google.vehicle.wakeup");
267 }
268 
TEST_F(RemoteAccessServiceUnitTest,TestNotifyApStateChangeWakeupRequired)269 TEST_F(RemoteAccessServiceUnitTest, TestNotifyApStateChangeWakeupRequired) {
270     bool isWakeupRequired = false;
271     EXPECT_CALL(*getGrpcWakeupClientStub(), NotifyWakeupRequired)
272             .WillOnce([&isWakeupRequired]([[maybe_unused]] ClientContext* context,
273                                           const NotifyWakeupRequiredRequest& request,
274                                           [[maybe_unused]] NotifyWakeupRequiredResponse* response) {
275                 isWakeupRequired = request.iswakeuprequired();
276                 return Status();
277             });
278 
279     ApState newState = {
280             .isWakeupRequired = true,
281     };
282     ScopedAStatus status = getService()->notifyApStateChange(newState);
283 
284     EXPECT_TRUE(status.isOk());
285     EXPECT_TRUE(isWakeupRequired);
286 }
287 
TEST_F(RemoteAccessServiceUnitTest,TestGetRemoteTasks)288 TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasks) {
289     GetRemoteTasksResponse response1;
290     std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
291     response1.set_clientid("1");
292     response1.set_data(testData.data(), testData.size());
293     GetRemoteTasksResponse response2;
294     response2.set_clientid("2");
295     std::shared_ptr<FakeRemoteTaskCallback> callback =
296             ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
297 
298     ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
299             .WillByDefault(
300                     [response1, response2]([[maybe_unused]] ClientContext* context,
301                                            [[maybe_unused]] const GetRemoteTasksRequest& request) {
302                         // mockReader ownership will be transferred to the client so we don't own it
303                         // here.
304                         MockClientReader<GetRemoteTasksResponse>* mockClientReader =
305                                 new MockClientReader<GetRemoteTasksResponse>();
306                         EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
307                         EXPECT_CALL(*mockClientReader, Read(_))
308                                 .WillOnce(DoAll(SetArgPointee<0>(response1), Return(true)))
309                                 .WillOnce(DoAll(SetArgPointee<0>(response2), Return(true)))
310                                 .WillRepeatedly(Return(false));
311                         return mockClientReader;
312                     });
313 
314     getService()->setRemoteTaskCallback(callback);
315     // Start the long live connection to receive tasks.
316     ApState newState = {
317             .isReadyForRemoteTask = true,
318     };
319     ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
320 
321     ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
322             << "Did not receive enough tasks";
323     EXPECT_EQ(callback->getData("1"), testData);
324     EXPECT_EQ(callback->getData("2"), std::vector<uint8_t>());
325 }
326 
TEST_F(RemoteAccessServiceUnitTest,TestGetRemoteTasksRetryConnection)327 TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksRetryConnection) {
328     GetRemoteTasksResponse response;
329     std::shared_ptr<FakeRemoteTaskCallback> callback =
330             ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
331 
332     ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
333             .WillByDefault([response]([[maybe_unused]] ClientContext* context,
334                                       [[maybe_unused]] const GetRemoteTasksRequest& request) {
335                 // mockReader ownership will be transferred to the client so we don't own it here.
336                 MockClientReader<GetRemoteTasksResponse>* mockClientReader =
337                         new MockClientReader<GetRemoteTasksResponse>();
338                 EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
339                 // Connection fails after receiving one task. Should retry after some time.
340                 EXPECT_CALL(*mockClientReader, Read(_))
341                         .WillOnce(DoAll(SetArgPointee<0>(response), Return(true)))
342                         .WillRepeatedly(Return(false));
343                 return mockClientReader;
344             });
345 
346     getService()->setRemoteTaskCallback(callback);
347     setRetryWaitInMs(100);
348     // Start the long live connection to receive tasks.
349     ApState newState = {
350             .isReadyForRemoteTask = true,
351     };
352     ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
353 
354     ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
355             << "Did not receive enough tasks";
356 }
357 
TEST_F(RemoteAccessServiceUnitTest,TestGetRemoteTasksDefaultNotReady)358 TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksDefaultNotReady) {
359     GetRemoteTasksResponse response1;
360     std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
361     response1.set_clientid("1");
362     response1.set_data(testData.data(), testData.size());
363     GetRemoteTasksResponse response2;
364     response2.set_clientid("2");
365     std::shared_ptr<FakeRemoteTaskCallback> callback =
366             ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
367 
368     EXPECT_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw).Times(0);
369 
370     // Default state is not ready for remote tasks, so no callback will be called.
371     getService()->setRemoteTaskCallback(callback);
372 
373     std::this_thread::sleep_for(std::chrono::milliseconds(100));
374 }
375 
TEST_F(RemoteAccessServiceUnitTest,TestGetRemoteTasksNotReadyAfterReady)376 TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksNotReadyAfterReady) {
377     GetRemoteTasksResponse response1;
378     std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
379     response1.set_clientid("1");
380     response1.set_data(testData.data(), testData.size());
381     GetRemoteTasksResponse response2;
382     response2.set_clientid("2");
383     std::shared_ptr<FakeRemoteTaskCallback> callback =
384             ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
385 
386     ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
387             .WillByDefault(
388                     [response1, response2]([[maybe_unused]] ClientContext* context,
389                                            [[maybe_unused]] const GetRemoteTasksRequest& request) {
390                         // mockReader ownership will be transferred to the client so we don't own it
391                         // here.
392                         MockClientReader<GetRemoteTasksResponse>* mockClientReader =
393                                 new MockClientReader<GetRemoteTasksResponse>();
394                         EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
395                         EXPECT_CALL(*mockClientReader, Read(_))
396                                 .WillOnce(DoAll(SetArgPointee<0>(response1), Return(true)))
397                                 .WillOnce(DoAll(SetArgPointee<0>(response2), Return(true)))
398                                 .WillRepeatedly(Return(false));
399                         return mockClientReader;
400                     });
401     // Should only be called once when is is ready for remote task.
402     EXPECT_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw).Times(1);
403 
404     getService()->setRemoteTaskCallback(callback);
405     setRetryWaitInMs(100);
406     // Start the long live connection to receive tasks.
407     ApState newState = {
408             .isReadyForRemoteTask = true,
409     };
410     ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
411     ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
412             << "Did not receive enough tasks";
413 
414     // Stop the long live connection.
415     newState.isReadyForRemoteTask = false;
416     ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
417 
418     // Wait for the retry delay, but the loop should already exit.
419     std::this_thread::sleep_for(std::chrono::milliseconds(150));
420 }
421 
TEST_F(RemoteAccessServiceUnitTest,testGetVehicleId)422 TEST_F(RemoteAccessServiceUnitTest, testGetVehicleId) {
423     std::string vehicleId;
424 
425     FakeVhalClient vhalClient;
426 
427     ASSERT_TRUE(getVehicleIdWithClient(vhalClient, &vehicleId).isOk());
428     ASSERT_EQ(vehicleId, kTestVin);
429 }
430 
TEST_F(RemoteAccessServiceUnitTest,TestIsTaskScheduleSupported)431 TEST_F(RemoteAccessServiceUnitTest, TestIsTaskScheduleSupported) {
432     bool out = false;
433     ScopedAStatus status = getService()->isTaskScheduleSupported(&out);
434 
435     EXPECT_TRUE(status.isOk());
436     EXPECT_TRUE(out);
437 }
438 
TEST_F(RemoteAccessServiceUnitTest,TestGetSupportedTaskTypesForScheduling)439 TEST_F(RemoteAccessServiceUnitTest, TestGetSupportedTaskTypesForScheduling) {
440     std::vector<TaskType> out;
441     ScopedAStatus status = getService()->getSupportedTaskTypesForScheduling(&out);
442 
443     EXPECT_TRUE(status.isOk());
444     EXPECT_THAT(out, ElementsAre(TaskType::CUSTOM));
445 }
446 
TEST_F(RemoteAccessServiceUnitTest,TestScheduleTask)447 TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask) {
448     ScheduleTaskRequest grpcRequest = {};
449     EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask)
450             .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
451                                      const ScheduleTaskRequest& request,
452                                      [[maybe_unused]] ScheduleTaskResponse* response) {
453                 grpcRequest = request;
454                 return Status();
455             });
456     ScheduleInfo scheduleInfo = {
457             .clientId = kTestClientId,
458             .scheduleId = kTestScheduleId,
459             .taskData = kTestData,
460             .count = kTestCount,
461             .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
462             .periodicInSeconds = kTestPeriodicInSeconds,
463     };
464 
465     ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
466 
467     ASSERT_TRUE(status.isOk());
468     EXPECT_EQ(grpcRequest.scheduleinfo().clientid(), kTestClientId);
469     EXPECT_EQ(grpcRequest.scheduleinfo().scheduleid(), kTestScheduleId);
470     EXPECT_EQ(grpcRequest.scheduleinfo().data(), std::string(kTestData.begin(), kTestData.end()));
471     EXPECT_EQ(grpcRequest.scheduleinfo().count(), kTestCount);
472     EXPECT_EQ(grpcRequest.scheduleinfo().starttimeinepochseconds(), kTestStartTimeInEpochSeconds);
473     EXPECT_EQ(grpcRequest.scheduleinfo().periodicinseconds(), kTestPeriodicInSeconds);
474 }
475 
TEST_F(RemoteAccessServiceUnitTest,TestScheduleTask_InvalidCount)476 TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_InvalidCount) {
477     ScheduleInfo scheduleInfo = {
478             .clientId = kTestClientId,
479             .scheduleId = kTestScheduleId,
480             .taskData = kTestData,
481             .count = -1,
482             .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
483             .periodicInSeconds = kTestPeriodicInSeconds,
484     };
485 
486     ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
487 
488     ASSERT_FALSE(status.isOk());
489     ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
490 }
491 
TEST_F(RemoteAccessServiceUnitTest,TestScheduleTask_InvalidStartTimeInEpochSeconds)492 TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_InvalidStartTimeInEpochSeconds) {
493     ScheduleInfo scheduleInfo = {
494             .clientId = kTestClientId,
495             .scheduleId = kTestScheduleId,
496             .taskData = kTestData,
497             .count = kTestCount,
498             .startTimeInEpochSeconds = -1,
499             .periodicInSeconds = kTestPeriodicInSeconds,
500     };
501 
502     ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
503 
504     ASSERT_FALSE(status.isOk());
505     ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
506 }
507 
TEST_F(RemoteAccessServiceUnitTest,TestScheduleTask_InvalidPeriodicInSeconds)508 TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_InvalidPeriodicInSeconds) {
509     ScheduleInfo scheduleInfo = {
510             .clientId = kTestClientId,
511             .scheduleId = kTestScheduleId,
512             .taskData = kTestData,
513             .count = kTestCount,
514             .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
515             .periodicInSeconds = -1,
516     };
517 
518     ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
519 
520     ASSERT_FALSE(status.isOk());
521     ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
522 }
523 
TEST_F(RemoteAccessServiceUnitTest,TestScheduleTask_TaskDataTooLarge)524 TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_TaskDataTooLarge) {
525     ScheduleInfo scheduleInfo = {
526             .clientId = kTestClientId,
527             .scheduleId = kTestScheduleId,
528             .taskData = std::vector<uint8_t>(ScheduleInfo::MAX_TASK_DATA_SIZE_IN_BYTES + 1),
529             .count = kTestCount,
530             .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
531             .periodicInSeconds = kTestPeriodicInSeconds,
532     };
533 
534     ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
535 
536     ASSERT_FALSE(status.isOk());
537     ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
538 }
539 
TEST_F(RemoteAccessServiceUnitTest,TestScheduleTask_InvalidArgFromGrpcServer)540 TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_InvalidArgFromGrpcServer) {
541     EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask)
542             .WillOnce([]([[maybe_unused]] ClientContext* context,
543                          [[maybe_unused]] const ScheduleTaskRequest& request,
544                          ScheduleTaskResponse* response) {
545                 response->set_errorcode(ErrorCode::INVALID_ARG);
546                 return Status();
547             });
548     ScheduleInfo scheduleInfo = {
549             .clientId = kTestClientId,
550             .scheduleId = kTestScheduleId,
551             .taskData = kTestData,
552             .count = kTestCount,
553             .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
554             .periodicInSeconds = kTestPeriodicInSeconds,
555     };
556 
557     ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
558 
559     ASSERT_FALSE(status.isOk());
560     ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
561 }
562 
TEST_F(RemoteAccessServiceUnitTest,TestScheduleTask_UnspecifiedError)563 TEST_F(RemoteAccessServiceUnitTest, TestScheduleTask_UnspecifiedError) {
564     EXPECT_CALL(*getGrpcWakeupClientStub(), ScheduleTask)
565             .WillOnce([]([[maybe_unused]] ClientContext* context,
566                          [[maybe_unused]] const ScheduleTaskRequest& request,
567                          ScheduleTaskResponse* response) {
568                 response->set_errorcode(ErrorCode::UNSPECIFIED);
569                 return Status();
570             });
571     ScheduleInfo scheduleInfo = {
572             .clientId = kTestClientId,
573             .scheduleId = kTestScheduleId,
574             .taskData = kTestData,
575             .count = kTestCount,
576             .startTimeInEpochSeconds = kTestStartTimeInEpochSeconds,
577             .periodicInSeconds = kTestPeriodicInSeconds,
578     };
579 
580     ScopedAStatus status = getService()->scheduleTask(scheduleInfo);
581 
582     ASSERT_FALSE(status.isOk());
583     ASSERT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
584 }
585 
TEST_F(RemoteAccessServiceUnitTest,TestUnscheduleTask)586 TEST_F(RemoteAccessServiceUnitTest, TestUnscheduleTask) {
587     UnscheduleTaskRequest grpcRequest = {};
588     EXPECT_CALL(*getGrpcWakeupClientStub(), UnscheduleTask)
589             .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
590                                      const UnscheduleTaskRequest& request,
591                                      [[maybe_unused]] UnscheduleTaskResponse* response) {
592                 grpcRequest = request;
593                 return Status();
594             });
595 
596     ScopedAStatus status = getService()->unscheduleTask(kTestClientId, kTestScheduleId);
597 
598     ASSERT_TRUE(status.isOk());
599     EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
600     EXPECT_EQ(grpcRequest.scheduleid(), kTestScheduleId);
601 }
602 
TEST_F(RemoteAccessServiceUnitTest,TestUnscheduleAllTasks)603 TEST_F(RemoteAccessServiceUnitTest, TestUnscheduleAllTasks) {
604     UnscheduleAllTasksRequest grpcRequest = {};
605     EXPECT_CALL(*getGrpcWakeupClientStub(), UnscheduleAllTasks)
606             .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
607                                      const UnscheduleAllTasksRequest& request,
608                                      [[maybe_unused]] UnscheduleAllTasksResponse* response) {
609                 grpcRequest = request;
610                 return Status();
611             });
612 
613     ScopedAStatus status = getService()->unscheduleAllTasks(kTestClientId);
614 
615     ASSERT_TRUE(status.isOk());
616     EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
617 }
618 
TEST_F(RemoteAccessServiceUnitTest,TestIsTaskScheduled)619 TEST_F(RemoteAccessServiceUnitTest, TestIsTaskScheduled) {
620     bool isTaskScheduled = false;
621     IsTaskScheduledRequest grpcRequest = {};
622     EXPECT_CALL(*getGrpcWakeupClientStub(), IsTaskScheduled)
623             .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
624                                      const IsTaskScheduledRequest& request,
625                                      IsTaskScheduledResponse* response) {
626                 grpcRequest = request;
627                 response->set_istaskscheduled(true);
628                 return Status();
629             });
630 
631     ScopedAStatus status =
632             getService()->isTaskScheduled(kTestClientId, kTestScheduleId, &isTaskScheduled);
633 
634     ASSERT_TRUE(status.isOk());
635     EXPECT_TRUE(isTaskScheduled);
636     EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
637     EXPECT_EQ(grpcRequest.scheduleid(), kTestScheduleId);
638 }
639 
TEST_F(RemoteAccessServiceUnitTest,testGetAllPendingScheduledTasks)640 TEST_F(RemoteAccessServiceUnitTest, testGetAllPendingScheduledTasks) {
641     std::vector<ScheduleInfo> result;
642     GetAllPendingScheduledTasksRequest grpcRequest = {};
643     EXPECT_CALL(*getGrpcWakeupClientStub(), GetAllPendingScheduledTasks)
644             .WillOnce([&grpcRequest]([[maybe_unused]] ClientContext* context,
645                                      const GetAllPendingScheduledTasksRequest& request,
646                                      GetAllPendingScheduledTasksResponse* response) {
647                 grpcRequest = request;
648                 GrpcScheduleInfo* newInfo = response->add_allscheduledtasks();
649                 newInfo->set_clientid(kTestClientId);
650                 newInfo->set_scheduleid(kTestScheduleId);
651                 newInfo->set_data(kTestData.data(), kTestData.size());
652                 newInfo->set_count(kTestCount);
653                 newInfo->set_starttimeinepochseconds(kTestStartTimeInEpochSeconds);
654                 newInfo->set_periodicinseconds(kTestPeriodicInSeconds);
655                 return Status();
656             });
657 
658     ScopedAStatus status = getService()->getAllPendingScheduledTasks(kTestClientId, &result);
659 
660     ASSERT_TRUE(status.isOk());
661     EXPECT_EQ(grpcRequest.clientid(), kTestClientId);
662     ASSERT_EQ(result.size(), 1u);
663     ASSERT_EQ(result[0].clientId, kTestClientId);
664     ASSERT_EQ(result[0].scheduleId, kTestScheduleId);
665     ASSERT_EQ(result[0].taskData, kTestData);
666     ASSERT_EQ(result[0].count, kTestCount);
667     ASSERT_EQ(result[0].startTimeInEpochSeconds, kTestStartTimeInEpochSeconds);
668     ASSERT_EQ(result[0].periodicInSeconds, kTestPeriodicInSeconds);
669 }
670 
671 }  // namespace remoteaccess
672 }  // namespace automotive
673 }  // namespace hardware
674 }  // namespace android
675