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