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