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