1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <aidl/android/automotive/computepipe/registry/BnClientInfo.h>
16 #include <aidl/android/automotive/computepipe/registry/IPipeQuery.h>
17 #include <aidl/android/automotive/computepipe/registry/IPipeRegistration.h>
18 #include <aidl/android/automotive/computepipe/runner/BnPipeStateCallback.h>
19 #include <aidl/android/automotive/computepipe/runner/BnPipeStream.h>
20 #include <aidl/android/automotive/computepipe/runner/PipeState.h>
21 #include <android/binder_manager.h>
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 
25 #include <utility>
26 #include <vector>
27 
28 #include "ConfigurationCommand.pb.h"
29 #include "ControlCommand.pb.h"
30 #include "MemHandle.h"
31 #include "MockEngine.h"
32 #include "MockMemHandle.h"
33 #include "MockRunnerEvent.h"
34 #include "Options.pb.h"
35 #include "ProfilingType.pb.h"
36 #include "runner/client_interface/AidlClient.h"
37 #include "runner/client_interface/include/ClientEngineInterface.h"
38 #include "types/Status.h"
39 
40 namespace android {
41 namespace automotive {
42 namespace computepipe {
43 namespace runner {
44 namespace client_interface {
45 namespace aidl_client {
46 namespace {
47 
48 using ::aidl::android::automotive::computepipe::registry::BnClientInfo;
49 using ::aidl::android::automotive::computepipe::registry::IPipeQuery;
50 using ::aidl::android::automotive::computepipe::runner::BnPipeStateCallback;
51 using ::aidl::android::automotive::computepipe::runner::BnPipeStream;
52 using ::aidl::android::automotive::computepipe::runner::IPipeRunner;
53 using ::aidl::android::automotive::computepipe::runner::IPipeStateCallback;
54 using ::aidl::android::automotive::computepipe::runner::PacketDescriptor;
55 using ::aidl::android::automotive::computepipe::runner::PipeState;
56 using ::android::automotive::computepipe::runner::tests::MockRunnerEvent;
57 using ::android::automotive::computepipe::tests::MockMemHandle;
58 using ::ndk::ScopedAStatus;
59 using ::ndk::SharedRefBase;
60 using ::testing::_;
61 using ::testing::AnyNumber;
62 using ::testing::AtLeast;
63 using ::testing::DoAll;
64 using ::testing::Return;
65 using ::testing::SaveArg;
66 
67 const char kRegistryInterfaceName[] = "router";
68 int testIx = 0;
69 
70 class StateChangeCallback : public BnPipeStateCallback {
71   public:
handleState(PipeState state)72     ScopedAStatus handleState(PipeState state) {
73         mState = state;
74         return ScopedAStatus::ok();
75     }
76     PipeState mState = PipeState::RESET;
77 };
78 
79 class StreamCallback : public BnPipeStream {
80   public:
deliverPacket(const PacketDescriptor & in_packet)81     ScopedAStatus deliverPacket(const PacketDescriptor& in_packet) override {
82         data = std::string(in_packet.data.begin(), in_packet.data.end());
83         timestamp = in_packet.sourceTimeStampMillis;
84         return ScopedAStatus::ok();
85     }
86     std::string data;
87     uint64_t timestamp;
88 };
89 
90 class ClientInfo : public BnClientInfo {
91   public:
getClientName(std::string * _aidl_return)92     ScopedAStatus getClientName(std::string* _aidl_return) {
93         if (_aidl_return) {
94             *_aidl_return = "ClientInfo";
95             return ScopedAStatus::ok();
96         }
97         return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
98     }
99 };
100 
101 class ClientInterface : public ::testing::Test {
102   protected:
SetUp()103     void SetUp() override {
104         const std::string graphName = "graph " + std::to_string(++testIx);
105         proto::Options options;
106         options.set_graph_name(graphName);
107         mAidlClient = std::make_unique<AidlClient>(options, mEngine);
108 
109         // Register the instance with router.
110         EXPECT_EQ(mAidlClient->activate(), Status::SUCCESS);
111 
112         // Init is not a blocking call, so sleep for 3 seconds to allow the runner to register with
113         // router.
114         sleep(3);
115 
116         // Retrieve router query instance from service manager.
117         std::string instanceName =
118             std::string() + IPipeQuery::descriptor + "/" + kRegistryInterfaceName;
119         ndk::SpAIBinder binder(AServiceManager_getService(instanceName.c_str()));
120         ASSERT_TRUE(binder.get() != nullptr);
121         std::shared_ptr<IPipeQuery> queryService = IPipeQuery::fromBinder(binder);
122 
123         // Retrieve pipe runner instance from the router.
124         std::shared_ptr<ClientInfo> clientInfo = ndk::SharedRefBase::make<ClientInfo>();
125         ASSERT_TRUE(queryService->getPipeRunner(graphName, clientInfo, &mPipeRunner).isOk());
126     }
127 
128     std::shared_ptr<tests::MockEngine> mEngine = std::make_unique<tests::MockEngine>();
129     std::shared_ptr<AidlClient> mAidlClient = nullptr;
130     std::shared_ptr<IPipeRunner> mPipeRunner = nullptr;
131 };
132 
TEST_F(ClientInterface,TestSetConfiguration)133 TEST_F(ClientInterface, TestSetConfiguration) {
134     proto::ConfigurationCommand command;
135 
136     // Configure runner to return success.
137     EXPECT_CALL(*mEngine, processClientConfigUpdate(_))
138         .Times(AtLeast(4))
139         .WillRepeatedly(DoAll(SaveArg<0>(&command), Return(Status::SUCCESS)));
140 
141     // Initialize pipe runner.
142     std::shared_ptr<StateChangeCallback> stateCallback =
143         ndk::SharedRefBase::make<StateChangeCallback>();
144     EXPECT_TRUE(mPipeRunner->init(stateCallback).isOk());
145 
146     // Test that set input source returns ok status.
147     EXPECT_TRUE(mPipeRunner->setPipeInputSource(1).isOk());
148     EXPECT_EQ(command.has_set_input_source(), true);
149     EXPECT_EQ(command.set_input_source().source_id(), 1);
150 
151     // Test that set offload option returns ok status.
152     EXPECT_TRUE(mPipeRunner->setPipeOffloadOptions(5).isOk());
153     EXPECT_EQ(command.has_set_offload_offload(), true);
154     EXPECT_EQ(command.set_offload_offload().offload_option_id(), 5);
155 
156     // Test that set termination option returns ok status.
157     EXPECT_TRUE(mPipeRunner->setPipeTermination(3).isOk());
158     EXPECT_EQ(command.has_set_termination_option(), true);
159     EXPECT_EQ(command.set_termination_option().termination_option_id(), 3);
160 
161     // Test that set output callback returns ok status.
162     std::shared_ptr<StreamCallback> streamCb = ndk::SharedRefBase::make<StreamCallback>();
163     EXPECT_TRUE(mPipeRunner->setPipeOutputConfig(0, 10, streamCb).isOk());
164     EXPECT_EQ(command.has_set_output_stream(), true);
165     EXPECT_EQ(command.set_output_stream().stream_id(), 0);
166     EXPECT_EQ(command.set_output_stream().max_inflight_packets_count(), 10);
167 
168     // Release runner here. This should remove registry entry from router registry.
169     mAidlClient.reset();
170 }
171 
TEST_F(ClientInterface,TestSetConfigurationError)172 TEST_F(ClientInterface, TestSetConfigurationError) {
173     proto::ConfigurationCommand command;
174 
175     // Configure runner to return error.
176     EXPECT_CALL(*mEngine, processClientConfigUpdate(_))
177         .Times(AtLeast(4))
178         .WillRepeatedly(DoAll(SaveArg<0>(&command), Return(Status::INTERNAL_ERROR)));
179 
180     ScopedAStatus status;
181 
182     // Initialize pipe runner.
183     std::shared_ptr<StateChangeCallback> stateCallback =
184         ndk::SharedRefBase::make<StateChangeCallback>();
185     EXPECT_TRUE(mPipeRunner->init(stateCallback).isOk());
186 
187     // Test that set input source returns error status.
188     status = mPipeRunner->setPipeInputSource(1);
189     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
190     EXPECT_EQ(command.has_set_input_source(), true);
191     EXPECT_EQ(command.set_input_source().source_id(), 1);
192 
193     // Test that set offload option returns error status.
194     status = mPipeRunner->setPipeOffloadOptions(5);
195     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
196     EXPECT_EQ(command.has_set_offload_offload(), true);
197     EXPECT_EQ(command.set_offload_offload().offload_option_id(), 5);
198 
199     // Test that set termination option returns error status.
200     status = mPipeRunner->setPipeTermination(3);
201     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
202     EXPECT_EQ(command.has_set_termination_option(), true);
203     EXPECT_EQ(command.set_termination_option().termination_option_id(), 3);
204 
205     // Test that set output callback returns error status.
206     std::shared_ptr<StreamCallback> streamCb = ndk::SharedRefBase::make<StreamCallback>();
207     status = mPipeRunner->setPipeOutputConfig(0, 10, streamCb);
208     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
209     EXPECT_EQ(command.has_set_output_stream(), true);
210     EXPECT_EQ(command.set_output_stream().stream_id(), 0);
211     EXPECT_EQ(command.set_output_stream().max_inflight_packets_count(), 10);
212 
213     // Release runner here. This should remove registry entry from router registry.
214     mAidlClient.reset();
215 }
216 
TEST_F(ClientInterface,TestControlCommands)217 TEST_F(ClientInterface, TestControlCommands) {
218     proto::ControlCommand command;
219     // Configure runner to return success.
220     EXPECT_CALL(*mEngine, processClientCommand(_))
221         .Times(AtLeast(4))
222         .WillRepeatedly(DoAll(SaveArg<0>(&command), Return(Status::SUCCESS)));
223 
224     // Initialize pipe runner.
225     std::shared_ptr<StateChangeCallback> stateCallback =
226         ndk::SharedRefBase::make<StateChangeCallback>();
227     EXPECT_TRUE(mPipeRunner->init(stateCallback).isOk());
228 
229     // Test that apply-configs api returns ok status.
230     EXPECT_TRUE(mPipeRunner->applyPipeConfigs().isOk());
231     EXPECT_EQ(command.has_apply_configs(), true);
232 
233     // Test that set stop graph api returns ok status.
234     EXPECT_TRUE(mPipeRunner->resetPipeConfigs().isOk());
235     EXPECT_EQ(command.has_reset_configs(), true);
236 
237     // Test that set start graph api returns ok status.
238     EXPECT_TRUE(mPipeRunner->startPipe().isOk());
239     EXPECT_EQ(command.has_start_graph(), true);
240 
241     // Test that set stop graph api returns ok status.
242     EXPECT_TRUE(mPipeRunner->stopPipe().isOk());
243     EXPECT_EQ(command.has_stop_graph(), true);
244 
245     // Release runner here. This should remove registry entry from router registry.
246     mAidlClient.reset();
247 }
248 
TEST_F(ClientInterface,TestControlCommandsFailure)249 TEST_F(ClientInterface, TestControlCommandsFailure) {
250     proto::ControlCommand command;
251 
252     // Configure runner to return success.
253     EXPECT_CALL(*mEngine, processClientCommand(_))
254         .Times(AtLeast(4))
255         .WillRepeatedly(DoAll(SaveArg<0>(&command), Return(Status::INTERNAL_ERROR)));
256     ScopedAStatus status;
257 
258     // Initialize pipe runner.
259     std::shared_ptr<StateChangeCallback> stateCallback =
260         ndk::SharedRefBase::make<StateChangeCallback>();
261     EXPECT_TRUE(mPipeRunner->init(stateCallback).isOk());
262 
263     // Test that apply-configs api returns error status.
264     status = mPipeRunner->applyPipeConfigs();
265     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
266     EXPECT_EQ(command.has_apply_configs(), true);
267 
268     status = mPipeRunner->resetPipeConfigs();
269     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
270     EXPECT_EQ(command.has_reset_configs(), true);
271 
272     // Test that start graph api returns error status.
273     status = mPipeRunner->startPipe();
274     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
275     EXPECT_EQ(command.has_start_graph(), true);
276 
277     // Test that stop graph api returns error status.
278     status = mPipeRunner->stopPipe();
279     EXPECT_EQ(status.getExceptionCode(), EX_TRANSACTION_FAILED);
280     EXPECT_EQ(command.has_stop_graph(), true);
281 
282     // Release runner here. This should remove registry entry from router registry.
283     mAidlClient.reset();
284 }
285 
TEST_F(ClientInterface,TestFailureWithoutInit)286 TEST_F(ClientInterface, TestFailureWithoutInit) {
287     EXPECT_CALL(*mEngine, processClientConfigUpdate(_)).Times(0);
288     EXPECT_CALL(*mEngine, processClientCommand(_)).Times(0);
289 
290     // Pipe runner is not initalized here, test that a configuration command returns error status.
291     ScopedAStatus status;
292     status = mPipeRunner->setPipeInputSource(1);
293     EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_STATE);
294 
295     // Test that a control command returns error status.
296     status = mPipeRunner->applyPipeConfigs();
297     EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_STATE);
298 }
299 
TEST_F(ClientInterface,TestStateChangeNotification)300 TEST_F(ClientInterface, TestStateChangeNotification) {
301     EXPECT_CALL(*mEngine, processClientConfigUpdate(_)).Times(0);
302     EXPECT_CALL(*mEngine, processClientCommand(_)).Times(0);
303 
304     // Initialize pipe runner.
305     std::shared_ptr<StateChangeCallback> stateCallback =
306         ndk::SharedRefBase::make<StateChangeCallback>();
307     EXPECT_TRUE(mPipeRunner->init(stateCallback).isOk());
308 
309     // Test that config complete status is conveyed to client.
310     std::map<int, int> m;
311     ClientConfig config(0, 0, 0, m, proto::ProfilingType::DISABLED);
312     config.setPhaseState(TRANSITION_COMPLETE);
313     EXPECT_EQ(mAidlClient->handleConfigPhase(config), Status::SUCCESS);
314     EXPECT_EQ(stateCallback->mState, PipeState::CONFIG_DONE);
315 
316     MockRunnerEvent event;
317     EXPECT_CALL(event, isTransitionComplete()).Times(AnyNumber()).WillRepeatedly(Return(true));
318     EXPECT_CALL(event, isPhaseEntry()).Times(AnyNumber()).WillRepeatedly(Return(false));
319 
320     // Test that reset status is conveyed to client.
321     EXPECT_EQ(mAidlClient->handleResetPhase(event), Status::SUCCESS);
322     EXPECT_EQ(stateCallback->mState, PipeState::RESET);
323 
324     // Test that execution start status is conveyed to client.
325     EXPECT_EQ(mAidlClient->handleExecutionPhase(event), Status::SUCCESS);
326     EXPECT_EQ(stateCallback->mState, PipeState::RUNNING);
327 
328     // Test that execution complete status is conveyed to client.
329     EXPECT_EQ(mAidlClient->handleStopWithFlushPhase(event), Status::SUCCESS);
330     EXPECT_EQ(stateCallback->mState, PipeState::DONE);
331 
332     // Test that execution error status is conveyed to client.
333     EXPECT_EQ(mAidlClient->handleStopImmediatePhase(event), Status::SUCCESS);
334     EXPECT_EQ(stateCallback->mState, PipeState::ERR_HALT);
335 }
336 
TEST_F(ClientInterface,TestStateChangeToError)337 TEST_F(ClientInterface, TestStateChangeToError) {
338     EXPECT_CALL(*mEngine, processClientConfigUpdate(_)).Times(0);
339     EXPECT_CALL(*mEngine, processClientCommand(_)).Times(0);
340 
341     // Initialize pipe runner.
342     std::shared_ptr<StateChangeCallback> stateCallback =
343         ndk::SharedRefBase::make<StateChangeCallback>();
344     EXPECT_TRUE(mPipeRunner->init(stateCallback).isOk());
345 
346     // Test that error while applying config is conveyed to client.
347     std::map<int, int> m;
348     ClientConfig config(0, 0, 0, m, proto::ProfilingType::DISABLED);
349     config.setPhaseState(ABORTED);
350     EXPECT_EQ(mAidlClient->handleConfigPhase(config), Status::SUCCESS);
351     EXPECT_EQ(stateCallback->mState, PipeState::ERR_HALT);
352 
353     MockRunnerEvent event;
354     EXPECT_CALL(event, isTransitionComplete()).Times(AnyNumber()).WillRepeatedly(Return(false));
355     EXPECT_CALL(event, isPhaseEntry()).Times(AnyNumber()).WillRepeatedly(Return(false));
356     EXPECT_CALL(event, isAborted()).Times(AnyNumber()).WillRepeatedly(Return(true));
357 
358     // Test that error while starting pipe execution is conveyed to client.
359     EXPECT_EQ(mAidlClient->handleExecutionPhase(event), Status::SUCCESS);
360     EXPECT_EQ(stateCallback->mState, PipeState::ERR_HALT);
361 }
362 
TEST_F(ClientInterface,TestPacketDelivery)363 TEST_F(ClientInterface, TestPacketDelivery) {
364     proto::ConfigurationCommand command;
365 
366     // Configure runner to return success.
367     EXPECT_CALL(*mEngine, processClientConfigUpdate(_))
368         .Times(1)
369         .WillOnce(DoAll(SaveArg<0>(&command), Return(Status::SUCCESS)));
370 
371     // Initialize pipe runner.
372     std::shared_ptr<StateChangeCallback> stateCallback =
373         ndk::SharedRefBase::make<StateChangeCallback>();
374     EXPECT_TRUE(mPipeRunner->init(stateCallback).isOk());
375 
376     // Set callback for stream id 0.
377     std::shared_ptr<StreamCallback> streamCb = ndk::SharedRefBase::make<StreamCallback>();
378     EXPECT_TRUE(mPipeRunner->setPipeOutputConfig(0, 10, streamCb).isOk());
379     EXPECT_EQ(command.has_set_output_stream(), true);
380     EXPECT_EQ(command.set_output_stream().stream_id(), 0);
381     EXPECT_EQ(command.set_output_stream().max_inflight_packets_count(), 10);
382 
383     // Send a packet to client and verify the packet.
384     std::shared_ptr<MockMemHandle> packet = std::make_unique<MockMemHandle>();
385     uint64_t timestamp = 100;
386     const std::string testData = "Test String.";
387     EXPECT_CALL(*packet, getType())
388         .Times(AtLeast(1))
389         .WillRepeatedly(Return(proto::PacketType::SEMANTIC_DATA));
390     EXPECT_CALL(*packet, getTimeStamp()).Times(AtLeast(1)).WillRepeatedly(Return(timestamp));
391     EXPECT_CALL(*packet, getSize()).Times(AtLeast(1)).WillRepeatedly(Return(testData.size()));
392     EXPECT_CALL(*packet, getData()).Times(AtLeast(1)).WillRepeatedly(Return(testData.c_str()));
393     EXPECT_EQ(
394         mAidlClient->dispatchPacketToClient(0, static_cast<std::shared_ptr<MemHandle>>(packet)),
395         Status::SUCCESS);
396     EXPECT_EQ(streamCb->data, packet->getData());
397     EXPECT_EQ(streamCb->timestamp, packet->getTimeStamp());
398 }
399 
400 }  // namespace
401 }  // namespace aidl_client
402 }  // namespace client_interface
403 }  // namespace runner
404 }  // namespace computepipe
405 }  // namespace automotive
406 }  // namespace android
407