Implement QoS in NNAPI Bug: 136739795 Bug: 142902514 Bug: 145300530 Test: mma Test: CtsNNAPITestCases Test: NeuralNetworksTest_static Change-Id: I9b4ed67102b6b1fae2b2ef50ddf746ed912163cc Merged-In: I9b4ed67102b6b1fae2b2ef50ddf746ed912163cc (cherry picked from commit 699ffdacfca7a42c059dc6f581eec913d74be9b3)
diff --git a/runtime/Callbacks.cpp b/runtime/Callbacks.cpp index 6655a1a..6a81b9c 100644 --- a/runtime/Callbacks.cpp +++ b/runtime/Callbacks.cpp
@@ -32,7 +32,7 @@ // PreparedModelCallback methods begin here -Return<void> PreparedModelCallback::notifyInternal(ErrorStatus errorStatus, +Return<void> PreparedModelCallback::notifyInternal(bool deadObject, ErrorStatus errorStatus, const sp<V1_0::IPreparedModel>& preparedModel) { { std::lock_guard<std::mutex> hold(mMutex); @@ -43,6 +43,7 @@ } // store results and mark as notified + mDeadObject = deadObject; mErrorStatus = errorStatus; mPreparedModel = preparedModel; mNotified = true; @@ -54,17 +55,21 @@ Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus errorStatus, const sp<V1_0::IPreparedModel>& preparedModel) { - return notifyInternal(static_cast<ErrorStatus>(errorStatus), preparedModel); + return notifyInternal(false, static_cast<ErrorStatus>(errorStatus), preparedModel); } Return<void> PreparedModelCallback::notify_1_2(V1_0::ErrorStatus errorStatus, const sp<V1_2::IPreparedModel>& preparedModel) { - return notifyInternal(static_cast<ErrorStatus>(errorStatus), preparedModel); + return notifyInternal(false, static_cast<ErrorStatus>(errorStatus), preparedModel); } Return<void> PreparedModelCallback::notify_1_3(ErrorStatus errorStatus, const sp<V1_3::IPreparedModel>& preparedModel) { - return notifyInternal(errorStatus, preparedModel); + return notifyInternal(false, errorStatus, preparedModel); +} + +void PreparedModelCallback::notifyAsDeadObject() { + notifyInternal(true, ErrorStatus::GENERAL_FAILURE, nullptr); } void PreparedModelCallback::wait() const { @@ -82,22 +87,31 @@ return mPreparedModel; } +bool PreparedModelCallback::isDeadObject() const { + wait(); + return mDeadObject; +} + // ExecutionCallback methods begin here Return<void> ExecutionCallback::notify(V1_0::ErrorStatus errorStatus) { - return notifyInternal(static_cast<ErrorStatus>(errorStatus), {}, kNoTiming); + return notifyInternal(false, static_cast<ErrorStatus>(errorStatus), {}, kNoTiming); } Return<void> ExecutionCallback::notify_1_2(V1_0::ErrorStatus errorStatus, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) { - return notifyInternal(static_cast<ErrorStatus>(errorStatus), outputShapes, timing); + return notifyInternal(false, static_cast<ErrorStatus>(errorStatus), outputShapes, timing); } Return<void> ExecutionCallback::notify_1_3(V1_3::ErrorStatus errorStatus, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) { - return notifyInternal(errorStatus, outputShapes, timing); + return notifyInternal(false, errorStatus, outputShapes, timing); +} + +void ExecutionCallback::notifyAsDeadObject() { + notifyInternal(true, ErrorStatus::GENERAL_FAILURE, {}, kNoTiming); } void ExecutionCallback::wait() const { @@ -135,6 +149,11 @@ return mTiming; } +bool ExecutionCallback::isDeadObject() const { + wait(); + return mDeadObject; +} + bool ExecutionCallback::bindThread(std::thread asyncThread) { std::lock_guard<std::mutex> lock(mMutex); @@ -180,25 +199,30 @@ mOnFinish = finish; } -Return<void> ExecutionCallback::notifyInternal(ErrorStatus errorStatus, - hidl_vec<OutputShape> outputShapes, Timing timing) { +Return<void> ExecutionCallback::notifyInternal(bool deadObject, ErrorStatus errorStatus, + std::vector<OutputShape> outputShapes, + Timing timing) { // check results - if (errorStatus == ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) { - // outputShapes must not be empty if OUTPUT_INSUFFICIENT_SIZE. - if (outputShapes.size() == 0) { - LOG(ERROR) << "Notified with empty output shape vector when OUTPUT_INSUFFICIENT_SIZE"; - errorStatus = ErrorStatus::GENERAL_FAILURE; - outputShapes = {}; - timing = kNoTiming; - } - } else if (errorStatus != ErrorStatus::NONE) { - // outputShapes must be empty if errorStatus is neither NONE nor OUTPUT_INSUFFICIENT_SIZE. - if (outputShapes.size() != 0) { - LOG(ERROR) << "Notified with non-empty output shape vector when error status is " - "neither NONE nor OUTPUT_INSUFFICIENT_SIZE"; - errorStatus = ErrorStatus::GENERAL_FAILURE; - outputShapes = {}; - timing = kNoTiming; + if (!deadObject) { + if (errorStatus == ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) { + // outputShapes must not be empty if OUTPUT_INSUFFICIENT_SIZE. + if (outputShapes.size() == 0) { + LOG(ERROR) + << "Notified with empty output shape vector when OUTPUT_INSUFFICIENT_SIZE"; + errorStatus = ErrorStatus::GENERAL_FAILURE; + outputShapes = {}; + timing = kNoTiming; + } + } else if (errorStatus != ErrorStatus::NONE) { + // outputShapes must be empty if errorStatus is neither NONE nor + // OUTPUT_INSUFFICIENT_SIZE. + if (outputShapes.size() != 0) { + LOG(ERROR) << "Notified with non-empty output shape vector when error status is " + "neither NONE nor OUTPUT_INSUFFICIENT_SIZE"; + errorStatus = ErrorStatus::GENERAL_FAILURE; + outputShapes = {}; + timing = kNoTiming; + } } } @@ -211,8 +235,9 @@ return Void(); } + mDeadObject = deadObject; mErrorStatus = errorStatus; - mOutputShapes = outputShapes; + mOutputShapes = std::move(outputShapes); mTiming = timing; mNotified = true;