1 /*
2  * Copyright (C) 2020 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_FRAMEWORKS_ML_NN_RUNTIME_EVENT_H
18 #define ANDROID_FRAMEWORKS_ML_NN_RUNTIME_EVENT_H
19 
20 #include <android/sync.h>
21 #include <utility>
22 
23 #include "Callbacks.h"
24 #include "HalInterfaces.h"
25 
26 namespace android::nn {
27 
28 class IEvent {
29    public:
30     virtual ~IEvent() = default;
31     virtual void wait() const = 0;
32     virtual hal::ErrorStatus getStatus() const = 0;
33     virtual int getSyncFenceFd(bool shouldDup) const = 0;
34 };
35 
36 // The CallbackEvent wraps ExecutionCallback
37 class CallbackEvent : public IEvent {
38    public:
CallbackEvent(sp<ExecutionCallback> callback)39     CallbackEvent(sp<ExecutionCallback> callback) : kExecutionCallback(std::move(callback)) {
40         CHECK(kExecutionCallback != nullptr);
41     }
42 
wait()43     void wait() const override { kExecutionCallback->wait(); }
getStatus()44     hal::ErrorStatus getStatus() const override { return kExecutionCallback->getStatus(); }
45     // Always return -1 as this is not backed by a sync fence.
getSyncFenceFd(bool)46     int getSyncFenceFd(bool /*should_dup*/) const override { return -1; }
47 
48    private:
49     const sp<ExecutionCallback> kExecutionCallback;
50 };
51 
52 // The SyncFenceEvent wraps sync fence and IFencedExecutionCallback
53 class SyncFenceEvent : public IEvent {
54    public:
SyncFenceEvent(int sync_fence_fd,const sp<hal::IFencedExecutionCallback> & callback)55     SyncFenceEvent(int sync_fence_fd, const sp<hal::IFencedExecutionCallback>& callback)
56         : kFencedExecutionCallback(callback) {
57         if (sync_fence_fd > 0) {
58             // Dup the provided file descriptor
59             mSyncFenceFd = dup(sync_fence_fd);
60             CHECK(mSyncFenceFd > 0);
61         }
62     }
63 
64     // Close the fd the event owns.
~SyncFenceEvent()65     ~SyncFenceEvent() { close(mSyncFenceFd); }
66 
67     // Use syncWait to wait for the sync fence until the status change.
wait()68     void wait() const override { syncWait(mSyncFenceFd, -1); }
69 
70     // Get the status of the event.
71     // In case of syncWait error, query the dispatch callback for detailed
72     // error status.
getStatus()73     hal::ErrorStatus getStatus() const override {
74         auto error = hal::ErrorStatus::NONE;
75         if (mSyncFenceFd > 0 && syncWait(mSyncFenceFd, -1) != FenceState::SIGNALED) {
76             error = hal::ErrorStatus::GENERAL_FAILURE;
77             // If there is a callback available, use the callback to get the error code.
78             if (kFencedExecutionCallback != nullptr) {
79                 const hal::Return<void> ret = kFencedExecutionCallback->getExecutionInfo(
80                         [&error](hal::ErrorStatus status, hal::Timing, hal::Timing) {
81                             error = status;
82                         });
83                 if (!ret.isOk()) {
84                     error = hal::ErrorStatus::GENERAL_FAILURE;
85                 }
86             }
87         }
88         return error;
89     }
90 
91     // Return the sync fence fd.
92     // If shouldDup is true, the caller must close the fd returned:
93     //  - When being used internally within NNAPI runtime, set shouldDup to false.
94     //  - When being used to return a fd to application code, set shouldDup to
95     //  true.
getSyncFenceFd(bool shouldDup)96     int getSyncFenceFd(bool shouldDup) const override {
97         if (shouldDup) {
98             return dup(mSyncFenceFd);
99         }
100         return mSyncFenceFd;
101     }
102 
103    private:
104     // TODO(b/148423931): used android::base::unique_fd instead.
105     int mSyncFenceFd = -1;
106     const sp<hal::IFencedExecutionCallback> kFencedExecutionCallback;
107 };
108 
109 }  // namespace android::nn
110 
111 #endif  // ANDROID_FRAMEWORKS_ML_NN_RUNTIME_EVENT_H
112