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 #include <gtest/gtest.h>
18
19 #include <string>
20 #include <vector>
21
22 #include "HalInterfaces.h"
23 #include "Manager.h"
24 #include "NeuralNetworks.h"
25 #include "NeuralNetworksExtensions.h"
26 #include "SampleDriver.h"
27 #include "TypeManager.h"
28
29 namespace {
30
31 using DeviceManager = ::android::nn::DeviceManager;
32 using SampleDriver = ::android::nn::sample_driver::SampleDriver;
33 using TypeManager = ::android::nn::TypeManager;
34
35 using namespace android::nn::hal;
36
37 const char* kTestDriverName = "extensions-test-driver";
38 const char* kTestExtension1 = "vendor.test.one";
39 const char* kTestExtension2 = "vendor.test.two";
40 const char* kTestExtension3 = "vendor.test.three";
41
42 class TestDriver : public SampleDriver {
43 public:
TestDriver()44 TestDriver() : SampleDriver(kTestDriverName) {}
~TestDriver()45 ~TestDriver() override {}
46
getSupportedExtensions(getSupportedExtensions_cb cb)47 Return<void> getSupportedExtensions(getSupportedExtensions_cb cb) override {
48 cb(V1_0::ErrorStatus::NONE, {
49 {.name = kTestExtension1},
50 {.name = kTestExtension2},
51 {.name = kTestExtension3},
52 });
53 return Void();
54 }
55
getCapabilities_1_3(getCapabilities_1_3_cb cb)56 Return<void> getCapabilities_1_3(getCapabilities_1_3_cb cb) override {
57 cb(V1_3::ErrorStatus::NONE, {/* Placeholder zero-filled capabilities. */});
58 return Void();
59 }
60
getSupportedOperations_1_3(const Model &,getSupportedOperations_1_3_cb)61 Return<void> getSupportedOperations_1_3(const Model&, getSupportedOperations_1_3_cb) override {
62 CHECK(false) << "not implemented";
63 return Void();
64 }
65 };
66
67 class ExtensionsTest : public ::testing::Test {
68 protected:
SetUp()69 virtual void SetUp() {
70 // This is needed before we have the CPU fallback path being treated as a Device.
71 if (DeviceManager::get()->getUseCpuOnly()) {
72 GTEST_SKIP();
73 }
74
75 DeviceManager::get()->forTest_registerDevice(kTestDriverName, new TestDriver());
76 // Discover extensions provided by registered devices.
77 TypeManager::get()->forTest_reset();
78 mDevice = getDeviceByName(kTestDriverName);
79 ASSERT_NE(mDevice, nullptr);
80 }
81
TearDown()82 virtual void TearDown() {
83 DeviceManager::get()->forTest_reInitializeDeviceList();
84 TypeManager::get()->forTest_reset();
85 }
86
getDeviceByName(const std::string & name)87 ANeuralNetworksDevice* getDeviceByName(const std::string& name) {
88 ANeuralNetworksDevice* result = nullptr;
89 uint32_t numDevices = 0;
90 EXPECT_EQ(ANeuralNetworks_getDeviceCount(&numDevices), ANEURALNETWORKS_NO_ERROR);
91 EXPECT_GE(numDevices, 1u);
92 for (uint32_t i = 0; i < numDevices; i++) {
93 ANeuralNetworksDevice* device = nullptr;
94 EXPECT_EQ(ANeuralNetworks_getDevice(i, &device), ANEURALNETWORKS_NO_ERROR);
95 const char* buffer = nullptr;
96 EXPECT_EQ(ANeuralNetworksDevice_getName(device, &buffer), ANEURALNETWORKS_NO_ERROR);
97 if (name.compare(buffer) == 0) {
98 EXPECT_EQ(result, nullptr) << "multiple devices named " << name;
99 result = device;
100 }
101 }
102 return result;
103 }
104
testDriverSupportsExtension(const char * extensionName)105 bool testDriverSupportsExtension(const char* extensionName) {
106 bool result;
107 EXPECT_EQ(ANeuralNetworksDevice_getExtensionSupport(mDevice, extensionName, &result),
108 ANEURALNETWORKS_NO_ERROR);
109 return result;
110 }
111
112 private:
113 ANeuralNetworksDevice* mDevice;
114 };
115
TEST_F(ExtensionsTest,DeviceReportsSupportedExtensions)116 TEST_F(ExtensionsTest, DeviceReportsSupportedExtensions) {
117 EXPECT_TRUE(testDriverSupportsExtension(kTestExtension1));
118 EXPECT_FALSE(testDriverSupportsExtension("vendor.test.unknown"));
119 EXPECT_FALSE(testDriverSupportsExtension("asdfasdfas"));
120 EXPECT_TRUE(testDriverSupportsExtension(kTestExtension2));
121 EXPECT_TRUE(testDriverSupportsExtension(kTestExtension3));
122 }
123
TEST_F(ExtensionsTest,TestAllowedNativeBinaries)124 TEST_F(ExtensionsTest, TestAllowedNativeBinaries) {
125 std::vector<std::string> allowlist = {"/data/foo", "/vendor/foo", "/odm/foo",
126 "/product/foo", "/system/allowlisted", "/foobar/foo"};
127
128 auto native_info =
129 [&](const std::string& binaryPath) -> android::nn::TypeManager::AppPackageInfo {
130 return {.binaryPath = binaryPath,
131 .appPackageName = "",
132 .appIsSystemApp = false,
133 .appIsOnVendorImage = false,
134 .appIsOnProductImage = false};
135 };
136
137 // No binary info
138 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info(""),
139 /* useOnProductImageEnabled = */ false,
140 allowlist));
141 // Non-approved top-level dir
142 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/foobar/foo"),
143 /* useOnProductImageEnabled = */ false,
144 allowlist));
145 // Allowlisted /data binary
146 EXPECT_TRUE(TypeManager::isExtensionsUseAllowed(native_info("/data/foo"),
147 /* useOnProductImageEnabled = */ false,
148 allowlist));
149 // Allowlisted /vendor binary
150 EXPECT_TRUE(TypeManager::isExtensionsUseAllowed(native_info("/vendor/foo"),
151 /* useOnProductImageEnabled = */ false,
152 allowlist));
153 // Allowlisted /odm binary
154 EXPECT_TRUE(TypeManager::isExtensionsUseAllowed(native_info("/odm/foo"),
155 /* useOnProductImageEnabled = */ false,
156 allowlist));
157 // Non-allowlisted /system binary
158 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/system/foo"),
159 /* useOnProductImageEnabled = */ false,
160 allowlist));
161 // allowlisted /system binary (can't be allowlisted)
162 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/system/allowlisted"),
163 /* useOnProductImageEnabled = */ false,
164 allowlist));
165 // Allowlisted /product binary, product disabled
166 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/product/foo"),
167 /* useOnProductImageEnabled = */ false,
168 allowlist));
169 // Allowlisted /product binary, product enabled
170 EXPECT_TRUE(TypeManager::isExtensionsUseAllowed(native_info("/product/foo"),
171 /* useOnProductImageEnabled = */ true,
172 allowlist));
173 // Non-allowlisted /product binary, product enabled
174 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/product/foo_not_allowlisted"),
175 /* useOnProductImageEnabled = */ true,
176 allowlist));
177 // Non-allowlisted /odm binary
178 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/odm/foo_not_allowlisted"),
179 /* useOnProductImageEnabled = */ false,
180 allowlist));
181 // Non-allowlisted /vendor binary
182 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/vendor/foo_not_allowlisted"),
183 /* useOnProductImageEnabled = */ false,
184 allowlist));
185 // Non-allowlisted /data binary
186 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed(native_info("/data/foo_not_allowlisted"),
187 /* useOnProductImageEnabled = */ false,
188 allowlist));
189 }
190
TEST_F(ExtensionsTest,TestAllowedApps)191 TEST_F(ExtensionsTest, TestAllowedApps) {
192 std::string app_process32 = "/system/bin/app_process32";
193 std::string app_process64 = "/system/bin/app_process64";
194 std::string other_binary = "/system/bin/foo";
195
196 std::string package = "com.foo";
197 std::string package_non_allowlisted = "com.foo2";
198
199 std::vector<std::string> allowlist = {"com.foo"};
200
201 auto test_app_process = [&](const std::string& binary) {
202 // /data app
203 EXPECT_TRUE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
204 .appPackageName = package,
205 .appIsSystemApp = false,
206 .appIsOnVendorImage = false,
207 .appIsOnProductImage = false},
208 /* useOnProductImageEnabled = */ false,
209 allowlist));
210
211 // /system app
212 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
213 .appPackageName = package,
214 .appIsSystemApp = true,
215 .appIsOnVendorImage = false,
216 .appIsOnProductImage = false},
217 /* useOnProductImageEnabled = */ false,
218 allowlist));
219
220 // /vendor || /odm app
221 EXPECT_TRUE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
222 .appPackageName = package,
223 .appIsSystemApp = true,
224 .appIsOnVendorImage = true,
225 .appIsOnProductImage = false},
226 /* useOnProductImageEnabled = */ false,
227 allowlist));
228
229 // /product app, disabled
230 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
231 .appPackageName = package,
232 .appIsSystemApp = true,
233 .appIsOnVendorImage = false,
234 .appIsOnProductImage = true},
235 /* useOnProductImageEnabled = */ false,
236 allowlist));
237
238 // /product app, enabled
239 EXPECT_TRUE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
240 .appPackageName = package,
241 .appIsSystemApp = true,
242 .appIsOnVendorImage = false,
243 .appIsOnProductImage = true},
244 /* useOnProductImageEnabled = */ true,
245 allowlist));
246
247 // /product app, enabled, package name not on allowlist
248 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
249 .appPackageName = package_non_allowlisted,
250 .appIsSystemApp = true,
251 .appIsOnVendorImage = false,
252 .appIsOnProductImage = true},
253 /* useOnProductImageEnabled = */ true,
254 allowlist));
255
256 // /data app, package name not on allowlist
257 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
258 .appPackageName = package_non_allowlisted,
259 .appIsSystemApp = false,
260 .appIsOnVendorImage = false,
261 .appIsOnProductImage = false},
262 /* useOnProductImageEnabled = */ false,
263 allowlist));
264
265 // /vendor || /odm app, package name not on allowlist
266 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = binary,
267 .appPackageName = package_non_allowlisted,
268 .appIsSystemApp = true,
269 .appIsOnVendorImage = true,
270 .appIsOnProductImage = false},
271 /* useOnProductImageEnabled = */ false,
272 allowlist));
273 };
274 test_app_process(app_process64);
275 test_app_process(app_process32);
276
277 // Test all positive cases fail if binary is not app_process32|64
278 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = other_binary,
279 .appPackageName = package,
280 .appIsSystemApp = false,
281 .appIsOnVendorImage = false,
282 .appIsOnProductImage = false},
283 /* useOnProductImageEnabled = */ false,
284 allowlist));
285 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = other_binary,
286 .appPackageName = package,
287 .appIsSystemApp = true,
288 .appIsOnVendorImage = true,
289 .appIsOnProductImage = false},
290 /* useOnProductImageEnabled = */ false,
291 allowlist));
292
293 EXPECT_FALSE(TypeManager::isExtensionsUseAllowed({.binaryPath = other_binary,
294 .appPackageName = package,
295 .appIsSystemApp = true,
296 .appIsOnVendorImage = false,
297 .appIsOnProductImage = true},
298 /* useOnProductImageEnabled = */ true,
299 allowlist));
300 }
301
302 } // namespace
303