1 /*
2  * Copyright (C) 2019 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_FRAMEWORKS_ML_NN_RUNTIME_TYPE_MANAGER_H
18 #define ANDROID_FRAMEWORKS_ML_NN_RUNTIME_TYPE_MANAGER_H
19 
20 #include <map>
21 #include <set>
22 #include <string>
23 #include <vector>
24 
25 #include "HalInterfaces.h"
26 #include "Manager.h"
27 
28 namespace android {
29 namespace nn {
30 
31 // Manages runtime operand and operation type information.
32 //
33 // This class gathers information about extension types from all devices
34 // and provides a unified way to access information about any known type.
35 class TypeManager {
36    public:
get()37     static TypeManager* get() {
38         static TypeManager manager;
39         return &manager;
40     }
41 
42     // Creates an operand/operation type corresponding to a given extension
43     // name and type within extension.
44     //
45     // Returns false if the extension is unknown.
46     bool getExtensionType(const char* extensionName, uint16_t typeWithinExtension, int32_t* type);
47 
48     // Looks up information about the extension corresponding to the given prefix
49     //
50     // Returns false if no extension corresponds to the given prefix.
51     bool getExtensionInfo(uint16_t prefix, const hal::Extension** extension) const;
52 
53     // Looks up information about an extension operand type
54     //
55     // Returns false if the extension or type is unknown.
56     bool getExtensionOperandTypeInfo(hal::OperandType type,
57                                      const hal::Extension::OperandTypeInformation** info) const;
58 
59     // Returns true if an operand type is a tensor type.
60     //
61     // Aborts if the type is an unknown extension type.
62     bool isTensorType(hal::OperandType type) const;
63 
64     // Returns the amount of space needed to store a value of the dimensions and
65     // type of this operand. For a tensor with unspecified rank or at least one
66     // unspecified dimension, returns zero.
67     //
68     // Aborts if the type is an unknown extension type.
69     // Aborts if the size would overflow the return type.
getSizeOfData(const hal::Operand & operand)70     uint32_t getSizeOfData(const hal::Operand& operand) const {
71         return getSizeOfData(operand.type, operand.dimensions);
72     }
73 
74     // Returns the amount of space needed to store a value of the specified
75     // dimensions and type. For a tensor with unspecified rank or at least one
76     // unspecified dimension, returns zero.
77     //
78     // Aborts if the type is an unknown extension type.
79     uint32_t getSizeOfData(hal::OperandType type, const std::vector<uint32_t>& dimensions) const;
80 
81     // Returns true if the amount of space needed to store a value of the specified
82     // dimensions and element size overflows the uint32_t type.
83     //
84     // See also TypeManager::sizeOfDataOverflowsUInt32().
85     bool sizeOfDataOverflowsUInt32(hal::OperandType type,
86                                    const std::vector<uint32_t>& dimensions) const;
87 
88     // Returns true if extensions usage is allowed in current process.
areExtensionsAllowed()89     bool areExtensionsAllowed() const { return mExtensionsAllowed; }
90 
91     // This method is intended for use only by internal unit tests.
92     //
93     // Registers an extension.
94     //
95     // Returns true if the registration was successful.
forTest_registerExtension(const hal::Extension & extension)96     bool forTest_registerExtension(const hal::Extension& extension) {
97         return registerExtension(extension, "INTERNAL TEST");
98     }
99 
100     // This method is intended for use only by internal unit tests.
101     //
102     // Resets the internal state.
103     //
104     // After calling forTest_registerExtension() any number of times, call
105     // forTest_reset() to return to the state as if forTest_registerExtension()
106     // had never been called. Note that forTest_reset() resets all internal
107     // state (including assigned prefixes) and re-discovers extensions from
108     // available devices.
forTest_reset()109     void forTest_reset() { *this = TypeManager(); }
110 
111     // Collection of app-related arguments for the isExtensionsUseAllowed method.
112     struct AppPackageInfo {
113         // Path of the binary (/proc/$PID/exe)
114         std::string binaryPath;
115         // Package name of the Android app (empty string if not Android app).
116         std::string appPackageName;
117         // Is the app a system app? (false if not an Android app)
118         bool appIsSystemApp;
119         // Is the app preinstalled on vendor image? (false if not an Android app)
120         bool appIsOnVendorImage;
121         // Is the app preinstalled on product image? (false if not an Android app)
122         bool appIsOnProductImage;
123     };
124 
125     // Check if NNAPI Vendor extensions are usable in the process with the given app
126     // and supplemental infomation.
127     //
128     // useOnProductImageEnabled - whether apps/binaries preinstalled on /product partition
129     // can be enabled for extensions use.
130     // allowlist - list of apps/binaries which are allowed to use extensions.
131     static bool isExtensionsUseAllowed(const AppPackageInfo& appPackageInfo,
132                                        bool useOnProductImageEnabled,
133                                        const std::vector<std::string>& allowlist);
134 
135    private:
136     TypeManager();
137     void findAvailableExtensions();
138     bool registerExtension(hal::Extension extension, const std::string& deviceName);
139 
140     // Returns the numeric "prefix" value corresponding to an extension.
141     //
142     // Returns false when assigning a new prefix would overflow uint16_t.
143     bool getExtensionPrefix(const std::string& extensionName, uint16_t* prefix);
144 
145     const DeviceManager* mDeviceManager = DeviceManager::get();
146 
147     // Contains all registered extensions.
148     std::map<std::string, hal::Extension> mExtensionNameToExtension;
149 
150     // Contains the name of the first discovered device that supports an
151     // extension. Used for error reporting.
152     std::map<std::string, std::string> mExtensionNameToFirstDevice;
153 
154     // When multiple devices report conflicting information about an extension,
155     // the extension is disabled.
156     std::set<std::string> mDisabledExtensions;
157 
158     // The fields below are used to support efficient extension name to
159     // prefix mapping. New prefixes are created by getExtensionPrefix.
160     std::map<std::string, uint16_t> mExtensionNameToPrefix;
161     // Entries of mPrefixToExtension point into mExtensionNameToExtension.
162     // prefix=0 corresponds to no extension and should never be looked up.
163     std::vector<hal::Extension*> mPrefixToExtension = {nullptr};
164 
165     // True if Extensions can be used in current process.
166     bool mExtensionsAllowed = false;
167 };
168 
169 }  // namespace nn
170 }  // namespace android
171 
172 #endif  // ANDROID_FRAMEWORKS_ML_NN_RUNTIME_TYPE_MANAGER_H
173