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 #include "hidden_api.h"
18
19 #include <fstream>
20 #include <sstream>
21
22 #include "android-base/stringprintf.h"
23 #include "base/file_utils.h"
24 #include "base/sdk_version.h"
25 #include "base/stl_util.h"
26 #include "common_runtime_test.h"
27 #include "jni/jni_internal.h"
28 #include "proxy_test.h"
29 #include "well_known_classes.h"
30
31 namespace art {
32
33 using android::base::StringPrintf;
34 using hiddenapi::detail::MemberSignature;
35 using hiddenapi::detail::ShouldDenyAccessToMemberImpl;
36
37 // Should be the same as dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_P_HIDDEN_APIS,
38 // dalvik.system.VMRuntime.HIDE_MAXTARGETSDK_Q_HIDDEN_APIS, and
39 // dalvik.system.VMRuntime.EXEMPT_TEST_API_ACCESS_VERIFICATION.
40 static constexpr uint64_t kHideMaxtargetsdkPHiddenApis = 149997251;
41 static constexpr uint64_t kHideMaxtargetsdkQHiddenApis = 149994052;
42 static constexpr uint64_t kAllowTestApiAccess = 166236554;
43
44
Copy(const std::string & src,const std::string & dst,std::string * error_msg)45 static bool Copy(const std::string& src, const std::string& dst, /*out*/ std::string* error_msg) {
46 std::ifstream src_stream(src, std::ios::binary);
47 std::ofstream dst_stream(dst, std::ios::binary);
48 dst_stream << src_stream.rdbuf();
49 src_stream.close();
50 dst_stream.close();
51 if (src_stream.good() && dst_stream.good()) {
52 return true;
53 } else {
54 *error_msg = "Copy " + src + " => " + dst + " (src_good="
55 + (src_stream.good() ? "true" : "false") + ", dst_good="
56 + (dst_stream.good() ? "true" : "false") + ")";
57 return false;
58 }
59 }
60
LoadDexFiles(const std::string & path,ScopedObjectAccess & soa,std::vector<std::unique_ptr<const DexFile>> * dex_files,ObjPtr<mirror::ClassLoader> * class_loader,std::string * error_msg)61 static bool LoadDexFiles(const std::string& path,
62 ScopedObjectAccess& soa,
63 /* out */ std::vector<std::unique_ptr<const DexFile>>* dex_files,
64 /* out */ ObjPtr<mirror::ClassLoader>* class_loader,
65 /* out */ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
66 if (!ArtDexFileLoader().Open(path.c_str(),
67 path,
68 /* verify= */ true,
69 /* verify_checksum= */ true,
70 error_msg,
71 dex_files)) {
72 return false;
73 }
74
75 ClassLinker* const linker = Runtime::Current()->GetClassLinker();
76
77 StackHandleScope<2> hs(soa.Self());
78 Handle<mirror::Class> h_class = hs.NewHandle(soa.Decode<mirror::Class>(
79 WellKnownClasses::dalvik_system_PathClassLoader));
80 Handle<mirror::ClassLoader> h_loader = hs.NewHandle(linker->CreateWellKnownClassLoader(
81 soa.Self(),
82 MakeNonOwningPointerVector(*dex_files),
83 h_class,
84 /* parent_loader= */ ScopedNullHandle<mirror::ClassLoader>(),
85 /* shared_libraries= */ ScopedNullHandle<mirror::ObjectArray<mirror::ClassLoader>>()));
86 for (const auto& dex_file : *dex_files) {
87 linker->RegisterDexFile(*dex_file.get(), h_loader.Get());
88 }
89
90 *class_loader = h_loader.Get();
91 return true;
92 }
93
Remove(const std::string & path,std::string * error_msg)94 static bool Remove(const std::string& path, /*out*/ std::string* error_msg) {
95 if (TEMP_FAILURE_RETRY(remove(path.c_str())) == 0) {
96 return true;
97 }
98 *error_msg = StringPrintf("Unable to remove(\"%s\"): %s", path.c_str(), strerror(errno));
99 return false;
100 }
101
CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,const std::vector<std::unique_ptr<const DexFile>> & dex_files,hiddenapi::Domain expected_domain,std::string * error_msg)102 static bool CheckAllDexFilesInDomain(ObjPtr<mirror::ClassLoader> loader,
103 const std::vector<std::unique_ptr<const DexFile>>& dex_files,
104 hiddenapi::Domain expected_domain,
105 /* out */ std::string* error_msg)
106 REQUIRES_SHARED(Locks::mutator_lock_) {
107 for (const auto& dex_file : dex_files) {
108 hiddenapi::AccessContext context(loader, dex_file.get());
109 if (context.GetDomain() != expected_domain) {
110 std::stringstream ss;
111 ss << dex_file->GetLocation() << ": access context domain does not match "
112 << "(expected=" << static_cast<uint32_t>(expected_domain)
113 << ", actual=" << static_cast<uint32_t>(context.GetDomain()) << ")";
114 *error_msg = ss.str();
115 return false;
116 }
117 if (dex_file->GetHiddenapiDomain() != expected_domain) {
118 std::stringstream ss;
119 ss << dex_file->GetLocation() << ": dex file domain does not match "
120 << "(expected=" << static_cast<uint32_t>(expected_domain)
121 << ", actual=" << static_cast<uint32_t>(dex_file->GetHiddenapiDomain()) << ")";
122 *error_msg = ss.str();
123 return false;
124 }
125 }
126
127 return true;
128 }
129
130 class HiddenApiTest : public CommonRuntimeTest {
131 protected:
SetUp()132 void SetUp() override {
133 // Do the normal setup.
134 CommonRuntimeTest::SetUp();
135 self_ = Thread::Current();
136 self_->TransitionFromSuspendedToRunnable();
137 jclass_loader_ = LoadDex("HiddenApiSignatures");
138 bool started = runtime_->Start();
139 CHECK(started);
140
141 class1_field1_ = GetArtField("mypackage/packagea/Class1", "field1", "I");
142 class1_field12_ = GetArtField("mypackage/packagea/Class1", "field12", "I");
143 class1_init_ = GetArtMethod("mypackage/packagea/Class1", "<init>", "()V");
144 class1_method1_ = GetArtMethod("mypackage/packagea/Class1", "method1", "()V");
145 class1_method1_i_ = GetArtMethod("mypackage/packagea/Class1", "method1", "(I)V");
146 class1_method12_ = GetArtMethod("mypackage/packagea/Class1", "method12", "()V");
147 class12_field1_ = GetArtField("mypackage/packagea/Class12", "field1", "I");
148 class12_method1_ = GetArtMethod("mypackage/packagea/Class12", "method1", "()V");
149 class2_field1_ = GetArtField("mypackage/packagea/Class2", "field1", "I");
150 class2_method1_ = GetArtMethod("mypackage/packagea/Class2", "method1", "()V");
151 class2_method1_i_ = GetArtMethod("mypackage/packagea/Class2", "method1", "(I)V");
152 class3_field1_ = GetArtField("mypackage/packageb/Class3", "field1", "I");
153 class3_method1_ = GetArtMethod("mypackage/packageb/Class3", "method1", "()V");
154 class3_method1_i_ = GetArtMethod("mypackage/packageb/Class3", "method1", "(I)V");
155 }
156
GetArtMethod(const char * class_name,const char * name,const char * signature)157 ArtMethod* GetArtMethod(const char* class_name, const char* name, const char* signature) {
158 JNIEnv* env = Thread::Current()->GetJniEnv();
159 jclass klass = env->FindClass(class_name);
160 jmethodID method_id = env->GetMethodID(klass, name, signature);
161 ArtMethod* art_method = jni::DecodeArtMethod(method_id);
162 return art_method;
163 }
164
GetArtField(const char * class_name,const char * name,const char * signature)165 ArtField* GetArtField(const char* class_name, const char* name, const char* signature) {
166 JNIEnv* env = Thread::Current()->GetJniEnv();
167 jclass klass = env->FindClass(class_name);
168 jfieldID field_id = env->GetFieldID(klass, name, signature);
169 ArtField* art_field = jni::DecodeArtField(field_id);
170 return art_field;
171 }
172
SetChangeIdState(uint64_t change,bool enabled)173 void SetChangeIdState(uint64_t change, bool enabled) {
174 CompatFramework& compat_framework = runtime_->GetCompatFramework();
175 std::set<uint64_t> disabled_changes = compat_framework.GetDisabledCompatChanges();
176 if (enabled) {
177 disabled_changes.erase(change);
178 } else {
179 disabled_changes.insert(change);
180 }
181 compat_framework.SetDisabledCompatChanges(disabled_changes);
182 }
183
ShouldDenyAccess(hiddenapi::ApiList list)184 bool ShouldDenyAccess(hiddenapi::ApiList list) REQUIRES_SHARED(Locks::mutator_lock_) {
185 // Choose parameters such that there are no side effects (AccessMethod::kNone)
186 // and that the member is not on the exemptions list (here we choose one which
187 // is not even in boot class path).
188 return ShouldDenyAccessToMemberImpl(/* member= */ class1_field1_,
189 list,
190 /* access_method= */ hiddenapi::AccessMethod::kNone);
191 }
192
TestLocation(const std::string & location,hiddenapi::Domain expected_domain)193 void TestLocation(const std::string& location, hiddenapi::Domain expected_domain) {
194 ScopedObjectAccess soa(Thread::Current());
195 std::vector<std::unique_ptr<const DexFile>> dex_files;
196 std::string error_msg;
197 ObjPtr<mirror::ClassLoader> class_loader;
198
199 ASSERT_TRUE(Copy(GetTestDexFileName("Main"), location, &error_msg)) << error_msg;
200 ASSERT_TRUE(LoadDexFiles(location, soa, &dex_files, &class_loader, &error_msg))
201 << error_msg;
202 ASSERT_GE(dex_files.size(), 1u);
203 ASSERT_TRUE(CheckAllDexFilesInDomain(class_loader,
204 dex_files,
205 expected_domain,
206 &error_msg)) << error_msg;
207
208 dex_files.clear();
209 ASSERT_TRUE(Remove(location, &error_msg)) << error_msg;
210 }
211
212 protected:
213 Thread* self_;
214 jobject jclass_loader_;
215 ArtField* class1_field1_;
216 ArtField* class1_field12_;
217 ArtMethod* class1_init_;
218 ArtMethod* class1_method1_;
219 ArtMethod* class1_method1_i_;
220 ArtMethod* class1_method12_;
221 ArtField* class12_field1_;
222 ArtMethod* class12_method1_;
223 ArtField* class2_field1_;
224 ArtMethod* class2_method1_;
225 ArtMethod* class2_method1_i_;
226 ArtField* class3_field1_;
227 ArtMethod* class3_method1_;
228 ArtMethod* class3_method1_i_;
229 };
230
TEST_F(HiddenApiTest,CheckGetActionFromRuntimeFlags)231 TEST_F(HiddenApiTest, CheckGetActionFromRuntimeFlags) {
232 ScopedObjectAccess soa(self_);
233
234 runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kJustWarn);
235 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
236 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
237 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
238 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
239 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
240 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), false);
241 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), false);
242
243 runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
244 runtime_->SetTargetSdkVersion(
245 static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetO().GetMaxAllowedSdkVersion()));
246 SetChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
247 SetChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
248 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
249 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
250 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
251 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
252 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
253 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), false);
254 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
255
256 runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
257 runtime_->SetTargetSdkVersion(
258 static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetO().GetMaxAllowedSdkVersion()) + 1);
259 SetChangeIdState(kHideMaxtargetsdkPHiddenApis, false);
260 SetChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
261 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
262 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
263 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
264 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
265 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
266 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
267 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
268 SetChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
269 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
270 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
271 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), true);
272 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), false);
273 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
274 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
275
276 runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
277 runtime_->SetTargetSdkVersion(
278 static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetP().GetMaxAllowedSdkVersion()) + 1);
279 SetChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
280 SetChangeIdState(kHideMaxtargetsdkQHiddenApis, false);
281 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
282 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
283 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
284 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), false);
285 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), true);
286 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
287 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
288
289 runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
290 runtime_->SetTargetSdkVersion(
291 static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetQ().GetMaxAllowedSdkVersion()) + 1);
292 SetChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
293 SetChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
294 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
295 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
296 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), false);
297 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), true);
298 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), true);
299 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
300 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
301
302 runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
303 runtime_->SetTargetSdkVersion(
304 static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetR().GetMaxAllowedSdkVersion()) + 1);
305 SetChangeIdState(kHideMaxtargetsdkPHiddenApis, true);
306 SetChangeIdState(kHideMaxtargetsdkQHiddenApis, true);
307 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Sdk()), false);
308 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Unsupported()), false);
309 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetR()), true);
310 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetQ()), true);
311 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetP()), true);
312 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::MaxTargetO()), true);
313 ASSERT_EQ(ShouldDenyAccess(hiddenapi::ApiList::Blocked()), true);
314 }
315
TEST_F(HiddenApiTest,CheckTestApiEnforcement)316 TEST_F(HiddenApiTest, CheckTestApiEnforcement) {
317 ScopedObjectAccess soa(self_);
318
319 runtime_->SetHiddenApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
320 runtime_->SetTargetSdkVersion(
321 static_cast<uint32_t>(hiddenapi::ApiList::MaxTargetR().GetMaxAllowedSdkVersion()) + 1);
322
323 // Default case where all TestApis are treated like non-TestApi.
324 runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
325 SetChangeIdState(kAllowTestApiAccess, false);
326 ASSERT_EQ(
327 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Sdk()), false);
328 ASSERT_EQ(
329 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Unsupported()), false);
330 ASSERT_EQ(
331 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetR()), true);
332 ASSERT_EQ(
333 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetQ()), true);
334 ASSERT_EQ(
335 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetP()), true);
336 ASSERT_EQ(
337 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetO()), true);
338 ASSERT_EQ(
339 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blocked()), true);
340
341 // A case where we want to allow access to TestApis.
342 runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kDisabled);
343 SetChangeIdState(kAllowTestApiAccess, false);
344 ASSERT_EQ(
345 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Sdk()), false);
346 ASSERT_EQ(
347 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Unsupported()), false);
348 ASSERT_EQ(
349 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetR()), false);
350 ASSERT_EQ(
351 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetQ()), false);
352 ASSERT_EQ(
353 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetP()), false);
354 ASSERT_EQ(
355 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetO()), false);
356 ASSERT_EQ(
357 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blocked()), false);
358
359 // A second case where we want to allow access to TestApis.
360 runtime_->SetTestApiEnforcementPolicy(hiddenapi::EnforcementPolicy::kEnabled);
361 SetChangeIdState(kAllowTestApiAccess, true);
362 ASSERT_EQ(
363 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Sdk()), false);
364 ASSERT_EQ(
365 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Unsupported()), false);
366 ASSERT_EQ(
367 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetR()), false);
368 ASSERT_EQ(
369 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetQ()), false);
370 ASSERT_EQ(
371 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetP()), false);
372 ASSERT_EQ(
373 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::MaxTargetO()), false);
374 ASSERT_EQ(
375 ShouldDenyAccess(hiddenapi::ApiList::TestApi() | hiddenapi::ApiList::Blocked()), false);
376 }
377
TEST_F(HiddenApiTest,CheckMembersRead)378 TEST_F(HiddenApiTest, CheckMembersRead) {
379 ASSERT_NE(nullptr, class1_field1_);
380 ASSERT_NE(nullptr, class1_field12_);
381 ASSERT_NE(nullptr, class1_init_);
382 ASSERT_NE(nullptr, class1_method1_);
383 ASSERT_NE(nullptr, class1_method1_i_);
384 ASSERT_NE(nullptr, class1_method12_);
385 ASSERT_NE(nullptr, class12_field1_);
386 ASSERT_NE(nullptr, class12_method1_);
387 ASSERT_NE(nullptr, class2_field1_);
388 ASSERT_NE(nullptr, class2_method1_);
389 ASSERT_NE(nullptr, class2_method1_i_);
390 ASSERT_NE(nullptr, class3_field1_);
391 ASSERT_NE(nullptr, class3_method1_);
392 ASSERT_NE(nullptr, class3_method1_i_);
393 }
394
TEST_F(HiddenApiTest,CheckEverythingMatchesL)395 TEST_F(HiddenApiTest, CheckEverythingMatchesL) {
396 ScopedObjectAccess soa(self_);
397 std::string prefix("L");
398 ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
399 ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
400 ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
401 ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
402 ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
403 ASSERT_TRUE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
404 ASSERT_TRUE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
405 ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
406 ASSERT_TRUE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
407 ASSERT_TRUE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
408 ASSERT_TRUE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
409 ASSERT_TRUE(MemberSignature(class3_field1_).DoesPrefixMatch(prefix));
410 ASSERT_TRUE(MemberSignature(class3_method1_).DoesPrefixMatch(prefix));
411 ASSERT_TRUE(MemberSignature(class3_method1_i_).DoesPrefixMatch(prefix));
412 }
413
TEST_F(HiddenApiTest,CheckPackageMatch)414 TEST_F(HiddenApiTest, CheckPackageMatch) {
415 ScopedObjectAccess soa(self_);
416 std::string prefix("Lmypackage/packagea/");
417 ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
418 ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
419 ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
420 ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
421 ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
422 ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
423 ASSERT_TRUE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
424 ASSERT_TRUE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
425 ASSERT_TRUE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
426 ASSERT_TRUE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
427 ASSERT_TRUE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
428 ASSERT_FALSE(MemberSignature(class3_field1_).DoesPrefixMatch(prefix));
429 ASSERT_FALSE(MemberSignature(class3_method1_).DoesPrefixMatch(prefix));
430 ASSERT_FALSE(MemberSignature(class3_method1_i_).DoesPrefixMatch(prefix));
431 }
432
TEST_F(HiddenApiTest,CheckClassMatch)433 TEST_F(HiddenApiTest, CheckClassMatch) {
434 ScopedObjectAccess soa(self_);
435 std::string prefix("Lmypackage/packagea/Class1");
436 ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
437 ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
438 ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
439 ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
440 ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
441 ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
442 ASSERT_TRUE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
443 ASSERT_TRUE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
444 ASSERT_FALSE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
445 ASSERT_FALSE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
446 ASSERT_FALSE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
447 }
448
TEST_F(HiddenApiTest,CheckClassExactMatch)449 TEST_F(HiddenApiTest, CheckClassExactMatch) {
450 ScopedObjectAccess soa(self_);
451 std::string prefix("Lmypackage/packagea/Class1;");
452 ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
453 ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
454 ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
455 ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
456 ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
457 ASSERT_FALSE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
458 ASSERT_FALSE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
459 ASSERT_FALSE(MemberSignature(class2_field1_).DoesPrefixMatch(prefix));
460 ASSERT_FALSE(MemberSignature(class2_method1_).DoesPrefixMatch(prefix));
461 ASSERT_FALSE(MemberSignature(class2_method1_i_).DoesPrefixMatch(prefix));
462 }
463
TEST_F(HiddenApiTest,CheckMethodMatch)464 TEST_F(HiddenApiTest, CheckMethodMatch) {
465 ScopedObjectAccess soa(self_);
466 std::string prefix("Lmypackage/packagea/Class1;->method1");
467 ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
468 ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
469 ASSERT_FALSE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
470 ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
471 ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
472 ASSERT_TRUE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
473 ASSERT_FALSE(MemberSignature(class12_field1_).DoesPrefixMatch(prefix));
474 ASSERT_FALSE(MemberSignature(class12_method1_).DoesPrefixMatch(prefix));
475 }
476
TEST_F(HiddenApiTest,CheckMethodExactMatch)477 TEST_F(HiddenApiTest, CheckMethodExactMatch) {
478 ScopedObjectAccess soa(self_);
479 std::string prefix("Lmypackage/packagea/Class1;->method1(");
480 ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
481 ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
482 ASSERT_FALSE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
483 ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
484 ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
485 ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
486 }
487
TEST_F(HiddenApiTest,CheckMethodSignatureMatch)488 TEST_F(HiddenApiTest, CheckMethodSignatureMatch) {
489 ScopedObjectAccess soa(self_);
490 std::string prefix("Lmypackage/packagea/Class1;->method1(I)");
491 ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
492 ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
493 ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
494 ASSERT_TRUE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
495 ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
496 }
497
TEST_F(HiddenApiTest,CheckMethodSignatureAndReturnMatch)498 TEST_F(HiddenApiTest, CheckMethodSignatureAndReturnMatch) {
499 ScopedObjectAccess soa(self_);
500 std::string prefix("Lmypackage/packagea/Class1;->method1()V");
501 ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
502 ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
503 ASSERT_TRUE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
504 ASSERT_FALSE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
505 ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
506 }
507
TEST_F(HiddenApiTest,CheckFieldMatch)508 TEST_F(HiddenApiTest, CheckFieldMatch) {
509 ScopedObjectAccess soa(self_);
510 std::string prefix("Lmypackage/packagea/Class1;->field1");
511 ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
512 ASSERT_TRUE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
513 ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
514 ASSERT_FALSE(MemberSignature(class1_method1_i_).DoesPrefixMatch(prefix));
515 ASSERT_FALSE(MemberSignature(class1_method12_).DoesPrefixMatch(prefix));
516 }
517
TEST_F(HiddenApiTest,CheckFieldExactMatch)518 TEST_F(HiddenApiTest, CheckFieldExactMatch) {
519 ScopedObjectAccess soa(self_);
520 std::string prefix("Lmypackage/packagea/Class1;->field1:");
521 ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
522 ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
523 ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
524 }
525
TEST_F(HiddenApiTest,CheckFieldTypeMatch)526 TEST_F(HiddenApiTest, CheckFieldTypeMatch) {
527 ScopedObjectAccess soa(self_);
528 std::string prefix("Lmypackage/packagea/Class1;->field1:I");
529 ASSERT_TRUE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
530 ASSERT_FALSE(MemberSignature(class1_field12_).DoesPrefixMatch(prefix));
531 ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
532 }
533
TEST_F(HiddenApiTest,CheckConstructorMatch)534 TEST_F(HiddenApiTest, CheckConstructorMatch) {
535 ScopedObjectAccess soa(self_);
536 std::string prefix("Lmypackage/packagea/Class1;-><init>");
537 ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
538 ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
539 }
540
TEST_F(HiddenApiTest,CheckConstructorExactMatch)541 TEST_F(HiddenApiTest, CheckConstructorExactMatch) {
542 ScopedObjectAccess soa(self_);
543 std::string prefix("Lmypackage/packagea/Class1;-><init>()V");
544 ASSERT_TRUE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
545 ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
546 }
547
TEST_F(HiddenApiTest,CheckMethodSignatureTrailingCharsNoMatch)548 TEST_F(HiddenApiTest, CheckMethodSignatureTrailingCharsNoMatch) {
549 ScopedObjectAccess soa(self_);
550 std::string prefix("Lmypackage/packagea/Class1;->method1()Vfoo");
551 ASSERT_FALSE(MemberSignature(class1_method1_).DoesPrefixMatch(prefix));
552 }
553
TEST_F(HiddenApiTest,CheckConstructorTrailingCharsNoMatch)554 TEST_F(HiddenApiTest, CheckConstructorTrailingCharsNoMatch) {
555 ScopedObjectAccess soa(self_);
556 std::string prefix("Lmypackage/packagea/Class1;-><init>()Vfoo");
557 ASSERT_FALSE(MemberSignature(class1_init_).DoesPrefixMatch(prefix));
558 }
559
TEST_F(HiddenApiTest,CheckFieldTrailingCharsNoMatch)560 TEST_F(HiddenApiTest, CheckFieldTrailingCharsNoMatch) {
561 ScopedObjectAccess soa(self_);
562 std::string prefix("Lmypackage/packagea/Class1;->field1:Ifoo");
563 ASSERT_FALSE(MemberSignature(class1_field1_).DoesPrefixMatch(prefix));
564 }
565
TEST_F(HiddenApiTest,CheckMemberSignatureForProxyClass)566 TEST_F(HiddenApiTest, CheckMemberSignatureForProxyClass) {
567 ScopedObjectAccess soa(self_);
568 StackHandleScope<4> hs(soa.Self());
569 Handle<mirror::ClassLoader> class_loader(
570 hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader_)));
571
572 // Find interface we will create a proxy for.
573 Handle<mirror::Class> h_iface(hs.NewHandle(
574 class_linker_->FindClass(soa.Self(), "Lmypackage/packagea/Interface;", class_loader)));
575 ASSERT_TRUE(h_iface != nullptr);
576
577 // Create the proxy class.
578 std::vector<Handle<mirror::Class>> interfaces;
579 interfaces.push_back(h_iface);
580 Handle<mirror::Class> proxyClass = hs.NewHandle(proxy_test::GenerateProxyClass(
581 soa, jclass_loader_, runtime_->GetClassLinker(), "$Proxy1234", interfaces));
582 ASSERT_TRUE(proxyClass != nullptr);
583 ASSERT_TRUE(proxyClass->IsProxyClass());
584 ASSERT_TRUE(proxyClass->IsInitialized());
585
586 // Find the "method" virtual method.
587 ArtMethod* method = nullptr;
588 for (auto& m : proxyClass->GetDeclaredVirtualMethods(kRuntimePointerSize)) {
589 if (strcmp("method", m.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetName()) == 0) {
590 method = &m;
591 break;
592 }
593 }
594 ASSERT_TRUE(method != nullptr);
595
596 // Find the "interfaces" static field. This is generated for all proxies.
597 ArtField* field = nullptr;
598 for (size_t i = 0; i < proxyClass->NumStaticFields(); ++i) {
599 ArtField* f = proxyClass->GetStaticField(i);
600 if (strcmp("interfaces", f->GetName()) == 0) {
601 field = f;
602 break;
603 }
604 }
605 ASSERT_TRUE(field != nullptr);
606
607 // Test the signature. We expect the signature from the interface class.
608 std::ostringstream ss_method;
609 MemberSignature(method->GetInterfaceMethodIfProxy(kRuntimePointerSize)).Dump(ss_method);
610 ASSERT_EQ("Lmypackage/packagea/Interface;->method()V", ss_method.str());
611
612 // Test the signature. We expect the signature of the proxy class.
613 std::ostringstream ss_field;
614 MemberSignature(field).Dump(ss_field);
615 ASSERT_EQ("L$Proxy1234;->interfaces:[Ljava/lang/Class;", ss_field.str());
616 }
617
TEST_F(HiddenApiTest,DexDomain_DataDir)618 TEST_F(HiddenApiTest, DexDomain_DataDir) {
619 // Load file from a non-system directory and check that it is not flagged as framework.
620 std::string data_location_path = android_data_ + "/foo.jar";
621 ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path.c_str()));
622 TestLocation(data_location_path, hiddenapi::Domain::kApplication);
623 }
624
TEST_F(HiddenApiTest,DexDomain_SystemDir)625 TEST_F(HiddenApiTest, DexDomain_SystemDir) {
626 // Load file from a system, non-framework directory and check that it is not flagged as framework.
627 std::string system_location_path = GetAndroidRoot() + "/foo.jar";
628 ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path.c_str()));
629 TestLocation(system_location_path, hiddenapi::Domain::kApplication);
630 }
631
TEST_F(HiddenApiTest,DexDomain_SystemExtDir)632 TEST_F(HiddenApiTest, DexDomain_SystemExtDir) {
633 // Load file from a system_ext, non-framework directory and check that it is not flagged as
634 // framework.
635 std::string system_ext_location_path = android_system_ext_ + "/foo.jar";
636 ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_location_path.c_str()));
637 TestLocation(system_ext_location_path, hiddenapi::Domain::kApplication);
638 }
639
TEST_F(HiddenApiTest,DexDomain_SystemSystemExtDir)640 TEST_F(HiddenApiTest, DexDomain_SystemSystemExtDir) {
641 // Load file from a system/system_ext, non-framework directory and check that it is not flagged as
642 // framework.
643 std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
644 std::string system_ext_location_path = GetAndroidRoot() + "/system_ext/foo.jar";
645 ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_location_path.c_str()));
646 TestLocation(system_ext_location_path, hiddenapi::Domain::kApplication);
647 }
648
TEST_F(HiddenApiTest,DexDomain_SystemFrameworkDir)649 TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir) {
650 // Load file from a system/framework directory and check that it is flagged as a framework dex.
651 std::filesystem::create_directory(GetAndroidRoot() + "/framework");
652 std::string system_framework_location_path = GetAndroidRoot() + "/framework/foo.jar";
653 ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path.c_str()));
654 TestLocation(system_framework_location_path, hiddenapi::Domain::kPlatform);
655 }
656
TEST_F(HiddenApiTest,DexDomain_SystemExtFrameworkDir)657 TEST_F(HiddenApiTest, DexDomain_SystemExtFrameworkDir) {
658 // Load file from a system_ext/framework directory and check that it is flagged as a framework dex.
659 std::filesystem::create_directory(android_system_ext_ + "/framework");
660 std::string system_ext_framework_location_path = android_system_ext_ + "/framework/foo.jar";
661 ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_location_path.c_str()));
662 TestLocation(system_ext_framework_location_path, hiddenapi::Domain::kPlatform);
663 }
664
TEST_F(HiddenApiTest,DexDomain_SystemSystemExtFrameworkDir)665 TEST_F(HiddenApiTest, DexDomain_SystemSystemExtFrameworkDir) {
666 // Load file from a system/system_ext/framework directory and check that it is flagged as a
667 // framework dex.
668 std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
669 std::filesystem::create_directory(GetAndroidRoot() + "/system_ext/framework");
670 std::string system_ext_framework_location_path =
671 GetAndroidRoot() + "/system_ext/framework/foo.jar";
672 ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_location_path.c_str()));
673 TestLocation(system_ext_framework_location_path, hiddenapi::Domain::kPlatform);
674 }
675
TEST_F(HiddenApiTest,DexDomain_DataDir_MultiDex)676 TEST_F(HiddenApiTest, DexDomain_DataDir_MultiDex) {
677 // Load multidex file from a non-system directory and check that it is not flagged as framework.
678 std::string data_multi_location_path = android_data_ + "/multifoo.jar";
679 ASSERT_FALSE(LocationIsOnSystemFramework(data_multi_location_path.c_str()));
680 TestLocation(data_multi_location_path, hiddenapi::Domain::kApplication);
681 }
682
TEST_F(HiddenApiTest,DexDomain_SystemDir_MultiDex)683 TEST_F(HiddenApiTest, DexDomain_SystemDir_MultiDex) {
684 // Load multidex file from a system, non-framework directory and check that it is not flagged
685 // as framework.
686 std::string system_multi_location_path = GetAndroidRoot() + "/multifoo.jar";
687 ASSERT_FALSE(LocationIsOnSystemFramework(system_multi_location_path.c_str()));
688 TestLocation(system_multi_location_path, hiddenapi::Domain::kApplication);
689 }
690
TEST_F(HiddenApiTest,DexDomain_SystemExtDir_MultiDex)691 TEST_F(HiddenApiTest, DexDomain_SystemExtDir_MultiDex) {
692 // Load multidex file from a system_ext, non-framework directory and check that it is not flagged
693 // as framework.
694 std::string system_ext_multi_location_path = android_system_ext_ + "/multifoo.jar";
695 ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_multi_location_path.c_str()));
696 TestLocation(system_ext_multi_location_path, hiddenapi::Domain::kApplication);
697 }
698
TEST_F(HiddenApiTest,DexDomain_SystemSystemExtDir_MultiDex)699 TEST_F(HiddenApiTest, DexDomain_SystemSystemExtDir_MultiDex) {
700 // Load multidex file from a system/system_ext, non-framework directory and check that it is not
701 // flagged as framework.
702 std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
703 std::string system_ext_multi_location_path =
704 GetAndroidRoot() + "/system_ext/multifoo.jar";
705 ASSERT_FALSE(LocationIsOnSystemExtFramework(system_ext_multi_location_path.c_str()));
706 TestLocation(system_ext_multi_location_path, hiddenapi::Domain::kApplication);
707 }
708
TEST_F(HiddenApiTest,DexDomain_SystemFrameworkDir_MultiDex)709 TEST_F(HiddenApiTest, DexDomain_SystemFrameworkDir_MultiDex) {
710 // Load multidex file from a system/framework directory and check that it is flagged as a
711 // framework dex.
712 std::filesystem::create_directory(GetAndroidRoot() + "/framework");
713 std::string system_framework_multi_location_path = GetAndroidRoot() + "/framework/multifoo.jar";
714 ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_multi_location_path.c_str()));
715 TestLocation(system_framework_multi_location_path, hiddenapi::Domain::kPlatform);
716 }
717
TEST_F(HiddenApiTest,DexDomain_SystemExtFrameworkDir_MultiDex)718 TEST_F(HiddenApiTest, DexDomain_SystemExtFrameworkDir_MultiDex) {
719 // Load multidex file from a system_ext/framework directory and check that it is flagged as a
720 // framework dex.
721 std::filesystem::create_directory(android_system_ext_ + "/framework");
722 std::string system_ext_framework_multi_location_path =
723 android_system_ext_ + "/framework/multifoo.jar";
724 ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_multi_location_path.c_str()));
725 TestLocation(system_ext_framework_multi_location_path, hiddenapi::Domain::kPlatform);
726 }
727
TEST_F(HiddenApiTest,DexDomain_SystemSystemExtFrameworkDir_MultiDex)728 TEST_F(HiddenApiTest, DexDomain_SystemSystemExtFrameworkDir_MultiDex) {
729 // Load multidex file from a system/system_ext/framework directory and check that it is flagged
730 // as a framework dex.
731 std::filesystem::create_directory(GetAndroidRoot() + "/system_ext");
732 std::filesystem::create_directory(GetAndroidRoot() + "/system_ext/framework");
733 std::string system_ext_framework_multi_location_path =
734 GetAndroidRoot() + "/system_ext/framework/multifoo.jar";
735 ASSERT_TRUE(LocationIsOnSystemExtFramework(system_ext_framework_multi_location_path.c_str()));
736 TestLocation(system_ext_framework_multi_location_path, hiddenapi::Domain::kPlatform);
737 }
738
739 } // namespace art
740