1 /*
2  * Copyright (C) 2019 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 #ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_3_CALLBACKS_H
18 #define ANDROID_HARDWARE_NEURALNETWORKS_V1_3_CALLBACKS_H
19 
20 #include <android-base/thread_annotations.h>
21 #include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
22 #include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
23 #include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
24 #include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
25 #include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
26 #include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
27 #include <hidl/Status.h>
28 #include <condition_variable>
29 #include <mutex>
30 
31 /*
32  * The Callback classes are used internally by the NeuralNetworks runtime to
33  * synchronize between different threads. An asynchronous task is launched
34  * paired with a callback object. When a client thread requires the output being
35  * generated by the asynchronous task, the client thread can wait for the result
36  * and be blocked until it has completed. Any wait may safely be called
37  * concurrently, even on the same callback object. When the asynchronous task
38  * has finished its workload, it must immediately call "notify*". If the
39  * asynchronous task has failed to launch, the function that tried to launch the
40  * asynchronous task must immediately call "notify*". This "notify*" call
41  * awakens any client threads waiting on the callback object.
42  *
43  * These classes exist to enable synchronization across HIDL. When
44  * synchronization is only required in the same process, consider using
45  * std::future, std::mutex, std::condition_variable, or std::experimental::latch
46  * instead.
47  */
48 
49 namespace android::hardware::neuralnetworks::V1_3::implementation {
50 
51 /**
52  * The PreparedModelCallback class is used to receive the error status of
53  * preparing a model as well as the prepared model from a task executing
54  * asynchronously with respect to the runtime. If a calling thread calls wait
55  * or get* on a PreparedModelCallback object and the corresponding asynchronous
56  * task has not finished preparing the model, the calling thread will block
57  * until the asynchronous task has called notify*.
58  *
59  * If the callback object is notified more than once, only the results of the
60  * first call to notify* are used, and the results from subsequent calls are
61  * discarded.
62  *
63  * This callback object is passed as an argument to IDevice::prepareModel*.
64  */
65 class PreparedModelCallback : public IPreparedModelCallback {
66   public:
67     /**
68      * IPreparedModelCallback::notify marks the callback object with the return
69      * status of the asynchronous model preparation along with the prepared
70      * model, and allows all prior and future wait calls on the
71      * PreparedModelCallback object to proceed.
72      *
73      * One of IPreparedModelCallback::notify, IPreparedModelCallback::notify_1_2,
74      * or IPreparedModelCallback::notify_1_3 must be called on a given
75      * PreparedModelCallback object.
76      *
77      * If the callback object is notified more than once, only the results of
78      * the first call to notify* are used, and the results from subsequent calls
79      * are discarded.
80      *
81      * @param status Error status returned from asynchronously preparing the
82      *     model; will be:
83      *     - NONE if the asynchronous preparation was successful
84      *     - DEVICE_UNAVAILABLE if driver is offline or busy
85      *     - GENERAL_FAILURE if there is an unspecified error
86      *     - INVALID_ARGUMENT if the input model is invalid
87      * @param preparedModel Returned model that has been prepared for execution,
88      *     nullptr if the model was unable to be prepared.
89      */
90     Return<void> notify(V1_0::ErrorStatus status,
91                         const sp<V1_0::IPreparedModel>& preparedModel) override;
92 
93     /**
94      * IPreparedModelCallback::notify_1_2 marks the callback object with the
95      * return status of the asynchronous model preparation along with the
96      * prepared model, and allows all prior and future wait calls on the
97      * PreparedModelCallback object to proceed.
98      *
99      * One of IPreparedModelCallback::notify, IPreparedModelCallback::notify_1_2,
100      * or IPreparedModelCallback::notify_1_3 must be called on a given
101      * PreparedModelCallback object.
102      *
103      * If the callback object is notified more than once, only the results of
104      * the first call to notify* are used, and the results from subsequent calls
105      * are discarded.
106      *
107      * @param status Error status returned from asynchronously preparing the
108      *     model; will be:
109      *     - NONE if the asynchronous preparation was successful
110      *     - DEVICE_UNAVAILABLE if driver is offline or busy
111      *     - GENERAL_FAILURE if there is an unspecified error
112      *     - INVALID_ARGUMENT if the input model is invalid
113      * @param preparedModel Returned model that has been prepared for execution,
114      *     nullptr if the model was unable to be prepared.
115      */
116     Return<void> notify_1_2(V1_0::ErrorStatus status,
117                             const sp<V1_2::IPreparedModel>& preparedModel) override;
118 
119     /**
120      * IPreparedModelCallback::notify_1_3 marks the callback object with the
121      * return status of the asynchronous model preparation along with the
122      * prepared model, and allows all prior and future wait calls on the
123      * PreparedModelCallback object to proceed.
124      *
125      * One of IPreparedModelCallback::notify, IPreparedModelCallback::notify_1_2,
126      * or IPreparedModelCallback::notify_1_3 must be called on a given
127      * PreparedModelCallback object.
128      *
129      * If the callback object is notified more than once, only the results of
130      * the first call to notify* are used, and the results from subsequent calls
131      * are discarded.
132      *
133      * @param status Error status returned from asynchronously preparing the
134      *     model; will be:
135      *     - NONE if the asynchronous preparation was successful
136      *     - DEVICE_UNAVAILABLE if driver is offline or busy
137      *     - GENERAL_FAILURE if there is an unspecified error
138      *     - INVALID_ARGUMENT if the input model is invalid
139      * @param preparedModel Returned model that has been prepared for execution,
140      *     nullptr if the model was unable to be prepared.
141      */
142     Return<void> notify_1_3(V1_3::ErrorStatus status,
143                             const sp<V1_3::IPreparedModel>& preparedModel) override;
144 
145     /**
146      * PreparedModelCallback::wait blocks until notify* has been called on the
147      * callback object.
148      */
149     void wait() const;
150 
151     /**
152      * Retrieves the error status returned from the asynchronous task launched
153      * by IDevice::prepareModel*. If IDevice::prepareModel* has not finished
154      * asynchronously preparing the model, this call will block until the
155      * asynchronous task notifies the object.
156      *
157      * @return status Error status returned from asynchronously preparing the
158      *     model; will be:
159      *     - NONE if the asynchronous preparation was successful
160      *     - DEVICE_UNAVAILABLE if driver is offline or busy
161      *     - GENERAL_FAILURE if there is an unspecified error
162      *     - INVALID_ARGUMENT if the input model is invalid
163      */
164     ErrorStatus getStatus() const;
165 
166     /**
167      * Retrieves the model that has been prepared for execution from the
168      * asynchronous task launched by IDevice::prepareModel*. If
169      * IDevice::prepareModel* has not finished asynchronously preparing the
170      * model, this call will block until the asynchronous task notifies the
171      * object.
172      *
173      * @return preparedModel Returned model that has been prepared for
174      *     execution, nullptr if the model was unable to be prepared.
175      */
176     sp<V1_0::IPreparedModel> getPreparedModel() const;
177 
178   private:
179     Return<void> notifyInternal(ErrorStatus status, const sp<V1_0::IPreparedModel>& preparedModel);
180 
181     mutable std::mutex mMutex;
182     mutable std::condition_variable mCondition;
183     bool mNotified GUARDED_BY(mMutex) = false;
184     ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
185     sp<V1_0::IPreparedModel> mPreparedModel;
186 };
187 
188 /**
189  * The ExecutionCallback class is used to receive the results of the execution
190  * from a task executing asynchronously with respect to the runtime. If a
191  * calling thread calls wait or get* on a ExecutionCallback object and the
192  * corresponding asynchronous task has not finished the execution, the calling
193  * thread will block until the asynchronous task has either called one of the
194  * notify* methods.
195  *
196  * If the callback object is notified more than once, only the results of the
197  * first call to notify* are used, and the results from subsequent calls are
198  * discarded.
199  *
200  * This callback object is passed as an argument to IPreparedModel::execute*.
201  */
202 class ExecutionCallback : public IExecutionCallback {
203   public:
204     /**
205      * IExecutionCallback::notify marks the callback object with the return
206      * status of the asynchronous execution that held this callback and enables
207      * all prior and future wait calls on the ExecutionCallback object to
208      * proceed.
209      *
210      * One of the IExecutionCallback::notify* methods must be called on a given
211      * ExecutionCallback object.
212      *
213      * If the callback object is notified more than once, only the results of
214      * the first call to notify* are used, and the results from subsequent calls
215      * are discarded.
216      *
217      * @param status Error status returned from launching the asynchronous task
218      *     (if the launch fails) or from the asynchronous task itself (if the
219      *     launch succeeds). Must be:
220      *     - NONE if the asynchronous execution was successful
221      *     - DEVICE_UNAVAILABLE if driver is offline or busy
222      *     - GENERAL_FAILURE if there is an unspecified error
223      *     - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is not large
224      *         enough to store the resultant values
225      *     - INVALID_ARGUMENT if the input request is invalid
226      */
227     Return<void> notify(V1_0::ErrorStatus status) override;
228 
229     /**
230      * IExecutionCallback::notify_1_2 marks the callback object with the results
231      * (error status, dynamic output shapes, and timing information) of the
232      * asynchronous execution that held this callback and enables all prior and
233      * future wait calls on the ExecutionCallback object to proceed.
234      *
235      * One of the IExecutionCallback::notify* methods must be called on a given
236      * ExecutionCallback object.
237      *
238      * If the callback object is notified more than once, only the results of
239      * the first call to notify* are used, and the results from subsequent calls
240      * are discarded.
241      *
242      * @param status Error status returned from launching the asynchronous task
243      *     (if the launch fails) or from the asynchronous task itself (if the
244      *     launch succeeds). Must be:
245      *     - NONE if the asynchronous execution was successful
246      *     - DEVICE_UNAVAILABLE if driver is offline or busy
247      *     - GENERAL_FAILURE if the asynchronous task resulted in an unspecified
248      *         error
249      *     - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is
250      *         not large enough to store the corresponding output
251      *     - INVALID_ARGUMENT if one of the input arguments to prepareModel is
252      *         invalid
253      * @param outputShapes A list of shape information of model output operands.
254      *     The index into "outputShapes" corresponds to the index of the output
255      *     operand in the Request outputs vector. outputShapes must be empty
256      *     unless the status is either NONE or OUTPUT_INSUFFICIENT_SIZE.
257      * @param Timing Duration of execution. Unless MeasureTiming::YES was passed
258      *     when launching the execution and status is NONE, all times must be
259      *     reported as UINT64_MAX. A driver may choose to report any time as
260      *     UINT64_MAX, indicating that particular measurement is not available.
261      */
262     Return<void> notify_1_2(V1_0::ErrorStatus status,
263                             const hidl_vec<V1_2::OutputShape>& outputShapes,
264                             const V1_2::Timing& timing) override;
265 
266     /**
267      * IExecutionCallback::notify_1_3 marks the callback object with the results
268      * (error status, dynamic output shapes, and timing information) of the
269      * asynchronous execution that held this callback and enables all prior and
270      * future wait calls on the ExecutionCallback object to proceed.
271      *
272      * One of the IExecutionCallback::notify* methods must be called on a given
273      * ExecutionCallback object.
274      *
275      * If the callback object is notified more than once, only the results of
276      * the first call to notify* are used, and the results from subsequent calls
277      * are discarded.
278      *
279      * @param status Error status returned from launching the asynchronous task
280      *     (if the launch fails) or from the asynchronous task itself (if the
281      *     launch succeeds). Must be:
282      *     - NONE if the asynchronous execution was successful
283      *     - DEVICE_UNAVAILABLE if driver is offline or busy
284      *     - GENERAL_FAILURE if the asynchronous task resulted in an unspecified
285      *         error
286      *     - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is
287      *         not large enough to store the corresponding output
288      *     - INVALID_ARGUMENT if one of the input arguments to prepareModel is
289      *         invalid
290      *     - MISSED_DEADLINE_* if the deadline was not met
291      * @param outputShapes A list of shape information of model output operands.
292      *     The index into "outputShapes" corresponds to the index of the output
293      *     operand in the Request outputs vector. outputShapes must be empty
294      *     unless the status is either NONE or OUTPUT_INSUFFICIENT_SIZE.
295      * @param Timing Duration of execution. Unless MeasureTiming::YES was passed
296      *     when launching the execution and status is NONE, all times must be
297      *     reported as UINT64_MAX. A driver may choose to report any time as
298      *     UINT64_MAX, indicating that particular measurement is not available.
299      */
300     Return<void> notify_1_3(V1_3::ErrorStatus status,
301                             const hidl_vec<V1_2::OutputShape>& outputShapes,
302                             const V1_2::Timing& timing) override;
303 
304     /**
305      * ExecutionCallback::wait blocks until notify* has been called on the
306      * callback object.
307      */
308     void wait() const;
309 
310     /**
311      * Retrieves the error status returned from the asynchronous task launched
312      * by one of the IPreparedModel::execute* methods. If
313      * IPreparedModel::execute* (but not IPreparedModel::executeSynchronously*)
314      * has not finished asynchronously executing, this call will block until the
315      * asynchronous task notifies the object.
316      *
317      * @return status Error status returned from launching the asynchronous task
318      *     (if the launch fails) or from the asynchronous task itself (if the
319      *     launch succeeds). Must be:
320      *     - NONE if the asynchronous execution was successful
321      *     - DEVICE_UNAVAILABLE if driver is offline or busy
322      *     - GENERAL_FAILURE if the asynchronous task resulted in an unspecified
323      *         error
324      *     - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is
325      *         not large enough to store the corresponding output
326      *     - INVALID_ARGUMENT if one of the input arguments to prepareModel is
327      *         invalid
328      *     - MISSED_DEADLINE_* if the deadline could not be met
329      */
330     V1_3::ErrorStatus getStatus() const;
331 
332     /**
333      * Retrieves the error status returned from the asynchronous task launched
334      * by one of the IPreparedModel::execute* methods. If
335      * IPreparedModel::execute* (but not IPreparedModel::executeSynchronously*)
336      * has not finished asynchronously executing, this call will block until the
337      * asynchronous task notifies the object.
338      *
339      * If the asynchronous task was launched by IPreparedModel::execute, an
340      * empty vector will be returned.
341      *
342      * @return outputShapes A list of shape information of model output
343      *     operands. The index into "outputShapes" corresponds to the index of
344      *     the output operand in the Request outputs vector. outputShapes must
345      *     be empty unless the status is either NONE or
346      *     OUTPUT_INSUFFICIENT_SIZE. outputShaps may be empty if the status is
347      *     NONE and all model output operands are fully-specified at execution
348      *     time. outputShapes must have the same number of elements as the
349      *     number of model output operands if the status is
350      *     OUTPUT_INSUFFICIENT_SIZE, or if the status is NONE and the model has
351      *     at least one output operand that is not fully-specified.
352      */
353     const std::vector<V1_2::OutputShape>& getOutputShapes() const;
354 
355     /**
356      * Retrieves the error status returned from the asynchronous task launched
357      * by one of the IPreparedModel::execute* methods. If
358      * IPreparedModel::execute* (but not IPreparedModel::executeSynchronously*)
359      * has not finished asynchronously executing, this call will block until the
360      * asynchronous task notifies the object.
361      *
362      * If the asynchronous task was launched by IPreparedModel::execute, every
363      * time must be UINT64_MAX.
364      *
365      * @return timing Duration of the execution. Every time must be UINT64_MAX
366      *     unless the status is NONE.
367      */
368     V1_2::Timing getTiming() const;
369 
370   private:
371     /*
372      * ExecutionCallback::notifyInternal stores the results of the execution
373      * (status, output shapes, and timing information) in the ExecutionCallback
374      * object before any call to wait or get* return. It then enables all prior
375      * and future wait calls on the ExecutionCallback object to proceed.
376      */
377     Return<void> notifyInternal(V1_3::ErrorStatus errorStatus,
378                                 hidl_vec<V1_2::OutputShape> outputShapes, V1_2::Timing timing);
379 
380     // members
381     mutable std::mutex mMutex;
382     mutable std::condition_variable mCondition;
383     bool mNotified GUARDED_BY(mMutex) = false;
384     V1_3::ErrorStatus mErrorStatus = V1_3::ErrorStatus::GENERAL_FAILURE;
385     std::vector<V1_2::OutputShape> mOutputShapes = {};
386     V1_2::Timing mTiming = {};
387 };
388 
389 }  // namespace android::hardware::neuralnetworks::V1_3::implementation
390 
391 #endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_3_CALLBACKS_H
392