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