blob: 939b7a0beb495e8757343cca216b61c2ed3a0a5c [file] [log] [blame]
Alan Viverette82f4b263a2016-12-19 15:40:05 -05001/*
Winson33eacc62020-01-24 12:02:58 -08002 * Copyright (C) 2020 The Android Open Source Project
Alan Viverette82f4b263a2016-12-19 15:40:05 -05003 *
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
Winson33eacc62020-01-24 12:02:58 -080017package com.android.server.pm.parsing;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050018
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertNotNull;
21import static org.junit.Assert.assertNull;
Garrett Boyer52136662017-05-23 13:47:58 -070022import static org.junit.Assert.assertTrue;
Anton Hanssonb2f709d2020-01-09 10:25:23 +000023import static org.junit.Assert.fail;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050024
Gavin Corkeryef441722019-05-09 17:02:10 +010025import android.apex.ApexInfo;
Garrett Boyer52136662017-05-23 13:47:58 -070026import android.content.Context;
Winson33eacc62020-01-24 12:02:58 -080027import android.content.pm.ApplicationInfo;
28import android.content.pm.PackageInfo;
29import android.content.pm.PackageManager;
30import android.content.pm.PackageParser;
31import android.content.pm.PermissionInfo;
Winsonf00c7552020-01-28 12:52:01 -080032import android.content.pm.parsing.component.ParsedComponent;
33import android.content.pm.parsing.component.ParsedPermission;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050034import android.os.Build;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070035import android.os.Bundle;
Garrett Boyer52136662017-05-23 13:47:58 -070036import android.os.FileUtils;
Winson33eacc62020-01-24 12:02:58 -080037import android.platform.test.annotations.Presubmit;
Oli Lan72ae4472020-04-14 16:50:41 +010038import android.util.SparseIntArray;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090039
40import androidx.test.InstrumentationRegistry;
41import androidx.test.filters.SmallTest;
42import androidx.test.runner.AndroidJUnit4;
Alan Viverette82f4b263a2016-12-19 15:40:05 -050043
Winson33eacc62020-01-24 12:02:58 -080044import com.android.frameworks.servicestests.R;
Winson14ff7172019-10-23 10:42:27 -070045import com.android.internal.util.ArrayUtils;
Winson33eacc62020-01-24 12:02:58 -080046import com.android.server.pm.parsing.pkg.AndroidPackage;
47import com.android.server.pm.parsing.pkg.ParsedPackage;
Garrett Boyer52136662017-05-23 13:47:58 -070048
Alan Viverette82f4b263a2016-12-19 15:40:05 -050049import org.junit.Test;
50import org.junit.runner.RunWith;
51
Garrett Boyer52136662017-05-23 13:47:58 -070052import java.io.File;
53import java.io.InputStream;
Makoto Onuki4501c61d2017-07-27 15:56:40 -070054import java.util.function.Function;
Garrett Boyer52136662017-05-23 13:47:58 -070055
Winson33eacc62020-01-24 12:02:58 -080056/**
57 * {@link ParsedPackage} was moved to the server, so this test moved along with it.
58 *
59 * This should be eventually refactored to a comprehensive parsing test, combined with its
60 * server variant in the parent package.
61 *
62 * TODO(b/135203078): Remove this test and replicate the cases in the actual com.android.server
63 * variant.
64 */
65@Presubmit
Alan Viverette82f4b263a2016-12-19 15:40:05 -050066@SmallTest
67@RunWith(AndroidJUnit4.class)
Winson33eacc62020-01-24 12:02:58 -080068public class PackageParserLegacyCoreTest {
Alan Viverette82f4b263a2016-12-19 15:40:05 -050069 private static final String RELEASED = null;
70 private static final String OLDER_PRE_RELEASE = "A";
71 private static final String PRE_RELEASE = "B";
72 private static final String NEWER_PRE_RELEASE = "C";
73
Narayan Kamath71fcc142019-01-15 18:20:39 +000074 // Codenames with a fingerprint attached to them. These may only be present in the apps
75 // declared min SDK and not as platform codenames.
76 private static final String OLDER_PRE_RELEASE_WITH_FINGERPRINT = "A.fingerprint";
77 private static final String PRE_RELEASE_WITH_FINGERPRINT = "B.fingerprint";
78 private static final String NEWER_PRE_RELEASE_WITH_FINGERPRINT = "C.fingerprint";
79
Winson14ff7172019-10-23 10:42:27 -070080 private static final String[] CODENAMES_RELEASED = { /* empty */};
81 private static final String[] CODENAMES_PRE_RELEASE = {PRE_RELEASE};
Alan Viverette82f4b263a2016-12-19 15:40:05 -050082
83 private static final int OLDER_VERSION = 10;
84 private static final int PLATFORM_VERSION = 20;
85 private static final int NEWER_VERSION = 30;
86
87 private void verifyComputeMinSdkVersion(int minSdkVersion, String minSdkCodename,
88 boolean isPlatformReleased, int expectedMinSdk) {
89 final String[] outError = new String[1];
90 final int result = PackageParser.computeMinSdkVersion(
91 minSdkVersion,
92 minSdkCodename,
93 PLATFORM_VERSION,
94 isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE,
95 outError);
96
Narayan Kamath71fcc142019-01-15 18:20:39 +000097 assertEquals("Error msg: " + outError[0], expectedMinSdk, result);
Alan Viverette82f4b263a2016-12-19 15:40:05 -050098
99 if (expectedMinSdk == -1) {
100 assertNotNull(outError[0]);
101 } else {
102 assertNull(outError[0]);
103 }
104 }
105
106 @Test
107 public void testComputeMinSdkVersion_preReleasePlatform() {
108 // Do allow older release minSdkVersion on pre-release platform.
109 // APP: Released API 10
110 // DEV: Pre-release API 20
111 verifyComputeMinSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION);
112
113 // Do allow same release minSdkVersion on pre-release platform.
114 // APP: Released API 20
115 // DEV: Pre-release API 20
116 verifyComputeMinSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION);
117
118 // Don't allow newer release minSdkVersion on pre-release platform.
119 // APP: Released API 30
120 // DEV: Pre-release API 20
121 verifyComputeMinSdkVersion(NEWER_VERSION, RELEASED, false, -1);
122
123 // Don't allow older pre-release minSdkVersion on pre-release platform.
124 // APP: Pre-release API 10
125 // DEV: Pre-release API 20
126 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000127 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500128
129 // Do allow same pre-release minSdkVersion on pre-release platform,
130 // but overwrite the specified version with CUR_DEVELOPMENT.
131 // APP: Pre-release API 20
132 // DEV: Pre-release API 20
133 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false,
134 Build.VERSION_CODES.CUR_DEVELOPMENT);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000135 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false,
136 Build.VERSION_CODES.CUR_DEVELOPMENT);
137
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500138
139 // Don't allow newer pre-release minSdkVersion on pre-release platform.
140 // APP: Pre-release API 30
141 // DEV: Pre-release API 20
142 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000143 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500144 }
145
146 @Test
147 public void testComputeMinSdkVersion_releasedPlatform() {
148 // Do allow older release minSdkVersion on released platform.
149 // APP: Released API 10
150 // DEV: Released API 20
151 verifyComputeMinSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION);
152
153 // Do allow same release minSdkVersion on released platform.
154 // APP: Released API 20
155 // DEV: Released API 20
156 verifyComputeMinSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION);
157
158 // Don't allow newer release minSdkVersion on released platform.
159 // APP: Released API 30
160 // DEV: Released API 20
161 verifyComputeMinSdkVersion(NEWER_VERSION, RELEASED, true, -1);
162
163 // Don't allow older pre-release minSdkVersion on released platform.
164 // APP: Pre-release API 10
165 // DEV: Released API 20
166 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000167 verifyComputeMinSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500168
169 // Don't allow same pre-release minSdkVersion on released platform.
170 // APP: Pre-release API 20
171 // DEV: Released API 20
172 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000173 verifyComputeMinSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1);
174
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500175
176 // Don't allow newer pre-release minSdkVersion on released platform.
177 // APP: Pre-release API 30
178 // DEV: Released API 20
179 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000180 verifyComputeMinSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500181 }
182
183 private void verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000184 boolean isPlatformReleased, int expectedTargetSdk) {
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500185 final String[] outError = new String[1];
186 final int result = PackageParser.computeTargetSdkVersion(
187 targetSdkVersion,
188 targetSdkCodename,
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500189 isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000190 outError);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500191
192 assertEquals(result, expectedTargetSdk);
193
194 if (expectedTargetSdk == -1) {
195 assertNotNull(outError[0]);
196 } else {
197 assertNull(outError[0]);
198 }
199 }
200
201 @Test
202 public void testComputeTargetSdkVersion_preReleasePlatform() {
203 // Do allow older release targetSdkVersion on pre-release platform.
204 // APP: Released API 10
205 // DEV: Pre-release API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000206 verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500207
208 // Do allow same release targetSdkVersion on pre-release platform.
209 // APP: Released API 20
210 // DEV: Pre-release API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000211 verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500212
213 // Do allow newer release targetSdkVersion on pre-release platform.
214 // APP: Released API 30
215 // DEV: Pre-release API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000216 verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500217
218 // Don't allow older pre-release targetSdkVersion on pre-release platform.
219 // APP: Pre-release API 10
220 // DEV: Pre-release API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000221 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1);
222 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000223
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500224
225 // Do allow same pre-release targetSdkVersion on pre-release platform,
226 // but overwrite the specified version with CUR_DEVELOPMENT.
227 // APP: Pre-release API 20
228 // DEV: Pre-release API 20
229 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000230 Build.VERSION_CODES.CUR_DEVELOPMENT);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000231 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false,
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000232 Build.VERSION_CODES.CUR_DEVELOPMENT);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000233
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500234
235 // Don't allow newer pre-release targetSdkVersion on pre-release platform.
236 // APP: Pre-release API 30
237 // DEV: Pre-release API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000238 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1);
239 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500240 }
241
242 @Test
243 public void testComputeTargetSdkVersion_releasedPlatform() {
244 // Do allow older release targetSdkVersion on released platform.
245 // APP: Released API 10
246 // DEV: Released API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000247 verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500248
249 // Do allow same release targetSdkVersion on released platform.
250 // APP: Released API 20
251 // DEV: Released API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000252 verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500253
254 // Do allow newer release targetSdkVersion on released platform.
255 // APP: Released API 30
256 // DEV: Released API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000257 verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500258
259 // Don't allow older pre-release targetSdkVersion on released platform.
260 // APP: Pre-release API 10
261 // DEV: Released API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000262 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1);
263 verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500264
265 // Don't allow same pre-release targetSdkVersion on released platform.
266 // APP: Pre-release API 20
267 // DEV: Released API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000268 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1);
269 verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1);
Narayan Kamath71fcc142019-01-15 18:20:39 +0000270
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500271
272 // Don't allow newer pre-release targetSdkVersion on released platform.
273 // APP: Pre-release API 30
274 // DEV: Released API 20
Nicholas Lativyeb23e4d2019-02-01 13:39:28 +0000275 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1);
276 verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500277 }
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800278
279 /**
280 * Unit test for PackageParser.getActivityConfigChanges().
281 * If the bit is 1 in the original configChanges, it is still 1 in the final configChanges.
282 * If the bit is 0 in the original configChanges and the bit is not set to 1 in
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700283 * recreateOnConfigChanges, the bit is changed to 1 in the final configChanges by default.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800284 */
285 @Test
286 public void testGetActivityConfigChanges() {
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700287 // Not set in either configChanges or recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800288 int configChanges = 0x0000; // 00000000.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700289 int recreateOnConfigChanges = 0x0000; // 00000000.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800290 int finalConfigChanges =
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700291 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800292 assertEquals(0x0003, finalConfigChanges); // Should be 00000011.
293
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700294 // Not set in configChanges, but set in recreateOnConfigChanges.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800295 configChanges = 0x0000; // 00000000.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700296 recreateOnConfigChanges = 0x0003; // 00000011.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800297 finalConfigChanges =
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700298 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800299 assertEquals(0x0000, finalConfigChanges); // Should be 00000000.
300
301 // Set in configChanges.
302 configChanges = 0x0003; // 00000011.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700303 recreateOnConfigChanges = 0X0000; // 00000000.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800304 finalConfigChanges =
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700305 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800306 assertEquals(0x0003, finalConfigChanges); // Should be 00000011.
307
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700308 recreateOnConfigChanges = 0x0003; // 00000011.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800309 finalConfigChanges =
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700310 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800311 assertEquals(0x0003, finalConfigChanges); // Should still be 00000011.
312
313 // Other bit set in configChanges.
314 configChanges = 0x0080; // 10000000, orientation.
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700315 recreateOnConfigChanges = 0x0000; // 00000000.
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800316 finalConfigChanges =
Holly Jiuyu Sunc93c3b92017-04-28 15:34:44 -0700317 PackageParser.getActivityConfigChanges(configChanges, recreateOnConfigChanges);
Holly Jiuyu Sunb6d76952017-01-11 17:34:03 -0800318 assertEquals(0x0083, finalConfigChanges); // Should be 10000011.
319 }
Garrett Boyer52136662017-05-23 13:47:58 -0700320
321 /**
Jiyong Park5b1b7342019-01-18 09:45:17 +0900322 * Copies a specified {@code resourceId} to a file. Returns a non-null file if the copy
323 * succeeded, or {@code null} otherwise.
324 */
325 File copyRawResourceToFile(String baseName, int resourceId) throws Exception {
326 // Copy the resource to a file.
327 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
328 InputStream is = context.getResources().openRawResource(resourceId);
329 File outFile = null;
330 try {
331 outFile = new File(context.getFilesDir(), baseName);
332 assertTrue(FileUtils.copyToFile(is, outFile));
333 return outFile;
334 } catch (Exception e) {
335 if (outFile != null) {
336 outFile.delete();
337 }
338
339 return null;
340 }
341 }
342
343 /**
Garrett Boyer52136662017-05-23 13:47:58 -0700344 * Attempts to parse a package.
345 *
346 * APKs are put into coretests/apks/packageparser_*.
347 *
Winson14ff7172019-10-23 10:42:27 -0700348 * @param apkFileName temporary file name to store apk extracted from resources
Garrett Boyer52136662017-05-23 13:47:58 -0700349 * @param apkResourceId identifier of the apk as a resource
350 */
Winson14ff7172019-10-23 10:42:27 -0700351 ParsedPackage parsePackage(String apkFileName, int apkResourceId,
352 Function<ParsedPackage, ParsedPackage> converter) throws Exception {
Garrett Boyer52136662017-05-23 13:47:58 -0700353 // Copy the resource to a file.
Jiyong Park5b1b7342019-01-18 09:45:17 +0900354 File outFile = null;
Garrett Boyer52136662017-05-23 13:47:58 -0700355 try {
Jiyong Park5b1b7342019-01-18 09:45:17 +0900356 outFile = copyRawResourceToFile(apkFileName, apkResourceId);
Winson727da642020-03-10 15:25:32 -0700357 return converter.apply(new TestPackageParser2()
358 .parsePackage(outFile, 0 /* flags */, false));
Garrett Boyer52136662017-05-23 13:47:58 -0700359 } finally {
Jiyong Park5b1b7342019-01-18 09:45:17 +0900360 if (outFile != null) {
361 outFile.delete();
362 }
Garrett Boyer52136662017-05-23 13:47:58 -0700363 }
364 }
365
366 /**
367 * Asserts basic properties about a component.
368 */
Winsonf00c7552020-01-28 12:52:01 -0800369 private void assertComponent(String className, int numIntents, ParsedComponent component) {
370 assertEquals(className, component.getName());
371 assertEquals(numIntents, component.getIntents().size());
Garrett Boyer52136662017-05-23 13:47:58 -0700372 }
373
374 /**
375 * Asserts four regularly-named components of each type: one Activity, one Service, one
376 * Provider, and one Receiver.
Winson14ff7172019-10-23 10:42:27 -0700377 *
Garrett Boyer52136662017-05-23 13:47:58 -0700378 * @param template templated string with %s subbed with Activity, Service, Provider, Receiver
379 */
Winson14ff7172019-10-23 10:42:27 -0700380 private void assertOneComponentOfEachType(String template, AndroidPackage p) {
Winson6571c8a2019-10-23 17:00:42 -0700381 assertEquals(1, p.getActivities().size());
Garrett Boyer52136662017-05-23 13:47:58 -0700382 assertComponent(String.format(template, "Activity"),
Winson14ff7172019-10-23 10:42:27 -0700383 0 /* intents */, p.getActivities().get(0));
384 assertEquals(1, p.getServices().size());
Garrett Boyer52136662017-05-23 13:47:58 -0700385 assertComponent(String.format(template, "Service"),
Winson14ff7172019-10-23 10:42:27 -0700386 0 /* intents */, p.getServices().get(0));
387 assertEquals(1, p.getProviders().size());
Garrett Boyer52136662017-05-23 13:47:58 -0700388 assertComponent(String.format(template, "Provider"),
Winson14ff7172019-10-23 10:42:27 -0700389 0 /* intents */, p.getProviders().get(0));
390 assertEquals(1, p.getReceivers().size());
Garrett Boyer52136662017-05-23 13:47:58 -0700391 assertComponent(String.format(template, "Receiver"),
Winson14ff7172019-10-23 10:42:27 -0700392 0 /* intents */, p.getReceivers().get(0));
Garrett Boyer52136662017-05-23 13:47:58 -0700393 }
394
Winson14ff7172019-10-23 10:42:27 -0700395 private void assertPermission(String name, int protectionLevel, ParsedPermission permission) {
396 assertEquals(name, permission.getName());
397 assertEquals(protectionLevel, permission.getProtection());
Garrett Boyer52136662017-05-23 13:47:58 -0700398 }
399
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700400 private void assertMetadata(Bundle b, String... keysAndValues) {
401 assertTrue("Odd number of elements in keysAndValues", (keysAndValues.length % 2) == 0);
402
403 assertNotNull(b);
404 assertEquals(keysAndValues.length / 2, b.size());
405
406 for (int i = 0; i < keysAndValues.length; i += 2) {
407 final String key = keysAndValues[i];
408 final String value = keysAndValues[i + 1];
409
410 assertEquals(value, b.getString(key));
411 }
412 }
413
414 // TODO Add a "_cached" test for testMultiPackageComponents() too, after fixing b/64295061.
415 // Package.writeToParcel can't handle circular package references.
416
Garrett Boyer52136662017-05-23 13:47:58 -0700417 @Test
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700418 public void testPackageWithComponents_no_cache() throws Exception {
419 checkPackageWithComponents(p -> p);
420 }
421
422 @Test
423 public void testPackageWithComponents_cached() throws Exception {
424 checkPackageWithComponents(p ->
Winson33eacc62020-01-24 12:02:58 -0800425 PackageCacher.fromCacheEntryStatic(PackageCacher.toCacheEntryStatic(p)));
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700426 }
427
428 private void checkPackageWithComponents(
Winson14ff7172019-10-23 10:42:27 -0700429 Function<ParsedPackage, ParsedPackage> converter) throws Exception {
430 ParsedPackage p = parsePackage(
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700431 "install_complete_package_info.apk", R.raw.install_complete_package_info,
432 converter);
Garrett Boyer52136662017-05-23 13:47:58 -0700433 String packageName = "com.android.frameworks.coretests.install_complete_package_info";
434
Winson14ff7172019-10-23 10:42:27 -0700435 assertEquals(packageName, p.getPackageName());
436 assertEquals(1, p.getPermissions().size());
Garrett Boyer52136662017-05-23 13:47:58 -0700437 assertPermission(
438 "com.android.frameworks.coretests.install_complete_package_info.test_permission",
Winson14ff7172019-10-23 10:42:27 -0700439 PermissionInfo.PROTECTION_NORMAL, p.getPermissions().get(0));
Garrett Boyer52136662017-05-23 13:47:58 -0700440
phweiss26d34962019-10-29 13:37:54 +0100441 findAndRemoveAppDetailsActivity(p);
Oli Lanae2f5f32019-07-26 14:31:59 +0100442
Garrett Boyer52136662017-05-23 13:47:58 -0700443 assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", p);
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700444
Winson33eacc62020-01-24 12:02:58 -0800445 assertMetadata(p.getMetaData(),
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700446 "key1", "value1",
447 "key2", "this_is_app");
Winson14ff7172019-10-23 10:42:27 -0700448 assertMetadata(p.getActivities().get(0).getMetaData(),
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700449 "key1", "value1",
450 "key2", "this_is_activity");
Winson14ff7172019-10-23 10:42:27 -0700451 assertMetadata(p.getServices().get(0).getMetaData(),
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700452 "key1", "value1",
453 "key2", "this_is_service");
Winson14ff7172019-10-23 10:42:27 -0700454 assertMetadata(p.getReceivers().get(0).getMetaData(),
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700455 "key1", "value1",
456 "key2", "this_is_receiver");
Winson14ff7172019-10-23 10:42:27 -0700457 assertMetadata(p.getProviders().get(0).getMetaData(),
Makoto Onuki4501c61d2017-07-27 15:56:40 -0700458 "key1", "value1",
459 "key2", "this_is_provider");
phweiss26d34962019-10-29 13:37:54 +0100460
461 }
462
463 private void findAndRemoveAppDetailsActivity(ParsedPackage p) {
464 // Hidden "app details" activity is added to every package.
465 boolean foundAppDetailsActivity = false;
466 for (int i = 0; i < ArrayUtils.size(p.getActivities()); i++) {
Winsonf00c7552020-01-28 12:52:01 -0800467 if (p.getActivities().get(i).getClassName().equals(
phweiss26d34962019-10-29 13:37:54 +0100468 PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)) {
469 foundAppDetailsActivity = true;
470 p.getActivities().remove(i);
471 break;
472 }
473 }
474 assertTrue("Did not find app details activity", foundAppDetailsActivity);
475 }
476
477 @Test
478 public void testPackageWithIntentFilters_no_cache() throws Exception {
479 checkPackageWithIntentFilters(p -> p);
480 }
481
482 @Test
483 public void testPackageWithIntentFilters_cached() throws Exception {
484 checkPackageWithIntentFilters(p ->
Winson33eacc62020-01-24 12:02:58 -0800485 PackageCacher.fromCacheEntryStatic(PackageCacher.toCacheEntryStatic(p)));
phweiss26d34962019-10-29 13:37:54 +0100486 }
487
488 private void checkPackageWithIntentFilters(
489 Function<ParsedPackage, ParsedPackage> converter) throws Exception {
490 ParsedPackage p = parsePackage(
491 "install_intent_filters.apk", R.raw.install_intent_filters,
492 converter);
Winson33eacc62020-01-24 12:02:58 -0800493 String packageName = "com.android.frameworks.servicestests.install_intent_filters";
phweiss26d34962019-10-29 13:37:54 +0100494
495 assertEquals(packageName, p.getPackageName());
496
497 findAndRemoveAppDetailsActivity(p);
498
phweiss26d34962019-10-29 13:37:54 +0100499 assertEquals("Expected exactly one activity", 1, p.getActivities().size());
500 assertEquals("Expected exactly one intent filter",
Winsonf00c7552020-01-28 12:52:01 -0800501 1, p.getActivities().get(0).getIntents().size());
phweiss26d34962019-10-29 13:37:54 +0100502 assertEquals("Expected exactly one mime group in intent filter",
Winsonf00c7552020-01-28 12:52:01 -0800503 1, p.getActivities().get(0).getIntents().get(0).countMimeGroups());
phweiss26d34962019-10-29 13:37:54 +0100504 assertTrue("Did not find expected mime group 'mime_group_1'",
Winsonf00c7552020-01-28 12:52:01 -0800505 p.getActivities().get(0).getIntents().get(0).hasMimeGroup("mime_group_1"));
Garrett Boyer52136662017-05-23 13:47:58 -0700506 }
507
Jiyong Park5b1b7342019-01-18 09:45:17 +0900508 @Test
509 public void testApexPackageInfoGeneration() throws Exception {
Nikita Ioffeec673952019-06-28 15:46:04 +0100510 String apexModuleName = "com.android.tzdata.apex";
511 File apexFile = copyRawResourceToFile(apexModuleName,
Jiyong Park5b1b7342019-01-18 09:45:17 +0900512 R.raw.com_android_tzdata);
Gavin Corkeryef441722019-05-09 17:02:10 +0100513 ApexInfo apexInfo = new ApexInfo();
514 apexInfo.isActive = true;
515 apexInfo.isFactory = false;
Nikita Ioffeec673952019-06-28 15:46:04 +0100516 apexInfo.moduleName = apexModuleName;
517 apexInfo.modulePath = apexFile.getPath();
Gavin Corkeryef441722019-05-09 17:02:10 +0100518 apexInfo.versionCode = 191000070;
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +0000519 int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES;
Oli Lanc2c7a222019-07-31 15:27:22 +0100520
521 PackageParser pp = new PackageParser();
Winson14ff7172019-10-23 10:42:27 -0700522 PackageParser.Package p = pp.parsePackage(apexFile, flags, false);
Oli Lanc2c7a222019-07-31 15:27:22 +0100523 PackageParser.collectCertificates(p, false);
524 PackageInfo pi = PackageParser.generatePackageInfo(p, apexInfo, flags);
525
Winson Chiue4790152020-01-24 00:57:20 +0000526 assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName);
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000527 assertTrue(pi.applicationInfo.enabled);
528 assertEquals(28, pi.applicationInfo.targetSdkVersion);
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +0000529 assertEquals(191000070, pi.applicationInfo.longVersionCode);
530 assertNotNull(pi.applicationInfo.metaData);
531 assertEquals(apexFile.getPath(), pi.applicationInfo.sourceDir);
532 assertEquals("Bundle[{com.android.vending.derived.apk.id=1}]",
533 pi.applicationInfo.metaData.toString());
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000534
Winson Chiue4790152020-01-24 00:57:20 +0000535 assertEquals("com.google.android.tzdata", pi.packageName);
Mohammad Samiul Islam7aa7d2e2019-03-27 12:23:47 +0000536 assertEquals(191000070, pi.getLongVersionCode());
Jiyong Park5b1b7342019-01-18 09:45:17 +0900537 assertNotNull(pi.signingInfo);
538 assertTrue(pi.signingInfo.getApkContentsSigners().length > 0);
Mohammad Samiul Islam935a1562019-03-12 16:52:56 +0000539 assertTrue(pi.isApex);
Gavin Corkeryef441722019-05-09 17:02:10 +0100540 assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0);
541 assertTrue((pi.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0);
Jiyong Park5b1b7342019-01-18 09:45:17 +0900542 }
Anton Hanssonb2f709d2020-01-09 10:25:23 +0000543
544 @Test
545 public void testUsesSdk() throws Exception {
Oli Lan72ae4472020-04-14 16:50:41 +0100546 ParsedPackage pkg =
547 parsePackage("install_uses_sdk.apk_r0", R.raw.install_uses_sdk_r0, x -> x);
548 SparseIntArray minExtVers = pkg.getMinExtensionVersions();
549 assertEquals(1, minExtVers.size());
550 assertEquals(0, minExtVers.get(10000, -1));
551
Anton Hanssonb2f709d2020-01-09 10:25:23 +0000552 try {
553 parsePackage("install_uses_sdk.apk_r5", R.raw.install_uses_sdk_r5, x -> x);
554 fail("Expected parsing exception due to incompatible extension SDK version");
555 } catch (PackageParser.PackageParserException expected) {
556 assertEquals(PackageManager.INSTALL_FAILED_OLDER_SDK, expected.error);
557 }
558 try {
559 parsePackage("install_uses_sdk.apk_q0", R.raw.install_uses_sdk_q0, x -> x);
560 fail("Expected parsing exception due to non-existent extension SDK");
561 } catch (PackageParser.PackageParserException expected) {
562 assertEquals(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, expected.error);
563 }
564 try {
565 parsePackage("install_uses_sdk.apk_r", R.raw.install_uses_sdk_r, x -> x);
566 fail("Expected parsing exception due to unspecified extension SDK version");
567 } catch (PackageParser.PackageParserException expected) {
568 assertEquals(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, expected.error);
569 }
570 try {
571 parsePackage("install_uses_sdk.apk_0", R.raw.install_uses_sdk_0, x -> x);
572 fail("Expected parsing exception due to unspecified extension SDK");
573 } catch (PackageParser.PackageParserException expected) {
574 assertEquals(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, expected.error);
575 }
576
577 }
Alan Viverette82f4b263a2016-12-19 15:40:05 -0500578}