1 /* 2 * Copyright (C) 2018 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_ML_NN_RUNTIME_VERSIONED_IDEVICE_H 18 #define ANDROID_ML_NN_RUNTIME_VERSIONED_IDEVICE_H 19 20 #include "HalInterfaces.h" 21 22 #include <android-base/macros.h> 23 #include <string> 24 #include <tuple> 25 26 namespace android { 27 namespace nn { 28 29 /** 30 * This object is either a V1_1::IDevice or V1_0::IDevice object. This class 31 * abstracts away version differences, allowing the remainder of the runtime to 32 * always use the most up-to-date version of all HIDL types. As such, any 33 * reference to a HIDL type in the rest of the runtime will--by default--be the 34 * latest HIDL version. 35 * 36 * This class will attempt to call the latest version of each interface method 37 * if possible. If the latest method is unavailable, the VersionedIDevice class 38 * will attempt to upcast the type (e.g., V1_1::Model to V1_0::Model), and 39 * invoke the latest interface method possible. If the VersionedIDevice class 40 * fails to find a matching applicable function, it will return an error. 41 */ 42 class VersionedIDevice { 43 DISALLOW_IMPLICIT_CONSTRUCTORS(VersionedIDevice); 44 public: 45 /** 46 * Constructor for the VersionedIDevice object. 47 * 48 * VersionedIDevice is constructed with the V1_0::IDevice object, which 49 * represents a device that is at least v1.0 of the interface. The 50 * constructor downcasts to the latest version of the IDevice interface, and 51 * will default to using the latest version of all IDevice interface 52 * methods automatically. 53 * 54 * @param device A device object that is least version 1.0 of the IDevice 55 * interface. 56 */ 57 VersionedIDevice(sp<V1_0::IDevice> device); 58 59 /** 60 * Gets the capabilities of a driver. 61 * 62 * @return status Error status of the call, must be: 63 * - NONE if successful 64 * - DEVICE_UNAVAILABLE if driver is offline or busy 65 * - GENERAL_FAILURE if there is an unspecified error 66 * @return capabilities Capabilities of the driver. 67 */ 68 std::pair<ErrorStatus, Capabilities> getCapabilities(); 69 70 /** 71 * Gets the supported operations in a model. 72 * 73 * getSupportedSubgraph indicates which operations of a model are fully 74 * supported by the vendor driver. If an operation may not be supported for 75 * any reason, getSupportedOperations must return false for that operation. 76 * 77 * @param model A model whose operations--and their corresponding 78 * operands--are to be verified by the driver. 79 * @return status Error status of the call, must be: 80 * - NONE if successful 81 * - DEVICE_UNAVAILABLE if driver is offline or busy 82 * - GENERAL_FAILURE if there is an unspecified error 83 * - INVALID_ARGUMENT if provided model is invalid 84 * @return supportedOperations A list of supported operations, where true 85 * indicates the operation is supported and 86 * false indicates the operation is not 87 * supported. The index of "supported" 88 * corresponds with the index of the operation 89 * it is describing. 90 */ 91 std::pair<ErrorStatus, hidl_vec<bool>> getSupportedOperations(const Model& model); 92 93 /** 94 * Creates a prepared model for execution. 95 * 96 * prepareModel is used to make any necessary transformations or alternative 97 * representations to a model for execution, possiblly including 98 * transformations on the constant data, optimization on the model's graph, 99 * or compilation into the device's native binary format. The model itself 100 * is not changed. 101 * 102 * The model is prepared asynchronously with respect to the caller. The 103 * prepareModel function must verify the inputs to the prepareModel function 104 * are correct. If there is an error, prepareModel must immediately invoke 105 * the callback with the appropriate ErrorStatus value and nullptr for the 106 * IPreparedModel, then return with the same ErrorStatus. If the inputs to 107 * the prepareModel function are valid and there is no error, prepareModel 108 * must launch an asynchronous task to prepare the model in the background, 109 * and immediately return from prepareModel with ErrorStatus::NONE. If the 110 * asynchronous task fails to launch, prepareModel must immediately invoke 111 * the callback with ErrorStatus::GENERAL_FAILURE and nullptr for the 112 * IPreparedModel, then return with ErrorStatus::GENERAL_FAILURE. 113 * 114 * When the asynchronous task has finished preparing the model, it must 115 * immediately invoke the callback function provided as an input to 116 * prepareModel. If the model was prepared successfully, the callback object 117 * must be invoked with an error status of ErrorStatus::NONE and the 118 * produced IPreparedModel object. If an error occurred preparing the model, 119 * the callback object must be invoked with the appropriate ErrorStatus 120 * value and nullptr for the IPreparedModel. 121 * 122 * The only information that may be unknown to the model at this stage is 123 * the shape of the tensors, which may only be known at execution time. As 124 * such, some driver services may return partially prepared models, where 125 * the prepared model can only be finished when it is paired with a set of 126 * inputs to the model. Note that the same prepared model object can be 127 * used with different shapes of inputs on different (possibly concurrent) 128 * executions. 129 * 130 * Multiple threads can call prepareModel on the same model concurrently. 131 * 132 * @param model The model to be prepared for execution. 133 * @param callback A callback object used to return the error status of 134 * preparing the model for execution and the prepared model 135 * if successful, nullptr otherwise. The callback object's 136 * notify function must be called exactly once, even if the 137 * model could not be prepared. 138 * @return status Error status of launching a task which prepares the model 139 * in the background; must be: 140 * - NONE if preparation task is successfully launched 141 * - DEVICE_UNAVAILABLE if driver is offline or busy 142 * - GENERAL_FAILURE if there is an unspecified error 143 * - INVALID_ARGUMENT if one of the input arguments is 144 * invalid 145 */ 146 ErrorStatus prepareModel(const Model& model, ExecutionPreference preference, 147 const sp<IPreparedModelCallback>& callback); 148 149 /** 150 * Returns the current status of a driver. 151 * 152 * @return status Status of the driver, one of: 153 * - DeviceStatus::AVAILABLE 154 * - DeviceStatus::BUSY 155 * - DeviceStatus::OFFLINE 156 * - DeviceStatus::UNKNOWN 157 */ 158 DeviceStatus getStatus(); 159 160 /** 161 * Returns whether this handle to an IDevice object is valid or not. 162 * 163 * @return bool true if V1_0::IDevice (which could be V1_1::IDevice) is 164 * valid, false otherwise. 165 */ 166 bool operator!=(nullptr_t); 167 168 /** 169 * Returns whether this handle to an IDevice object is valid or not. 170 * 171 * @return bool true if V1_0::IDevice (which could be V1_1::IDevice) is 172 * invalid, false otherwise. 173 */ 174 bool operator==(nullptr_t); 175 176 private: 177 /** 178 * Both versions of IDevice are necessary because the driver could be v1.0, 179 * v1.1, or a later version. These two pointers logically represent the same 180 * object. 181 * 182 * The general strategy is: HIDL returns a V1_0 device object, which 183 * (if not nullptr) could be v1.0, v1.1, or a greater version. The V1_0 184 * object is then "dynamically cast" to a V1_1 object. If successful, 185 * mDeviceV1_1 will point to the same object as mDeviceV1_0; otherwise, 186 * mDeviceV1_1 will be nullptr. 187 * 188 * In general: 189 * * If the device is truly v1.0, mDeviceV1_0 will point to a valid object 190 * and mDeviceV1_1 will be nullptr. 191 * * If the device is truly v1.1 or later, both mDeviceV1_0 and mDeviceV1_1 192 * will point to the same valid object. 193 * 194 * Idiomatic usage: if mDeviceV1_1 is non-null, do V1_1 dispatch; otherwise, 195 * do V1_0 dispatch. 196 */ 197 sp<V1_0::IDevice> mDeviceV1_0; 198 sp<V1_1::IDevice> mDeviceV1_1; 199 }; 200 201 } // namespace nn 202 } // namespace android 203 204 #endif // ANDROID_ML_NN_RUNTIME_VERSIONED_IDEVICE_H 205