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