1 /*
2  * Copyright (C) 2021 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_PACKAGES_MODULES_NEURALNETWORKS_DRIVER_SAMPLE_AIDL_SAMPLE_DRIVER_AIDL_H
18 #define ANDROID_PACKAGES_MODULES_NEURALNETWORKS_DRIVER_SAMPLE_AIDL_SAMPLE_DRIVER_AIDL_H
19 
20 #include <android/binder_auto_utils.h>
21 #include <nnapi/hal/aidl/BufferTracker.h>
22 #include <nnapi/hal/aidl/HalInterfaces.h>
23 
24 #include <memory>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 
29 #include "CpuExecutor.h"
30 #include "NeuralNetworks.h"
31 
32 namespace android {
33 namespace nn {
34 namespace sample_driver_aidl {
35 
36 // Manages the data buffer for an operand.
37 class SampleBuffer : public aidl_hal::BnBuffer {
38    public:
SampleBuffer(std::shared_ptr<AidlManagedBuffer> buffer,std::unique_ptr<AidlBufferTracker::Token> token)39     SampleBuffer(std::shared_ptr<AidlManagedBuffer> buffer,
40                  std::unique_ptr<AidlBufferTracker::Token> token)
41         : kBuffer(std::move(buffer)), kToken(std::move(token)) {
42         CHECK(kBuffer != nullptr);
43         CHECK(kToken != nullptr);
44     }
45     ndk::ScopedAStatus copyFrom(const aidl_hal::Memory& src,
46                                 const std::vector<int32_t>& dimensions) override;
47     ndk::ScopedAStatus copyTo(const aidl_hal::Memory& dst) override;
48 
49    private:
50     const std::shared_ptr<AidlManagedBuffer> kBuffer;
51     const std::unique_ptr<AidlBufferTracker::Token> kToken;
52 };
53 
54 // Base class used to create sample drivers for the NN HAL.  This class
55 // provides some implementation of the more common functions.
56 //
57 // Since these drivers simulate hardware, they must run the computations
58 // on the CPU.  An actual driver would not do that.
59 class SampleDriver : public aidl_hal::BnDevice {
60    public:
61     SampleDriver(const char* name,
62                  const IOperationResolver* operationResolver = BuiltinOperationResolver::get())
mName(name)63         : mName(name),
64           mOperationResolver(operationResolver),
65           mBufferTracker(AidlBufferTracker::create()) {
66         android::nn::initVLogMask();
67     }
68     ndk::ScopedAStatus allocate(const aidl_hal::BufferDesc& desc,
69                                 const std::vector<aidl_hal::IPreparedModelParcel>& preparedModels,
70                                 const std::vector<aidl_hal::BufferRole>& inputRoles,
71                                 const std::vector<aidl_hal::BufferRole>& outputRoles,
72                                 aidl_hal::DeviceBuffer* buffer) override;
73     ndk::ScopedAStatus getNumberOfCacheFilesNeeded(
74             aidl_hal::NumberOfCacheFiles* numberOfCacheFiles) override;
75     ndk::ScopedAStatus getSupportedExtensions(
76             std::vector<aidl_hal::Extension>* extensions) override;
77     ndk::ScopedAStatus getType(aidl_hal::DeviceType* deviceType) override;
78     ndk::ScopedAStatus getVersionString(std::string* version) override;
79     ndk::ScopedAStatus prepareModel(
80             const aidl_hal::Model& model, aidl_hal::ExecutionPreference preference,
81             aidl_hal::Priority priority, int64_t deadlineNs,
82             const std::vector<ndk::ScopedFileDescriptor>& modelCache,
83             const std::vector<ndk::ScopedFileDescriptor>& dataCache,
84             const std::vector<uint8_t>& token,
85             const std::shared_ptr<aidl_hal::IPreparedModelCallback>& callback) override;
86     ndk::ScopedAStatus prepareModelWithConfig(
87             const aidl_hal::Model& model, const aidl_hal::PrepareModelConfig& config,
88             const std::shared_ptr<aidl_hal::IPreparedModelCallback>& callback) override;
89     ndk::ScopedAStatus prepareModelFromCache(
90             int64_t deadlineNs, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
91             const std::vector<ndk::ScopedFileDescriptor>& dataCache,
92             const std::vector<uint8_t>& token,
93             const std::shared_ptr<aidl_hal::IPreparedModelCallback>& callback) override;
94 
getExecutor()95     CpuExecutor getExecutor() const { return CpuExecutor(mOperationResolver); }
getBufferTracker()96     const std::shared_ptr<AidlBufferTracker>& getBufferTracker() const { return mBufferTracker; }
97 
98    protected:
99     std::string mName;
100     const IOperationResolver* mOperationResolver;
101     const std::shared_ptr<AidlBufferTracker> mBufferTracker;
102 };
103 
104 class SamplePreparedModel : public aidl_hal::BnPreparedModel {
105    public:
SamplePreparedModel(aidl_hal::Model && model,const SampleDriver * driver,aidl_hal::ExecutionPreference preference,uid_t userId,aidl_hal::Priority priority)106     SamplePreparedModel(aidl_hal::Model&& model, const SampleDriver* driver,
107                         aidl_hal::ExecutionPreference preference, uid_t userId,
108                         aidl_hal::Priority priority)
109         : mModel(std::move(model)),
110           mDriver(driver),
111           kPreference(preference),
112           kUserId(userId),
113           kPriority(priority) {
114         (void)kUserId;
115         (void)kPriority;
116     }
117     bool initialize();
118     ndk::ScopedAStatus executeSynchronously(const aidl_hal::Request& request, bool measureTiming,
119                                             int64_t deadlineNs, int64_t loopTimeoutDurationNs,
120                                             aidl_hal::ExecutionResult* executionResult) override;
121     ndk::ScopedAStatus executeFenced(const aidl_hal::Request& request,
122                                      const std::vector<ndk::ScopedFileDescriptor>& waitFor,
123                                      bool measureTiming, int64_t deadlineNs,
124                                      int64_t loopTimeoutDurationNs, int64_t durationNs,
125                                      aidl_hal::FencedExecutionResult* executionResult) override;
126     ndk::ScopedAStatus executeSynchronouslyWithConfig(
127             const aidl_hal::Request& request, const aidl_hal::ExecutionConfig& config,
128             int64_t deadlineNs, aidl_hal::ExecutionResult* executionResult) override;
129     ndk::ScopedAStatus executeFencedWithConfig(
130             const aidl_hal::Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
131             const aidl_hal::ExecutionConfig& config, int64_t deadlineNs, int64_t durationNs,
132             aidl_hal::FencedExecutionResult* executionResult) override;
133     ndk::ScopedAStatus configureExecutionBurst(std::shared_ptr<aidl_hal::IBurst>* burst) override;
134     ndk::ScopedAStatus createReusableExecution(
135             const aidl_hal::Request& request, const aidl_hal::ExecutionConfig& config,
136             std::shared_ptr<aidl_hal::IExecution>* execution) override;
getModel()137     const aidl_hal::Model* getModel() const { return &mModel; }
138 
139    protected:
140     aidl_hal::Model mModel;
141     const SampleDriver* mDriver;
142     std::vector<RunTimePoolInfo> mPoolInfos;
143     const aidl_hal::ExecutionPreference kPreference;
144     const uid_t kUserId;
145     const aidl_hal::Priority kPriority;
146 };
147 
148 class SampleFencedExecutionCallback : public aidl_hal::BnFencedExecutionCallback {
149    public:
SampleFencedExecutionCallback(aidl_hal::Timing timingSinceLaunch,aidl_hal::Timing timingAfterFence,aidl_hal::ErrorStatus error)150     SampleFencedExecutionCallback(aidl_hal::Timing timingSinceLaunch,
151                                   aidl_hal::Timing timingAfterFence, aidl_hal::ErrorStatus error)
152         : kTimingSinceLaunch(timingSinceLaunch),
153           kTimingAfterFence(timingAfterFence),
154           kErrorStatus(error) {}
getExecutionInfo(aidl_hal::Timing * timingLaunched,aidl_hal::Timing * timingFenced,aidl_hal::ErrorStatus * errorStatus)155     ndk::ScopedAStatus getExecutionInfo(aidl_hal::Timing* timingLaunched,
156                                         aidl_hal::Timing* timingFenced,
157                                         aidl_hal::ErrorStatus* errorStatus) override {
158         *timingLaunched = kTimingSinceLaunch;
159         *timingFenced = kTimingAfterFence;
160         *errorStatus = kErrorStatus;
161         return ndk::ScopedAStatus::ok();
162     }
163 
164    private:
165     const aidl_hal::Timing kTimingSinceLaunch;
166     const aidl_hal::Timing kTimingAfterFence;
167     const aidl_hal::ErrorStatus kErrorStatus;
168 };
169 
170 class SampleBurst : public aidl_hal::BnBurst {
171    public:
172     // Precondition: preparedModel != nullptr
173     explicit SampleBurst(std::shared_ptr<SamplePreparedModel> preparedModel);
174 
175     ndk::ScopedAStatus executeSynchronously(const aidl_hal::Request& request,
176                                             const std::vector<int64_t>& memoryIdentifierTokens,
177                                             bool measureTiming, int64_t deadlineNs,
178                                             int64_t loopTimeoutDurationNs,
179                                             aidl_hal::ExecutionResult* executionResult) override;
180     ndk::ScopedAStatus executeSynchronouslyWithConfig(
181             const aidl_hal::Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
182             const aidl_hal::ExecutionConfig& config, int64_t deadlineNs,
183             aidl_hal::ExecutionResult* executionResult) override;
184     ndk::ScopedAStatus releaseMemoryResource(int64_t memoryIdentifierToken) override;
185 
186    protected:
187     std::atomic_flag mExecutionInFlight = ATOMIC_FLAG_INIT;
188     const std::shared_ptr<SamplePreparedModel> kPreparedModel;
189 };
190 
191 class SampleExecution : public aidl_hal::BnExecution {
192    public:
SampleExecution(std::shared_ptr<SamplePreparedModel> preparedModel,aidl_hal::Request request,bool measureTiming,int64_t loopTimeoutDurationNs)193     SampleExecution(std::shared_ptr<SamplePreparedModel> preparedModel, aidl_hal::Request request,
194                     bool measureTiming, int64_t loopTimeoutDurationNs)
195         : kPreparedModel(std::move(preparedModel)),
196           kHalRequest(std::move(request)),
197           kMeasureTiming(measureTiming),
198           kLoopTimeoutDurationNs(loopTimeoutDurationNs) {
199         CHECK(kPreparedModel != nullptr);
200     }
201 
202     ndk::ScopedAStatus executeSynchronously(int64_t deadlineNs,
203                                             aidl_hal::ExecutionResult* executionResult) override;
204 
205     ndk::ScopedAStatus executeFenced(const std::vector<ndk::ScopedFileDescriptor>& waitFor,
206                                      int64_t deadlineNs, int64_t durationNs,
207                                      aidl_hal::FencedExecutionResult* executionResult) override;
208 
209    private:
210     std::atomic_flag mComputationInFlight = ATOMIC_FLAG_INIT;
211     const std::shared_ptr<SamplePreparedModel> kPreparedModel;
212 
213     const aidl_hal::Request kHalRequest;
214     const bool kMeasureTiming;
215     const int64_t kLoopTimeoutDurationNs;
216 };
217 
218 }  // namespace sample_driver_aidl
219 }  // namespace nn
220 }  // namespace android
221 
222 #endif  // ANDROID_PACKAGES_MODULES_NEURALNETWORKS_DRIVER_SAMPLE_AIDL_SAMPLE_DRIVER_AIDL_H
223