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