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;