Home | History | Annotate | Download | only in runtime
      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_INTERFACES_H
     18 #define ANDROID_ML_NN_RUNTIME_VERSIONED_INTERFACES_H
     19 
     20 #include "HalInterfaces.h"
     21 
     22 #include <android-base/macros.h>
     23 #include <cstddef>
     24 #include <functional>
     25 #include <memory>
     26 #include <optional>
     27 #include <shared_mutex>
     28 #include <string>
     29 #include <tuple>
     30 #include <utility>
     31 #include "Callbacks.h"
     32 
     33 namespace android {
     34 namespace nn {
     35 
     36 // forward declarations
     37 class ExecutionBurstController;
     38 class IDeviceDeathHandler;
     39 class IModelSlicer;
     40 class IPreparedModelDeathHandler;
     41 class VersionedIPreparedModel;
     42 
     43 /**
     44  * Each class (VersionedIDevice, VersionedIPreparedModel) wraps a HIDL interface
     45  * of any version to abstract away version differences. It allows the remainder
     46  * of the runtime to always use the most up-to-date version of all HIDL types.
     47  * As such, any reference to a HIDL type in the rest of the runtime
     48  * will--by default--be the latest HIDL version.
     49  *
     50  * Each class will attempt to call the latest version of each interface method
     51  * if possible. If the latest method is unavailable, the versioned class
     52  * will attempt to upcast the type (e.g., V1_1::Model to V1_0::Model), and
     53  * invoke the latest interface method possible. If the versioned class
     54  * fails to find a matching applicable function, it will return an error.
     55  */
     56 
     57 /** This class wraps an IDevice object of any version. */
     58 class VersionedIDevice {
     59     DISALLOW_IMPLICIT_CONSTRUCTORS(VersionedIDevice);
     60 
     61     // forward declaration of nested class
     62     class Core;
     63 
     64    public:
     65     /**
     66      * Create a VersionedIDevice object.
     67      *
     68      * Prefer using this function over the constructor, as it adds more
     69      * protections.
     70      *
     71      * @param serviceName The name of the service that provides "device".
     72      * @param device A device object that is at least version 1.0 of the IDevice
     73      *               interface.
     74      * @return A valid VersionedIDevice object, otherwise nullptr.
     75      */
     76     static std::shared_ptr<VersionedIDevice> create(std::string serviceName,
     77                                                     sp<V1_0::IDevice> device);
     78 
     79     /**
     80      * Constructor for the VersionedIDevice object.
     81      *
     82      * VersionedIDevice will default to using the latest version of all IDevice
     83      * interface methods automatically.
     84      *
     85      * @param serviceName The name of the service that provides core.getDevice<V1_0::IDevice>().
     86      * @param core An object that encapsulates a V1_0::IDevice, any appropriate downcasts to
     87      *             newer interfaces, and a hidl_death_recipient that will proactively handle
     88      *             the case when the service containing the IDevice object crashes.
     89      */
     90     VersionedIDevice(std::string serviceName, Core core);
     91 
     92     /**
     93      * Gets the capabilities of a driver.
     94      *
     95      * @return status Error status of the call, must be:
     96      *                - NONE if successful
     97      *                - DEVICE_UNAVAILABLE if driver is offline or busy
     98      *                - GENERAL_FAILURE if there is an unspecified error
     99      * @return capabilities Capabilities of the driver.
    100      */
    101     std::pair<ErrorStatus, Capabilities> getCapabilities();
    102 
    103     /**
    104      * Gets information about extensions supported by the driver implementation.
    105      *
    106      * Extensions of category ExtensionCategory::BASE must not appear
    107      * in the list.
    108      *
    109      * All extension operations and operands must be fully supported for the
    110      * extension to appear in the list of supported extensions.
    111      *
    112      * @return status Error status of the call, must be:
    113      *     - NONE if successful
    114      *     - DEVICE_UNAVAILABLE if driver is offline or busy
    115      *     - GENERAL_FAILURE if there is an unspecified error
    116      * @return extensions A list of supported extensions.
    117      */
    118     std::pair<ErrorStatus, hidl_vec<Extension>> getSupportedExtensions();
    119 
    120     /**
    121      * Gets the supported operations in a model.
    122      *
    123      * getSupportedOperations indicates which operations of a model are fully
    124      * supported by the vendor driver. If an operation may not be supported for
    125      * any reason, getSupportedOperations must return false for that operation.
    126      *
    127      * @param model A model whose operations--and their corresponding
    128      *              operands--are to be verified by the driver.
    129      * @param slicer When the model is not compliant with the HAL version of the
    130      *               vendor driver, the slicer (if any) is employed to query the
    131      *               vendor driver about which of the subset of compliant
    132      *               operations are supported.  See the IModelSlicer class in
    133      *               Utils.h for more details.
    134      * @return status Error status of the call, must be:
    135      *                - NONE if successful
    136      *                - DEVICE_UNAVAILABLE if driver is offline or busy
    137      *                - GENERAL_FAILURE if there is an unspecified error
    138      *                - INVALID_ARGUMENT if provided model is invalid
    139      * @return supportedOperations A list of supported operations, where true
    140      *                             indicates the operation is supported and
    141      *                             false indicates the operation is not
    142      *                             supported. The index of "supported"
    143      *                             corresponds with the index of the operation
    144      *                             it is describing.
    145      */
    146     std::pair<ErrorStatus, hidl_vec<bool>> getSupportedOperations(const Model& model,
    147                                                                   IModelSlicer* slicer = nullptr);
    148 
    149     /**
    150      * Synchronously creates a prepared model for execution and optionally saves it
    151      * into cache files.
    152      *
    153      * prepareModel is used to make any necessary transformations or alternative
    154      * representations to a model for execution, possibly including
    155      * transformations on the constant data, optimization on the model's graph,
    156      * or compilation into the device's native binary format. The model itself
    157      * is not changed.
    158      *
    159      * Optionally, caching information may be provided for the driver to save
    160      * the prepared model to cache files for faster model compilation time
    161      * when the same model preparation is requested in the future. There are
    162      * two types of cache file handles provided to the driver: model cache
    163      * and data cache. For more information on the two types of cache handles,
    164      * refer to getNumberOfCacheFilesNeeded.
    165      *
    166      * The file descriptors must be opened with read and write permission. A file may
    167      * have any size, and the corresponding file descriptor may have any offset. The
    168      * driver must truncate a file to zero size before writing to that file. The file
    169      * descriptors may be closed by the client once the asynchronous preparation has
    170      * finished. The driver must dup a file descriptor if it wants to get access to
    171      * the cache file later.
    172      *
    173      * The model is prepared synchronously with respect to the caller. The
    174      * prepareModel function must verify the inputs to the preparedModel
    175      * function related to preparing the model (as opposed to saving the
    176      * prepared model to cache) are correct. If there is an error, prepareModel
    177      * must immediately return the appropriate ErrorStatus value and nullptr for
    178      * the VersionedIPreparedModel. If the inputs to the prepareModel function
    179      * that are related to preparing the model are valid and there is no error,
    180      * prepareModel must prepare the model.
    181      *
    182      * If the model was prepared successfully, prepareModel must return
    183      * ErrorStatus::NONE and the produced VersionedIPreparedModel object. If an
    184      * error occurred preparing the model, prepareModel must return the
    185      * appropriate ErrorStatus value and nullptr for the
    186      * VersionedIPreparedModel.
    187      *
    188      * Optionally, the driver may save the prepared model to cache during
    189      * preparation. Any error that occurs when saving to cache must not affect
    190      * the status of preparing the model. Even if the input arguments related to
    191      * the cache may be invalid, or the driver may fail to save to cache, the
    192      * prepareModel function must finish preparing the model. The driver may
    193      * choose not to save to cache even if the caching information is provided
    194      * and valid.
    195      *
    196      * The only information that may be unknown to the model at this stage is
    197      * the shape of the tensors, which may only be known at execution time. As
    198      * such, some driver services may return partially prepared models, where
    199      * the prepared model may only be finished when it is paired with a set of
    200      * inputs to the model. Note that the same prepared model object may be
    201      * used with different shapes of inputs on different (possibly concurrent)
    202      * executions.
    203      *
    204      * Multiple threads may call prepareModel on the same model concurrently.
    205      *
    206      * @param model The model to be prepared for execution.
    207      * @param preference Indicates the intended execution behavior of a prepared
    208      *     model.
    209      * @param modelCache A vector of handles with each entry holding exactly one
    210      *     cache file descriptor for the security-sensitive cache. The length of
    211      *     the vector must either be 0 indicating that caching information is not provided,
    212      *     or match the numModelCache returned from getNumberOfCacheFilesNeeded. The cache
    213      *     handles will be provided in the same order when retrieving the
    214      *     preparedModel from cache files with prepareModelFromCache.
    215      * @param dataCache A vector of handles with each entry holding exactly one
    216      *     cache file descriptor for the constants' cache. The length of
    217      *     the vector must either be 0 indicating that caching information is not provided,
    218      *     or match the numDataCache returned from getNumberOfCacheFilesNeeded. The cache
    219      *     handles will be provided in the same order when retrieving the
    220      *     preparedModel from cache files with prepareModelFromCache.
    221      * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
    222      *     identifying the prepared model. The same token will be provided when retrieving
    223      *     the prepared model from the cache files with prepareModelFromCache.
    224      *     Tokens should be chosen to have a low rate of collision for a particular
    225      *     application. The driver cannot detect a collision; a collision will result
    226      *     in a failed execution or in a successful execution that produces incorrect
    227      *     output values. If both modelCache and dataCache are empty indicating that
    228      *     caching information is not provided, this token must be ignored.
    229      * @return A pair of:
    230      *     - status Error status of preparing the model; must be:
    231      *         - NONE if preparation succeeded
    232      *         - DEVICE_UNAVAILABLE if driver is offline or busy
    233      *         - GENERAL_FAILURE if there is an unspecified error
    234      *         - INVALID_ARGUMENT if one of the input arguments related to
    235      *             preparing the model is invalid
    236      *     - preparedModel A VersionedIPreparedModel object representing a model
    237      *         that has been prepared for execution, else nullptr.
    238      */
    239     std::pair<ErrorStatus, std::shared_ptr<VersionedIPreparedModel>> prepareModel(
    240             const Model& model, ExecutionPreference preference,
    241             const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
    242             const hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>&
    243                     token);
    244 
    245     /**
    246      * Creates a prepared model from cache files for execution.
    247      *
    248      * prepareModelFromCache is used to retrieve a prepared model directly from
    249      * cache files to avoid slow model compilation time. There are
    250      * two types of cache file handles provided to the driver: model cache
    251      * and data cache. For more information on the two types of cache handles,
    252      * refer to getNumberOfCacheFilesNeeded.
    253      *
    254      * The file descriptors must be opened with read and write permission. A file may
    255      * have any size, and the corresponding file descriptor may have any offset. The
    256      * driver must truncate a file to zero size before writing to that file. The file
    257      * descriptors may be closed by the client once the asynchronous preparation has
    258      * finished. The driver must dup a file descriptor if it wants to get access to
    259      * the cache file later.
    260      *
    261      * The model is prepared synchronously with respect to the caller. The
    262      * prepareModelFromCache function must verify the inputs to the
    263      * prepareModelFromCache function are correct, and that the
    264      * security-sensitive cache has not been modified since it was last written
    265      * by the driver. If there is an error, or if compilation caching is not
    266      * supported, or if the security-sensitive cache has been modified,
    267      * prepareModelFromCache must return the appropriate ErrorStatus value and
    268      * nullptr for the VersionedIPreparedModel. If the inputs to the
    269      * prepareModelFromCache function are valid, the security-sensitive cache is
    270      * not modified, and there is no error, prepareModelFromCache must prepare
    271      * the model.
    272      *
    273      * If the model was prepared successfully, prepareModelFromCache must return
    274      * ErrorStatus::NONE and the produced VersionedIPreparedModel object. If an
    275      * error occurred preparing the model, prepareModelFromCache must return the
    276      * appropriate ErrorStatus value and nullptr for the
    277      * VersionedIPreparedModel.
    278      *
    279      * The only information that may be unknown to the model at this stage is
    280      * the shape of the tensors, which may only be known at execution time. As
    281      * such, some driver services may return partially prepared models, where
    282      * the prepared model may only be finished when it is paired with a set of
    283      * inputs to the model. Note that the same prepared model object may be
    284      * used with different shapes of inputs on different (possibly concurrent)
    285      * executions.
    286      *
    287      * @param modelCache A vector of handles with each entry holding exactly one
    288      *     cache file descriptor for the security-sensitive cache. The length of
    289      *     the vector must match the numModelCache returned from getNumberOfCacheFilesNeeded.
    290      *     The cache handles will be provided in the same order as with prepareModel_1_2.
    291      * @param dataCache A vector of handles with each entry holding exactly one
    292      *     cache file descriptor for the constants' cache. The length of the vector
    293      *     must match the numDataCache returned from getNumberOfCacheFilesNeeded.
    294      *     The cache handles will be provided in the same order as with prepareModel_1_2.
    295      * @param token A caching token of length Constant::BYTE_SIZE_OF_CACHE_TOKEN
    296      *     identifying the prepared model. It is the same token provided when saving
    297      *     the cache files with prepareModel_1_2. Tokens should be chosen
    298      *     to have a low rate of collision for a particular application. The driver
    299      *     cannot detect a collision; a collision will result in a failed execution
    300      *     or in a successful execution that produces incorrect output values.
    301      * @return A pair of:
    302      *     - status Error status of preparing the model; must be:
    303      *         - NONE if preparation succeeded
    304      *         - DEVICE_UNAVAILABLE if driver is offline or busy
    305      *         - GENERAL_FAILURE if caching is not supported or if there is an
    306      *             unspecified error
    307      *         - INVALID_ARGUMENT if one of the input arguments is invalid
    308      *     - preparedModel A VersionedIPreparedModel object representing a model
    309      *        that has been prepared for execution, else nullptr.
    310      */
    311     std::pair<ErrorStatus, std::shared_ptr<VersionedIPreparedModel>> prepareModelFromCache(
    312             const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
    313             const hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>&
    314                     token);
    315 
    316     /**
    317      * Returns the current status of a driver.
    318      *
    319      * @return status Status of the driver, one of:
    320      *                - DeviceStatus::AVAILABLE
    321      *                - DeviceStatus::BUSY
    322      *                - DeviceStatus::OFFLINE
    323      *                - DeviceStatus::UNKNOWN
    324      */
    325     DeviceStatus getStatus();
    326 
    327     /**
    328      * Returns the feature level of a driver.
    329      *
    330      * @return featureLevel The API level of the most advanced feature this driver implements.
    331      *                      For example, if the driver implements the features introduced in
    332      *                      Android P, the value would be 28.
    333      *                      Return -1 if the driver is offline or busy, or the query resulted in
    334      *                      an unspecified error.
    335      */
    336     int64_t getFeatureLevel();
    337 
    338     /**
    339      * Returns the device type of a driver.
    340      *
    341      * @return deviceType The type of a given device, which can help application developers
    342      *                    developers to distribute Machine Learning workloads and other workloads
    343      *                    such as graphical rendering. E.g., for an app which renders AR scenes
    344      *                    based on real time object detection results, the developer could choose
    345      *                    an ACCELERATOR type device for ML workloads, and reserve GPU for
    346      *                    graphical rendering.
    347      *                    Return -1 if the driver is offline or busy, or the query resulted in
    348      *                    an unspecified error.
    349      */
    350     int32_t getType() const;
    351 
    352     /**
    353      * Get the version string of the driver implementation.
    354      *
    355      * The version string must be a unique token among the set of version strings of
    356      * drivers of a specific device. The token identifies the device driver's
    357      * implementation. The token must not be confused with the feature level which is solely
    358      * defined by the interface version. This API is opaque to the Android framework, but the
    359      * Android framework may use the information for debugging or to pass on to NNAPI applications.
    360      *
    361      * Application developers sometimes have specific requirements to ensure good user experiences,
    362      * and they need more information to make intelligent decisions when the Android framework
    363      * cannot. For example, combined with the device name and other information, the token can help
    364      * NNAPI applications filter devices based on their needs:
    365      *     - An application demands a certain level of performance, but a specific version of
    366      *       the driver cannot meet that requirement because of a performance regression.
    367      *       The application can blacklist the driver based on the version provided.
    368      *     - An application has a minimum precision requirement, but certain versions of
    369      *       the driver cannot meet that requirement because of bugs or certain optimizations.
    370      *       The application can filter out versions of these drivers.
    371      *
    372      * @return status Error status returned from querying the version string. Must be:
    373      *     - NONE if the query was successful
    374      *     - DEVICE_UNAVAILABLE if driver is offline or busy
    375      *     - GENERAL_FAILURE if the query resulted in an
    376      *       unspecified error
    377      * @return version The version string of the device implementation.
    378      *     Must have nonzero length if the query is successful, and must be an empty string if not.
    379      */
    380     std::pair<ErrorStatus, hidl_string> getVersionString();
    381 
    382     /**
    383      * Gets the caching requirements of the driver implementation.
    384      *
    385      * There are two types of cache file descriptors provided to the driver: model cache
    386      * and data cache.
    387      *
    388      * The data cache is for caching constant data, possibly including preprocessed
    389      * and transformed tensor buffers. Any modification to the data cache should
    390      * have no worse effect than generating bad output values at execution time.
    391      *
    392      * The model cache is for caching security-sensitive data such as compiled
    393      * executable machine code in the device's native binary format. A modification
    394      * to the model cache may affect the driver's execution behavior, and a malicious
    395      * client could make use of this to execute beyond the granted permission. Thus,
    396      * the driver must always check whether the model cache is corrupted before
    397      * preparing the model from cache.
    398      *
    399      * getNumberOfCacheFilesNeeded returns how many of each type of cache files the driver
    400      * implementation needs to cache a single prepared model. Returning 0 for both types
    401      * indicates compilation caching is not supported by this driver. The driver may
    402      * still choose not to cache certain compiled models even if it reports that caching
    403      * is supported.
    404      *
    405      * If the device reports that caching is not supported, the user may avoid calling
    406      * IDevice::prepareModelFromCache or providing cache file descriptors to
    407      * IDevice::prepareModel_1_2.
    408      *
    409      * @return status Error status of the call, must be:
    410      *     - NONE if successful
    411      *     - DEVICE_UNAVAILABLE if driver is offline or busy
    412      *     - GENERAL_FAILURE if there is an unspecified error
    413      * @return numModelCache An unsigned integer indicating how many files for model cache
    414      *                       the driver needs to cache a single prepared model. It must
    415      *                       be less than or equal to Constant::MAX_NUMBER_OF_CACHE_FILES.
    416      * @return numDataCache An unsigned integer indicating how many files for data cache
    417      *                      the driver needs to cache a single prepared model. It must
    418      *                      be less than or equal to Constant::MAX_NUMBER_OF_CACHE_FILES.
    419      */
    420     std::tuple<ErrorStatus, uint32_t, uint32_t> getNumberOfCacheFilesNeeded();
    421 
    422     /**
    423      * Returns the name of the service that implements the driver
    424      *
    425      * @return serviceName The name of the service.
    426      */
    427     std::string getServiceName() const { return mServiceName; }
    428 
    429     /**
    430      * Returns whether this handle to an IDevice object is valid or not.
    431      *
    432      * @return bool true if V1_0::IDevice (which could be V1_1::IDevice) is
    433      *              valid, false otherwise.
    434      */
    435     bool operator!=(nullptr_t) const;
    436 
    437     /**
    438      * Returns whether this handle to an IDevice object is valid or not.
    439      *
    440      * @return bool true if V1_0::IDevice (which could be V1_1::IDevice) is
    441      *              invalid, false otherwise.
    442      */
    443     bool operator==(nullptr_t) const;
    444 
    445    private:
    446     /**
    447      * This is a utility class for VersionedIDevice that encapsulates a
    448      * V1_0::IDevice, any appropriate downcasts to newer interfaces, and a
    449      * hidl_death_recipient that will proactively handle the case when the
    450      * service containing the IDevice object crashes.
    451      *
    452      * This is a convenience class to help VersionedIDevice recover from an
    453      * IDevice object crash: It bundles together all the data that needs to
    454      * change when recovering from a crash, and simplifies the process of
    455      * instantiating that data (at VersionedIDevice creation time) and
    456      * re-instantiating that data (at crash recovery time).
    457      */
    458     class Core {
    459        public:
    460         /**
    461          * Constructor for the Core object.
    462          *
    463          * Core is constructed with a V1_0::IDevice object, which represents a
    464          * device that is at least v1.0 of the interface. The constructor
    465          * downcasts to the latest version of the IDevice interface, allowing
    466          * VersionedIDevice to default to using the latest version of all
    467          * IDevice interface methods automatically.
    468          *
    469          * @param device A device object that is at least version 1.0 of the IDevice
    470          *               interface.
    471          * @param deathHandler A hidl_death_recipient that will proactively handle
    472          *                     the case when the service containing the IDevice
    473          *                     object crashes.
    474          */
    475         Core(sp<V1_0::IDevice> device, sp<IDeviceDeathHandler> deathHandler);
    476 
    477         /**
    478          * Destructor for the Core object.
    479          *
    480          * This destructor unlinksToDeath this object's hidl_death_recipient as it
    481          * no longer needs to handle the case where the IDevice's service crashes.
    482          */
    483         ~Core();
    484 
    485         // Support move but not copy
    486         Core(Core&&) noexcept;
    487         Core& operator=(Core&&) noexcept;
    488         Core(const Core&) = delete;
    489         Core& operator=(const Core&) = delete;
    490 
    491         /**
    492          * Create a Core object.
    493          *
    494          * Prefer using this function over the constructor, as it adds more
    495          * protections.
    496          *
    497          * This call linksToDeath a hidl_death_recipient that can
    498          * proactively handle the case when the service containing the IDevice
    499          * object crashes.
    500          *
    501          * @param device A device object that is at least version 1.0 of the IDevice
    502          *               interface.
    503          * @return A valid Core object, otherwise nullopt.
    504          */
    505         static std::optional<Core> create(sp<V1_0::IDevice> device);
    506 
    507         /**
    508          * Returns sp<*::IDevice> that is a downcast of the sp<V1_0::IDevice>
    509          * passed to the constructor.  This will be nullptr if that IDevice is
    510          * not actually of the specified downcast type.
    511          */
    512         template <typename T_IDevice>
    513         sp<T_IDevice> getDevice() const;
    514         template <>
    515         sp<V1_0::IDevice> getDevice() const {
    516             return mDeviceV1_0;
    517         }
    518         template <>
    519         sp<V1_1::IDevice> getDevice() const {
    520             return mDeviceV1_1;
    521         }
    522         template <>
    523         sp<V1_2::IDevice> getDevice() const {
    524             return mDeviceV1_2;
    525         }
    526 
    527         /**
    528          * Returns sp<*::IDevice> (as per getDevice()) and the
    529          * hidl_death_recipient that will proactively handle the case when the
    530          * service containing the IDevice object crashes.
    531          */
    532         template <typename T_IDevice>
    533         std::pair<sp<T_IDevice>, sp<IDeviceDeathHandler>> getDeviceAndDeathHandler() const;
    534 
    535        private:
    536         /**
    537          * All versions of IDevice are necessary because the driver could be v1.0,
    538          * v1.1, or a later version. All these pointers logically represent the same
    539          * object.
    540          *
    541          * The general strategy is: HIDL returns a V1_0 device object, which
    542          * (if not nullptr) could be v1.0, v1.1, or a greater version. The V1_0
    543          * object is then "dynamically cast" to a V1_1 object. If successful,
    544          * mDeviceV1_1 will point to the same object as mDeviceV1_0; otherwise,
    545          * mDeviceV1_1 will be nullptr.
    546          *
    547          * In general:
    548          * * If the device is truly v1.0, mDeviceV1_0 will point to a valid object
    549          *   and mDeviceV1_1 will be nullptr.
    550          * * If the device is truly v1.1 or later, both mDeviceV1_0 and mDeviceV1_1
    551          *   will point to the same valid object.
    552          *
    553          * Idiomatic usage: if mDeviceV1_1 is non-null, do V1_1 dispatch; otherwise,
    554          * do V1_0 dispatch.
    555          */
    556         sp<V1_0::IDevice> mDeviceV1_0;
    557         sp<V1_1::IDevice> mDeviceV1_1;
    558         sp<V1_2::IDevice> mDeviceV1_2;
    559 
    560         /**
    561          * HIDL callback to be invoked if the service for mDeviceV1_0 crashes.
    562          *
    563          * nullptr if this Core instance is a move victim and hence has no
    564          * callback to be unlinked.
    565          */
    566         sp<IDeviceDeathHandler> mDeathHandler;
    567     };
    568 
    569     // This method retrieves the appropriate mCore.mDevice* field, under a read lock.
    570     template <typename T_IDevice>
    571     sp<T_IDevice> getDevice() const EXCLUDES(mMutex) {
    572         std::shared_lock lock(mMutex);
    573         return mCore.getDevice<T_IDevice>();
    574     }
    575 
    576     // This method retrieves the appropriate mCore.mDevice* fields, under a read lock.
    577     template <typename T_IDevice>
    578     auto getDeviceAndDeathHandler() const EXCLUDES(mMutex) {
    579         std::shared_lock lock(mMutex);
    580         return mCore.getDeviceAndDeathHandler<T_IDevice>();
    581     }
    582 
    583     // This method calls the function fn in a manner that supports recovering
    584     // from a driver crash: If the driver implementation is dead because the
    585     // driver crashed either before the call to fn or during the call to fn, we
    586     // will attempt to obtain a new instance of the same driver and call fn
    587     // again.
    588     //
    589     // If a callback is provided, this method protects it against driver death
    590     // and waits for it (callback->wait()).
    591     template <typename T_Return, typename T_IDevice, typename T_Callback = std::nullptr_t>
    592     Return<T_Return> recoverable(const char* context,
    593                                  const std::function<Return<T_Return>(const sp<T_IDevice>&)>& fn,
    594                                  const T_Callback& callback = nullptr) const EXCLUDES(mMutex);
    595 
    596     // The name of the service that implements the driver.
    597     const std::string mServiceName;
    598 
    599     // Guards access to mCore.
    600     mutable std::shared_mutex mMutex;
    601 
    602     // Data that can be rewritten during driver recovery.  Guarded againt
    603     // synchronous access by a mutex: Any number of concurrent read accesses is
    604     // permitted, but a write access excludes all other accesses.
    605     mutable Core mCore GUARDED_BY(mMutex);
    606 };
    607 
    608 /** This class wraps an IPreparedModel object of any version. */
    609 class VersionedIPreparedModel {
    610     DISALLOW_IMPLICIT_CONSTRUCTORS(VersionedIPreparedModel);
    611 
    612    public:
    613     /**
    614      * Constructor for the VersionedIPreparedModel object.
    615      *
    616      * This constructor should not be used directly. Instead,
    617      * VersionedIPreparedModel should be created via
    618      * VersionedIDevice::prepareModel*.
    619      *
    620      * VersionedIPreparedModel is constructed with the V1_0::IPreparedModel object, which
    621      * represents a device that is at least v1.0 of the interface. The constructor downcasts
    622      * to the latest version of the IPreparedModel interface, and will default to using the
    623      * latest version of all IPreparedModel interface methods automatically.
    624      *
    625      * @param preparedModel A prepared model object that is least version 1.0 of the
    626      *                      IPreparedModel interface.
    627      * @param deathHandler A hidl_death_recipient that will proactively handle
    628      *                     the case when the service containing the IDevice
    629      *                     object crashes.
    630      */
    631     VersionedIPreparedModel(sp<V1_0::IPreparedModel> preparedModel,
    632                             sp<IPreparedModelDeathHandler> deathHandler);
    633 
    634     /**
    635      * Destructor for the VersionedIPreparedModel object.
    636      *
    637      * This destructor unlinksToDeath this object's hidl_death_recipient as it
    638      * no longer needs to handle the case where the IPreparedModel's service
    639      * crashes.
    640      */
    641     ~VersionedIPreparedModel();
    642 
    643     /**
    644      * Launches an asynchronous execution on a prepared model.
    645      *
    646      * The execution is performed asynchronously with respect to the caller.
    647      * execute must verify the inputs to the function are correct. If there is
    648      * an error, execute must immediately invoke the callback with the
    649      * appropriate ErrorStatus value, then return with the same ErrorStatus. If
    650      * the inputs to the function are valid and there is no error, execute must
    651      * launch an asynchronous task to perform the execution in the background,
    652      * and immediately return with ErrorStatus::NONE. If the asynchronous task
    653      * fails to launch, execute must immediately invoke the callback with
    654      * ErrorStatus::GENERAL_FAILURE, then return with
    655      * ErrorStatus::GENERAL_FAILURE.
    656      *
    657      * When the asynchronous task has finished its execution, it must
    658      * immediately invoke the callback object provided as an input to the
    659      * execute function. This callback must be provided with the ErrorStatus of
    660      * the execution.
    661      *
    662      * If the prepared model was prepared from a model wherein all
    663      * tensor operands have fully specified dimensions, and the inputs
    664      * to the function are valid, then the execution should launch
    665      * and complete successfully (ErrorStatus::NONE). There must be
    666      * no failure unless the device itself is in a bad state.
    667      *
    668      * Multiple threads can call the execute and ExecuteSynchronously functions
    669      * on the same VersionedIPreparedModel object concurrently with different
    670      * requests.
    671      *
    672      * @param request The input and output information on which the prepared
    673      *                model is to be executed.
    674      * @param measure Specifies whether or not to measure duration of the execution.
    675      * @param callback A callback object used to return the error status of
    676      *                 the execution. The callback object's notify function must
    677      *                 be called exactly once, even if the execution was
    678      *                 unsuccessful.
    679      * @return status Error status of the call, must be:
    680      *                - NONE if task is successfully launched
    681      *                - DEVICE_UNAVAILABLE if driver is offline or busy
    682      *                - GENERAL_FAILURE if there is an unspecified error
    683      *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
    684      *                  not large enough to store the resultant values
    685      *                - INVALID_ARGUMENT if one of the input arguments is
    686      *                  invalid
    687      */
    688     ErrorStatus execute(const Request& request, MeasureTiming timing,
    689                         const sp<ExecutionCallback>& callback);
    690 
    691     /**
    692      * Performs a synchronous execution on a prepared model.
    693      *
    694      * The execution is performed synchronously with respect to the caller.
    695      * executeSynchronously must verify the inputs to the function are
    696      * correct. If there is an error, executeSynchronously must immediately
    697      * return with the appropriate ErrorStatus value. If the inputs to the
    698      * function are valid and there is no error, executeSynchronously must
    699      * perform the execution, and must not return until the execution is
    700      * complete.
    701      *
    702      * If the prepared model was prepared from a model wherein all tensor
    703      * operands have fully specified dimensions, and the inputs to the function
    704      * are valid, then the execution should complete successfully
    705      * (ErrorStatus::NONE). There must be no failure unless the device itself is
    706      * in a bad state.
    707      *
    708      * Any number of calls to the execute and executeSynchronously
    709      * functions, in any combination, may be made concurrently, even on the same
    710      * VersionedIPreparedModel object.
    711      *
    712      * @param request The input and output information on which the prepared
    713      *                model is to be executed.
    714      * @param measure Specifies whether or not to measure duration of the execution.
    715      * @return status Error status of the execution, must be:
    716      *                - NONE if execution is performed successfully
    717      *                - DEVICE_UNAVAILABLE if driver is offline or busy
    718      *                - GENERAL_FAILURE if there is an unspecified error
    719      *                - OUTPUT_INSUFFICIENT_SIZE if at least one output
    720      *                  operand buffer is not large enough to store the
    721      *                  corresponding output
    722      *                - INVALID_ARGUMENT if one of the input arguments is
    723      *                  invalid
    724      * @return outputShapes A list of shape information of model output operands.
    725      *                      The index into "outputShapes" corresponds with the index
    726      *                      of the output operand in the Request outputs vector.
    727      *                      outputShapes nust be empty unless the status is either
    728      *                      NONE or OUTPUT_INSUFFICIENT_SIZE. outputShaps may be
    729      *                      empty if the status is NONE and all model output operands
    730      *                      are fully-specified at execution time. outputShapes must
    731      *                      have the same number of elements as the number of model
    732      *                      output operands if the status is OUTPUT_INSUFFICIENT_SIZE,
    733      *                      or if the status is NONE and the model has at least one
    734      *                      output operand that is not fully-specified.
    735      * @return Timing Duration of execution. Unless measure is YES and status is
    736      *                NONE, all times must be reported as UINT64_MAX. A driver may
    737      *                choose to report any time as UINT64_MAX, indicating that
    738      *                measurement is not available.
    739      */
    740     std::tuple<ErrorStatus, hidl_vec<OutputShape>, Timing> executeSynchronously(
    741             const Request& request, MeasureTiming measure);
    742 
    743     /**
    744      * Creates a burst controller on a prepared model.
    745      *
    746      * @param blocking 'true' if the FMQ should block until data is available.
    747      * @return ExecutionBurstController Execution burst controller object.
    748      *                                  nullptr is returned if the burst cannot
    749      *                                  be configured for any reason.
    750      */
    751     std::shared_ptr<ExecutionBurstController> configureExecutionBurst(bool blocking) const;
    752 
    753     /**
    754      * Returns whether this handle to an IPreparedModel object is valid or not.
    755      *
    756      * @return bool true if V1_0::IPreparedModel (which could be V1_2::IPreparedModel) is
    757      *              valid, false otherwise.
    758      */
    759     bool operator!=(nullptr_t) const;
    760 
    761     /**
    762      * Returns whether this handle to an IPreparedModel object is valid or not.
    763      *
    764      * @return bool true if V1_0::IPreparedModel (which could be V1_2::IPreparedModel) is
    765      *              invalid, false otherwise.
    766      */
    767     bool operator==(nullptr_t) const;
    768 
    769    private:
    770     /**
    771      * All versions of IPreparedModel are necessary because the preparedModel could be v1.0,
    772      * v1.2, or a later version. All these pointers logically represent the same object.
    773      *
    774      * The general strategy is: HIDL returns a V1_0 prepared model object, which
    775      * (if not nullptr) could be v1.0, v1.2, or a greater version. The V1_0
    776      * object is then "dynamically cast" to a V1_2 object. If successful,
    777      * mPreparedModelV1_2 will point to the same object as mPreparedModelV1_0; otherwise,
    778      * mPreparedModelV1_2 will be nullptr.
    779      *
    780      * In general:
    781      * * If the prepared model is truly v1.0, mPreparedModelV1_0 will point to a valid object
    782      *   and mPreparedModelV1_2 will be nullptr.
    783      * * If the prepared model is truly v1.2 or later, both mPreparedModelV1_0 and
    784      *   mPreparedModelV1_2 will point to the same valid object.
    785      *
    786      * Idiomatic usage: if mPreparedModelV1_2 is non-null, do V1_2 dispatch; otherwise,
    787      * do V1_0 dispatch.
    788      */
    789     sp<V1_0::IPreparedModel> mPreparedModelV1_0;
    790     sp<V1_2::IPreparedModel> mPreparedModelV1_2;
    791 
    792     /**
    793      * HIDL callback to be invoked if the service for mPreparedModelV1_0 crashes.
    794      */
    795     const sp<IPreparedModelDeathHandler> mDeathHandler;
    796 };
    797 
    798 }  // namespace nn
    799 }  // namespace android
    800 
    801 #endif  // ANDROID_ML_NN_RUNTIME_VERSIONED_INTERFACES_H
    802