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