1 /* 2 * Copyright (C) 2008 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 package android.content.pm.cts; 18 19 import static android.content.pm.ApplicationInfo.CATEGORY_ACCESSIBILITY; 20 import static android.content.pm.ApplicationInfo.CATEGORY_MAPS; 21 import static android.content.pm.ApplicationInfo.CATEGORY_PRODUCTIVITY; 22 import static android.content.pm.ApplicationInfo.CATEGORY_UNDEFINED; 23 import static android.content.pm.ApplicationInfo.FLAG_SUPPORTS_RTL; 24 25 import static org.junit.Assert.assertArrayEquals; 26 import static org.junit.Assert.assertEquals; 27 import static org.junit.Assert.assertFalse; 28 import static org.junit.Assert.assertNotNull; 29 import static org.junit.Assert.assertNotSame; 30 import static org.junit.Assert.assertNull; 31 import static org.junit.Assert.assertSame; 32 import static org.junit.Assert.assertTrue; 33 import static org.junit.Assume.assumeFalse; 34 import static org.junit.Assume.assumeNotNull; 35 36 import android.content.Context; 37 import android.content.pm.ApplicationInfo; 38 import android.content.pm.PackageInfo; 39 import android.content.pm.PackageManager; 40 import android.content.pm.PackageManager.NameNotFoundException; 41 import android.os.Build; 42 import android.os.Environment; 43 import android.os.Parcel; 44 import android.os.Process; 45 import android.os.UserHandle; 46 import android.platform.test.annotations.AppModeFull; 47 import android.platform.test.annotations.DisabledOnRavenwood; 48 import android.platform.test.ravenwood.RavenwoodRule; 49 import android.util.StringBuilderPrinter; 50 51 import androidx.test.platform.app.InstrumentationRegistry; 52 import androidx.test.runner.AndroidJUnit4; 53 54 import com.android.compatibility.common.util.SystemUtil; 55 56 import org.junit.Rule; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 60 /** 61 * Test {@link ApplicationInfo}. 62 */ 63 @RunWith(AndroidJUnit4.class) 64 @AppModeFull // TODO(Instant) Figure out which APIs should work. 65 public class ApplicationInfoTest { 66 @Rule 67 public final RavenwoodRule mRavenwood = new RavenwoodRule(); 68 69 private static final String SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME = "com.android.cts.stub"; 70 private static final String DIRECT_BOOT_UNAWARE_PACKAGE_NAME = 71 "android.content.cts.directbootunaware"; 72 private static final String PARTIALLY_DIRECT_BOOT_AWARE_PACKAGE_NAME = 73 "android.content.cts.partiallydirectbootaware"; 74 private static final String NO_APPLICATION_PACKAGE_NAME = 75 "android.content.cts.emptytestapp.stub"; 76 77 private static final String SAMPLE_APK_BASE = "/data/local/tmp/cts/content/"; 78 79 private static final String STUB_PACKAGE_APK = SAMPLE_APK_BASE 80 + "CtsSyncAccountAccessStubs.apk"; 81 getContext()82 private Context getContext() { 83 return InstrumentationRegistry.getInstrumentation().getTargetContext(); 84 } 85 getPackageName()86 private String getPackageName() { 87 return getContext().getPackageName(); 88 } 89 90 @Test testConstructor()91 public void testConstructor() { 92 ApplicationInfo info = new ApplicationInfo(); 93 // simple test to ensure packageName is copied by copy constructor 94 // TODO: consider expanding to check all member variables 95 info.packageName = "com.example"; 96 ApplicationInfo copy = new ApplicationInfo(info); 97 assertEquals(info.packageName, copy.packageName); 98 } 99 100 @Test 101 @DisabledOnRavenwood(blockedBy = PackageManager.class) testWriteToParcel()102 public void testWriteToParcel() throws NameNotFoundException { 103 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 104 getPackageName(), PackageManager.ApplicationInfoFlags.of(0)); 105 106 Parcel p = Parcel.obtain(); 107 applicationInfo.writeToParcel(p, 0); 108 109 p.setDataPosition(0); 110 ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(p); 111 assertEquals(applicationInfo.taskAffinity, info.taskAffinity); 112 assertEquals(applicationInfo.permission, info.permission); 113 assertEquals(applicationInfo.processName, info.processName); 114 assertEquals(applicationInfo.className, info.className); 115 assertEquals(applicationInfo.theme, info.theme); 116 assertEquals(applicationInfo.flags, info.flags); 117 assertEquals(applicationInfo.sourceDir, info.sourceDir); 118 assertEquals(applicationInfo.publicSourceDir, info.publicSourceDir); 119 assertEquals(applicationInfo.sharedLibraryFiles, info.sharedLibraryFiles); 120 assertEquals(applicationInfo.dataDir, info.dataDir); 121 assertEquals(applicationInfo.uid, info.uid); 122 assertEquals(applicationInfo.enabled, info.enabled); 123 assertEquals(applicationInfo.manageSpaceActivityName, info.manageSpaceActivityName); 124 assertEquals(applicationInfo.descriptionRes, info.descriptionRes); 125 } 126 127 @Test testToString()128 public void testToString() { 129 ApplicationInfo applicationInfo = new ApplicationInfo(); 130 assertNotNull(applicationInfo.toString()); 131 } 132 133 @Test 134 @DisabledOnRavenwood(blockedBy = PackageManager.class) testDescribeContents()135 public void testDescribeContents() throws NameNotFoundException { 136 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 137 getPackageName(), PackageManager.ApplicationInfoFlags.of(0)); 138 139 assertEquals(0, applicationInfo.describeContents()); 140 } 141 142 @Test testDump()143 public void testDump() { 144 ApplicationInfo applicationInfo = new ApplicationInfo(); 145 146 StringBuilder sb = new StringBuilder(); 147 assertEquals(0, sb.length()); 148 StringBuilderPrinter p = new StringBuilderPrinter(sb); 149 150 String prefix = ""; 151 applicationInfo.dump(p, prefix); 152 assertNotNull(sb.toString()); 153 assertTrue(sb.length() > 0); 154 } 155 156 @Test 157 @DisabledOnRavenwood(blockedBy = PackageManager.class) testLoadDescription()158 public void testLoadDescription() throws NameNotFoundException { 159 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 160 getPackageName(), PackageManager.ApplicationInfoFlags.of(0)); 161 162 assertNull(applicationInfo.loadDescription(getContext().getPackageManager())); 163 164 final int resHelloWorld = getContext().getResources() 165 .getIdentifier("hello_world", "string", getContext().getPackageName()); 166 applicationInfo.descriptionRes = resHelloWorld; 167 assertEquals(getContext().getResources().getString(resHelloWorld), 168 applicationInfo.loadDescription(getContext().getPackageManager())); 169 } 170 171 @Test 172 @DisabledOnRavenwood(blockedBy = PackageManager.class) verifyOwnInfo()173 public void verifyOwnInfo() throws NameNotFoundException { 174 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 175 getPackageName(), PackageManager.ApplicationInfoFlags.of(0)); 176 177 assertEquals("Android TestCase", applicationInfo.nonLocalizedLabel); 178 final int resSize4848 = getContext().getResources() 179 .getIdentifier("size_48x48", "drawable", getContext().getPackageName()); 180 assertEquals(resSize4848, applicationInfo.icon); 181 assertEquals("android.content.cts.MockApplication", applicationInfo.name); 182 int flags = FLAG_SUPPORTS_RTL; 183 assertEquals(flags, applicationInfo.flags & flags); 184 assertEquals(CATEGORY_PRODUCTIVITY, applicationInfo.category); 185 } 186 installPackage(String apkPath)187 private void installPackage(String apkPath) { 188 assertEquals("Success\n", SystemUtil.runShellCommand( 189 "pm install -t " + apkPath)); 190 } 191 192 @Test 193 @DisabledOnRavenwood(blockedBy = PackageManager.class) verifyDefaultValues()194 public void verifyDefaultValues() throws NameNotFoundException { 195 // Make sure we install the original version of com.android.cts.stub. 196 installPackage(STUB_PACKAGE_APK); 197 198 // The application "com.android.cts.stub" does not have any attributes set 199 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 200 SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, PackageManager.ApplicationInfoFlags.of(0)); 201 int currentUserId = Process.myUserHandle().getIdentifier(); 202 203 assertNull(applicationInfo.className); 204 assertNull(applicationInfo.permission); 205 assertEquals(SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, applicationInfo.packageName); 206 assertEquals(SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, applicationInfo.processName); 207 assertEquals(SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, applicationInfo.taskAffinity); 208 assertTrue(UserHandle.isApp(applicationInfo.uid)); 209 assertEquals(0, applicationInfo.theme); 210 assertEquals(0, applicationInfo.requiresSmallestWidthDp); 211 assertEquals(0, applicationInfo.compatibleWidthLimitDp); 212 assertEquals(0, applicationInfo.largestWidthLimitDp); 213 assertNotNull(applicationInfo.sourceDir); 214 assertEquals(applicationInfo.sourceDir, applicationInfo.publicSourceDir); 215 assertNull(applicationInfo.splitSourceDirs); 216 assertArrayEquals(applicationInfo.splitSourceDirs, applicationInfo.splitPublicSourceDirs); 217 assertEquals("/data/user/" + currentUserId + "/" + SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, 218 applicationInfo.dataDir); 219 assertEquals("/data/user_de/" + currentUserId + "/" + SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, 220 applicationInfo.deviceProtectedDataDir); 221 assertEquals("/data/user/" + currentUserId + "/" + SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, 222 applicationInfo.credentialProtectedDataDir); 223 assertNull(applicationInfo.sharedLibraryFiles); 224 assertTrue(applicationInfo.enabled); 225 assertNull(applicationInfo.manageSpaceActivityName); 226 assertEquals(0, applicationInfo.descriptionRes); 227 assertEquals(0, applicationInfo.uiOptions); 228 assertEquals(CATEGORY_UNDEFINED, applicationInfo.category); 229 assertFalse(applicationInfo.hasFragileUserData()); 230 } 231 232 @Test(expected=IllegalArgumentException.class) 233 @DisabledOnRavenwood(blockedBy = PackageManager.class) setOwnAppCategory()234 public void setOwnAppCategory() throws Exception { 235 getContext().getPackageManager().setApplicationCategoryHint(getContext().getPackageName(), 236 CATEGORY_MAPS); 237 } 238 239 @Test(expected=IllegalArgumentException.class) 240 @DisabledOnRavenwood(blockedBy = PackageManager.class) setAppCategoryByNotInstaller()241 public void setAppCategoryByNotInstaller() throws Exception { 242 getContext().getPackageManager().setApplicationCategoryHint( 243 SYNC_ACCOUNT_ACCESS_STUB_PACKAGE_NAME, CATEGORY_MAPS); 244 } 245 246 @Test 247 @DisabledOnRavenwood(blockedBy = PackageManager.class) testDirectBootUnawareAppIsNotEncryptionAware()248 public void testDirectBootUnawareAppIsNotEncryptionAware() throws Exception { 249 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 250 DIRECT_BOOT_UNAWARE_PACKAGE_NAME, PackageManager.ApplicationInfoFlags.of(0)); 251 assertFalse(applicationInfo.isEncryptionAware()); 252 } 253 254 @Test 255 @DisabledOnRavenwood(blockedBy = PackageManager.class) testDirectBootUnawareAppCategoryIsAccessibility()256 public void testDirectBootUnawareAppCategoryIsAccessibility() throws Exception { 257 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 258 DIRECT_BOOT_UNAWARE_PACKAGE_NAME, PackageManager.ApplicationInfoFlags.of(0)); 259 assertEquals(CATEGORY_ACCESSIBILITY, applicationInfo.category); 260 } 261 262 @Test 263 @DisabledOnRavenwood(blockedBy = PackageManager.class) testDefaultAppCategoryIsUndefined()264 public void testDefaultAppCategoryIsUndefined() throws Exception { 265 final ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 266 NO_APPLICATION_PACKAGE_NAME, PackageManager.ApplicationInfoFlags.of(0)); 267 assertEquals(CATEGORY_UNDEFINED, applicationInfo.category); 268 } 269 270 @Test 271 @DisabledOnRavenwood(blockedBy = PackageManager.class) testPartiallyDirectBootAwareAppIsEncryptionAware()272 public void testPartiallyDirectBootAwareAppIsEncryptionAware() throws Exception { 273 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 274 PARTIALLY_DIRECT_BOOT_AWARE_PACKAGE_NAME, 275 PackageManager.ApplicationInfoFlags.of(0)); 276 assertTrue(applicationInfo.isEncryptionAware()); 277 } 278 279 @Test 280 @DisabledOnRavenwood(blockedBy = PackageManager.class) testWriteToParcelDontSquash()281 public void testWriteToParcelDontSquash() throws Exception { 282 // Make sure ApplicationInfo.writeToParcel() doesn't do the "squashing", 283 // because Parcel.allowSquashing() isn't called. 284 285 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 286 getPackageName(), PackageManager.ApplicationInfoFlags.of(0)); 287 288 final Parcel p = Parcel.obtain(); 289 applicationInfo.writeToParcel(p, 0); 290 applicationInfo.writeToParcel(p, 0); 291 292 // Don't call Parcel.allowSquashing() 293 294 p.setDataPosition(0); 295 final ApplicationInfo copy1 = ApplicationInfo.CREATOR.createFromParcel(p); 296 final ApplicationInfo copy2 = ApplicationInfo.CREATOR.createFromParcel(p); 297 298 p.recycle(); 299 300 assertNotSame(applicationInfo, copy1); 301 302 // writeToParcel() doesn't do the squashing, so copy1 and copy2 will be different. 303 assertNotSame(copy1, copy2); 304 305 // Check several fields to make sure they're properly copied. 306 assertEquals(applicationInfo.packageName, copy2.packageName); 307 assertEquals(copy1.packageName, copy2.packageName); 308 309 assertEquals(applicationInfo.flags, copy2.flags); 310 assertEquals(copy1.flags, copy2.flags); 311 } 312 313 @Test 314 @DisabledOnRavenwood(blockedBy = PackageManager.class) testWriteToParcelSquash()315 public void testWriteToParcelSquash() throws Exception { 316 // Make sure ApplicationInfo.writeToParcel() does the "squashing", after 317 // Parcel.allowSquashing() is called. 318 319 ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo( 320 getPackageName(), PackageManager.ApplicationInfoFlags.of(0)); 321 322 final Parcel p = Parcel.obtain(); 323 324 final boolean prevSquashing = p.allowSquashing(); // Allow squashing. 325 326 applicationInfo.writeToParcel(p, 0); 327 applicationInfo.writeToParcel(p, 0); 328 329 p.setDataPosition(0); 330 final ApplicationInfo copy1 = ApplicationInfo.CREATOR.createFromParcel(p); 331 final ApplicationInfo copy2 = ApplicationInfo.CREATOR.createFromParcel(p); 332 333 p.recycle(); 334 335 assertNotSame(applicationInfo, copy1); 336 assertSame(copy1, copy2); // 337 338 p.restoreAllowSquashing(prevSquashing); 339 } 340 341 @Test 342 @DisabledOnRavenwood(blockedBy = PackageManager.class) testIsProduct()343 public void testIsProduct() throws Exception { 344 // The product flag is supported since P. Suppose that devices lauch on Android P may not 345 // have product partition. 346 assumeFalse(Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.P); 347 348 final String systemPath = Environment.getRootDirectory().getAbsolutePath(); 349 final String productPath = Environment.getProductDirectory().getAbsolutePath(); 350 final String packageName = getPartitionFirstPackageName(systemPath, productPath); 351 assertNotNull("Can not find any product packages on " + productPath + " or " 352 + systemPath + productPath, packageName); 353 354 final PackageInfo info = getContext().getPackageManager().getPackageInfo( 355 packageName.trim(), 0 /* flags */); 356 assertTrue(packageName + " is not product package.", info.applicationInfo.isProduct()); 357 } 358 359 @Test 360 @DisabledOnRavenwood(blockedBy = PackageManager.class) testIsVendor()361 public void testIsVendor() throws Exception { 362 final String systemPath = Environment.getRootDirectory().getAbsolutePath(); 363 final String vendorPath = Environment.getVendorDirectory().getAbsolutePath(); 364 final String packageName = getPartitionFirstPackageName(systemPath, vendorPath); 365 // vendor package may not exist in every builds 366 assumeNotNull(packageName); 367 368 final PackageInfo info = getContext().getPackageManager().getPackageInfo( 369 packageName.trim(), PackageManager.PackageInfoFlags.of(0)); 370 assertTrue(packageName + " is not vendor package.", info.applicationInfo.isVendor()); 371 } 372 373 @Test 374 @DisabledOnRavenwood(blockedBy = PackageManager.class) testIsOem()375 public void testIsOem() throws Exception { 376 final String systemPath = Environment.getRootDirectory().getAbsolutePath(); 377 final String oemPath = Environment.getOemDirectory().getAbsolutePath(); 378 final String packageName = getPartitionFirstPackageName(systemPath, oemPath); 379 // Oem package may not exist in every builds like aosp. 380 assumeNotNull(packageName); 381 382 final PackageInfo info = getContext().getPackageManager().getPackageInfo( 383 packageName.trim(), PackageManager.PackageInfoFlags.of(0)); 384 assertTrue(packageName + " is not oem package.", info.applicationInfo.isOem()); 385 } 386 getPartitionFirstPackageName(final String system, final String partition)387 private String getPartitionFirstPackageName(final String system, final String partition) 388 throws Exception { 389 // List package with "-f" option which contains package direction, use that to distinguish 390 // package partition and find out target package. 391 final String output = SystemUtil.runShellCommand( 392 InstrumentationRegistry.getInstrumentation(), "pm list package -f -s"); 393 final String[] packages = output.split("package:"); 394 assertTrue("No system packages.", packages.length > 0); 395 396 for (int i = 0; i < packages.length; i++) { 397 // Split package info to direction and name. 398 String[] info = packages[i].split("\\.apk="); 399 if (info.length != 2) continue; // Package info need include direction and name. 400 if (info[0] != null 401 && (info[0].startsWith(partition + "/") || info[0].startsWith(system + partition + "/"))) { 402 return info[1]; // Package name. 403 } 404 } 405 return null; 406 } 407 } 408