diff options
Diffstat (limited to 'services/tests')
17 files changed, 739 insertions, 71 deletions
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java index ee0a16a70265..2e0cadf264cf 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.pm.dex; @@ -28,28 +28,34 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.os.BatteryManager; import android.os.Build; +import android.os.PowerManager; import android.os.UserHandle; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.dx.mockito.inline.extended.ExtendedMockito; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.server.pm.Installer; +import com.android.server.pm.PackageManagerService; import dalvik.system.DelegateLastClassLoader; import dalvik.system.PathClassLoader; import dalvik.system.VMRuntime; +import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; import java.io.File; @@ -69,9 +75,15 @@ public class DexManagerTests { DelegateLastClassLoader.class.getName(); private static final String UNSUPPORTED_CLASS_LOADER_NAME = "unsupported.class_loader"; - @Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); + private static final int TEST_BATTERY_LEVEL_CRITICAL = 10; + private static final int TEST_BATTERY_LEVEL_DEFAULT = 80; + + public StaticMockitoSession mMockitoSession; @Mock Installer mInstaller; @Mock IPackageManager mPM; + @Mock BatteryManager mMockBatteryManager; + @Mock PowerManager mMockPowerManager; + private final Object mInstallLock = new Object(); private DexManager mDexManager; @@ -117,7 +129,37 @@ public class DexManagerTests { mSystemServerJarUpdatedContext = new TestData("android", isa, mUser0, DELEGATE_LAST_CLASS_LOADER_NAME); - mDexManager = new DexManager(/*Context*/ null, mPM, /*PackageDexOptimizer*/ null, + // Initialize Static Mocking + + mMockitoSession = ExtendedMockito.mockitoSession() + .initMocks(this) + .strictness(Strictness.LENIENT) + .startMocking(); + + // Mock.... + + mMockBatteryManager = ExtendedMockito.mock(BatteryManager.class); + mMockPowerManager = ExtendedMockito.mock(PowerManager.class); + + setDefaultMockValues(); + + Resources mockResources = ExtendedMockito.mock(Resources.class); + ExtendedMockito.when(mockResources + .getInteger(com.android.internal.R.integer.config_criticalBatteryWarningLevel)) + .thenReturn(15); + + Context mockContext = ExtendedMockito.mock(Context.class); + ExtendedMockito.doReturn(mockResources) + .when(mockContext) + .getResources(); + ExtendedMockito.doReturn(mMockBatteryManager) + .when(mockContext) + .getSystemService(BatteryManager.class); + ExtendedMockito.doReturn(mMockPowerManager) + .when(mockContext) + .getSystemService(PowerManager.class); + + mDexManager = new DexManager(mockContext, mPM, /*PackageDexOptimizer*/ null, mInstaller, mInstallLock); // Foo and Bar are available to user0. @@ -128,6 +170,25 @@ public class DexManagerTests { mDexManager.load(existingPackages); } + @After + public void teardown() throws Exception { + mMockitoSession.finishMocking(); + } + + private void setDefaultMockValues() { + ExtendedMockito.doReturn(BatteryManager.BATTERY_STATUS_DISCHARGING) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS); + + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_DEFAULT) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + ExtendedMockito.doReturn(PowerManager.THERMAL_STATUS_NONE) + .when(mMockPowerManager) + .getCurrentThermalStatus(); + } + @Test public void testNotifyPrimaryUse() { // The main dex file and splits are re-loaded by the app. @@ -633,6 +694,114 @@ public class DexManagerTests { assertNoDclInfo(mSystemServerJarInvalid); } + @Test + public void testInstallScenarioToReasonDefault() { + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonThermal() { + ExtendedMockito.doReturn(PowerManager.THERMAL_STATUS_SEVERE) + .when(mMockPowerManager) + .getCurrentThermalStatus(); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonBatteryDischarging() { + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_CRITICAL) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + + @Test + public void testInstallScenarioToReasonBatteryCharging() { + ExtendedMockito.doReturn(TEST_BATTERY_LEVEL_CRITICAL) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); + + ExtendedMockito.doReturn(BatteryManager.BATTERY_STATUS_CHARGING) + .when(mMockBatteryManager) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_STATUS); + + assertEquals( + PackageManagerService.REASON_INSTALL, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_DEFAULT)); + + assertEquals( + PackageManagerService.REASON_INSTALL_FAST, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_FAST)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK)); + + assertEquals( + PackageManagerService.REASON_INSTALL_BULK_SECONDARY, + mDexManager.getCompilationReasonForInstallScenario( + PackageManager.INSTALL_SCENARIO_BULK_SECONDARY)); + } + private void assertSecondaryUse(TestData testData, PackageUseInfo pui, List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId, String[] expectedContexts) { diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS new file mode 100644 index 000000000000..5a4431ee8c89 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/OWNERS @@ -0,0 +1,2 @@ +calin@google.com +ngeoffray@google.com diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java index 07f67327b2bf..1c9683803857 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java @@ -40,9 +40,11 @@ import android.content.pm.UserInfo; import android.net.Uri; import android.os.RemoteException; import android.os.UserManager; +import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; +import com.android.server.LocalServices; import com.android.server.SystemService; import org.junit.Before; @@ -60,6 +62,7 @@ import java.util.List; * Tests for {@link com.android.server.apphibernation.AppHibernationService} */ @SmallTest +@Presubmit public final class AppHibernationServiceTest { private static final String PACKAGE_SCHEME = "package"; private static final String PACKAGE_NAME_1 = "package1"; @@ -91,6 +94,7 @@ public final class AppHibernationServiceTest { MockitoAnnotations.initMocks(this); doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt()); + LocalServices.removeServiceForTest(AppHibernationManagerInternal.class); mAppHibernationService = new AppHibernationService(new MockInjector(mContext)); verify(mContext).registerReceiver(mReceiverCaptor.capture(), any()); diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java index 59f3c35f2137..2237c845cde7 100644 --- a/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/apphibernation/HibernationStateDiskStoreTest.java @@ -19,6 +19,7 @@ package com.android.server.apphibernation; import static org.junit.Assert.assertEquals; import android.os.FileUtils; +import android.platform.test.annotations.Presubmit; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoOutputStream; @@ -48,6 +49,7 @@ import java.util.concurrent.TimeoutException; @SmallTest +@Presubmit public class HibernationStateDiskStoreTest { private static final String STATES_FILE_NAME = "states"; private final MockScheduledExecutorService mMockScheduledExecutorService = diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java index f00edcc85404..fcd6b842426a 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java @@ -120,6 +120,11 @@ class CompatConfigBuilder { return this; } + CompatConfigBuilder addEnabledSinceApexChangeWithId(int sdk, long id) { + mChanges.add(new CompatChange(id, "", -1, sdk, false, false, "", false)); + return this; + } + CompatConfig build() { CompatConfig config = new CompatConfig(mBuildClassifier, mContext); config.forceNonDebuggableFinalForTest(false); diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java index 8b0e948579fb..bd774056aef8 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java @@ -86,6 +86,7 @@ public class CompatConfigTest { // Assume userdebug/eng non-final build when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); when(mBuildClassifier.isFinalBuild()).thenReturn(false); + when(mBuildClassifier.platformTargetSdk()).thenReturn(30); ChangeIdStateCache.disable(); when(mPackageManager.getApplicationInfo(anyString(), anyInt())) .thenThrow(new NameNotFoundException()); @@ -567,6 +568,34 @@ public class CompatConfigTest { } @Test + public void testReadApexConfig() throws IOException { + String configXml = "<config>" + + "<compat-change id=\"1234\" name=\"MY_CHANGE1\" enableAfterTargetSdk=\"2\" />" + + "<compat-change id=\"1235\" name=\"MY_CHANGE2\" disabled=\"true\" />" + + "<compat-change id=\"1236\" name=\"MY_CHANGE3\" />" + + "<compat-change id=\"1237\" name=\"MY_CHANGE4\" enableSinceTargetSdk=\"31\" />" + + "</config>"; + + File dir = createTempDir(); + writeToFile(dir, "platform_compat_config.xml", configXml); + CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext); + compatConfig.forceNonDebuggableFinalForTest(false); + + compatConfig.initConfigFromLib(dir); + + assertThat(compatConfig.isChangeEnabled(1234L, + ApplicationInfoBuilder.create().withTargetSdk(1).build())).isFalse(); + assertThat(compatConfig.isChangeEnabled(1234L, + ApplicationInfoBuilder.create().withTargetSdk(3).build())).isTrue(); + assertThat(compatConfig.isChangeEnabled(1235L, + ApplicationInfoBuilder.create().withTargetSdk(5).build())).isFalse(); + assertThat(compatConfig.isChangeEnabled(1236L, + ApplicationInfoBuilder.create().withTargetSdk(1).build())).isTrue(); + assertThat(compatConfig.isChangeEnabled(1237L, + ApplicationInfoBuilder.create().withTargetSdk(31).build())).isTrue(); + } + + @Test public void testReadConfigMultipleFiles() throws IOException { String configXml1 = "<config>" + "<compat-change id=\"1234\" name=\"MY_CHANGE1\" enableAfterTargetSdk=\"2\" />" @@ -602,12 +631,12 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) .thenReturn(ApplicationInfoBuilder.create() - .withPackageName("foo.bar") - .debuggable() - .build()); + .withPackageName("foo.bar") + .debuggable() + .build()); when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt())) .thenThrow(new NameNotFoundException()); @@ -649,7 +678,7 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L, new PackageOverride.Builder() @@ -673,11 +702,11 @@ public class CompatConfigTest { } @Test - public void testLoadOverridesRaw() throws Exception { + public void testInitOverridesRaw() throws Exception { File tempDir = createTempDir(); File overridesFile = new File(tempDir, "overrides.xml"); // Change 1 is enabled for foo.bar (validated) - // Change 2 is disabled for bar.baz (deferred) + // Change 2 is disabled for bar.baz (raw) String xmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<overrides>\n" + " <change-overrides changeId=\"1\">\n" @@ -709,7 +738,7 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .withPackageName("foo.bar") .withVersionCode(100L) @@ -728,7 +757,7 @@ public class CompatConfigTest { } @Test - public void testLoadOverridesDeferred() throws Exception { + public void testInitOverridesDeferred() throws Exception { File tempDir = createTempDir(); File overridesFile = new File(tempDir, "overrides.xml"); // Change 1 is enabled for foo.bar (validated) @@ -754,7 +783,7 @@ public class CompatConfigTest { .addEnableSinceSdkChangeWithId(2, 2L) .build(); compatConfig.forceNonDebuggableFinalForTest(true); - compatConfig.initOverrides(overridesFile); + compatConfig.initOverrides(overridesFile, new File("")); ApplicationInfo applicationInfo = ApplicationInfoBuilder.create() .withPackageName("foo.bar") .debuggable() @@ -767,4 +796,115 @@ public class CompatConfigTest { assertThat(compatConfig.isChangeEnabled(1L, applicationInfo)).isTrue(); assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse(); } + + @Test + public void testInitOverridesWithStaticFile() throws Exception { + File tempDir = createTempDir(); + File dynamicOverridesFile = new File(tempDir, "dynamic_overrides.xml"); + File staticOverridesFile = new File(tempDir, "static_overrides.xml"); + // Change 1 is enabled for foo.bar (raw) + // Change 2 is disabled for bar.baz (raw) + String dynamicXmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<overrides>" + + "<change-overrides changeId=\"1\">" + + "<raw>" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "<change-overrides changeId=\"2\">" + + "<raw>" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "</overrides>"; + writeToFile(tempDir, "dynamic_overrides.xml", dynamicXmlData); + // Change 2 is enabled for foo.bar and bar.baz (raw) + // Change 3 is enabled for bar.baz (raw) + String staticXmlData = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + + "<overrides>" + + "<change-overrides changeId=\"2\">" + + "<raw>" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "<change-overrides changeId=\"3\">" + + "<raw>" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + "</raw>" + + "</change-overrides>" + + "</overrides>"; + writeToFile(tempDir, "static_overrides.xml", staticXmlData); + CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext) + .addDisabledChangeWithId(1L) + .addDisabledChangeWithId(2L) + .addDisabledChangeWithId(3L) + .build(); + compatConfig.forceNonDebuggableFinalForTest(true); + // Adding an override that will be cleared after initOverrides is called. + compatConfig.addOverride(1L, "bar.baz", true); + compatConfig.initOverrides(dynamicOverridesFile, staticOverridesFile); + when(mPackageManager.getApplicationInfo(eq("foo.bar"), anyInt())) + .thenThrow(new NameNotFoundException()); + when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt())) + .thenThrow(new NameNotFoundException()); + + assertThat(compatConfig.willChangeBeEnabled(1L, "foo.bar")).isTrue(); + assertThat(compatConfig.willChangeBeEnabled(2L, "foo.bar")).isTrue(); + assertThat(compatConfig.willChangeBeEnabled(2L, "bar.baz")).isFalse(); + assertThat(compatConfig.willChangeBeEnabled(3L, "bar.baz")).isTrue(); + assertThat(readFile(dynamicOverridesFile)) + .isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + + "<overrides>\n" + + " <change-overrides changeId=\"1\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + " <change-overrides changeId=\"2\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"foo.bar\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"false\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + " <change-overrides changeId=\"3\">\n" + + " <validated>\n" + + " </validated>\n" + + " <raw>\n" + + " <raw-override-value packageName=\"bar.baz\" " + + "minVersionCode=\"-9223372036854775808\" " + + "maxVersionCode=\"9223372036854775807\" enabled=\"true\">\n" + + " </raw-override-value>\n" + + " </raw>\n" + + " </change-overrides>\n" + + "</overrides>\n"); + } } diff --git a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java index 0fd6445fbeeb..57fdcd340a02 100644 --- a/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/OverrideValidatorImplTest.java @@ -22,6 +22,7 @@ import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARG import static com.android.internal.compat.OverrideAllowedState.DISABLED_NOT_DEBUGGABLE; import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH; import static com.android.internal.compat.OverrideAllowedState.LOGGING_ONLY_CHANGE; +import static com.android.internal.compat.OverrideAllowedState.PLATFORM_TOO_OLD; import static com.google.common.truth.Truth.assertThat; @@ -52,6 +53,7 @@ public class OverrideValidatorImplTest { private static final int TARGET_SDK = 10; private static final int TARGET_SDK_BEFORE = 9; private static final int TARGET_SDK_AFTER = 11; + private static final int PLATFORM_SDK_VERSION = 30; @Mock private PackageManager mPackageManager; @@ -61,6 +63,7 @@ public class OverrideValidatorImplTest { private AndroidBuildClassifier debuggableBuild() { AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class); when(buildClassifier.isDebuggableBuild()).thenReturn(true); + when(buildClassifier.platformTargetSdk()).thenReturn(PLATFORM_SDK_VERSION); return buildClassifier; } @@ -68,6 +71,7 @@ public class OverrideValidatorImplTest { AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class); when(buildClassifier.isDebuggableBuild()).thenReturn(false); when(buildClassifier.isFinalBuild()).thenReturn(false); + when(buildClassifier.platformTargetSdk()).thenReturn(PLATFORM_SDK_VERSION); return buildClassifier; } @@ -75,6 +79,7 @@ public class OverrideValidatorImplTest { AndroidBuildClassifier buildClassifier = mock(AndroidBuildClassifier.class); when(buildClassifier.isDebuggableBuild()).thenReturn(false); when(buildClassifier.isFinalBuild()).thenReturn(true); + when(buildClassifier.platformTargetSdk()).thenReturn(PLATFORM_SDK_VERSION); return buildClassifier; } @@ -333,6 +338,26 @@ public class OverrideValidatorImplTest { } @Test + public void getOverrideAllowedState_targetSdkChangeGreaterThanOsVersion_rejectOverride() + throws Exception { + final AndroidBuildClassifier buildClassifier = finalBuild(); + CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) + .addEnabledSinceApexChangeWithId(PLATFORM_SDK_VERSION + 1, 1).build(); + IOverrideValidator overrideValidator = config.getOverrideValidator(); + when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) + .thenReturn(ApplicationInfoBuilder.create() + .withPackageName(PACKAGE_NAME) + .debuggable() + .build()); + + OverrideAllowedState stateTargetSdkLessChange = + overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME); + assertThat(stateTargetSdkLessChange).isEqualTo( + new OverrideAllowedState(PLATFORM_TOO_OLD, -1, + PLATFORM_SDK_VERSION)); + } + + @Test public void getOverrideAllowedState_finalBuildEnabledChangeDebugApp_rejectOverride() throws Exception { CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext) diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java index 799b06734b54..3fc6e9918382 100644 --- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java @@ -78,11 +78,12 @@ public class PlatformCompatTest { when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) .thenThrow(new PackageManager.NameNotFoundException()); mCompatConfig = new CompatConfig(mBuildClassifier, mContext); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); // Assume userdebug/eng non-final build mCompatConfig.forceNonDebuggableFinalForTest(false); when(mBuildClassifier.isDebuggableBuild()).thenReturn(true); when(mBuildClassifier.isFinalBuild()).thenReturn(false); + when(mBuildClassifier.platformTargetSdk()).thenReturn(30); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal); } @@ -99,7 +100,7 @@ public class PlatformCompatTest { .addLoggingOnlyChangeWithId(7L) .addOverridableChangeWithId(8L) .build(); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly( new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false), new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false), @@ -125,8 +126,9 @@ public class PlatformCompatTest { .addEnableSinceSdkChangeWithId(Build.VERSION_CODES.Q, 5L) .addEnableSinceSdkChangeWithId(Build.VERSION_CODES.R, 6L) .addLoggingOnlyChangeWithId(7L) + .addEnableSinceSdkChangeWithId(31, 8L) .build(); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); assertThat(mPlatformCompat.listUIChanges()).asList().containsExactly( new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false), new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false), @@ -144,7 +146,7 @@ public class PlatformCompatTest { .addEnableAfterSdkChangeWithId(Build.VERSION_CODES.O, 3L) .build(); mCompatConfig.forceNonDebuggableFinalForTest(true); - mPlatformCompat = new PlatformCompat(mContext, mCompatConfig); + mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); // Before adding overrides. assertThat(mPlatformCompat.isChangeEnabledByPackageName(1, PACKAGE_NAME, 0)).isTrue(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java index b51f4df43259..91342ce925f6 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; @@ -109,7 +110,8 @@ public class RebootEscrowManagerTests { public interface MockableRebootEscrowInjected { int getBootCount(); - void reportMetric(boolean success); + void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, + int escrowDurationInSeconds, int vbmetaDigestStatus, int durationSinceBootComplete); } static class MockInjector extends RebootEscrowManager.Injector { @@ -119,6 +121,7 @@ public class RebootEscrowManagerTests { private final UserManager mUserManager; private final MockableRebootEscrowInjected mInjected; private final RebootEscrowKeyStoreManager mKeyStoreManager; + private final boolean mServerBased; MockInjector(Context context, UserManager userManager, IRebootEscrow rebootEscrow, @@ -128,6 +131,7 @@ public class RebootEscrowManagerTests { super(context, storage); mRebootEscrow = rebootEscrow; mServiceConnection = null; + mServerBased = false; RebootEscrowProviderHalImpl.Injector halInjector = new RebootEscrowProviderHalImpl.Injector() { @Override @@ -149,6 +153,7 @@ public class RebootEscrowManagerTests { super(context, storage); mServiceConnection = serviceConnection; mRebootEscrow = null; + mServerBased = true; RebootEscrowProviderServerBasedImpl.Injector injector = new RebootEscrowProviderServerBasedImpl.Injector(serviceConnection); mRebootEscrowProvider = new RebootEscrowProviderServerBasedImpl(storage, injector); @@ -168,6 +173,11 @@ public class RebootEscrowManagerTests { } @Override + public boolean serverBasedResumeOnReboot() { + return mServerBased; + } + + @Override public RebootEscrowProviderInterface getRebootEscrowProvider() { return mRebootEscrowProvider; } @@ -195,8 +205,11 @@ public class RebootEscrowManagerTests { } @Override - public void reportMetric(boolean success) { - mInjected.reportMetric(success); + public void reportMetric(boolean success, int errorCode, int serviceType, int attemptCount, + int escrowDurationInSeconds, int vbmetaDigestStatus, + int durationSinceBootComplete) { + mInjected.reportMetric(success, errorCode, serviceType, attemptCount, + escrowDurationInSeconds, vbmetaDigestStatus, durationSinceBootComplete); } } @@ -418,7 +431,9 @@ public class RebootEscrowManagerTests { when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + eq(0) /* error code */, eq(1) /* HAL based */, eq(1) /* attempt count */, + anyInt(), anyInt(), anyInt()); when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); mService.loadRebootEscrowDataIfAvailable(null); @@ -451,7 +466,9 @@ public class RebootEscrowManagerTests { // pretend reboot happens here when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + eq(0) /* error code */, eq(2) /* Server based */, eq(1) /* attempt count */, + anyInt(), anyInt(), anyInt()); when(mServiceConnection.unwrap(any(), anyLong())) .thenAnswer(invocation -> invocation.getArgument(0)); @@ -485,7 +502,8 @@ public class RebootEscrowManagerTests { // pretend reboot happens here when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + anyInt(), anyInt(), eq(2) /* attempt count */, anyInt(), anyInt(), anyInt()); when(mServiceConnection.unwrap(any(), anyLong())) .thenThrow(new IOException()) @@ -528,7 +546,8 @@ public class RebootEscrowManagerTests { mService.loadRebootEscrowDataIfAvailable(null); verify(mRebootEscrow).retrieveKey(); - verify(mInjected, never()).reportMetric(anyBoolean()); + verify(mInjected, never()).reportMetric(anyBoolean(), anyInt(), anyInt(), anyInt(), + anyInt(), anyInt(), anyInt()); } @Test @@ -554,7 +573,8 @@ public class RebootEscrowManagerTests { when(mRebootEscrow.retrieveKey()).thenReturn(new byte[32]); mService.loadRebootEscrowDataIfAvailable(null); - verify(mInjected, never()).reportMetric(anyBoolean()); + verify(mInjected, never()).reportMetric(anyBoolean(), anyInt(), anyInt(), anyInt(), + anyInt(), anyInt(), anyInt()); } @Test @@ -588,7 +608,8 @@ public class RebootEscrowManagerTests { when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); mService.loadRebootEscrowDataIfAvailable(null); - verify(mInjected).reportMetric(eq(true)); + verify(mInjected).reportMetric(eq(true), eq(0) /* error code */, eq(1) /* HAL based */, + eq(1) /* attempt count */, anyInt(), anyInt(), anyInt()); } @Test @@ -615,7 +636,9 @@ public class RebootEscrowManagerTests { when(mInjected.getBootCount()).thenReturn(1); ArgumentCaptor<Boolean> metricsSuccessCaptor = ArgumentCaptor.forClass(Boolean.class); - doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture()); + doNothing().when(mInjected).reportMetric(metricsSuccessCaptor.capture(), + anyInt() /* error code */, eq(1) /* HAL based */, eq(1) /* attempt count */, + anyInt(), anyInt(), anyInt()); when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> new byte[32]); mService.loadRebootEscrowDataIfAvailable(null); verify(mRebootEscrow).retrieveKey(); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java b/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java index b9af82b64c02..f3a38e6ec79c 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/ResumeOnRebootServiceProviderTests.java @@ -19,12 +19,12 @@ package com.android.server.locksettings; 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.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.Manifest; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -53,12 +53,9 @@ public class ResumeOnRebootServiceProviderTests { Context mMockContext; @Mock PackageManager mMockPackageManager; - @Mock - ResolveInfo mMockResolvedInfo; - @Mock - ServiceInfo mMockServiceInfo; - @Mock - ComponentName mMockComponentName; + + ResolveInfo mFakeResolvedInfo; + ServiceInfo mFakeServiceInfo; @Captor ArgumentCaptor<Intent> mIntentArgumentCaptor; @@ -66,8 +63,13 @@ public class ResumeOnRebootServiceProviderTests { public void setUp() { MockitoAnnotations.initMocks(this); when(mMockContext.getUserId()).thenReturn(0); - when(mMockResolvedInfo.serviceInfo).thenReturn(mMockServiceInfo); - when(mMockServiceInfo.getComponentName()).thenReturn(mMockComponentName); + + mFakeServiceInfo = new ServiceInfo(); + mFakeServiceInfo.packageName = "fakePackageName"; + mFakeServiceInfo.name = "fakeName"; + + mFakeResolvedInfo = new ResolveInfo(); + mFakeResolvedInfo.serviceInfo = mFakeServiceInfo; } @Test @@ -82,10 +84,9 @@ public class ResumeOnRebootServiceProviderTests { @Test public void serviceNotGuardedWithPermission() throws Exception { ArrayList<ResolveInfo> resultList = new ArrayList<>(); - when(mMockServiceInfo.permission).thenReturn(""); - resultList.add(mMockResolvedInfo); - when(mMockPackageManager.queryIntentServices(any(), any())).thenReturn( - resultList); + mFakeServiceInfo.permission = ""; + resultList.add(mFakeResolvedInfo); + when(mMockPackageManager.queryIntentServices(any(), anyInt())).thenReturn(resultList); assertThat(new ResumeOnRebootServiceProvider(mMockContext, mMockPackageManager).getServiceConnection()).isNull(); } @@ -93,18 +94,15 @@ public class ResumeOnRebootServiceProviderTests { @Test public void serviceResolved() throws Exception { ArrayList<ResolveInfo> resultList = new ArrayList<>(); - resultList.add(mMockResolvedInfo); - when(mMockServiceInfo.permission).thenReturn( - Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE); - when(mMockPackageManager.queryIntentServices(any(), - eq(PackageManager.MATCH_SYSTEM_ONLY))).thenReturn( - resultList); + resultList.add(mFakeResolvedInfo); + mFakeServiceInfo.permission = Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE; + when(mMockPackageManager.queryIntentServices(any(), anyInt())).thenReturn(resultList); assertThat(new ResumeOnRebootServiceProvider(mMockContext, mMockPackageManager).getServiceConnection()).isNotNull(); verify(mMockPackageManager).queryIntentServices(mIntentArgumentCaptor.capture(), - eq(PackageManager.MATCH_SYSTEM_ONLY)); + eq(PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_SERVICES)); assertThat(mIntentArgumentCaptor.getValue().getAction()).isEqualTo( ResumeOnRebootService.SERVICE_INTERFACE); } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index a38745f2a66e..d9af51f819c3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -42,7 +42,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.os.FileUtils; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.recovery.KeyChainSnapshot; @@ -109,7 +108,7 @@ public class KeySyncTaskTest { private RecoverySnapshotStorage mRecoverySnapshotStorage; private RecoverableKeyStoreDb mRecoverableKeyStoreDb; private File mDatabaseFile; - private AndroidKeyStoreSecretKey mWrappingKey; + private SecretKey mWrappingKey; private PlatformEncryptionKey mEncryptKey; private KeySyncTask mKeySyncTask; @@ -848,7 +847,7 @@ public class KeySyncTaskTest { return keyGenerator.generateKey(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -857,7 +856,7 @@ public class KeySyncTaskTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } private static byte[] utf8Bytes(String s) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java index 670bd8107bed..fd4fe56922dd 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java @@ -34,7 +34,6 @@ import android.app.KeyguardManager; import android.content.Context; import android.os.RemoteException; import android.security.GateKeeper; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; @@ -61,6 +60,7 @@ import java.security.UnrecoverableKeyException; import java.util.List; import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; @SmallTest @RunWith(AndroidJUnit4.class) @@ -586,7 +586,7 @@ public class PlatformKeyManagerTest { return (KeyProtection) mProtectionParameterCaptor.getValue(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -595,7 +595,7 @@ public class PlatformKeyManagerTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } class PlatformKeyManagerTestable extends PlatformKeyManager { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java index c295177814b0..64130266b2c4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import android.content.Context; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; @@ -45,6 +44,7 @@ import java.util.Random; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; @SmallTest @@ -77,7 +77,7 @@ public class RecoverableKeyGeneratorTest { mDatabaseFile = context.getDatabasePath(DATABASE_FILE_NAME); mRecoverableKeyStoreDb = RecoverableKeyStoreDb.newInstance(context); - AndroidKeyStoreSecretKey platformKey = generatePlatformKey(); + SecretKey platformKey = generatePlatformKey(); mPlatformKey = new PlatformEncryptionKey(TEST_GENERATION_ID, platformKey); mDecryptKey = new PlatformDecryptionKey(TEST_GENERATION_ID, platformKey); mRecoverableKeyGenerator = RecoverableKeyGenerator.newInstance(mRecoverableKeyStoreDb); @@ -168,7 +168,7 @@ public class RecoverableKeyGeneratorTest { assertArrayEquals(rawMaterial, unwrappedMaterial); } - private AndroidKeyStoreSecretKey generatePlatformKey() throws Exception { + private SecretKey generatePlatformKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -177,7 +177,7 @@ public class RecoverableKeyGeneratorTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } private static byte[] randomBytes(int n) { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index ac7447006444..f4e74bab2bd4 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -45,7 +45,6 @@ import android.content.Intent; import android.os.Binder; import android.os.ServiceSpecificException; import android.os.UserHandle; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.security.keystore.recovery.KeyChainProtectionParams; @@ -1311,7 +1310,7 @@ public class RecoverableKeyStoreManagerTest { mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -1320,6 +1319,6 @@ public class RecoverableKeyStoreManagerTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java index 9813ab74721e..60052f7114b3 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.util.Pair; @@ -117,7 +116,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_decryptsWrappedKeys_nullMetadata() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); @@ -136,7 +135,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_decryptsWrappedKeys_nonNullMetadata() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NON_NULL_METADATA); @@ -155,7 +154,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_doesNotDieIfSomeKeysAreUnwrappable() throws Exception { String alias = "karlin"; - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); @@ -171,7 +170,7 @@ public class WrappedKeyTest { @Test public void decryptWrappedKeys_throwsIfPlatformKeyGenerationIdDoesNotMatch() throws Exception { - AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey platformKey = generateAndroidKeyStoreKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( new PlatformEncryptionKey(GENERATION_ID, platformKey), generateKey(), /*metadata=*/ null); @@ -197,7 +196,7 @@ public class WrappedKeyTest { return keyGenerator.generateKey(); } - private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception { + private SecretKey generateAndroidKeyStoreKey() throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance( KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); @@ -207,6 +206,6 @@ public class WrappedKeyTest { .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); - return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); + return keyGenerator.generateKey(); } } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java new file mode 100644 index 000000000000..e605d755183f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java @@ -0,0 +1,300 @@ +/* + * 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.pm.dex; + +import static org.mockito.Mockito.inOrder; + +import com.android.internal.art.ArtStatsLog; +import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.InOrder; +import org.mockito.MockitoAnnotations; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * Unit tests for {@link com.android.server.pm.dex.ArtStatsLogUtils}. + * + * Run with "atest ArtStatsLogUtilsTest". + */ +@RunWith(JUnit4.class) +public final class ArtStatsLogUtilsTest { + private static final String TAG = ArtStatsLogUtilsTest.class.getSimpleName(); + private static final String COMPILER_FILTER = "space-profile"; + private static final String PROFILE_DEX_METADATA = "primary.prof"; + private static final String VDEX_DEX_METADATA = "primary.vdex"; + private static final byte[] DEX_CONTENT = "dexData".getBytes(); + private static final int COMPILATION_REASON = 1; + private static final int RESULT_CODE = 222; + private static final int UID = 111; + private static final long COMPILE_TIME = 333L; + private static final long SESSION_ID = 444L; + + @Mock + ArtStatsLogger mockLogger; + + private static Path TEST_DIR; + private static Path DEX; + private static Path NON_DEX; + + @BeforeClass + public static void setUpAll() throws IOException { + TEST_DIR = Files.createTempDirectory(null); + DEX = Files.createFile(TEST_DIR.resolve("classes.dex")); + NON_DEX = Files.createFile(TEST_DIR.resolve("test.dex")); + Files.write(DEX, DEX_CONTENT); + Files.write(NON_DEX, "empty".getBytes()); + } + + @AfterClass + public static void tearnDownAll() { + deleteSliently(DEX); + deleteSliently(NON_DEX); + deleteSliently(TEST_DIR); + } + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testProfileAndVdexDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata(PROFILE_DEX_METADATA, VDEX_DEX_METADATA); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE_AND_VDEX); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + @Test + public void testProfileOnlyDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata(PROFILE_DEX_METADATA); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_PROFILE); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + @Test + public void testVdexOnlyDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata(VDEX_DEX_METADATA); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_VDEX); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + @Test + public void testNoneDexMetadata() throws IOException { + // Setup + Path apk = null; + try { + apk = zipFiles(".apk", DEX, NON_DEX); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + /*dexMetadataPath=*/ null, + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_NONE); + } finally { + deleteSliently(apk); + } + } + + @Test + public void testUnKnownDexMetadata() throws IOException { + // Setup + Path dexMetadataPath = null; + Path apk = null; + try { + dexMetadataPath = createDexMetadata("unknown"); + apk = zipFiles(".apk", DEX, NON_DEX, dexMetadataPath); + + // Act + ArtStatsLogUtils.writeStatsLog( + mockLogger, + SESSION_ID, + apk.toString(), + COMPILER_FILTER, + UID, + COMPILE_TIME, + dexMetadataPath.toString(), + COMPILATION_REASON, + RESULT_CODE); + + // Assert + verifyWrites(ArtStatsLog. + ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN); + } finally { + deleteSliently(dexMetadataPath); + deleteSliently(apk); + } + } + + private void verifyWrites(int dexMetadataType) { + InOrder inorder = inOrder(mockLogger); + inorder.verify(mockLogger).write( + SESSION_ID, UID, + COMPILATION_REASON, + COMPILER_FILTER, + ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_RESULT_CODE, + RESULT_CODE, + dexMetadataType); + inorder.verify(mockLogger).write( + SESSION_ID, + UID, + COMPILATION_REASON, + COMPILER_FILTER, + ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_DEX_CODE_BYTES, + DEX_CONTENT.length, + dexMetadataType); + inorder.verify(mockLogger).write( + SESSION_ID, + UID, + COMPILATION_REASON, + COMPILER_FILTER, + ArtStatsLog.ART_DATUM_REPORTED__KIND__ART_DATUM_DEX2OAT_TOTAL_TIME, + COMPILE_TIME, + dexMetadataType); + } + + private Path zipFiles(String suffix, Path... files) throws IOException { + Path zipFile = Files.createTempFile(null, suffix); + try (final OutputStream os = Files.newOutputStream(zipFile)) { + try (final ZipOutputStream zos = new ZipOutputStream(os)) { + for (Path file : files) { + ZipEntry zipEntry = new ZipEntry(file.getFileName().toString()); + zos.putNextEntry(zipEntry); + zos.write(Files.readAllBytes(file)); + zos.closeEntry(); + } + } + } + return zipFile; + } + + private Path createDexMetadata(String... entryNames) throws IOException { + Path zipFile = Files.createTempFile(null, ".dm"); + try (final OutputStream os = Files.newOutputStream(zipFile)) { + try (final ZipOutputStream zos = new ZipOutputStream(os)) { + for (String entryName : entryNames) { + ZipEntry zipEntry = new ZipEntry(entryName); + zos.putNextEntry(zipEntry); + zos.write(entryName.getBytes()); + zos.closeEntry(); + } + } + } + return zipFile; + } + + private static void deleteSliently(Path file) { + if (file != null) { + try { + Files.deleteIfExists(file); + } catch (IOException e) { + // ignore + } + } + } +} diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS b/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS new file mode 100644 index 000000000000..72c0a9e6e90c --- /dev/null +++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/am/OWNERS |