1 /* 2 * Copyright (C) 2016 Google Inc. 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.os.cts; 18 19 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; 20 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 21 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; 22 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 26 import android.content.Intent; 27 import android.content.pm.ApplicationInfo; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageManager; 30 import android.content.pm.ResolveInfo; 31 import android.net.Uri; 32 import android.platform.test.annotations.AppModeFull; 33 import android.platform.test.annotations.AppModeInstant; 34 35 import androidx.test.InstrumentationRegistry; 36 import androidx.test.runner.AndroidJUnit4; 37 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import java.util.List; 42 43 /** 44 * Tests whether all platform components that are implemented 45 * as APKs for various reasons are present. 46 */ 47 @RunWith(AndroidJUnit4.class) 48 public class RequiredComponentsTest { 49 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 50 51 @AppModeFull 52 @Test 53 public void testPackageInstallerPresent() throws Exception { 54 Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE); 55 installerIntent.addCategory(Intent.CATEGORY_DEFAULT); 56 installerIntent.setDataAndType(Uri.parse("content://com.example/"), PACKAGE_MIME_TYPE); 57 List<ResolveInfo> installers = InstrumentationRegistry.getContext() 58 .getPackageManager().queryIntentActivities(installerIntent, MATCH_SYSTEM_ONLY 59 | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE); 60 if (installers.size() == 1) { 61 ResolveInfo resolveInfo = installers.get(0); 62 if (!resolveInfo.activityInfo.applicationInfo.isPrivilegedApp()) { 63 fail("The installer must be a privileged app"); 64 } 65 } else { 66 fail("There must be exactly one installer; found " + installers); 67 } 68 } 69 70 @AppModeFull 71 @Test 72 public void testExtServicesPresent() throws Exception { 73 enforceSharedLibPresentAndProperlyHosted( 74 PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES, 75 ApplicationInfo.FLAG_SYSTEM, 76 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); 77 } 78 79 @AppModeFull 80 @Test 81 public void testSharedServicesPresent() throws Exception { 82 enforceSharedLibPresentAndProperlyHosted( 83 PackageManager.SYSTEM_SHARED_LIBRARY_SHARED, 84 ApplicationInfo.FLAG_SYSTEM, 0); 85 } 86 87 @AppModeInstant 88 @Test 89 public void testNoPackageInfoAccess() { 90 try { 91 final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager(); 92 final String packageName = pm.getServicesSystemSharedLibraryPackageName(); 93 pm.getPackageInfo(packageName, 0); 94 fail("Instant app was able to fetch package info."); 95 } catch (PackageManager.NameNotFoundException ex) { 96 // Expected 97 } 98 } 99 100 @AppModeInstant 101 @Test 102 public void testNoPackageInstallerPresent() { 103 final Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE); 104 installerIntent.addCategory(Intent.CATEGORY_DEFAULT); 105 installerIntent.setDataAndType(Uri.parse("content://com.example/"), PACKAGE_MIME_TYPE); 106 final List<ResolveInfo> installers = InstrumentationRegistry.getContext() 107 .getPackageManager().queryIntentActivities(installerIntent, MATCH_SYSTEM_ONLY 108 | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE); 109 if (installers.size() != 0) { 110 fail("Instant app was able to get installer."); 111 } 112 } 113 114 private void enforceSharedLibPresentAndProperlyHosted(String libName, 115 int requiredHostAppFlags, int requiredHostAppPrivateFlags) throws Exception { 116 PackageManager packageManager = InstrumentationRegistry.getContext() 117 .getPackageManager(); 118 119 // Is the lib present? 120 String[] libs = packageManager.getSystemSharedLibraryNames(); 121 boolean libPresent = false; 122 for (String lib : libs) { 123 if (libName.equals(lib)) { 124 libPresent = true; 125 break; 126 } 127 } 128 if (!libPresent) { 129 fail("Missing required shared library:" + libName); 130 } 131 132 // Is it properly hosted? 133 String packageName = packageManager.getServicesSystemSharedLibraryPackageName(); 134 PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0); 135 136 assertTrue(libName + " must be hosted by a system app with flags:" 137 + requiredHostAppFlags, (packageInfo.applicationInfo.flags 138 & requiredHostAppFlags) == requiredHostAppFlags); 139 140 assertTrue(libName + " must be hosted by a system app with private flags:" 141 + requiredHostAppPrivateFlags, (packageInfo.applicationInfo.privateFlags 142 & requiredHostAppPrivateFlags) == requiredHostAppPrivateFlags); 143 } 144 } 145