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