diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-02-03 00:46:24 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-02-03 00:46:24 +0000 |
commit | ca926c544a956134055a195c680cacb83f6439c6 (patch) | |
tree | d7e4c349115c02703eb550a1c3f17d1a876b8791 | |
parent | 19e60fd1e79394e05bff86b46f007d6c36827e1f (diff) | |
parent | f4cf3e68fe97e5ec87afd811eb8e2b1bd4d57234 (diff) | |
download | robolectric-ca926c544a956134055a195c680cacb83f6439c6.tar.gz |
Merge "Snap for 11400057 from e5340a5031ab402cc91a47d89af3f833dd960ba7 to simpleperf-release" into simpleperf-release
44 files changed, 538 insertions, 233 deletions
diff --git a/Android.bp b/Android.bp index 0a83bf58a..3c278f580 100644 --- a/Android.bp +++ b/Android.bp @@ -51,33 +51,31 @@ license { ], } -// Empty library. Should be removed -java_library { - name: "robolectric_android-all-stub_upstream", - visibility: ["//visibility:public"], -} - // build.prop file created by module type defined in soong/robolectric.go robolectric_build_props { - name: "robolectric_build_props_upstream", + name: "robolectric_build_props", + visibility: [ + ":__subpackages__", + "//external/robolectric-shadows:__subpackages__", + ], } java_genrule { - name: "robolectric_framework_res_upstream", + name: "robolectric_framework_res", host_supported: true, tools: ["zip2zip"], srcs: [":framework-res"], - out: ["robolectric_framework_res_upstream.jar"], + out: ["robolectric_framework_res.jar"], cmd: "$(location zip2zip) " + "-i $(location :framework-res) " + - "-o $(location robolectric_framework_res_upstream.jar) " + + "-o $(location robolectric_framework_res.jar) " + "-x classes.dex " + "-x META-INF/**/* " + "-0 resources.arsc", } java_device_for_host { - name: "robolectric_android-all-device-deps_upstream", + name: "robolectric_android-all-device-deps", libs: [ "conscrypt-for-host", "core-icu4j-for-host", @@ -93,39 +91,38 @@ java_device_for_host { "services.accessibility", "telephony-common", "android.car", - "androidx.test.monitor", - "androidx.test.ext.truth", // -nodep? + "android.car.builtin", ], } java_library_host { - name: "robolectric-host-android_all_upstream", + name: "robolectric-host-android_all", static_libs: [ - "robolectric_android-all-device-deps_upstream", + "robolectric_android-all-device-deps", "robolectric_tzdata", - "robolectric_framework_res_upstream", + "robolectric_framework_res", ], dist: { targets: [ "sdk", "win_sdk", ], - dest: "android-all-robolectric_upstream.jar", + dest: "android-all-robolectric.jar", }, java_resources: [ // Copy the build.prop - ":robolectric_build_props_upstream", + ":robolectric_build_props", ], visibility: [ ":__subpackages__", + "//external/robolectric-shadows:__subpackages__", "//prebuilts/misc/common/robolectric", "//test/robolectric-extensions:__subpackages__", "//frameworks/base/packages/SettingsLib/tests/robotests:__subpackages__", ], } - java_library_host { name: "Robolectric_all_upstream", @@ -173,15 +170,21 @@ java_host_for_device { //java references "//frameworks/opt/net/wifi/libs/WifiTrackerLib/tests:__pkg__", "//prebuilts/sdk/current/androidx:__pkg__", + "//prebuilts/sdk/current/androidx/m2repository/androidx/car/app/app-testing/1.4.0-alpha01:__pkg__", "//prebuilts/sdk/current/aaos-libs:__pkg__", "//packages/apps/TV/tests/common:__pkg__", + "//external/android_onboarding/src/com/android/onboarding/contracts/testing:__pkg__", + "//external/android_onboarding/src/com/android/onboarding/testing:__pkg__", + "//external/android_onboarding/src/com/android/onboarding/nodes/testing:__pkg__", //robolectric tests "//platform_testing/libraries/runner:__pkg__", + "//platform_testing/libraries/screenshot/material_components:__pkg__", "//vendor:__subpackages__", "//platform_testing/robolab/roboStandaloneProj/tests:__pkg__", "//external/mobile-data-download/javatests:__pkg__", "//frameworks/base/services/robotests:__pkg__", "//frameworks/base/services/robotests/backup:__pkg__", + "//frameworks/base/packages/CredentialManager:__subpackages__", "//frameworks/base/packages/SettingsLib/tests/robotests:__subpackages__", "//frameworks/base/packages/SettingsLib/Spa/screenshot:__subpackages__", "//frameworks/base/packages/SystemUI:__pkg__", @@ -195,6 +198,7 @@ java_host_for_device { "//packages/modules/Connectivity/nearby/tests/multidevices/clients/test_support/snippet_helper/tests:__pkg__", "//packages/modules/Connectivity/nearby/tests/robotests:__pkg__", "//packages/modules/DeviceLock/DeviceLockController/tests/robolectric:__pkg__", + "//packages/modules/DeviceLock/tests/unittests:__pkg__", "//packages/services/Car/tests/CarLibTests:__pkg__", "//packages/services/Mms/tests/robotests:__pkg__", "//packages/apps/QuickAccessWallet/tests/robolectric:__pkg__", @@ -202,6 +206,7 @@ java_host_for_device { "//packages/apps/Car/libs/car-media-common/tests/robotests", "//packages/apps/Car/libs/car-ui-lib", "//packages/apps/Car/Notification/tests/robotests:__pkg__", + "//packages/apps/Car/Launcher/libs/appgrid/lib/robotests:__pkg__", "//packages/apps/Car/Cluster/DirectRenderingCluster/tests/robotests:__pkg__", "//packages/apps/Car/Settings/tests/robotests:__pkg__", "//packages/apps/EmergencyInfo/tests/robolectric:__pkg__", @@ -212,9 +217,13 @@ java_host_for_device { "//packages/apps/TvSettings/Settings/tests/robotests:__pkg__", "//packages/apps/KeyChain/robotests:__pkg__", "//packages/apps/CertInstaller/robotests:__pkg__", + "//packages/providers/MediaProvider:__subpackages__", + "//packages/apps/TV:__subpackages__", + "//frameworks/base/libs/WindowManager/Shell:__subpackages__", //tm-dev additions "//frameworks/base/packages/BackupEncryption/test/robolectric-integration:__pkg__", "//frameworks/base/packages/BackupEncryption/test/robolectric:__pkg__", + "//packages/apps/Settings/tests/screenshot:__pkg__", ], } @@ -235,6 +244,11 @@ java_device_for_host { } java_device_for_host { + name: "robolectric-host-androidx-test-ext-truth_upstream", + libs: ["androidx.test.ext.truth"], +} + +java_device_for_host { name: "robolectric-host-androidx-test-runner_upstream", libs: ["androidx.test.runner"], } @@ -249,11 +263,6 @@ java_device_for_host { libs: ["androidx.test.espresso.idling-resource"], } -//java_device_for_host { -// name: "robolectric-host-android-support-v4_upstream", -// libs: ["android-support-v4"], -//} - java_device_for_host { name: "robolectric-host-android-support-multidex_upstream", libs: [ @@ -49,12 +49,6 @@ Robolectric is built using Gradle. Both IntelliJ and Android Studio can import t ### Prerequisites -Those software configurations are recommended and tested. - -- JDK 17. Gradle JVM should be set to Java 17. - - For command line, make sure the environment variable `JAVA_HOME` is correctly point to JDK17, or set the build environment by [Gradle CLI option](https://docs.gradle.org/current/userguide/command_line_interface.html#sec:environment_options) `-Dorg.gradle.java.home="YourJdkHomePath"` or by [Gradle Properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties) `org.gradle.java.home=YourJdkHomePath`. - - For both IntelliJ and Android Studio, see _Settings/Preferences | Build, Execution, Deployment | Build Tools | Gradle_. - See [Building Robolectric](http://robolectric.org/building-robolectric/) for more details about setting up a build environment for Robolectric. ### Building diff --git a/annotations/Android.bp b/annotations/Android.bp index b325236d0..fd17be03c 100644 --- a/annotations/Android.bp +++ b/annotations/Android.bp @@ -16,7 +16,7 @@ java_library_host { static_libs: [ "jsr305", ], - libs: ["robolectric-host-android_all_upstream"], + libs: ["robolectric-host-android_all"], srcs: ["src/main/java/**/*.java"], visibility: ["//visibility:public"], } diff --git a/integration_tests/nativegraphics/Android.bp b/integration_tests/nativegraphics/Android.bp index 43040dc2d..b5a7ffe20 100644 --- a/integration_tests/nativegraphics/Android.bp +++ b/integration_tests/nativegraphics/Android.bp @@ -11,7 +11,10 @@ android_library { platform_apis: true, manifest: "AndroidManifest.xml", optimize: { - enabled: false + enabled: false, + }, + lint: { + baseline_filename: "lint-baseline.xml", }, } @@ -35,6 +38,9 @@ android_app { kotlincflags: ["-Xjvm-default=all"], plugins: ["dagger2-compiler"], + lint: { + baseline_filename: "lint-baseline.xml", + }, } android_robolectric_test { diff --git a/integration_tests/nativegraphics/lint-baseline.xml b/integration_tests/nativegraphics/lint-baseline.xml new file mode 100644 index 000000000..7fb99b50d --- /dev/null +++ b/integration_tests/nativegraphics/lint-baseline.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01"> + + <issue + id="NewApi" + message="`android:forceDarkAllowed` requires API level 29 (current min is 26)" + errorLine1=' <item name="android:forceDarkAllowed">false</item>' + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="external/robolectric/integration_tests/nativegraphics/src/main/res/values/themes.xml" + line="28" + column="15"/> + </issue> + + <issue + id="NewApi" + message="`android:forceDarkAllowed` requires API level 29 (current min is 26)" + errorLine1=' <item name="android:forceDarkAllowed">true</item>' + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="external/robolectric/integration_tests/nativegraphics/src/main/res/values/themes.xml" + line="31" + column="15"/> + </issue> + + <issue + id="NewApi" + message="`android:isLightTheme` requires API level 29 (current min is 26)" + errorLine1=' <item name="android:isLightTheme">true</item>' + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="external/robolectric/integration_tests/nativegraphics/src/main/res/values/themes.xml" + line="32" + column="15"/> + </issue> + +</issues>
\ No newline at end of file diff --git a/nativeruntime/Android.bp b/nativeruntime/Android.bp index 262b29db4..2110f4abc 100644 --- a/nativeruntime/Android.bp +++ b/nativeruntime/Android.bp @@ -32,7 +32,7 @@ java_library_host { "error_prone_annotations", "auto_service_annotations", // "jsr330", - "robolectric-host-android_all_upstream", + "robolectric-host-android_all", ], static_libs: [ "robolectric_nativeruntime_native_prebuilt", diff --git a/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java b/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java index 49127977d..00a11f5ff 100644 --- a/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java +++ b/resources/src/main/java/org/robolectric/manifest/AndroidManifest.java @@ -218,8 +218,7 @@ public class AndroidManifest implements UsesSdk { String targetSdkText = getTagAttributeText(manifestDocument, "uses-sdk", "android:targetSdkVersion"); if (targetSdkText != null) { - // Support Android O Preview. This can be removed once Android O is officially launched. - targetSdkVersion = targetSdkText.equals("O") ? 26 : Integer.parseInt(targetSdkText); + targetSdkVersion = Integer.parseInt(targetSdkText); } maxSdkVersion = @@ -240,6 +239,9 @@ public class AndroidManifest implements UsesSdk { System.out.println("Falling back to the Android OS resources only."); System.out.println( "To remove this warning, annotate your test class with @Config(manifest=Config.NONE)."); + System.out.println( + "If you're using Android Gradle Plugin, add " + + "testOptions.unitTests.includeAndroidResources = true to your build.gradle"); } if (packageName == null || packageName.equals("")) { @@ -247,10 +249,6 @@ public class AndroidManifest implements UsesSdk { } rClassName = packageName + ".R"; - - if (androidManifestFile != null) { - System.err.println("No such manifest file: " + androidManifestFile); - } } manifestIsParsed = true; diff --git a/robolectric/Android.bp b/robolectric/Android.bp index dde56624f..b6720e96f 100644 --- a/robolectric/Android.bp +++ b/robolectric/Android.bp @@ -37,7 +37,7 @@ java_library_host { "jsr305", "conscrypt-unbundled", "robolectric-host-androidx_test_espresso", - "robolectric-host-android_all_upstream", + "robolectric-host-android_all", ], srcs: ["src/main/java/**/*.java"], plugins: ["auto_service_plugin"], @@ -92,8 +92,9 @@ java_test_host { "asm-9.2", "jsr305", "robolectric-host-androidx_test_espresso", + "robolectric-host-androidx-test-ext-truth_upstream", ], - libs: ["robolectric-host-android_all_upstream"], + libs: ["robolectric-host-android_all"], // Robolectric tests do not work well with unit tests setup yet test_options: { unit_test: false, diff --git a/robolectric/src/main/java/org/robolectric/RobolectricTestRunner.java b/robolectric/src/main/java/org/robolectric/RobolectricTestRunner.java index 4cac1665f..def624b88 100644 --- a/robolectric/src/main/java/org/robolectric/RobolectricTestRunner.java +++ b/robolectric/src/main/java/org/robolectric/RobolectricTestRunner.java @@ -1,6 +1,5 @@ package org.robolectric; -import android.os.Build; import com.google.auto.service.AutoService; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; @@ -89,7 +88,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { private final ConfigurationStrategy configurationStrategy; private final AndroidConfigurer androidConfigurer; - private final ResModeStrategy resModeStrategy = getResModeStrategy(); private boolean alwaysIncludeVariantMarkersInName = Boolean.parseBoolean( System.getProperty("robolectric.alwaysIncludeVariantMarkersInTestName", "false")); @@ -185,31 +183,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { return DefaultTestLifecycle.class; } - enum ResModeStrategy { - legacy, - binary, - best, - both; - - static final ResModeStrategy DEFAULT = best; - - private static ResModeStrategy getFromProperties() { - String resourcesMode = System.getProperty("robolectric.resourcesMode"); - return resourcesMode == null ? DEFAULT : valueOf(resourcesMode); - } - - boolean includeLegacy(AndroidManifest appManifest) { - return appManifest.supportsLegacyResourcesMode() - && (this == legacy - || this == both); - } - - boolean includeBinary(AndroidManifest appManifest) { - return appManifest.supportsBinaryResourcesMode() - && (this == binary || this == best || this == both); - } - } - @Override protected List<FrameworkMethod> getChildren() { List<FrameworkMethod> children = new ArrayList<>(); @@ -222,19 +195,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { List<Sdk> sdksToRun = sdkPicker.selectSdks(configuration, appManifest); RobolectricFrameworkMethod last = null; for (Sdk sdk : sdksToRun) { - if (resModeStrategy.includeLegacy(appManifest)) { - children.add( - last = - new RobolectricFrameworkMethod( - frameworkMethod.getMethod(), - appManifest, - sdk, - configuration, - ResourcesMode.LEGACY, - resModeStrategy, - alwaysIncludeVariantMarkersInName)); - } - if (resModeStrategy.includeBinary(appManifest)) { children.add( last = new RobolectricFrameworkMethod( @@ -243,9 +203,7 @@ public class RobolectricTestRunner extends SandboxTestRunner { sdk, configuration, ResourcesMode.BINARY, - resModeStrategy, alwaysIncludeVariantMarkersInName)); - } } if (last != null) { last.dontIncludeVariantMarkersInTestName(); @@ -273,13 +231,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { InstrumentationConfiguration classLoaderConfig = createClassLoaderConfig(method); ResourcesMode resourcesMode = roboMethod.getResourcesMode(); - if (resourcesMode == ResourcesMode.LEGACY && sdk.getApiLevel() > Build.VERSION_CODES.P) { - System.err.println( - "Failure for " - + method.getName() - + " because Robolectric doesn't support legacy resources mode after P"); - throw new AssertionError("Robolectric doesn't support legacy resources mode after P"); - } LooperMode.Mode looperMode = roboMethod.configuration == null ? Mode.LEGACY @@ -323,12 +274,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { + "; resources=" + roboMethod.resourcesMode); - if (roboMethod.resourcesMode == ResourcesMode.LEGACY) { - Logger.warn( - "Legacy resources mode is deprecated; see" - + " http://robolectric.org/migrating/#migrating-to-40"); - } - roboMethod.setStuff(androidSandbox, androidSandbox.getTestEnvironment()); Class<TestLifecycle> cl = androidSandbox.bootstrappedClass(getTestLifecycleClass()); roboMethod.testLifecycle = ReflectionHelpers.newInstance(cl); @@ -559,11 +504,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { "this should always be invoked on the HelperTestRunner!"); } - @VisibleForTesting - ResModeStrategy getResModeStrategy() { - return ResModeStrategy.getFromProperties(); - } - public static class HelperTestRunner extends SandboxTestRunner.HelperTestRunner { public HelperTestRunner(Class bootstrappedTestClass) throws InitializationError { super(bootstrappedTestClass); @@ -606,7 +546,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { @Nonnull private final AndroidManifest appManifest; @Nonnull private final Configuration configuration; @Nonnull private final ResourcesMode resourcesMode; - @Nonnull private final ResModeStrategy defaultResModeStrategy; @Nonnull private final Sdk sdk; private final boolean alwaysIncludeVariantMarkersInName; @@ -623,7 +562,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { other.getSdk(), other.configuration, other.resourcesMode, - other.defaultResModeStrategy, other.alwaysIncludeVariantMarkersInName); includeVariantMarkersInTestName = other.includeVariantMarkersInTestName; @@ -636,7 +574,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { @Nonnull Sdk sdk, @Nonnull Configuration configuration, @Nonnull ResourcesMode resourcesMode, - @Nonnull ResModeStrategy defaultResModeStrategy, boolean alwaysIncludeVariantMarkersInName) { super(method); @@ -644,7 +581,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { this.appManifest = appManifest; this.configuration = configuration; this.resourcesMode = resourcesMode; - this.defaultResModeStrategy = defaultResModeStrategy; this.alwaysIncludeVariantMarkersInName = alwaysIncludeVariantMarkersInName; this.sdk = sdk; } @@ -657,10 +593,6 @@ public class RobolectricTestRunner extends SandboxTestRunner { if (includeVariantMarkersInTestName || alwaysIncludeVariantMarkersInName) { buf.append("[").append(getSdk().getApiLevel()).append("]"); - - if (defaultResModeStrategy == ResModeStrategy.both) { - buf.append("[").append(resourcesMode.name()).append("]"); - } } return buf.toString(); @@ -694,7 +626,7 @@ public class RobolectricTestRunner extends SandboxTestRunner { } public boolean isLegacy() { - return resourcesMode == ResourcesMode.LEGACY; + return false; } public ResourcesMode getResourcesMode() { diff --git a/robolectric/src/main/java/org/robolectric/android/internal/AndroidTestEnvironment.java b/robolectric/src/main/java/org/robolectric/android/internal/AndroidTestEnvironment.java index 6126b253a..f3a3f9ca7 100644 --- a/robolectric/src/main/java/org/robolectric/android/internal/AndroidTestEnvironment.java +++ b/robolectric/src/main/java/org/robolectric/android/internal/AndroidTestEnvironment.java @@ -130,7 +130,6 @@ public class AndroidTestEnvironment implements TestEnvironment { this.shadowProviders = shadowProviders; this.testEnvironmentLifecyclePlugins = lifecyclePlugins; - RuntimeEnvironment.setUseLegacyResources(resourcesMode == ResourcesMode.LEGACY); ReflectionHelpers.setStaticField(RuntimeEnvironment.class, "apiLevel", apiLevel); } diff --git a/robolectric/src/main/java/org/robolectric/internal/ResourcesMode.java b/robolectric/src/main/java/org/robolectric/internal/ResourcesMode.java index bc2701c7c..b4b8d82a6 100644 --- a/robolectric/src/main/java/org/robolectric/internal/ResourcesMode.java +++ b/robolectric/src/main/java/org/robolectric/internal/ResourcesMode.java @@ -1,6 +1,5 @@ package org.robolectric.internal; public enum ResourcesMode { - BINARY, - LEGACY + BINARY } diff --git a/robolectric/src/test/java/org/robolectric/RobolectricTestRunnerTest.java b/robolectric/src/test/java/org/robolectric/RobolectricTestRunnerTest.java index 95f71c295..69b17a2f4 100644 --- a/robolectric/src/test/java/org/robolectric/RobolectricTestRunnerTest.java +++ b/robolectric/src/test/java/org/robolectric/RobolectricTestRunnerTest.java @@ -43,7 +43,6 @@ import org.junit.runner.notification.RunNotifier; import org.junit.runners.JUnit4; import org.junit.runners.MethodSorters; import org.junit.runners.model.FrameworkMethod; -import org.robolectric.RobolectricTestRunner.ResModeStrategy; import org.robolectric.RobolectricTestRunner.RobolectricFrameworkMethod; import org.robolectric.android.internal.AndroidTestEnvironment; import org.robolectric.annotation.Config; @@ -217,8 +216,7 @@ public class RobolectricTestRunnerTest { mock(AndroidManifest.class), sdkCollection.getSdk(16), mock(Configuration.class), - ResourcesMode.LEGACY, - ResModeStrategy.legacy, + ResourcesMode.BINARY, false); RobolectricFrameworkMethod rfm17 = new RobolectricFrameworkMethod( @@ -226,8 +224,7 @@ public class RobolectricTestRunnerTest { mock(AndroidManifest.class), sdkCollection.getSdk(17), mock(Configuration.class), - ResourcesMode.LEGACY, - ResModeStrategy.legacy, + ResourcesMode.BINARY, false); RobolectricFrameworkMethod rfm16b = new RobolectricFrameworkMethod( @@ -235,22 +232,11 @@ public class RobolectricTestRunnerTest { mock(AndroidManifest.class), sdkCollection.getSdk(16), mock(Configuration.class), - ResourcesMode.LEGACY, - ResModeStrategy.legacy, - false); - RobolectricFrameworkMethod rfm16c = - new RobolectricFrameworkMethod( - method, - mock(AndroidManifest.class), - sdkCollection.getSdk(16), - mock(Configuration.class), ResourcesMode.BINARY, - ResModeStrategy.legacy, false); assertThat(rfm16).isNotEqualTo(rfm17); assertThat(rfm16).isEqualTo(rfm16b); - assertThat(rfm16).isNotEqualTo(rfm16c); assertThat(rfm16.hashCode()).isEqualTo(rfm16b.hashCode()); } diff --git a/robolectric/src/test/java/org/robolectric/SingleSdkRobolectricTestRunner.java b/robolectric/src/test/java/org/robolectric/SingleSdkRobolectricTestRunner.java index 1d35f8c0b..94bf451f4 100644 --- a/robolectric/src/test/java/org/robolectric/SingleSdkRobolectricTestRunner.java +++ b/robolectric/src/test/java/org/robolectric/SingleSdkRobolectricTestRunner.java @@ -45,11 +45,6 @@ public class SingleSdkRobolectricTestRunner extends RobolectricTestRunner { return latestSandbox; } - @Override - ResModeStrategy getResModeStrategy() { - return ResModeStrategy.binary; - } - public static class SingleSdkPicker implements SdkPicker { private final Sdk sdk; diff --git a/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java b/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java index 3847ed031..51b809b69 100644 --- a/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java +++ b/robolectric/src/test/java/org/robolectric/manifest/AndroidManifestTest.java @@ -242,19 +242,6 @@ public class AndroidManifestTest { .isEqualTo(VERSION_CODES.JELLY_BEAN); } - /** - * For Android O preview, apps are encouraged to use targetSdkVersion="O". - * - * @see <a href="http://google.com">https://developer.android.com/preview/migration.html</a> - */ - @Test - public void shouldReadTargetSDKVersionOPreview() throws Exception { - assertThat( - newConfigWith("TestAndroidManifestForPreview.xml", "android:targetSdkVersion=\"O\"") - .getTargetSdkVersion()) - .isEqualTo(26); - } - @Test public void shouldReadProcessFromAndroidManifest() throws Exception { assertThat(newConfig("TestAndroidManifestWithProcess.xml").getProcessName()) diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothAdapterTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothAdapterTest.java index b94d94e94..a9c3e8d81 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothAdapterTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothAdapterTest.java @@ -36,6 +36,8 @@ import android.content.Intent; import android.os.Looper; import androidx.test.ext.junit.runners.AndroidJUnit4; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.LinkedBlockingQueue; @@ -111,6 +113,27 @@ public class ShadowBluetoothAdapterTest { } @Test + @Config(minSdk = TIRAMISU) + public void canGetAndSetMostRecentlyConnectedDevices() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + + // By default return empty list for most recently connected devices + assertThat(adapter.getMostRecentlyConnectedDevices()).isEmpty(); + + // set most recently connected devices + BluetoothDevice remoteDevice1 = bluetoothAdapter.getRemoteDevice(MOCK_MAC_ADDRESS); + BluetoothDevice remoteDevice2 = bluetoothAdapter.getRemoteDevice(MOCK_MAC_ADDRESS); + List<BluetoothDevice> result = new ArrayList<>(); + result.add(remoteDevice1); + result.add(remoteDevice2); + shadowOf(adapter).setMostRecentlyConnectedDevices(result); + + assertThat(adapter.getMostRecentlyConnectedDevices()).hasSize(2); + assertThat(adapter.getMostRecentlyConnectedDevices()) + .containsExactly(remoteDevice1, remoteDevice2); + } + + @Test @Config(minSdk = LOLLIPOP) public void canGetBluetoothLeScanner() { if (RuntimeEnvironment.getApiLevel() < M) { @@ -868,4 +891,17 @@ public class ShadowBluetoothAdapterTest { public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {} }; } + + @Config(minSdk = TIRAMISU) + @Test + public void canGetAndSetLeAudioSupport() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + + // By default LE feature is not supported + assertThat(adapter.isLeAudioSupported()).isEqualTo(BluetoothStatusCodes.FEATURE_NOT_SUPPORTED); + + // set Le audio feature to supported. + shadowOf(adapter).setLeAudioSupported(BluetoothStatusCodes.FEATURE_SUPPORTED); + assertThat(adapter.isLeAudioSupported()).isEqualTo(BluetoothStatusCodes.FEATURE_SUPPORTED); + } } diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowMediaActionSoundTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowMediaActionSoundTest.java index a240ab221..ad6aeebdb 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowMediaActionSoundTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowMediaActionSoundTest.java @@ -4,6 +4,7 @@ import static com.google.common.truth.Truth.assertThat; import android.media.MediaActionSound; import android.os.Build; +import android.os.Build.VERSION_CODES; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,4 +75,22 @@ public final class ShadowMediaActionSoundTest { assertThat(ShadowMediaActionSound.getPlayCount(MediaActionSound.SHUTTER_CLICK)).isEqualTo(3); } + + @Test + @Config(minSdk = VERSION_CODES.TIRAMISU) + public void mustPlayShutterSound_defaultFalse() { + assertThat(MediaActionSound.mustPlayShutterSound()).isFalse(); + } + + @Test + @Config(minSdk = VERSION_CODES.TIRAMISU) + public void mustPlayShutterSound_overrident_correctValue() { + ShadowMediaActionSound.setMustPlayShutterSound(true); + + assertThat(MediaActionSound.mustPlayShutterSound()).isTrue(); + + ShadowMediaActionSound.setMustPlayShutterSound(false); + + assertThat(MediaActionSound.mustPlayShutterSound()).isFalse(); + } } diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowStorageManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowStorageManagerTest.java index 84120e001..ad410660e 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowStorageManagerTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowStorageManagerTest.java @@ -2,6 +2,7 @@ package org.robolectric.shadows; import static android.os.Build.VERSION_CODES.N; import static android.os.Build.VERSION_CODES.TIRAMISU; +import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; import static com.google.common.truth.Truth.assertThat; import static org.robolectric.RuntimeEnvironment.getApplication; import static org.robolectric.Shadows.shadowOf; @@ -91,10 +92,17 @@ public class ShadowStorageManagerTest { } @Test - @Config(minSdk = N) + @Config(minSdk = N, maxSdk = UPSIDE_DOWN_CAKE) public void isUserKeyUnlocked() { shadowOf(getApplication().getSystemService(UserManager.class)).setUserUnlocked(true); - assertThat(StorageManager.isUserKeyUnlocked(0)).isTrue(); + // Use reflection, as this method is planned to be removed from StorageManager in V. + assertThat( + (boolean) + ReflectionHelpers.callStaticMethod( + StorageManager.class, + "isUserKeyUnlocked", + ReflectionHelpers.ClassParameter.from(int.class, 0))) + .isTrue(); } private StorageVolume buildAndGetStorageVolume(File file, String description) { diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowTelecomManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowTelecomManagerTest.java index f1e6dadc1..826d36391 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowTelecomManagerTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowTelecomManagerTest.java @@ -130,6 +130,21 @@ public class ShadowTelecomManagerTest { } @Test + @Config(minSdk = M) + public void enableNonRegisteredAccountDoesNothing() { + PhoneAccountHandle accountHandle1 = createHandle("a.package", "OtherConnectionService", "id1"); + telecomService.registerPhoneAccount( + PhoneAccount.builder(accountHandle1, "another_package").build()); + + // Attempt to enable phone account that hasn't been registered should do nothing. + PhoneAccountHandle accountHandle2 = + createHandle("some.other.package", "OtherConnectionService", "id2"); + telecomService.enablePhoneAccount(accountHandle2, /* isEnabled= */ true); + + assertThat(telecomService.getPhoneAccount(accountHandle1).isEnabled()).isFalse(); + } + + @Test public void getPhoneAccountsSupportingScheme() { PhoneAccountHandle handleMatchingScheme = createHandle("id1"); telecomService.registerPhoneAccount( diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowVirtualDeviceManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowVirtualDeviceManagerTest.java index 98db027df..f11cf763e 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowVirtualDeviceManagerTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowVirtualDeviceManagerTest.java @@ -62,6 +62,20 @@ public class ShadowVirtualDeviceManagerTest { } @Test + public void testIsClosed() { + VirtualDevice virtualDevice = + virtualDeviceManager.createVirtualDevice( + 0, new VirtualDeviceParams.Builder().setName("foo").build()); + ShadowVirtualDevice shadowDevice = Shadow.extract(virtualDevice); + + assertThat(shadowDevice.isClosed()).isFalse(); + + virtualDevice.close(); + + assertThat(shadowDevice.isClosed()).isTrue(); + } + + @Test public void testIsValidVirtualDeviceId() { VirtualDevice virtualDevice = virtualDeviceManager.createVirtualDevice( diff --git a/sandbox/src/main/java/org/robolectric/config/AndroidConfigurer.java b/sandbox/src/main/java/org/robolectric/config/AndroidConfigurer.java index c03b88262..1fb7a98d2 100644 --- a/sandbox/src/main/java/org/robolectric/config/AndroidConfigurer.java +++ b/sandbox/src/main/java/org/robolectric/config/AndroidConfigurer.java @@ -106,6 +106,10 @@ public class AndroidConfigurer { // Instrumenting these classes causes a weird failure. builder.doNotInstrumentClass("android.R").doNotInstrumentClass("android.R$styleable"); + // Instrumenting this Exceptions causes "java.lang.NegativeArraySizeException: -2" and + // leads to java.lang.NoClassDefFoundError. + builder.doNotInstrumentClass("android.app.RecoverableSecurityException"); + builder .addInstrumentedPackage("dalvik.") .addInstrumentedPackage("libcore.") diff --git a/shadows/framework/Android.bp b/shadows/framework/Android.bp index 8c050b589..8e9f0e13b 100644 --- a/shadows/framework/Android.bp +++ b/shadows/framework/Android.bp @@ -39,16 +39,11 @@ java_library_host { "Robolectric_utils_upstream", "Robolectric_utils_reflector_upstream", "auto_value_annotations", - //jetpack - //"androidx.annotation_annotation-nodeps", "jsr305", "icu4j", "robolectric-accessibility-test-framework-2.1", "robolectric-javax.annotation-api-1.2", - //"hamcrest-library", - //"hamcrest", - //"stub-annotations", "robolectric-sqlite4java-0.282", "asm-commons-9.2", "guava", @@ -56,9 +51,12 @@ java_library_host { "asm-9.2", //standard tools "error_prone_annotations", - //"grpc-java-netty-shaded", // aar files that make up android and jetpack - "robolectric-host-android_all_upstream", + "robolectric-host-android_all", + "robolectric-host-androidx-test-core_upstream", + //"robolectric-host-androidx-test-ext-junit_upstream", + "robolectric-host-androidx-test-monitor_upstream", + //"robolectric-host-androidx-test-runner_upstream", ], plugins: [ "auto_value_plugin_1.9", diff --git a/shadows/framework/src/main/java/org/robolectric/RuntimeEnvironment.java b/shadows/framework/src/main/java/org/robolectric/RuntimeEnvironment.java index a58fd7069..cc7c1d457 100644 --- a/shadows/framework/src/main/java/org/robolectric/RuntimeEnvironment.java +++ b/shadows/framework/src/main/java/org/robolectric/RuntimeEnvironment.java @@ -53,7 +53,6 @@ public class RuntimeEnvironment { private static Path androidFrameworkJar; public static Path compileTimeSystemResourcesFile; - private static boolean useLegacyResources; private static Supplier<Application> applicationSupplier; private static final Object supplierLock = new Object(); @@ -341,16 +340,6 @@ public class RuntimeEnvironment { */ @Deprecated public static boolean useLegacyResources() { - return useLegacyResources; - } - - /** - * Internal only. - * - * @deprecated Do not use. - */ - @Deprecated - public static void setUseLegacyResources(boolean useLegacyResources) { - RuntimeEnvironment.useLegacyResources = useLegacyResources; + return false; } } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBinder.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBinder.java index a5f99b1ee..bb0cd86f3 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBinder.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBinder.java @@ -47,7 +47,7 @@ public class ShadowBinder { } @Implementation - protected static final int getCallingPid() { + protected static int getCallingPid() { if (callingPid != null) { return callingPid; } @@ -55,7 +55,7 @@ public class ShadowBinder { } @Implementation - protected static final int getCallingUid() { + protected static int getCallingUid() { if (callingUid != null) { return callingUid; } @@ -71,7 +71,7 @@ public class ShadowBinder { * @throws IllegalStateException if no UID has been set */ @Implementation(minSdk = Q) - protected static final int getCallingUidOrThrow() { + protected static int getCallingUidOrThrow() { if (callingUid != null) { return callingUid; } @@ -81,7 +81,7 @@ public class ShadowBinder { } @Implementation(minSdk = JELLY_BEAN_MR1) - protected static final UserHandle getCallingUserHandle() { + protected static UserHandle getCallingUserHandle() { if (callingUserHandle != null) { return callingUserHandle; } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothAdapter.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothAdapter.java index b3cb8f16d..5e89a77b6 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothAdapter.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothAdapter.java @@ -90,6 +90,7 @@ public class ShadowBluetoothAdapter { private static final Map<String, BluetoothDevice> deviceCache = new HashMap<>(); private Set<BluetoothDevice> bondedDevices = new HashSet<BluetoothDevice>(); + private List<BluetoothDevice> mostRecentlyConnectedDevices = new ArrayList<>(); private Set<LeScanCallback> leScanCallbacks = new HashSet<LeScanCallback>(); private boolean isDiscovering; private String address; @@ -99,6 +100,7 @@ public class ShadowBluetoothAdapter { private Duration discoverableTimeout; private boolean isBleScanAlwaysAvailable = true; private boolean isMultipleAdvertisementSupported = true; + private int isLeAudioSupported = BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; private boolean isLeExtendedAdvertisingSupported = true; private boolean isOverridingProxyBehavior; private final Map<Integer, Integer> profileConnectionStateData = new HashMap<>(); @@ -141,12 +143,24 @@ public class ShadowBluetoothAdapter { ClassParameter.from(AttributionSource.class, attributionSource)); } + /** Sets whether the Le Audio is supported or not. Minimum sdk version required is TIRAMISU. */ + public void setLeAudioSupported(int supported) { + isLeAudioSupported = supported; + } + + @Implementation(minSdk = VERSION_CODES.TIRAMISU) + protected int isLeAudioSupported() { + return isLeAudioSupported; + } + /** Determines if getDefaultAdapter() returns the default local adapter (true) or null (false). */ public static void setIsBluetoothSupported(boolean supported) { isBluetoothSupported = supported; } - /** @deprecated use real BluetoothLeAdvertiser instead */ + /** + * @deprecated use real BluetoothLeAdvertiser instead + */ @Deprecated public void setBluetoothLeAdvertiser(BluetoothLeAdvertiser advertiser) { if (RuntimeEnvironment.getApiLevel() <= VERSION_CODES.LOLLIPOP_MR1) { @@ -166,6 +180,15 @@ public class ShadowBluetoothAdapter { return deviceCache.get(address); } + public void setMostRecentlyConnectedDevices(List<BluetoothDevice> devices) { + mostRecentlyConnectedDevices = devices; + } + + @Implementation(minSdk = TIRAMISU) + protected List<BluetoothDevice> getMostRecentlyConnectedDevices() { + return mostRecentlyConnectedDevices; + } + @Implementation protected Set<BluetoothDevice> getBondedDevices() { return Collections.unmodifiableSet(bondedDevices); @@ -179,26 +202,26 @@ public class ShadowBluetoothAdapter { protected BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord( String serviceName, UUID uuid) { return ShadowBluetoothServerSocket.newInstance( - BluetoothSocket.TYPE_RFCOMM, /*auth=*/ false, /*encrypt=*/ false, new ParcelUuid(uuid)); + BluetoothSocket.TYPE_RFCOMM, /* auth= */ false, /* encrypt= */ false, new ParcelUuid(uuid)); } @Implementation protected BluetoothServerSocket listenUsingRfcommWithServiceRecord(String serviceName, UUID uuid) throws IOException { return ShadowBluetoothServerSocket.newInstance( - BluetoothSocket.TYPE_RFCOMM, /*auth=*/ false, /*encrypt=*/ true, new ParcelUuid(uuid)); + BluetoothSocket.TYPE_RFCOMM, /* auth= */ false, /* encrypt= */ true, new ParcelUuid(uuid)); } @Implementation(minSdk = Q) protected BluetoothServerSocket listenUsingInsecureL2capChannel() throws IOException { return ShadowBluetoothServerSocket.newInstance( - BluetoothSocket.TYPE_L2CAP, /*auth=*/ false, /*encrypt=*/ true, /*uuid=*/ null); + BluetoothSocket.TYPE_L2CAP, /* auth= */ false, /* encrypt= */ true, /* uuid= */ null); } @Implementation(minSdk = Q) protected BluetoothServerSocket listenUsingL2capChannel() throws IOException { return ShadowBluetoothServerSocket.newInstance( - BluetoothSocket.TYPE_L2CAP, /*auth=*/ false, /*encrypt=*/ true, /*uuid=*/ null); + BluetoothSocket.TYPE_L2CAP, /* auth= */ false, /* encrypt= */ true, /* uuid= */ null); } @Implementation @@ -464,7 +487,9 @@ public class ShadowBluetoothAdapter { this.state = state; } - /** @deprecated Use {@link BluetoothAdapter#enable()} or {@link BluetoothAdapter#disable()}. */ + /** + * @deprecated Use {@link BluetoothAdapter#enable()} or {@link BluetoothAdapter#disable()}. + */ @Deprecated public void setEnabled(boolean enabled) { if (enabled) { @@ -558,7 +583,7 @@ public class ShadowBluetoothAdapter { * Overrides behavior of {@link closeProfileProxy} if {@link * ShadowBluetoothAdapter#setProfileProxy} has been previously called. * - * If the given non-null BluetoothProfile {@code proxy} was previously set for the given {@code + * <p>If the given non-null BluetoothProfile {@code proxy} was previously set for the given {@code * profile} by {@link ShadowBluetoothAdapter#setProfileProxy}, this proxy will be "deactivated". */ @Implementation diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowHidlSupport.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowHidlSupport.java new file mode 100644 index 000000000..78f88891e --- /dev/null +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowHidlSupport.java @@ -0,0 +1,16 @@ +package org.robolectric.shadows; + +import android.os.HidlSupport; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.versioning.AndroidVersions.V; + +@SuppressWarnings("NewApi") +@Implements(value = HidlSupport.class, isInAndroidSdk = false, minSdk = V.SDK_INT) +public class ShadowHidlSupport { + + @Implementation + protected static boolean isHidlSupported() { + return true; + } +} diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowKeyCharacterMap.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowKeyCharacterMap.java index 7ce4c603b..ea29a43dc 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowKeyCharacterMap.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowKeyCharacterMap.java @@ -64,6 +64,7 @@ public class ShadowKeyCharacterMap { CHAR_TO_KEY_CODE.put(',', KeyEvent.KEYCODE_COMMA); CHAR_TO_KEY_CODE.put('[', KeyEvent.KEYCODE_LEFT_BRACKET); CHAR_TO_KEY_CODE.put(']', KeyEvent.KEYCODE_RIGHT_BRACKET); + CHAR_TO_KEY_CODE.put(';', KeyEvent.KEYCODE_SEMICOLON); CHAR_TO_KEY_CODE.put('\'', KeyEvent.KEYCODE_APOSTROPHE); CHAR_TO_KEY_CODE.put(')', KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN); CHAR_TO_KEY_CODE.put('(', KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN); @@ -76,14 +77,23 @@ public class ShadowKeyCharacterMap { CHAR_TO_KEY_CODE.put('\n', KeyEvent.KEYCODE_ENTER); CHAR_TO_KEY_CODE_SHIFT_ON.put('_', KeyEvent.KEYCODE_MINUS); + CHAR_TO_KEY_CODE_SHIFT_ON.put('+', KeyEvent.KEYCODE_EQUALS); CHAR_TO_KEY_CODE_SHIFT_ON.put('{', KeyEvent.KEYCODE_LEFT_BRACKET); CHAR_TO_KEY_CODE_SHIFT_ON.put('}', KeyEvent.KEYCODE_RIGHT_BRACKET); + CHAR_TO_KEY_CODE_SHIFT_ON.put(':', KeyEvent.KEYCODE_SEMICOLON); CHAR_TO_KEY_CODE_SHIFT_ON.put('\"', KeyEvent.KEYCODE_APOSTROPHE); + CHAR_TO_KEY_CODE_SHIFT_ON.put(')', KeyEvent.KEYCODE_0); CHAR_TO_KEY_CODE_SHIFT_ON.put('!', KeyEvent.KEYCODE_1); + CHAR_TO_KEY_CODE_SHIFT_ON.put('@', KeyEvent.KEYCODE_2); + CHAR_TO_KEY_CODE_SHIFT_ON.put('#', KeyEvent.KEYCODE_3); CHAR_TO_KEY_CODE_SHIFT_ON.put('$', KeyEvent.KEYCODE_4); CHAR_TO_KEY_CODE_SHIFT_ON.put('%', KeyEvent.KEYCODE_5); CHAR_TO_KEY_CODE_SHIFT_ON.put('^', KeyEvent.KEYCODE_6); CHAR_TO_KEY_CODE_SHIFT_ON.put('&', KeyEvent.KEYCODE_7); + CHAR_TO_KEY_CODE_SHIFT_ON.put('*', KeyEvent.KEYCODE_8); + CHAR_TO_KEY_CODE_SHIFT_ON.put('(', KeyEvent.KEYCODE_9); + CHAR_TO_KEY_CODE_SHIFT_ON.put('>', KeyEvent.KEYCODE_PERIOD); + CHAR_TO_KEY_CODE_SHIFT_ON.put('<', KeyEvent.KEYCODE_COMMA); CHAR_TO_KEY_CODE_SHIFT_ON.put('?', KeyEvent.KEYCODE_SLASH); CHAR_TO_KEY_CODE_SHIFT_ON.put('|', KeyEvent.KEYCODE_BACKSLASH); CHAR_TO_KEY_CODE_SHIFT_ON.put('~', KeyEvent.KEYCODE_GRAVE); @@ -132,6 +142,7 @@ public class ShadowKeyCharacterMap { KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_COMMA, ','); KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_LEFT_BRACKET, '['); KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_RIGHT_BRACKET, ']'); + KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_SEMICOLON, ';'); KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_APOSTROPHE, '\''); KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN, ')'); KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN, '('); @@ -144,14 +155,23 @@ public class ShadowKeyCharacterMap { KEY_CODE_TO_CHAR.put(KeyEvent.KEYCODE_ENTER, '\n'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_MINUS, '_'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_EQUALS, '+'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_LEFT_BRACKET, '{'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_RIGHT_BRACKET, '}'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_SEMICOLON, ':'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_APOSTROPHE, '\"'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_0, ')'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_1, '!'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_2, '@'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_3, '#'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_4, '$'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_5, '%'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_6, '^'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_7, '&'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_8, '*'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_9, '('); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_PERIOD, '>'); + KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_COMMA, '<'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_SLASH, '?'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_BACKSLASH, '|'); KEY_CODE_TO_CHAR_SHIFT_ON.put(KeyEvent.KEYCODE_GRAVE, '~'); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMediaActionSound.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMediaActionSound.java index 7d34663d4..82e405054 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMediaActionSound.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMediaActionSound.java @@ -1,5 +1,6 @@ package org.robolectric.shadows; +import static android.os.Build.VERSION_CODES.TIRAMISU; import static org.robolectric.util.reflector.Reflector.reflector; import android.media.MediaActionSound; @@ -28,6 +29,9 @@ public class ShadowMediaActionSound { private static final int NUM_SOUNDS = ALL_SOUNDS.length; private static final Map<Integer, AtomicInteger> playCount = initializePlayCountMap(); + @SuppressWarnings("NonFinalStaticField") + private static boolean mustPlayShutterSoundInternal = false; + private static final HashMap<Integer, AtomicInteger> initializePlayCountMap() { HashMap<Integer, AtomicInteger> playCount = new HashMap<>(); for (int sound : ALL_SOUNDS) { @@ -45,6 +49,11 @@ public class ShadowMediaActionSound { return playCount.get(soundName).get(); } + /** Sets the value returned by {@link MediaActionSound#mustPlayShutterSound()}. */ + public static void setMustPlayShutterSound(boolean mustPlayShutterSound) { + mustPlayShutterSoundInternal = mustPlayShutterSound; + } + @Resetter public static void reset() { synchronized (playCount) { @@ -62,6 +71,11 @@ public class ShadowMediaActionSound { playCount.get(soundName).incrementAndGet(); } + @Implementation(minSdk = TIRAMISU) + protected static boolean mustPlayShutterSound() { + return mustPlayShutterSoundInternal; + } + @ForType(MediaActionSound.class) interface MediaActionSoundReflector { diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativeHardwareRenderer.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativeHardwareRenderer.java index 1bfaa90e7..408ea1c27 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativeHardwareRenderer.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativeHardwareRenderer.java @@ -344,11 +344,13 @@ public class ShadowNativeHardwareRenderer { HardwareRendererNatives.nAllocateBuffers(nativeProxy); } - @Implementation + @Implementation(maxSdk = U.SDK_INT) protected static void nSetForceDark(long nativeProxy, boolean enabled) { HardwareRendererNatives.nSetForceDark(nativeProxy, enabled); } + // TODO(brettchabot): add support for V nSetForceDark(long, int) + @Implementation(minSdk = S) protected static void nSetDisplayDensityDpi(int densityDpi) { HardwareRendererNatives.nSetDisplayDensityDpi(densityDpi); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativePaint.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativePaint.java index 476477679..34cb9ebd9 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativePaint.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowNativePaint.java @@ -868,30 +868,32 @@ public class ShadowNativePaint { advancesIndex); } + /** Requires loose signatures because of RunInfo parameter */ @Implementation(minSdk = V.SDK_INT) protected static float nGetRunCharacterAdvance( - long paintPtr, - char[] text, - int start, - int end, - int contextStart, - int contextEnd, - boolean isRtl, - int offset, - float[] advances, - int advancesIndex, - RectF drawingBounds) { + Object /* long */ paintPtr, + Object /* char[] */ text, + Object /* int */ start, + Object /* int */ end, + Object /* int */ contextStart, + Object /* int */ contextEnd, + Object /* boolean */ isRtl, + Object /* int */ offset, + Object /* float[] */ advances, + Object /* int */ advancesIndex, + Object /* RectF */ drawingBounds, + Object /* RunInfo */ runInfo) { return nGetRunCharacterAdvance( - paintPtr, - text, - start, - end, - contextStart, - contextEnd, - isRtl, - offset, - advances, - advancesIndex); + (long) paintPtr, + (char[]) text, + (int) start, + (int) end, + (int) contextStart, + (int) contextEnd, + (boolean) isRtl, + (int) offset, + (float[]) advances, + (int) advancesIndex); } /** Shadow picker for {@link Paint}. */ diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPaint.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPaint.java index d56a7d7e5..e5bbc8287 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPaint.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPaint.java @@ -577,28 +577,29 @@ public class ShadowPaint { @Implementation(minSdk = V.SDK_INT) protected static float nGetRunCharacterAdvance( - long paintPtr, - char[] text, - int start, - int end, - int contextStart, - int contextEnd, - boolean isRtl, - int offset, - float[] advances, - int advancesIndex, - RectF drawingBounds) { + Object /* long */ paintPtr, + Object /* char[] */ text, + Object /* int */ start, + Object /* int */ end, + Object /* int */ contextStart, + Object /* int */ contextEnd, + Object /* boolean */ isRtl, + Object /* int */ offset, + Object /* float[] */ advances, + Object /* int */ advancesIndex, + Object /* RectF */ drawingBounds, + Object /* RunInfo */ runInfo) { return nGetRunCharacterAdvance( - paintPtr, - text, - start, - end, - contextStart, - contextEnd, - isRtl, - offset, - advances, - advancesIndex); + (long) paintPtr, + (char[]) text, + (int) start, + (int) end, + (int) contextStart, + (int) contextEnd, + (boolean) isRtl, + (int) offset, + (float[]) advances, + (int) advancesIndex); } @Implementation(minSdk = N, maxSdk = O_MR1) diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java index a597c971f..1dfbfeccf 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java @@ -95,6 +95,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.app.ISoundTriggerService; import com.android.internal.app.IVoiceInteractionManagerService; import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.compat.IPlatformCompat; import com.android.internal.os.IDropBoxManagerService; import com.android.internal.statusbar.IStatusBar; import com.android.internal.telephony.ITelephony; @@ -207,6 +208,7 @@ public class ShadowServiceManager { addBinderService(Context.AUTH_SERVICE, IAuthService.class); addBinderService(Context.TETHERING_SERVICE, ITetheringConnector.class); addBinderService("telephony.registry", ITelephonyRegistry.class); + addBinderService(Context.PLATFORM_COMPAT_SERVICE, IPlatformCompat.class); } if (RuntimeEnvironment.getApiLevel() >= S) { addBinderService("permissionmgr", IPermissionManager.class); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSettings.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSettings.java index 552d3101f..16cad3b6a 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSettings.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSettings.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableMap; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -565,6 +566,26 @@ public class ShadowSettings { lockScreenAllowPrivateNotifications ? 1 : 0); } + /** + * Shadow for {@link Settings.Config}. + * + * <p>This shadow is primarily to support {@link android.provider.DeviceConfig}, which queries + * {@link Settings.Config}. {@link android.provider.DeviceConfig} is pure Java code so it's not + * necessary to shadow that directly. + * + * <p>The underlying implementation calls into a system content provider. Starting in Android U, + * the internal logic of Activity is querying DeviceConfig, so to avoid crashes we need to make + * DeviceConfig a no-op. + */ + @Implements(value = Settings.Config.class, isInAndroidSdk = false) + public static class ShadowConfig { + @Implementation(minSdk = R) + protected static Map<String, String> getStrings( + ContentResolver resolver, String namespace, List<String> names) { + return ImmutableMap.of(); + } + } + @Resetter public static void reset() { canDrawOverlays = false; diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStorageManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStorageManager.java index 5bd08191e..929c36aef 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStorageManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStorageManager.java @@ -3,6 +3,7 @@ package org.robolectric.shadows; import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.N; import static android.os.Build.VERSION_CODES.TIRAMISU; +import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; import android.os.UserManager; import android.os.storage.StorageManager; @@ -101,8 +102,9 @@ public class ShadowStorageManager { isFileEncryptionSupported = isSupported; } + // Use maxSdk=U, as this method is planned to be removed from StorageManager in V. @HiddenApi - @Implementation(minSdk = N) + @Implementation(minSdk = N, maxSdk = UPSIDE_DOWN_CAKE) protected static boolean isUserKeyUnlocked(int userId) { ShadowUserManager extract = Shadow.extract(RuntimeEnvironment.getApplication().getSystemService(UserManager.class)); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelecomManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelecomManager.java index 152bbdd37..87dbf83e1 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelecomManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelecomManager.java @@ -6,7 +6,6 @@ import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.N; import static android.os.Build.VERSION_CODES.O; import static android.os.Build.VERSION_CODES.R; -import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Verify.verifyNotNull; import android.annotation.SystemApi; @@ -653,7 +652,10 @@ public class ShadowTelecomManager { @Implementation(minSdk = M) @HiddenApi public void enablePhoneAccount(PhoneAccountHandle handle, boolean isEnabled) { - checkNotNull(getPhoneAccount(handle)).setIsEnabled(isEnabled); + if (getPhoneAccount(handle) == null) { + return; + } + getPhoneAccount(handle).setIsEnabled(isEnabled); } /** diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowVirtualDeviceManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowVirtualDeviceManager.java index a945031ce..ea978511f 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowVirtualDeviceManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowVirtualDeviceManager.java @@ -17,6 +17,7 @@ import android.content.Context; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.IntConsumer; import java.util.stream.Collectors; @@ -125,6 +126,7 @@ public class ShadowVirtualDeviceManager { private int deviceId; private PendingIntent pendingIntent; private Integer pendingIntentResultCode = LAUNCH_SUCCESS; + private final AtomicBoolean isClosed = new AtomicBoolean(false); @Implementation protected void __constructor__( @@ -150,7 +152,13 @@ public class ShadowVirtualDeviceManager { /** Prevents a NPE when calling .close() on a VirtualDevice in unit tests. */ @Implementation - protected void close() {} + protected void close() { + isClosed.set(true); + } + + public boolean isClosed() { + return isClosed.get(); + } VirtualDeviceParams getParams() { return params; diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/WifiUsabilityStatsEntryBuilder.java b/shadows/framework/src/main/java/org/robolectric/shadows/WifiUsabilityStatsEntryBuilder.java index f50eba29f..37b3f8d65 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/WifiUsabilityStatsEntryBuilder.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/WifiUsabilityStatsEntryBuilder.java @@ -2,7 +2,6 @@ package org.robolectric.shadows; import android.net.wifi.WifiUsabilityStatsEntry; import android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats; -import android.net.wifi.WifiUsabilityStatsEntry.LinkStats; import android.net.wifi.WifiUsabilityStatsEntry.RadioStats; import android.net.wifi.WifiUsabilityStatsEntry.RateStats; import android.os.Build.VERSION_CODES; diff --git a/shadows/httpclient/Android.bp b/shadows/httpclient/Android.bp index 526ba2620..29b89f9fc 100644 --- a/shadows/httpclient/Android.bp +++ b/shadows/httpclient/Android.bp @@ -21,7 +21,7 @@ java_library_host { "robolectric-httpclient-4.0.3", "robolectric-httpcore-4.0.1", "robolectric-javax.annotation-api-1.2", - "robolectric-host-android_all_upstream", + "robolectric-host-android_all", "robolectric-host-org_apache_http_legacy_upstream", ], plugins: ["Robolectric_processor_upstream"], @@ -66,7 +66,7 @@ java_test_host { "jsr305", "grpc-java-netty-shaded", //"grpc-netty-shaded-1.16.1-jar", - "robolectric-host-android_all_upstream", + "robolectric-host-android_all", "robolectric-host-org_apache_http_legacy_upstream", "robolectric-host-androidx-test-ext-junit_upstream", ], diff --git a/shadows/multidex/Android.bp b/shadows/multidex/Android.bp index 91d3379c0..c8e214aed 100644 --- a/shadows/multidex/Android.bp +++ b/shadows/multidex/Android.bp @@ -18,7 +18,7 @@ java_library_host { "Robolectric_shadowapi_upstream", "robolectric-host-android-support-multidex_upstream", "robolectric-javax.annotation-api-1.2", - "robolectric-host-android_all_upstream", + "robolectric-host-android_all", ], plugins: ["Robolectric_processor_upstream"], javacflags: ["-Aorg.robolectric.annotation.processing.shadowPackage=org.robolectric.shadows.multidex"], diff --git a/shadows/playservices/Android.bp b/shadows/playservices/Android.bp index 4b6635e65..e63268c40 100644 --- a/shadows/playservices/Android.bp +++ b/shadows/playservices/Android.bp @@ -10,7 +10,7 @@ // "Robolectric_shadowapi_upstream", // "robolectric-javax.annotation-api-1.2", // "guava", -// "robolectric-host-android_all_upstream", +// "robolectric-host-android_all", // compileOnly "com.android.support:support-fragment:28.0.0" // compileOnly "com.google.android.gms:play-services-base:8.4.0" diff --git a/shadows/versioning/Android.bp b/shadows/versioning/Android.bp index 98a1ad353..3d44f1157 100644 --- a/shadows/versioning/Android.bp +++ b/shadows/versioning/Android.bp @@ -20,7 +20,7 @@ java_library_host { "Robolectric_utils_upstream", "jsr305", ], - libs: ["robolectric-host-android_all_upstream"], + libs: ["robolectric-host-android_all"], } //############################################# diff --git a/soong/Android.bp b/soong/Android.bp new file mode 100644 index 000000000..d725fd118 --- /dev/null +++ b/soong/Android.bp @@ -0,0 +1,32 @@ +// Copyright (C) 2019 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "external_robolectric-shadows_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["external_robolectric_license"], +} + +bootstrap_go_package { + name: "soong-robolectric", + pkgPath: "android/soong/robolectric", + srcs: ["robolectric.go"], + pluginFor: ["soong_build"], + deps: [ + "soong-android", + ], +} diff --git a/soong/robolectric.go b/soong/robolectric.go new file mode 100644 index 000000000..cadeb0fad --- /dev/null +++ b/soong/robolectric.go @@ -0,0 +1,101 @@ +// Copyright (C) 2019 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 robolectric + +import ( + "fmt" + "strings" + + "android/soong/android" +) + +var pctx = android.NewPackageContext("android/soong/robolectric") + +func init() { + pctx.Import("android/soong/android") + android.RegisterModuleType("robolectric_build_props", buildPropsFactory) +} + +type buildProps struct { + android.ModuleBase + output android.WritablePath +} + +var _ android.SourceFileProducer = (*buildProps)(nil) + +func (b *buildProps) Srcs() android.Paths { + return android.Paths{b.output} +} + +func (b *buildProps) GenerateAndroidBuildActions(ctx android.ModuleContext) { + + displayID := fmt.Sprintf("robolectric %s %s", + ctx.Config().PlatformVersionName(), + ctx.Config().BuildId()) + + lines := []string{ + "# build properties autogenerated by robolectric.go", + "", + "ro.build.id=" + ctx.Config().BuildId(), + "ro.build.display.id=" + displayID, + "ro.product.name=robolectric", + "ro.product.device=robolectric", + "ro.product.board=robolectric", + "ro.product.manufacturer=robolectric", + "ro.product.brand=robolectric", + "ro.product.model=robolectric", + "ro.hardware=robolectric", + "ro.build.version.security_patch=" + ctx.Config().PlatformSecurityPatch(), + "ro.build.version.sdk=" + ctx.Config().PlatformSdkVersion().String(), + "ro.build.version.release=" + ctx.Config().PlatformVersionName(), + "ro.build.version.preview_sdk=" + ctx.Config().PlatformPreviewSdkVersion(), + // We don't have the API fingerprint available, just use the preview SDK version. + "ro.build.version.preview_sdk_fingerprint=" + ctx.Config().PlatformPreviewSdkVersion(), + "ro.build.version.codename=" + ctx.Config().PlatformSdkCodename(), + "ro.build.version.all_codenames=" + strings.Join(ctx.Config().PlatformVersionActiveCodenames(), ","), + "ro.build.version.min_supported_target_sdk=" + ctx.Config().PlatformMinSupportedTargetSdkVersion(), + "ro.build.version.base_os=" + ctx.Config().PlatformBaseOS(), + "ro.build.tags=robolectric", + "ro.build.fingerprint=robolectric", + "ro.build.characteristics=robolectric", + "", + "# for backwards-compatibility reasons, set CPUs to unknown/ARM", + "ro.product.cpu.abi=unknown", + "ro.product.cpu.abi2=unknown", + "ro.product.cpu.abilist=armeabi-v7a", + "ro.product.cpu.abilist32=armeabi-v7a,armeabi", + "ro.product.cpu.abilist64=armeabi-v7a,armeabi", + "", + "# temp fix for robolectric freezing issue b/150011638", + "persist.debug.new_insets=0", + } + + b.output = android.PathForModuleGen(ctx, "build.prop") + + rule := android.NewRuleBuilder(pctx, ctx) + + rule.Command().Text("rm").Flag("-f").Output(b.output) + for _, l := range lines { + rule.Command().Text("echo").Text("'" + l + "'").Text(">>").Output(b.output) + } + + rule.Build("build_prop", "robolectric build.prop") +} + +func buildPropsFactory() android.Module { + module := &buildProps{} + android.InitAndroidModule(module) + return module +} diff --git a/testapp/Android.bp b/testapp/Android.bp index a11ba44f2..a8c52b815 100644 --- a/testapp/Android.bp +++ b/testapp/Android.bp @@ -11,7 +11,10 @@ android_library { platform_apis: true, manifest: "src/main/AndroidManifest.xml", optimize: { - enabled: false + enabled: false, + }, + lint: { + baseline_filename: "lint-baseline.xml", }, } @@ -38,4 +41,7 @@ android_app { kotlincflags: ["-Xjvm-default=all"], plugins: ["dagger2-compiler"], + lint: { + baseline_filename: "lint-baseline.xml", + }, } diff --git a/testapp/lint-baseline.xml b/testapp/lint-baseline.xml new file mode 100644 index 000000000..957e3d023 --- /dev/null +++ b/testapp/lint-baseline.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01"> + + <issue + id="NewApi" + message="`<vector>` requires API level 21 (current min is 16) or building with Android Gradle plugin 1.4.0 or higher" + errorLine1='<vector xmlns:android="http://schemas.android.com/apk/res/android"' + errorLine2=" ~~~~~~"> + <location + file="external/robolectric/testapp/src/main/res/drawable-anydpi/an_image_or_vector.xml" + line="2" + column="2"/> + </issue> + + <issue + id="NewApi" + message="`<vector>` requires API level 21 (current min is 16) or building with Android Gradle plugin 1.4.0 or higher" + errorLine1='<vector xmlns:android="http://schemas.android.com/apk/res/android"' + errorLine2=" ~~~~~~"> + <location + file="external/robolectric/testapp/src/main/res/drawable/vector.xml" + line="1" + column="2"/> + </issue> + +</issues>
\ No newline at end of file |