| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.compat.overrides; |
| |
| import static android.content.Intent.ACTION_PACKAGE_ADDED; |
| import static android.content.Intent.ACTION_PACKAGE_CHANGED; |
| import static android.content.Intent.ACTION_PACKAGE_REMOVED; |
| import static android.content.Intent.ACTION_USER_SWITCHED; |
| |
| import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; |
| import static com.android.server.compat.overrides.AppCompatOverridesParser.FLAG_OWNED_CHANGE_IDS; |
| import static com.android.server.compat.overrides.AppCompatOverridesParser.FLAG_REMOVE_OVERRIDES; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.anyInt; |
| import static org.mockito.ArgumentMatchers.argThat; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.Mockito.doThrow; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.when; |
| |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.app.compat.PackageOverride; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.ContextWrapper; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageManager; |
| import android.net.Uri; |
| import android.os.Handler; |
| import android.os.RemoteException; |
| import android.platform.test.annotations.Presubmit; |
| import android.provider.DeviceConfig; |
| import android.provider.DeviceConfig.Properties; |
| |
| import androidx.test.InstrumentationRegistry; |
| import androidx.test.filters.SmallTest; |
| |
| import com.android.internal.compat.CompatibilityOverrideConfig; |
| import com.android.internal.compat.CompatibilityOverridesToRemoveConfig; |
| import com.android.internal.compat.IPlatformCompat; |
| import com.android.server.testables.TestableDeviceConfig.TestableDeviceConfigRule; |
| |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.Captor; |
| import org.mockito.Mock; |
| import org.mockito.junit.MockitoJUnitRunner; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.Executor; |
| |
| /** |
| * Test class for {@link AppCompatOverridesService}. |
| * |
| * Build/Install/Run: |
| * atest FrameworksMockingServicesTests:AppCompatOverridesServiceTest |
| */ |
| @RunWith(MockitoJUnitRunner.class) |
| @SmallTest |
| @Presubmit |
| public class AppCompatOverridesServiceTest { |
| private static final String NAMESPACE_1 = "namespace_1"; |
| private static final String NAMESPACE_2 = "namespace_2"; |
| private static final String NAMESPACE_3 = "namespace_3"; |
| private static final List<String> SUPPORTED_NAMESPACES = Arrays.asList(NAMESPACE_1, |
| NAMESPACE_2, NAMESPACE_3); |
| |
| private static final String PACKAGE_1 = "com.android.test1"; |
| private static final String PACKAGE_2 = "com.android.test2"; |
| private static final String PACKAGE_3 = "com.android.test3"; |
| private static final String PACKAGE_4 = "com.android.test4"; |
| |
| private MockContext mMockContext; |
| private BroadcastReceiver mPackageReceiver; |
| private AppCompatOverridesService mService; |
| |
| @Mock |
| private PackageManager mPackageManager; |
| @Mock |
| private IPlatformCompat mPlatformCompat; |
| |
| @Captor |
| private ArgumentCaptor<CompatibilityOverrideConfig> mOverridesToAddConfigCaptor; |
| @Captor |
| private ArgumentCaptor<CompatibilityOverridesToRemoveConfig> mOverridesToRemoveConfigCaptor; |
| |
| @Rule |
| public TestableDeviceConfigRule mDeviceConfigRule = new TestableDeviceConfigRule(); |
| |
| class MockContext extends ContextWrapper { |
| MockContext(Context base) { |
| super(base); |
| } |
| |
| @Override |
| public PackageManager getPackageManager() { |
| return mPackageManager; |
| } |
| |
| @Override |
| public Executor getMainExecutor() { |
| // Run on current thread |
| return Runnable::run; |
| } |
| |
| @Override |
| @Nullable |
| public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver, |
| @NonNull IntentFilter filter, @Nullable String broadcastPermission, |
| @Nullable Handler scheduler) { |
| mPackageReceiver = receiver; |
| return null; |
| } |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| mMockContext = new MockContext( |
| InstrumentationRegistry.getInstrumentation().getTargetContext()); |
| mService = new AppCompatOverridesService(mMockContext, mPlatformCompat, |
| SUPPORTED_NAMESPACES); |
| mService.registerPackageReceiver(); |
| assertThat(mPackageReceiver).isNotNull(); |
| } |
| |
| @Test |
| public void onPropertiesChanged_removeOverridesFlagNotSet_appliesPackageOverrides() |
| throws Exception { |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 3); |
| mockGetApplicationInfoNotInstalled(PACKAGE_2); |
| mockGetApplicationInfo(PACKAGE_3, /* versionCode= */ 10); |
| mockGetApplicationInfo(PACKAGE_4, /* versionCode= */ 1); |
| |
| mService.registerDeviceConfigListeners(); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "123,456,789") |
| .setString(PACKAGE_1, "123:::true,456::1:false,456:2::true,789:::false") |
| .setString(PACKAGE_2, "123:::true") |
| .setString(PACKAGE_3, "123:1:9:true,123:10:11:false,123:11::true") |
| .setString(PACKAGE_4, "").build()); |
| |
| Map<Long, PackageOverride> addedOverrides; |
| // Package 1 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| addedOverrides = mOverridesToAddConfigCaptor.getValue().overrides; |
| assertThat(addedOverrides).hasSize(3); |
| assertThat(addedOverrides.get(123L)).isEqualTo( |
| new PackageOverride.Builder().setEnabled(true).build()); |
| assertThat(addedOverrides.get(456L)).isEqualTo( |
| new PackageOverride.Builder().setMinVersionCode(2).setEnabled(true).build()); |
| assertThat(addedOverrides.get(789L)).isEqualTo( |
| new PackageOverride.Builder().setEnabled(false).build()); |
| // Package 2 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_2)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_2)); |
| // Package 3 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_3)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_3)); |
| addedOverrides = mOverridesToAddConfigCaptor.getValue().overrides; |
| assertThat(addedOverrides).hasSize(1); |
| assertThat(addedOverrides.get(123L)).isEqualTo( |
| new PackageOverride.Builder().setMinVersionCode(10).setMaxVersionCode( |
| 11).setEnabled(false).build()); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(456L, 789L); |
| // Package 4 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_4)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_4)); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(123L, 456L, |
| 789L); |
| } |
| |
| @Test |
| public void onPropertiesChanged_ownedChangeIdsFlagNotSet_onlyAddsOverrides() |
| throws Exception { |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mService.registerDeviceConfigListeners(); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "123:::true").build()); |
| |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| assertThat(mOverridesToAddConfigCaptor.getValue().overrides.keySet()).containsExactly(123L); |
| } |
| |
| @Test |
| public void onPropertiesChanged_removeOverridesFlagSetBefore_skipsOverridesToRemove() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "123,456,789") |
| .setString(FLAG_REMOVE_OVERRIDES, PACKAGE_1 + "=123:456," + PACKAGE_2 + "=123") |
| .setString(PACKAGE_1, "123:::true") |
| .setString(PACKAGE_4, "123:::true").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_2, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_3, /* versionCode= */ 0); |
| |
| mService.registerDeviceConfigListeners(); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "123:::true,789:::false") |
| .setString(PACKAGE_2, "123:::true") |
| .setString(PACKAGE_3, "456:::true").build()); |
| |
| // Package 1 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| assertThat(mOverridesToAddConfigCaptor.getValue().overrides.keySet()).containsExactly(789L); |
| // Package 2 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_2)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_2)); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(456L, 789L); |
| // Package 3 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_3)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_3)); |
| assertThat(mOverridesToAddConfigCaptor.getValue().overrides.keySet()).containsExactly(456L); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(123L, 789L); |
| // Package 4 (not applied because it hasn't changed after the listener was added) |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_4)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_4)); |
| } |
| |
| @Test |
| public void onPropertiesChanged_removeOverridesFlagChangedNoPackageOverridesFlags_removesOnly() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "123,456,789") |
| .setString(PACKAGE_1, "") |
| .setString(PACKAGE_2, "").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_2, /* versionCode= */ 0); |
| |
| mService.registerDeviceConfigListeners(); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_REMOVE_OVERRIDES, |
| PACKAGE_1 + "=123:456," + PACKAGE_2 + "=*").build()); |
| |
| // Package 1 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, times(2)).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_1)); |
| List<CompatibilityOverridesToRemoveConfig> configs = |
| mOverridesToRemoveConfigCaptor.getAllValues(); |
| assertThat(configs.size()).isAtLeast(2); |
| assertThat(configs.get(configs.size() - 2).changeIds).containsExactly(123L, 456L); |
| assertThat(configs.get(configs.size() - 1).changeIds).containsExactly(789L); |
| // Package 2 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_2)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_2)); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(123L, 456L, |
| 789L); |
| } |
| |
| @Test |
| public void onPropertiesChanged_removeOverridesFlagAndSomePackageOverrideFlagsChanged_ok() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "123,456,789") |
| .setString(FLAG_REMOVE_OVERRIDES, PACKAGE_1 + "=123:456") |
| .setString(PACKAGE_1, "123:::true,789:::false") |
| .setString(PACKAGE_3, "456:::false,789:::true").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_2, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_3, /* versionCode= */ 0); |
| |
| mService.registerDeviceConfigListeners(); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_REMOVE_OVERRIDES, PACKAGE_2 + "=123," + PACKAGE_3 + "=789") |
| .setString(PACKAGE_2, "123:::true").build()); |
| |
| // Package 1 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_1)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_1)); |
| assertThat(mOverridesToAddConfigCaptor.getValue().overrides.keySet()).containsExactly(123L, |
| 789L); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(456L); |
| // Package 2 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_2)); |
| verify(mPlatformCompat, times(2)).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_2)); |
| List<CompatibilityOverridesToRemoveConfig> configs = |
| mOverridesToRemoveConfigCaptor.getAllValues(); |
| assertThat(configs.size()).isAtLeast(2); |
| assertThat(configs.get(configs.size() - 2).changeIds).containsExactly(123L); |
| assertThat(configs.get(configs.size() - 1).changeIds).containsExactly(456L, 789L); |
| // Package 3 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_3)); |
| verify(mPlatformCompat, times(2)).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_3)); |
| assertThat(mOverridesToAddConfigCaptor.getValue().overrides.keySet()).containsExactly(456L); |
| configs = mOverridesToRemoveConfigCaptor.getAllValues(); |
| assertThat(configs.size()).isAtLeast(2); |
| assertThat(configs.get(configs.size() - 2).changeIds).containsExactly(789L); |
| assertThat(configs.get(configs.size() - 1).changeIds).containsExactly(123L); |
| } |
| |
| @Test |
| public void onPropertiesChanged_ownedChangeIdsFlagAndSomePackageOverrideFlagsChanged_ok() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_REMOVE_OVERRIDES, PACKAGE_1 + "=*") |
| .setString(FLAG_OWNED_CHANGE_IDS, "123,456") |
| .setString(PACKAGE_1, "123:::true") |
| .setString(PACKAGE_3, "456:::false").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_2, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_3, /* versionCode= */ 0); |
| |
| mService.registerDeviceConfigListeners(); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "123,456,789") |
| .setString(PACKAGE_2, "123:::true").build()); |
| |
| // Package 1 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_1)); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(123L, 456L, |
| 789L); |
| // Package 2 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(mOverridesToAddConfigCaptor.capture(), |
| eq(PACKAGE_2)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_2)); |
| assertThat(mOverridesToAddConfigCaptor.getValue().overrides.keySet()).containsExactly(123L); |
| assertThat(mOverridesToRemoveConfigCaptor.getValue().changeIds).containsExactly(456L, 789L); |
| // Package 3 |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_3)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_3)); |
| } |
| |
| @Test |
| public void onPropertiesChanged_platformCompatThrowsExceptionForSomeCalls_skipsFailedCalls() |
| throws Exception { |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_2, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_3, /* versionCode= */ 0); |
| mockGetApplicationInfo(PACKAGE_4, /* versionCode= */ 0); |
| doThrow(new RemoteException()).when(mPlatformCompat).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_2)); |
| doThrow(new RemoteException()).when(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_3)); |
| |
| mService.registerDeviceConfigListeners(); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "123,456") |
| .setString(PACKAGE_1, "123:::true") |
| .setString(PACKAGE_2, "123:::true") |
| .setString(PACKAGE_3, "123:::true") |
| .setString(PACKAGE_4, "123:::true").build()); |
| |
| // Package 1 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(any(CompatibilityOverrideConfig.class), |
| eq(PACKAGE_1)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| // Package 2 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(any(CompatibilityOverrideConfig.class), |
| eq(PACKAGE_2)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_2)); |
| // Package 3 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(any(CompatibilityOverrideConfig.class), |
| eq(PACKAGE_3)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_3)); |
| // Package 4 |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds(any(CompatibilityOverrideConfig.class), |
| eq(PACKAGE_1)); |
| verify(mPlatformCompat).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_4)); |
| } |
| |
| @Test |
| public void packageReceiver_packageAddedIntentDataIsNull_doesNothing() throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_1, "201:::true").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, new Intent(ACTION_PACKAGE_ADDED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| @Test |
| public void packageReceiver_actionIsNull_doesNothing() throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_1, "201:::true").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, /* action= */ null)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| @Test |
| public void packageReceiver_unsupportedAction_doesNothing() throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_1, "201:::true").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_USER_SWITCHED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| @Test |
| public void packageReceiver_packageAddedIntentPackageNotInstalled_doesNothing() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_1, "201:::true").build()); |
| mockGetApplicationInfoNotInstalled(PACKAGE_1); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_ADDED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| @Test |
| public void packageReceiver_packageAddedIntentNoOverridesForPackage_doesNothing() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_2, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_3, "201:::true").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_ADDED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| @Test |
| public void packageReceiver_packageAddedIntent_appliesOverridesFromAllNamespaces() |
| throws Exception { |
| // We're adding the owned_change_ids flag to make sure it's ignored. |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "101,102,103") |
| .setString(PACKAGE_1, "101:::true") |
| .setString(PACKAGE_2, "102:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(FLAG_OWNED_CHANGE_IDS, "201,202,203") |
| .setString(PACKAGE_3, "201:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_3) |
| .setString(FLAG_OWNED_CHANGE_IDS, "301,302") |
| .setString(PACKAGE_1, "301:::true,302:::false") |
| .setString(PACKAGE_2, "302:::false").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_ADDED)); |
| |
| verify(mPlatformCompat, times(2)).putOverridesOnReleaseBuilds( |
| mOverridesToAddConfigCaptor.capture(), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| List<CompatibilityOverrideConfig> configs = mOverridesToAddConfigCaptor.getAllValues(); |
| assertThat(configs.get(0).overrides.keySet()).containsExactly(101L); |
| assertThat(configs.get(1).overrides.keySet()).containsExactly(301L, 302L); |
| } |
| |
| @Test |
| public void packageReceiver_packageChangedIntent_appliesOverrides() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "101:::true,103:::false").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_CHANGED)); |
| |
| verify(mPlatformCompat).putOverridesOnReleaseBuilds( |
| mOverridesToAddConfigCaptor.capture(), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| assertThat(mOverridesToAddConfigCaptor.getValue().overrides.keySet()).containsExactly(101L, |
| 103L); |
| } |
| |
| @Test |
| public void packageReceiver_packageAddedIntentRemoveOverridesSetForSomeNamespaces_skipsIds() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_REMOVE_OVERRIDES, PACKAGE_1 + "=103," + PACKAGE_2 + "=101") |
| .setString(PACKAGE_1, "101:::true,103:::false") |
| .setString(PACKAGE_2, "102:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_1, "201:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_3) |
| .setString(FLAG_REMOVE_OVERRIDES, PACKAGE_1 + "=301," + PACKAGE_3 + "=302") |
| .setString(PACKAGE_1, "301:::true,302:::false,303:::true") |
| .setString(PACKAGE_3, "302:::false").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_ADDED)); |
| |
| verify(mPlatformCompat, times(3)).putOverridesOnReleaseBuilds( |
| mOverridesToAddConfigCaptor.capture(), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| List<CompatibilityOverrideConfig> configs = mOverridesToAddConfigCaptor.getAllValues(); |
| assertThat(configs.get(0).overrides.keySet()).containsExactly(101L); |
| assertThat(configs.get(1).overrides.keySet()).containsExactly(201L); |
| assertThat(configs.get(2).overrides.keySet()).containsExactly(302L, 303L); |
| } |
| |
| @Test |
| public void packageReceiver_packageRemovedIntentNoOverridesForPackage_doesNothing() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "101,102") |
| .setString(PACKAGE_2, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(FLAG_OWNED_CHANGE_IDS, "201,202") |
| .setString(PACKAGE_3, "201:::true").build()); |
| mockGetApplicationInfoNotInstalled(PACKAGE_1); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_REMOVED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| @Test |
| public void packageReceiver_packageRemovedIntentPackageInstalledForAnotherUser_doesNothing() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "101,102,103") |
| .setString(PACKAGE_1, "101:::true,103:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(FLAG_OWNED_CHANGE_IDS, "201,202") |
| .setString(PACKAGE_1, "202:::false").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_REMOVED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| @Test |
| public void packageReceiver_packageRemovedIntent_removesOwnedOverridesForNamespacesWithPackage() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "101,102,103") |
| .setString(PACKAGE_1, "101:::true,103:::false") |
| .setString(PACKAGE_2, "102:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(FLAG_OWNED_CHANGE_IDS, "201") |
| .setString(PACKAGE_3, "201:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_3) |
| .setString(FLAG_OWNED_CHANGE_IDS, "301,302") |
| .setString(PACKAGE_1, "302:::false") |
| .setString(PACKAGE_2, "301:::true").build()); |
| mockGetApplicationInfoNotInstalled(PACKAGE_1); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_REMOVED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, times(2)).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_1)); |
| List<CompatibilityOverridesToRemoveConfig> configs = |
| mOverridesToRemoveConfigCaptor.getAllValues(); |
| assertThat(configs.get(0).changeIds).containsExactly(101L, 102L, 103L); |
| assertThat(configs.get(1).changeIds).containsExactly(301L, 302L); |
| } |
| |
| @Test |
| public void packageReceiver_packageRemovedIntentNoOwnedIdsForSomeNamespace_skipsNamespace() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(FLAG_OWNED_CHANGE_IDS, "101,102") |
| .setString(PACKAGE_1, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_1, "201:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_3) |
| .setString(FLAG_OWNED_CHANGE_IDS, "301") |
| .setString(PACKAGE_1, "301:::true").build()); |
| mockGetApplicationInfoNotInstalled(PACKAGE_1); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_REMOVED)); |
| |
| verify(mPlatformCompat, never()).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, times(2)).removeOverridesOnReleaseBuilds( |
| mOverridesToRemoveConfigCaptor.capture(), eq(PACKAGE_1)); |
| List<CompatibilityOverridesToRemoveConfig> configs = |
| mOverridesToRemoveConfigCaptor.getAllValues(); |
| assertThat(configs.get(0).changeIds).containsExactly(101L, 102L); |
| assertThat(configs.get(1).changeIds).containsExactly(301L); |
| } |
| |
| @Test |
| public void packageReceiver_platformCompatThrowsExceptionForSomeNamespace_skipsFailedCall() |
| throws Exception { |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_1) |
| .setString(PACKAGE_1, "101:::true").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_2) |
| .setString(PACKAGE_1, "201:::false").build()); |
| DeviceConfig.setProperties(new Properties.Builder(NAMESPACE_3) |
| .setString(PACKAGE_1, "301:::true").build()); |
| mockGetApplicationInfo(PACKAGE_1, /* versionCode= */ 0); |
| doThrow(new RemoteException()).when(mPlatformCompat).putOverridesOnReleaseBuilds( |
| argThat(config -> config.overrides.containsKey(201L)), eq(PACKAGE_1)); |
| |
| mPackageReceiver.onReceive(mMockContext, |
| createPackageIntent(PACKAGE_1, ACTION_PACKAGE_ADDED)); |
| |
| verify(mPlatformCompat, times(3)).putOverridesOnReleaseBuilds( |
| any(CompatibilityOverrideConfig.class), eq(PACKAGE_1)); |
| verify(mPlatformCompat, never()).removeOverridesOnReleaseBuilds( |
| any(CompatibilityOverridesToRemoveConfig.class), eq(PACKAGE_1)); |
| } |
| |
| private void mockGetApplicationInfo(String packageName, long versionCode) |
| throws Exception { |
| when(mPackageManager.getApplicationInfo(eq(packageName), anyInt())).thenReturn( |
| createAppInfo(versionCode)); |
| } |
| |
| private void mockGetApplicationInfoNotInstalled(String packageName) throws Exception { |
| when(mPackageManager.getApplicationInfo(eq(packageName), anyInt())) |
| .thenThrow(new PackageManager.NameNotFoundException()); |
| } |
| |
| private static ApplicationInfo createAppInfo(long versionCode) { |
| ApplicationInfo appInfo = new ApplicationInfo(); |
| appInfo.longVersionCode = versionCode; |
| return appInfo; |
| } |
| |
| private Intent createPackageIntent(String packageName, @Nullable String action) { |
| return new Intent(action, Uri.parse("package:" + packageName)); |
| } |
| } |