1 package android.content.pm; 2 3 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 4 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 5 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 6 import static android.content.pm.PackageManager.DONT_KILL_APP; 7 import static android.content.pm.PackageManager.GET_ACTIVITIES; 8 import static android.content.pm.PackageManager.GET_RESOLVED_FILTER; 9 import static android.content.pm.PackageManager.GET_SERVICES; 10 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; 11 import static android.os.Build.VERSION_CODES.O; 12 import static com.google.common.truth.Truth.assertThat; 13 import static org.junit.Assert.fail; 14 15 import android.content.ComponentName; 16 import android.content.Context; 17 import android.content.Intent; 18 import android.content.pm.PackageManager.NameNotFoundException; 19 import androidx.test.core.app.ApplicationProvider; 20 import androidx.test.ext.junit.runners.AndroidJUnit4; 21 import androidx.test.filters.SdkSuppress; 22 import java.util.ArrayList; 23 import java.util.List; 24 import org.junit.After; 25 import org.junit.Before; 26 import org.junit.Test; 27 import org.junit.runner.RunWith; 28 import org.robolectric.annotation.Config; 29 import org.robolectric.annotation.internal.DoNotInstrument; 30 import org.robolectric.testapp.TestService; 31 32 /** Compatibility test for {@link PackageManager} */ 33 @DoNotInstrument 34 @RunWith(AndroidJUnit4.class) 35 public final class PackageManagerTest { 36 private Context context; 37 private PackageManager pm; 38 39 @Before setup()40 public void setup() throws Exception { 41 context = ApplicationProvider.getApplicationContext(); 42 pm = context.getPackageManager(); 43 } 44 45 @After tearDown()46 public void tearDown() { 47 pm.setApplicationEnabledSetting( 48 context.getPackageName(), COMPONENT_ENABLED_STATE_DEFAULT, DONT_KILL_APP); 49 pm.setComponentEnabledSetting( 50 new ComponentName(context, "org.robolectric.testapp.TestActivity"), 51 COMPONENT_ENABLED_STATE_DEFAULT, 52 DONT_KILL_APP); 53 pm.setComponentEnabledSetting( 54 new ComponentName(context, "org.robolectric.testapp.DisabledTestActivity"), 55 COMPONENT_ENABLED_STATE_DEFAULT, 56 DONT_KILL_APP); 57 } 58 59 @Test 60 @Config(minSdk = O) 61 @SdkSuppress(minSdkVersion = O) isInstantApp_shouldNotBlowup()62 public void isInstantApp_shouldNotBlowup() { 63 assertThat(context.getPackageManager().isInstantApp()).isFalse(); 64 } 65 66 @Test getPackageInfo()67 public void getPackageInfo() throws Exception { 68 PackageInfo info = 69 pm.getPackageInfo( 70 context.getPackageName(), MATCH_DISABLED_COMPONENTS | GET_ACTIVITIES | GET_SERVICES); 71 ActivityInfo[] activities = filterExtraneous(info.activities); 72 73 assertThat(activities).hasLength(4); 74 assertThat(info.services).hasLength(1); 75 76 assertThat(activities[0].name).isEqualTo("org.robolectric.testapp.TestActivity"); 77 assertThat(activities[0].enabled).isTrue(); 78 assertThat(activities[1].name).isEqualTo("org.robolectric.testapp.DisabledTestActivity"); 79 assertThat(activities[1].enabled).isFalse(); 80 81 assertThat(info.services[0].name).isEqualTo("org.robolectric.testapp.TestService"); 82 assertThat(info.services[0].enabled).isTrue(); 83 } 84 85 @Test getPackageInfo_noFlagsGetNoComponents()86 public void getPackageInfo_noFlagsGetNoComponents() throws Exception { 87 PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0); 88 assertThat(info.activities).isNull(); 89 assertThat(info.services).isNull(); 90 } 91 92 @Test getPackageInfo_skipsDisabledComponents()93 public void getPackageInfo_skipsDisabledComponents() throws Exception { 94 PackageInfo info = pm.getPackageInfo(context.getPackageName(), GET_ACTIVITIES); 95 ActivityInfo[] activities = filterExtraneous(info.activities); 96 97 assertThat(activities).hasLength(3); 98 assertThat(activities[0].name).isEqualTo("org.robolectric.testapp.TestActivity"); 99 } 100 101 @Test getComponent_partialName()102 public void getComponent_partialName() { 103 ComponentName serviceName = new ComponentName(context, ".TestService"); 104 105 try { 106 pm.getServiceInfo(serviceName, 0); 107 fail("Expected NameNotFoundException"); 108 } catch (NameNotFoundException expected) { 109 } 110 } 111 112 @Test getComponent_wrongNameActivity()113 public void getComponent_wrongNameActivity() { 114 ComponentName activityName = new ComponentName(context, "WrongNameActivity"); 115 116 try { 117 pm.getActivityInfo(activityName, 0); 118 fail("Expected NameNotFoundException"); 119 } catch (NameNotFoundException expected) { 120 } 121 } 122 123 @Test getComponent_validName()124 public void getComponent_validName() throws Exception { 125 ComponentName componentName = new ComponentName(context, "org.robolectric.testapp.TestService"); 126 ServiceInfo info = pm.getServiceInfo(componentName, 0); 127 128 assertThat(info).isNotNull(); 129 } 130 131 @Test getComponent_validName_queryWithMoreFlags()132 public void getComponent_validName_queryWithMoreFlags() throws Exception { 133 ComponentName componentName = new ComponentName(context, "org.robolectric.testapp.TestService"); 134 ServiceInfo info = pm.getServiceInfo(componentName, MATCH_DISABLED_COMPONENTS); 135 136 assertThat(info).isNotNull(); 137 } 138 139 @Test queryIntentServices_noFlags()140 public void queryIntentServices_noFlags() { 141 List<ResolveInfo> result = pm.queryIntentServices(new Intent(context, TestService.class), 0); 142 143 assertThat(result).hasSize(1); 144 } 145 146 @Test getComponent_disabledComponent_doesntInclude()147 public void getComponent_disabledComponent_doesntInclude() { 148 ComponentName disabledActivityName = 149 new ComponentName(context, "org.robolectric.testapp.DisabledTestActivity"); 150 151 try { 152 pm.getActivityInfo(disabledActivityName, 0); 153 fail("NameNotFoundException expected"); 154 } catch (NameNotFoundException expected) { 155 } 156 } 157 158 @Test getComponent_disabledComponent_include()159 public void getComponent_disabledComponent_include() throws Exception { 160 ComponentName disabledActivityName = 161 new ComponentName(context, "org.robolectric.testapp.DisabledTestActivity"); 162 163 ActivityInfo info = pm.getActivityInfo(disabledActivityName, MATCH_DISABLED_COMPONENTS); 164 assertThat(info).isNotNull(); 165 assertThat(info.enabled).isFalse(); 166 } 167 168 @Test getPackageInfo_programmaticallyDisabledComponent_noFlags_notReturned()169 public void getPackageInfo_programmaticallyDisabledComponent_noFlags_notReturned() { 170 ComponentName activityName = new ComponentName(context, "org.robolectric.testapp.TestActivity"); 171 pm.setComponentEnabledSetting(activityName, COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP); 172 173 try { 174 pm.getActivityInfo(activityName, 0); 175 fail("NameNotFoundException expected"); 176 } catch (NameNotFoundException expected) { 177 } 178 } 179 180 @Test getPackageInfo_programmaticallyDisabledComponent_withFlags_returned()181 public void getPackageInfo_programmaticallyDisabledComponent_withFlags_returned() 182 throws Exception { 183 ComponentName activityName = new ComponentName(context, "org.robolectric.testapp.TestActivity"); 184 pm.setComponentEnabledSetting(activityName, COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP); 185 186 ActivityInfo info = pm.getActivityInfo(activityName, MATCH_DISABLED_COMPONENTS); 187 assertThat(info).isNotNull(); 188 // WHAT?? Seems like we always get the manifest value for ComponentInfo.enabled 189 assertThat(info.enabled).isTrue(); 190 assertThat(info.isEnabled()).isTrue(); 191 } 192 193 @Test getPackageInfo_programmaticallyEnabledComponent_returned()194 public void getPackageInfo_programmaticallyEnabledComponent_returned() throws Exception { 195 ComponentName activityName = 196 new ComponentName(context, "org.robolectric.testapp.DisabledTestActivity"); 197 pm.setComponentEnabledSetting(activityName, COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP); 198 199 ActivityInfo info = pm.getActivityInfo(activityName, 0); 200 assertThat(info).isNotNull(); 201 // WHAT?? Seems like we always get the manifest value for ComponentInfo.enabled 202 assertThat(info.enabled).isFalse(); 203 assertThat(info.isEnabled()).isFalse(); 204 } 205 206 @Test 207 @Config(maxSdk = 23) 208 @SdkSuppress(maxSdkVersion = 23) getPackageInfo_disabledApplication_stillReturned_below24()209 public void getPackageInfo_disabledApplication_stillReturned_below24() throws Exception { 210 pm.setApplicationEnabledSetting( 211 context.getPackageName(), COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP); 212 213 PackageInfo packageInfo = 214 pm.getPackageInfo(context.getPackageName(), GET_SERVICES | GET_ACTIVITIES); 215 ActivityInfo[] activities = filterExtraneous(packageInfo.activities); 216 217 assertThat(packageInfo.packageName).isEqualTo(context.getPackageName()); 218 assertThat(packageInfo.applicationInfo.enabled).isFalse(); 219 220 // Seems that although disabled app makes everything disabled it is still returned with its 221 // manifest state below API 23 222 assertThat(activities).hasLength(3); 223 assertThat(packageInfo.services).hasLength(1); 224 225 assertThat(activities[0].enabled).isTrue(); 226 assertThat(packageInfo.services[0].enabled).isTrue(); 227 assertThat(activities[0].isEnabled()).isFalse(); 228 assertThat(packageInfo.services[0].isEnabled()).isFalse(); 229 } 230 231 @Test 232 @Config(minSdk = 24) 233 @SdkSuppress(minSdkVersion = 24) getPackageInfo_disabledApplication_stillReturned_after24()234 public void getPackageInfo_disabledApplication_stillReturned_after24() throws Exception { 235 pm.setApplicationEnabledSetting( 236 context.getPackageName(), COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP); 237 238 PackageInfo packageInfo = 239 pm.getPackageInfo(context.getPackageName(), GET_SERVICES | GET_ACTIVITIES); 240 241 assertThat(packageInfo.packageName).isEqualTo(context.getPackageName()); 242 assertThat(packageInfo.applicationInfo.enabled).isFalse(); 243 244 // seems that since API 24 it is isEnabled() and not enabled that gets something into default 245 // result 246 assertThat(packageInfo.activities).isNull(); 247 assertThat(packageInfo.services).isNull(); 248 } 249 250 @Test getPackageInfo_disabledApplication_withFlags_returnedEverything()251 public void getPackageInfo_disabledApplication_withFlags_returnedEverything() throws Exception { 252 pm.setApplicationEnabledSetting( 253 context.getPackageName(), COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP); 254 255 PackageInfo packageInfo = 256 pm.getPackageInfo( 257 context.getPackageName(), 258 GET_SERVICES | GET_ACTIVITIES | MATCH_DISABLED_COMPONENTS); 259 ActivityInfo[] activities = filterExtraneous(packageInfo.activities); 260 261 assertThat(packageInfo.applicationInfo.enabled).isFalse(); 262 assertThat(packageInfo.packageName).isEqualTo(context.getPackageName()); 263 assertThat(activities).hasLength(4); 264 assertThat(packageInfo.services).hasLength(1); 265 assertThat(activities[0].enabled).isTrue(); // default enabled flag 266 } 267 268 @Test getApplicationInfo_disabledApplication_stillReturnedWithNoFlags()269 public void getApplicationInfo_disabledApplication_stillReturnedWithNoFlags() throws Exception { 270 pm.setApplicationEnabledSetting( 271 context.getPackageName(), COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP); 272 273 ApplicationInfo applicationInfo = pm.getApplicationInfo(context.getPackageName(), 0); 274 275 assertThat(applicationInfo.enabled).isFalse(); 276 assertThat(applicationInfo.packageName).isEqualTo(context.getPackageName()); 277 } 278 279 @Test queryIntentActivities_packageOnly()280 public void queryIntentActivities_packageOnly() { 281 List<ResolveInfo> resolveInfos = 282 pm.queryIntentActivities( 283 new Intent().setPackage(context.getPackageName()), 284 MATCH_DISABLED_COMPONENTS | GET_RESOLVED_FILTER); 285 286 for (ResolveInfo resolveInfo : resolveInfos) { 287 assertThat(resolveInfo.filter).isNotNull(); 288 } 289 } 290 filterExtraneous(ActivityInfo[] activities)291 private ActivityInfo[] filterExtraneous(ActivityInfo[] activities) { 292 List<ActivityInfo> filtered = new ArrayList<>(); 293 for (ActivityInfo activity : activities) { 294 if (activity.name.startsWith("org.robolectric")) { 295 filtered.add(activity); 296 } 297 } 298 return filtered.toArray(new ActivityInfo[0]); 299 } 300 } 301