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