1 /* 2 * Copyright (C) 2017 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 #define LOG_TAG "SampleDriver" 18 19 #include "SampleDriver.h" 20 21 #include "CpuExecutor.h" 22 #include "HalInterfaces.h" 23 24 #include <android-base/logging.h> 25 #include <hidl/LegacySupport.h> 26 #include <thread> 27 28 namespace android { 29 namespace nn { 30 namespace sample_driver { 31 32 Return<ErrorStatus> SampleDriver::prepareModel(const Model& model, 33 const sp<IPreparedModelCallback>& callback) { 34 if (VLOG_IS_ON(DRIVER)) { 35 VLOG(DRIVER) << "prepareModel"; 36 logModelToInfo(model); 37 } 38 if (callback.get() == nullptr) { 39 LOG(ERROR) << "invalid callback passed to prepareModel"; 40 return ErrorStatus::INVALID_ARGUMENT; 41 } 42 if (!validateModel(model)) { 43 callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr); 44 return ErrorStatus::INVALID_ARGUMENT; 45 } 46 47 // TODO: make asynchronous later 48 sp<SamplePreparedModel> preparedModel = new SamplePreparedModel(model); 49 if (!preparedModel->initialize()) { 50 callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr); 51 return ErrorStatus::INVALID_ARGUMENT; 52 } 53 callback->notify(ErrorStatus::NONE, preparedModel); 54 return ErrorStatus::NONE; 55 } 56 57 Return<DeviceStatus> SampleDriver::getStatus() { 58 VLOG(DRIVER) << "getStatus()"; 59 return DeviceStatus::AVAILABLE; 60 } 61 62 int SampleDriver::run() { 63 android::hardware::configureRpcThreadpool(4, true); 64 if (registerAsService(mName) != android::OK) { 65 LOG(ERROR) << "Could not register service"; 66 return 1; 67 } 68 android::hardware::joinRpcThreadpool(); 69 LOG(ERROR) << "Service exited!"; 70 return 1; 71 } 72 73 bool SamplePreparedModel::initialize() { 74 return setRunTimePoolInfosFromHidlMemories(&mPoolInfos, mModel.pools); 75 } 76 77 void SamplePreparedModel::asyncExecute(const Request& request, 78 const sp<IExecutionCallback>& callback) { 79 std::vector<RunTimePoolInfo> requestPoolInfos; 80 if (!setRunTimePoolInfosFromHidlMemories(&requestPoolInfos, request.pools)) { 81 callback->notify(ErrorStatus::GENERAL_FAILURE); 82 return; 83 } 84 85 CpuExecutor executor; 86 int n = executor.run(mModel, request, mPoolInfos, requestPoolInfos); 87 VLOG(DRIVER) << "executor.run returned " << n; 88 ErrorStatus executionStatus = 89 n == ANEURALNETWORKS_NO_ERROR ? ErrorStatus::NONE : ErrorStatus::GENERAL_FAILURE; 90 Return<void> returned = callback->notify(executionStatus); 91 if (!returned.isOk()) { 92 LOG(ERROR) << " hidl callback failed to return properly: " << returned.description(); 93 } 94 } 95 96 Return<ErrorStatus> SamplePreparedModel::execute(const Request& request, 97 const sp<IExecutionCallback>& callback) { 98 VLOG(DRIVER) << "execute(" << toString(request) << ")"; 99 if (callback.get() == nullptr) { 100 LOG(ERROR) << "invalid callback passed to execute"; 101 return ErrorStatus::INVALID_ARGUMENT; 102 } 103 if (!validateRequest(request, mModel)) { 104 callback->notify(ErrorStatus::INVALID_ARGUMENT); 105 return ErrorStatus::INVALID_ARGUMENT; 106 } 107 108 // This thread is intentionally detached because the sample driver service 109 // is expected to live forever. 110 std::thread([this, request, callback]{ asyncExecute(request, callback); }).detach(); 111 112 return ErrorStatus::NONE; 113 } 114 115 } // namespace sample_driver 116 } // namespace nn 117 } // namespace android 118