• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.c
14 
15 #include "AidlClientImpl.h"
16 
17 #include <vector>
18 
19 #include "OutputConfig.pb.h"
20 #include "PacketDescriptor.pb.h"
21 #include "PipeOptionsConverter.h"
22 #include "StatusUtil.h"
23 
24 #include <aidl/android/automotive/computepipe/runner/PacketDescriptor.h>
25 #include <aidl/android/automotive/computepipe/runner/PacketDescriptorPacketType.h>
26 #include <android-base/logging.h>
27 #include <android/binder_auto_utils.h>
28 
29 namespace android {
30 namespace automotive {
31 namespace computepipe {
32 namespace runner {
33 namespace client_interface {
34 namespace aidl_client {
35 namespace {
36 
37 using ::aidl::android::automotive::computepipe::runner::IPipeStateCallback;
38 using ::aidl::android::automotive::computepipe::runner::IPipeStream;
39 using ::aidl::android::automotive::computepipe::runner::PacketDescriptor;
40 using ::aidl::android::automotive::computepipe::runner::PacketDescriptorPacketType;
41 using ::aidl::android::automotive::computepipe::runner::PipeDescriptor;
42 using ::aidl::android::automotive::computepipe::runner::PipeState;
43 using ::ndk::ScopedAStatus;
44 
ToAidlState(GraphState state)45 PipeState ToAidlState(GraphState state) {
46     switch (state) {
47         case RESET:
48             return PipeState::RESET;
49         case CONFIG_DONE:
50             return PipeState::CONFIG_DONE;
51         case RUNNING:
52             return PipeState::RUNNING;
53         case DONE:
54             return PipeState::DONE;
55         case ERR_HALT:
56         default:
57             return PipeState::ERR_HALT;
58     }
59 }
60 
deathNotifier(void * cookie)61 void deathNotifier(void* cookie) {
62     CHECK(cookie);
63     AidlClientImpl* iface = static_cast<AidlClientImpl*>(cookie);
64     iface->clientDied();
65 }
66 
ToAidlPacketType(proto::PacketType type,PacketDescriptorPacketType * outType)67 Status ToAidlPacketType(proto::PacketType type, PacketDescriptorPacketType* outType) {
68     if (outType == nullptr) {
69         return Status::INTERNAL_ERROR;
70     }
71     switch (type) {
72         case proto::SEMANTIC_DATA:
73             *outType = PacketDescriptorPacketType::SEMANTIC_DATA;
74             return Status::SUCCESS;
75         case proto::PIXEL_DATA:
76             *outType = PacketDescriptorPacketType::PIXEL_DATA;
77             return Status::SUCCESS;
78         default:
79             LOG(ERROR) << "unknown packet type " << type;
80             return Status::INVALID_ARGUMENT;
81     }
82 }
83 
84 }  // namespace
85 
DispatchSemanticData(int32_t streamId,const std::shared_ptr<MemHandle> & packetHandle)86 Status AidlClientImpl::DispatchSemanticData(int32_t streamId,
87                                            const std::shared_ptr<MemHandle>& packetHandle) {
88     PacketDescriptor desc;
89 
90     if (mPacketHandlers.find(streamId) == mPacketHandlers.end()) {
91         LOG(ERROR) << "Bad streamId";
92         return Status::INVALID_ARGUMENT;
93     }
94     Status status = ToAidlPacketType(packetHandle->getType(), &desc.type);
95     if (status != SUCCESS) {
96         return status;
97     }
98     desc.data = std::vector(reinterpret_cast<const uint8_t*>(packetHandle->getData()),
99                             reinterpret_cast<const uint8_t*>(packetHandle->getData() +
100                                                              packetHandle->getSize()));
101     desc.size = packetHandle->getSize();
102     if (static_cast<int32_t>(desc.data.size()) != desc.size) {
103         LOG(ERROR) << "mismatch in char data size and reported size";
104         return Status::INVALID_ARGUMENT;
105     }
106     desc.sourceTimeStampMillis = packetHandle->getTimeStamp();
107     desc.bufId = 0;
108     ScopedAStatus ret = mPacketHandlers[streamId]->deliverPacket(desc);
109     if (!ret.isOk()) {
110         LOG(ERROR) << "Dropping Semantic packet due to error ";
111     }
112     return Status::SUCCESS;
113 }
114 
DispatchPixelData(int32_t streamId,const std::shared_ptr<MemHandle> & packetHandle)115 Status AidlClientImpl::DispatchPixelData(int32_t streamId,
116                                          const std::shared_ptr<MemHandle>& packetHandle) {
117     PacketDescriptor desc;
118 
119     if (mPacketHandlers.find(streamId) == mPacketHandlers.end()) {
120         LOG(ERROR) << "Bad stream id";
121         return Status::INVALID_ARGUMENT;
122     }
123     Status status = ToAidlPacketType(packetHandle->getType(), &desc.type);
124     if (status != Status::SUCCESS) {
125         LOG(ERROR) << "Invalid packet type";
126         return status;
127     }
128 
129     // Copies the native handle to the aidl interface.
130     const native_handle_t* nativeHandle =
131         AHardwareBuffer_getNativeHandle(packetHandle->getHardwareBuffer());
132     for (int i = 0; i < nativeHandle->numFds; i++) {
133         desc.handle.handle.fds.push_back(ndk::ScopedFileDescriptor(nativeHandle->data[i]));
134     }
135     for (int i = 0; i < nativeHandle->numInts; i++) {
136         desc.handle.handle.ints.push_back(nativeHandle->data[i + nativeHandle->numFds]);
137     }
138 
139     // Copies buffer descriptor to the aidl interface.
140     AHardwareBuffer_Desc bufferDesc;
141     AHardwareBuffer_describe(packetHandle->getHardwareBuffer(), &bufferDesc);
142     desc.handle.description.width = bufferDesc.width;
143     desc.handle.description.height = bufferDesc.height;
144     desc.handle.description.stride = bufferDesc.stride;
145     desc.handle.description.layers = bufferDesc.layers;
146     desc.handle.description.format =
147         static_cast<::aidl::android::hardware::graphics::common::PixelFormat>(bufferDesc.format);
148     desc.handle.description.usage =
149         static_cast<::aidl::android::hardware::graphics::common::BufferUsage>(bufferDesc.usage);
150 
151     desc.bufId = packetHandle->getBufferId();
152     desc.sourceTimeStampMillis = packetHandle->getTimeStamp();
153 
154     ScopedAStatus ret = mPacketHandlers[streamId]->deliverPacket(desc);
155     if (!ret.isOk()) {
156         LOG(ERROR) << "Unable to deliver packet. Dropping it and returning an error";
157         return Status::INTERNAL_ERROR;
158     }
159     return Status::SUCCESS;
160 }
161 
162 // Thread-safe function to deliver new packets to client.
dispatchPacketToClient(int32_t streamId,const std::shared_ptr<MemHandle> & packetHandle)163 Status AidlClientImpl::dispatchPacketToClient(int32_t streamId,
164                                               const std::shared_ptr<MemHandle>& packetHandle) {
165     // TODO(146464279) implement.
166     if (!packetHandle) {
167         LOG(ERROR) << "invalid packetHandle";
168         return Status::INVALID_ARGUMENT;
169     }
170     proto::PacketType packetType = packetHandle->getType();
171     switch (packetType) {
172         case proto::SEMANTIC_DATA:
173             return DispatchSemanticData(streamId, packetHandle);
174         case proto::PIXEL_DATA:
175             return DispatchPixelData(streamId, packetHandle);
176         default:
177             LOG(ERROR) << "Unsupported packet type " << packetHandle->getType();
178             return Status::INVALID_ARGUMENT;
179     }
180     return Status::SUCCESS;
181 }
182 
setPipeDebugger(const std::shared_ptr<aidl::android::automotive::computepipe::runner::IPipeDebugger> & pipeDebugger)183 void AidlClientImpl::setPipeDebugger(
184         const std::shared_ptr<aidl::android::automotive::computepipe::runner::IPipeDebugger>&
185         pipeDebugger) {
186     mPipeDebugger = pipeDebugger;
187 }
188 
stateUpdateNotification(const GraphState newState)189 Status AidlClientImpl::stateUpdateNotification(const GraphState newState) {
190     if (mClientStateChangeCallback) {
191         (void)mClientStateChangeCallback->handleState(ToAidlState(newState));
192     }
193     return Status::SUCCESS;
194 }
195 
getPipeDescriptor(PipeDescriptor * _aidl_return)196 ScopedAStatus AidlClientImpl::getPipeDescriptor(PipeDescriptor* _aidl_return) {
197     if (_aidl_return == nullptr) {
198         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
199     }
200     *_aidl_return = OptionsToPipeDescriptor(mGraphOptions);
201     return ScopedAStatus::ok();
202 }
203 
setPipeInputSource(int32_t configId)204 ScopedAStatus AidlClientImpl::setPipeInputSource(int32_t configId) {
205     if (!isClientInitDone()) {
206         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
207     }
208 
209     proto::ConfigurationCommand configurationCommand;
210     configurationCommand.mutable_set_input_source()->set_source_id(configId);
211 
212     Status status = mEngine->processClientConfigUpdate(configurationCommand);
213     return ToNdkStatus(status);
214 }
215 
setPipeOffloadOptions(int32_t configId)216 ScopedAStatus AidlClientImpl::setPipeOffloadOptions(int32_t configId) {
217     if (!isClientInitDone()) {
218         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
219     }
220 
221     proto::ConfigurationCommand configurationCommand;
222     configurationCommand.mutable_set_offload_offload()->set_offload_option_id(configId);
223 
224     Status status = mEngine->processClientConfigUpdate(configurationCommand);
225     return ToNdkStatus(status);
226 }
227 
setPipeTermination(int32_t configId)228 ScopedAStatus AidlClientImpl::setPipeTermination(int32_t configId) {
229     if (!isClientInitDone()) {
230         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
231     }
232 
233     proto::ConfigurationCommand configurationCommand;
234     configurationCommand.mutable_set_termination_option()->set_termination_option_id(configId);
235 
236     Status status = mEngine->processClientConfigUpdate(configurationCommand);
237     return ToNdkStatus(status);
238 }
239 
init(const std::shared_ptr<IPipeStateCallback> & stateCb)240 ScopedAStatus AidlClientImpl::init(const std::shared_ptr<IPipeStateCallback>& stateCb) {
241     if (isClientInitDone()) {
242         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
243     }
244 
245     AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(&deathNotifier);
246     AIBinder_linkToDeath(stateCb->asBinder().get(), recipient, this);
247 
248     mClientStateChangeCallback = stateCb;
249     return ScopedAStatus::ok();
250 }
251 
isClientInitDone()252 bool AidlClientImpl::isClientInitDone() {
253     if (mClientStateChangeCallback == nullptr) {
254         return false;
255     }
256     return true;
257 }
258 
clientDied()259 void AidlClientImpl::clientDied() {
260     LOG(INFO) << "Client has died";
261     releaseRunner();
262 }
263 
setPipeOutputConfig(int32_t streamId,int32_t maxInFlightCount,const std::shared_ptr<IPipeStream> & handler)264 ScopedAStatus AidlClientImpl::setPipeOutputConfig(int32_t streamId, int32_t maxInFlightCount,
265                                                   const std::shared_ptr<IPipeStream>& handler) {
266     if (!isClientInitDone()) {
267         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
268     }
269 
270     if (mPacketHandlers.find(streamId) != mPacketHandlers.end()) {
271         LOG(INFO) << "Handler for stream id " << streamId
272                   << " has already"
273                      " been registered.";
274         return ToNdkStatus(INVALID_ARGUMENT);
275     }
276 
277     mPacketHandlers.insert(std::pair<int, std::shared_ptr<IPipeStream>>(streamId, handler));
278 
279     proto::ConfigurationCommand configurationCommand;
280     configurationCommand.mutable_set_output_stream()->set_stream_id(streamId);
281     configurationCommand.mutable_set_output_stream()->set_max_inflight_packets_count(
282             maxInFlightCount);
283     Status status = mEngine->processClientConfigUpdate(configurationCommand);
284 
285     if (status != SUCCESS) {
286         LOG(INFO) << "Failed to register handler for stream id " << streamId;
287         mPacketHandlers.erase(streamId);
288     }
289     return ToNdkStatus(status);
290 }
291 
applyPipeConfigs()292 ScopedAStatus AidlClientImpl::applyPipeConfigs() {
293     if (!isClientInitDone()) {
294         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
295     }
296 
297     proto::ControlCommand controlCommand;
298     *controlCommand.mutable_apply_configs() = proto::ApplyConfigs();
299 
300     Status status = mEngine->processClientCommand(controlCommand);
301     return ToNdkStatus(status);
302 }
303 
resetPipeConfigs()304 ScopedAStatus AidlClientImpl::resetPipeConfigs() {
305     if (!isClientInitDone()) {
306         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
307     }
308 
309     proto::ControlCommand controlCommand;
310     *controlCommand.mutable_reset_configs() = proto::ResetConfigs();
311 
312     Status status = mEngine->processClientCommand(controlCommand);
313     return ToNdkStatus(status);
314 }
315 
startPipe()316 ScopedAStatus AidlClientImpl::startPipe() {
317     proto::ControlCommand controlCommand;
318     *controlCommand.mutable_start_graph() = proto::StartGraph();
319 
320     Status status = mEngine->processClientCommand(controlCommand);
321     return ToNdkStatus(status);
322 }
323 
stopPipe()324 ScopedAStatus AidlClientImpl::stopPipe() {
325     proto::ControlCommand controlCommand;
326     *controlCommand.mutable_stop_graph() = proto::StopGraph();
327 
328     Status status = mEngine->processClientCommand(controlCommand);
329     return ToNdkStatus(status);
330 }
331 
doneWithPacket(int32_t bufferId,int32_t streamId)332 ScopedAStatus AidlClientImpl::doneWithPacket(int32_t bufferId, int32_t streamId) {
333     auto it = mPacketHandlers.find(streamId);
334     if (it == mPacketHandlers.end()) {
335         LOG(ERROR) << "Bad stream id provided for doneWithPacket call";
336         return ToNdkStatus(Status::INVALID_ARGUMENT);
337     }
338 
339     return ToNdkStatus(mEngine->freePacket(bufferId, streamId));
340 }
341 
getPipeDebugger(std::shared_ptr<aidl::android::automotive::computepipe::runner::IPipeDebugger> * _aidl_return)342 ScopedAStatus AidlClientImpl::getPipeDebugger(
343     std::shared_ptr<aidl::android::automotive::computepipe::runner::IPipeDebugger>*
344     _aidl_return) {
345     if (_aidl_return == nullptr) {
346         return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
347     }
348     if (mPipeDebugger == nullptr) {
349         return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
350     }
351     *_aidl_return = mPipeDebugger;
352     return ScopedAStatus::ok();
353 }
354 
releaseRunner()355 ScopedAStatus AidlClientImpl::releaseRunner() {
356     proto::ControlCommand controlCommand;
357     *controlCommand.mutable_death_notification() = proto::DeathNotification();
358 
359     Status status = mEngine->processClientCommand(controlCommand);
360 
361     mClientStateChangeCallback = nullptr;
362     mPacketHandlers.clear();
363     return ToNdkStatus(status);
364 }
365 
366 }  // namespace aidl_client
367 }  // namespace client_interface
368 }  // namespace runner
369 }  // namespace computepipe
370 }  // namespace automotive
371 }  // namespace android
372