aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:01:56 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:01:56 +0000
commite6603d13b1ced9fa093927daed2aea8d1600a405 (patch)
treeb525d4e63285a47329bac37c594a6b9eb3980bfa
parentdc10306162ecb0c009b02aa679ea3f22d68dbdb8 (diff)
parentf0abff70c16cd0a8f16a68cf6b24adb083fa7ab9 (diff)
downloadrobolectric-shadows-e6603d13b1ced9fa093927daed2aea8d1600a405.tar.gz
Snap for 10447354 from f0abff70c16cd0a8f16a68cf6b24adb083fa7ab9 to mainline-cellbroadcast-releaseaml_cbr_341311010aml_cbr_341110000aml_cbr_341011000aml_cbr_340914000
Change-Id: I63a263f2adaaacbb4a746a9124c35d7e819e647b
-rw-r--r--Android.bp28
-rw-r--r--junit/Android.bp6
-rw-r--r--processor/Android.bp11
-rw-r--r--processor/AndroidTest.xml2
-rw-r--r--processor/sdks.txt7
-rw-r--r--processor/src/main/java/org/robolectric/annotation/processing/validator/SdkStore.java13
-rw-r--r--resources/Android.bp5
-rw-r--r--resources/src/main/java/org/robolectric/res/android/LoadedArsc.java12
-rw-r--r--resources/src/main/java/org/robolectric/res/android/ResTable.java11
-rw-r--r--resources/src/main/java/org/robolectric/res/android/ResourceTypes.java9
-rw-r--r--robolectric/Android.bp18
-rw-r--r--robolectric/src/main/java/org/robolectric/android/internal/LocalActivityInvoker.java18
-rw-r--r--robolectric/src/main/java/org/robolectric/android/internal/ParallelUniverse.java3
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowDateIntervalFormatTest.java6
-rw-r--r--robotest-internal.mk2
-rwxr-xr-xrobotest.sh6
-rw-r--r--run_robolectric_module_tests.mk11
-rw-r--r--run_robotests.mk6
-rw-r--r--sandbox/Android.bp17
-rw-r--r--sandbox/AndroidTest.xml1
-rw-r--r--sandbox/src/main/java/org/robolectric/internal/bytecode/ClassInstrumentor.java4
-rw-r--r--sandbox/src/main/java/org/robolectric/internal/bytecode/ProxyMaker.java75
-rw-r--r--sandbox/src/main/java/org/robolectric/internal/bytecode/RobolectricGeneratorAdapter.java2
-rw-r--r--shadowapi/Android.bp5
-rw-r--r--shadowapi/AndroidTest.xml2
-rw-r--r--shadowapi/src/main/java/org/robolectric/shadow/api/Shadow.java2
-rw-r--r--shadowapi/src/main/java/org/robolectric/util/ReflectionHelpers.java29
-rw-r--r--shadowapi/src/test/java/org/robolectric/util/ReflectionHelpersTest.java32
-rw-r--r--shadows/framework/Android.bp7
-rw-r--r--shadows/framework/src/main/java/org/robolectric/android/controller/ActivityController.java8
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ImageUtil.java20
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowAlarmManager.java17
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormat.java5
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormatU.java42
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowImageDecoder.java20
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowInputManager.java4
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowSQLiteConnection.java10
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensor.java36
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensorManager.java6
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java4
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowSettings.java17
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsbManager.java14
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowUserManager.java38
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowViewRootImpl.java15
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java5
-rw-r--r--shadows/httpclient/Android.bp6
-rw-r--r--shadows/supportv4/Android.bp6
47 files changed, 500 insertions, 123 deletions
diff --git a/Android.bp b/Android.bp
index 33d2ea864..c12f01202 100644
--- a/Android.bp
+++ b/Android.bp
@@ -54,27 +54,6 @@ robolectric_build_props {
name: "robolectric_build_props",
}
-// package the framework raw/uncompiled resources and assets into a jar
-// This logic can be removed once the transition to binary resources is complete
-java_library {
- name: "robolectric_framework_raw_res_orig",
- java_resources: [":robolectric_framework_raw_res_files"],
-}
-
-// Move the raw/uncompiled resources and assets into raw-res/
-// This logic can be removed once the transition to binary resources is complete
-java_genrule_host {
- name: "robolectric_framework_raw_res",
- out: ["robolectric_framework_raw_res.jar"],
- srcs: [":robolectric_framework_raw_res_orig"],
- tools: ["zip2zip"],
- cmd: "$(location zip2zip) " +
- "-i $(location :robolectric_framework_raw_res_orig) " +
- "-o $(location robolectric_framework_raw_res.jar) " +
- "-x META-INF/**/* " +
- "**/*:raw-res/",
-}
-
java_genrule_host {
name: "robolectric_framework_res",
tools: ["zip2zip"],
@@ -115,7 +94,6 @@ java_library_host {
"robolectric_android-all-device-deps",
"robolectric_tzdata",
"robolectric_framework_res",
- "robolectric_framework_raw_res",
],
dist: {
targets: [
@@ -155,11 +133,11 @@ java_library_host {
"Robolectric_sandbox",
"Robolectric_junit",
"Robolectric_utils",
- "asm-9.2",
+ "ow2-asm",
"junit",
- "asm-tree-9.2",
+ "ow2-asm-tree",
"guava",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"bouncycastle-unbundled",
"robolectric-sqlite4java-0.282",
"hamcrest",
diff --git a/junit/Android.bp b/junit/Android.bp
index 38ab52978..bee751423 100644
--- a/junit/Android.bp
+++ b/junit/Android.bp
@@ -18,12 +18,12 @@ java_library_host {
"Robolectric_shadowapi",
"Robolectric_sandbox",
"Robolectric_utils",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"guava",
- "asm-tree-9.2",
+ "ow2-asm-tree",
"hamcrest",
"junit",
- "asm-9.2",
+ "ow2-asm",
"jsr305",
],
srcs: ["src/main/java/**/*.java"],
diff --git a/processor/Android.bp b/processor/Android.bp
index 7dbdbc02e..a61af5000 100644
--- a/processor/Android.bp
+++ b/processor/Android.bp
@@ -21,16 +21,17 @@ java_library_host {
static_libs: [
"Robolectric_annotations",
"Robolectric_shadowapi",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"guava",
- "asm-tree-9.2",
- "gson-prebuilt-jar",
- "asm-9.2",
+ "ow2-asm-tree",
+ "gson",
+ "ow2-asm",
"jsr305",
],
openjdk9: {
javacflags: [
+ "--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
],
@@ -64,7 +65,7 @@ java_test_host {
"objenesis",
"junit",
"truth-prebuilt",
- "gson-prebuilt-jar",
+ "gson",
"jsr305",
],
diff --git a/processor/AndroidTest.xml b/processor/AndroidTest.xml
index 96fc65801..7f31410b0 100644
--- a/processor/AndroidTest.xml
+++ b/processor/AndroidTest.xml
@@ -18,6 +18,8 @@
<option name="jar" value="Robolectric_processor_tests.jar" />
<option name="java-flags" value="-Drobolectric.offline=true" />
<option name="java-flags" value="-Drobolectric.resourcesMode=binary" />
+ <option name="java-flags" value="--add-modules=jdk.compiler"/>
+ <option name="java-flags" value="--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"/>
<option name="exclude-paths" value="java/" />
</test>
</configuration>
diff --git a/processor/sdks.txt b/processor/sdks.txt
index 5444e46e9..3b4b80de4 100644
--- a/processor/sdks.txt
+++ b/processor/sdks.txt
@@ -10,7 +10,8 @@ prebuilts/misc/common/robolectric/android-all/android-all-7.1.0_r7-robolectric-r
prebuilts/misc/common/robolectric/android-all/android-all-8.0.0_r4-robolectric-r1.jar
prebuilts/misc/common/robolectric/android-all/android-all-8.1.0-robolectric-4611349.jar
prebuilts/misc/common/robolectric/android-all/android-all-9-robolectric-4913185-2.jar
-prebuilts/misc/common/robolectric/android-all/android-all-9plus-robolectric-5616371.jar
prebuilts/misc/common/robolectric/android-all/android-all-10-robolectric-5803371.jar
-prebuilts/misc/common/robolectric/android-all/android-all-R-beta2-robolectric-6625208.jar
-prebuilts/misc/common/robolectric/android-all/android-all-S-beta3-robolectric-7541949.jar
+prebuilts/misc/common/robolectric/android-all/android-all-11-robolectric-6757853.jar
+prebuilts/misc/common/robolectric/android-all/android-all-12-robolectric-7732740.jar
+prebuilts/misc/common/robolectric/android-all/android-all-12.1-robolectric-8229987.jar
+prebuilts/misc/common/robolectric/android-all/android-all-13-robolectric-9030017.jar
diff --git a/processor/src/main/java/org/robolectric/annotation/processing/validator/SdkStore.java b/processor/src/main/java/org/robolectric/annotation/processing/validator/SdkStore.java
index 1f11dbb3a..b1d8cb826 100644
--- a/processor/src/main/java/org/robolectric/annotation/processing/validator/SdkStore.java
+++ b/processor/src/main/java/org/robolectric/annotation/processing/validator/SdkStore.java
@@ -5,8 +5,6 @@ import static org.robolectric.annotation.processing.validator.ImplementsValidato
import static org.robolectric.annotation.processing.validator.ImplementsValidator.STATIC_INITIALIZER_METHOD_NAME;
import static org.robolectric.annotation.processing.validator.ImplementsValidator.getClassFQName;
-import com.sun.tools.javac.code.Type.ArrayType;
-import com.sun.tools.javac.code.Type.TypeVar;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
@@ -29,7 +27,10 @@ import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -100,10 +101,10 @@ class SdkStore {
}
private static String canonicalize(TypeMirror typeMirror) {
- if (typeMirror instanceof TypeVar) {
- return ((TypeVar) typeMirror).getUpperBound().toString();
- } else if (typeMirror instanceof ArrayType) {
- return canonicalize(((ArrayType) typeMirror).elemtype) + "[]";
+ if (typeMirror.getKind() == TypeKind.TYPEVAR) {
+ return ((TypeVariable) typeMirror).getUpperBound().toString();
+ } else if (typeMirror.getKind() == TypeKind.ARRAY) {
+ return canonicalize(((ArrayType) typeMirror).getComponentType()) + "[]";
} else {
return typeMirror.toString();
}
diff --git a/resources/Android.bp b/resources/Android.bp
index 76c2c052b..3d08f907f 100644
--- a/resources/Android.bp
+++ b/resources/Android.bp
@@ -20,6 +20,11 @@ java_library_host {
"guava",
"jsr305",
],
+ errorprone: {
+ javacflags: [
+ "-Xep:EmptyTopLevelDeclaration:WARN",
+ ],
+ },
}
//#############################################
diff --git a/resources/src/main/java/org/robolectric/res/android/LoadedArsc.java b/resources/src/main/java/org/robolectric/res/android/LoadedArsc.java
index 09f79572f..0c41714f6 100644
--- a/resources/src/main/java/org/robolectric/res/android/LoadedArsc.java
+++ b/resources/src/main/java/org/robolectric/res/android/LoadedArsc.java
@@ -400,15 +400,17 @@ public class LoadedArsc {
// });
ResTable_sparseTypeEntry result = null;
for (int i = 0; i < entry_count; i++) {
- ResTable_sparseTypeEntry entry = new ResTable_sparseTypeEntry(type_chunk.myBuf(),
- type_chunk.myOffset() + offsets_offset);
- if (entry.idxOrOffset >= entry_index) {
+ ResTable_sparseTypeEntry entry =
+ new ResTable_sparseTypeEntry(
+ type_chunk.myBuf(),
+ type_chunk.myOffset() + offsets_offset + i * ResTable_sparseTypeEntry.SIZEOF);
+ if (entry.idx >= entry_index) {
result = entry;
break;
}
}
- if (result == null || dtohs(result.idxOrOffset) != entry_index) {
+ if (result == null || dtohs(result.idx) != entry_index) {
// No entry found.
return ResTable_type.NO_ENTRY;
}
@@ -416,7 +418,7 @@ public class LoadedArsc {
// Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
// the real offset divided by 4.
// return int{dtohs(result.offset)} * 4u;
- return dtohs(result.idxOrOffset) * 4;
+ return dtohs(result.offset) * 4;
}
// This type is encoded as a dense array.
diff --git a/resources/src/main/java/org/robolectric/res/android/ResTable.java b/resources/src/main/java/org/robolectric/res/android/ResTable.java
index dbb2c6fc1..2176cafab 100644
--- a/resources/src/main/java/org/robolectric/res/android/ResTable.java
+++ b/resources/src/main/java/org/robolectric/res/android/ResTable.java
@@ -630,18 +630,18 @@ public class ResTable {
sparseIndices,
new ResTable_sparseTypeEntry(buf, sparseIndices.myOffset() + dtohl(thisType.entryCount)),
new ResTable_sparseTypeEntry(buf, realEntryIndex),
- (a, b) -> dtohs(a.idxOrOffset) < dtohs(b.idxOrOffset));
+ (a, b) -> dtohs(a.idx) < dtohs(b.idx));
// if (result == sparseIndices + dtohl(thisType.entryCount)
// || dtohs(result.idx) != realEntryIndex) {
if (result.myOffset() == sparseIndices.myOffset() + dtohl(thisType.entryCount)
- || dtohs(result.idxOrOffset) != realEntryIndex) {
+ || dtohs(result.idx) != realEntryIndex) {
// No entry found.
continue;
}
// Extract the offset from the entry. Each offset must be a multiple of 4
// so we store it as the real offset divided by 4.
// thisOffset = dtohs(result->offset) * 4u;
- thisOffset = dtohs(result.idxOrOffset) * 4;
+ thisOffset = dtohs(result.offset) * 4;
} else {
if (realEntryIndex >= dtohl(thisType.entryCount)) {
// Entry does not exist.
@@ -986,11 +986,6 @@ public class ResTable {
}
Type t = typeList.get(typeList.size() - 1);
- if (newEntryCount != t.entryCount) {
- ALOGE("ResTable_type entry count inconsistent: given %d, previously %d",
- (int) newEntryCount, (int) t.entryCount);
- return (mError = BAD_TYPE);
- }
if (t._package_ != _package) {
ALOGE("No TypeSpec for type %d", type.id);
diff --git a/resources/src/main/java/org/robolectric/res/android/ResourceTypes.java b/resources/src/main/java/org/robolectric/res/android/ResourceTypes.java
index ce12e4b3a..5438f33cb 100644
--- a/resources/src/main/java/org/robolectric/res/android/ResourceTypes.java
+++ b/resources/src/main/java/org/robolectric/res/android/ResourceTypes.java
@@ -1259,12 +1259,13 @@ public static class ResTable_ref
* An entry in a ResTable_type with the flag `FLAG_SPARSE` set.
*/
static class ResTable_sparseTypeEntry extends WithOffset {
- public static final int SIZEOF = 6;
+ public static final int SIZEOF = 4;
// Holds the raw uint32_t encoded value. Do not read this.
int entry;
- short idxOrOffset;
+ short idx;
+ short offset;
// struct {
// The index of the entry.
// uint16_t idx;
@@ -1276,8 +1277,8 @@ public static class ResTable_ref
public ResTable_sparseTypeEntry(ByteBuffer buf, int offset) {
super(buf, offset);
- entry = buf.getInt(offset);
- idxOrOffset = buf.getShort(offset + 4);
+ this.idx = buf.getShort(offset);
+ this.offset = buf.getShort(offset + 2);
}
};
diff --git a/robolectric/Android.bp b/robolectric/Android.bp
index ab08b47ff..4d2639d15 100644
--- a/robolectric/Android.bp
+++ b/robolectric/Android.bp
@@ -25,13 +25,13 @@ java_library_host {
"robolectric-host-androidx-test-monitor",
"robolectric-maven-ant-tasks-2.1.3",
"bouncycastle-unbundled",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"guava",
"robolectric-xstream-1.4.8",
- "asm-tree-9.2",
+ "ow2-asm-tree",
"junit",
"robolectric-ant-1.8.0",
- "asm-9.2",
+ "ow2-asm",
"jsr305",
"robolectric-host-android_all",
],
@@ -70,17 +70,17 @@ java_test_host {
"bouncycastle-unbundled",
"hamcrest",
"robolectric-sqlite4java-0.282",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"robolectric-diffutils-1.3.0",
"guava",
"objenesis",
"robolectric-xstream-1.4.8",
- "asm-tree-9.2",
+ "ow2-asm-tree",
"junit",
"icu4j",
"truth-prebuilt",
"robolectric-ant-1.8.0",
- "asm-9.2",
+ "ow2-asm",
"jsr305",
],
libs: ["robolectric-host-android_all"],
@@ -88,4 +88,10 @@ java_test_host {
test_options: {
unit_test: false,
},
+
+ errorprone: {
+ javacflags: [
+ "-Xep:ReturnValueIgnored:WARN",
+ ],
+ },
}
diff --git a/robolectric/src/main/java/org/robolectric/android/internal/LocalActivityInvoker.java b/robolectric/src/main/java/org/robolectric/android/internal/LocalActivityInvoker.java
index a3119e021..d44a05f42 100644
--- a/robolectric/src/main/java/org/robolectric/android/internal/LocalActivityInvoker.java
+++ b/robolectric/src/main/java/org/robolectric/android/internal/LocalActivityInvoker.java
@@ -29,6 +29,8 @@ public class LocalActivityInvoker implements ActivityInvoker {
@Nullable private ActivityController<? extends Activity> controller;
+ private boolean isActivityLaunchedForResult = false;
+
@Override
public void startActivity(Intent intent, @Nullable Bundle activityOptions) {
startActivity(intent);
@@ -54,7 +56,23 @@ public class LocalActivityInvoker implements ActivityInvoker {
}
@Override
+ public void startActivityForResult(Intent intent, @Nullable Bundle activityOptions) {
+ startActivityForResult(intent);
+ }
+
+ @Override
+ public void startActivityForResult(Intent intent) {
+ isActivityLaunchedForResult = true;
+ startActivity(intent);
+ }
+
+ @Override
public ActivityResult getActivityResult() {
+ if (!isActivityLaunchedForResult) {
+ throw new IllegalStateException(
+ "You must start Activity first. Make sure you are using launchActivityForResult() to"
+ + " launch an Activity.");
+ }
checkNotNull(controller);
checkState(controller.get().isFinishing(), "You must finish your Activity first");
ShadowActivity shadowActivity = Shadow.extract(controller.get());
diff --git a/robolectric/src/main/java/org/robolectric/android/internal/ParallelUniverse.java b/robolectric/src/main/java/org/robolectric/android/internal/ParallelUniverse.java
index e74a03cdb..5de048893 100644
--- a/robolectric/src/main/java/org/robolectric/android/internal/ParallelUniverse.java
+++ b/robolectric/src/main/java/org/robolectric/android/internal/ParallelUniverse.java
@@ -420,7 +420,8 @@ public class ParallelUniverse implements ParallelUniverseInterface {
* Create a file system safe directory path name for the current test.
*/
private String createTestDataDirRootPath(Method method) {
- return method.getClass().getSimpleName() + "_" + method.getName().replaceAll("[^a-zA-Z0-9.-]", "_");
+ return method.getDeclaringClass().getSimpleName() + "_" +
+ method.getName().replaceAll("[^a-zA-Z0-9.-]", "_");
}
@Override
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowDateIntervalFormatTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowDateIntervalFormatTest.java
index bde0e7263..f9721e464 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowDateIntervalFormatTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowDateIntervalFormatTest.java
@@ -1,6 +1,6 @@
package org.robolectric.shadows;
-import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
import static com.google.common.truth.Truth.assertThat;
import android.icu.text.DateFormat;
@@ -12,13 +12,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
-import libcore.icu.DateIntervalFormat;
+import android.text.format.DateIntervalFormat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
@RunWith(AndroidJUnit4.class)
-@Config(minSdk = M)
+@Config(minSdk = UPSIDE_DOWN_CAKE)
public class ShadowDateIntervalFormatTest {
@Test
public void testDateInterval_FormatDateRange() throws ParseException {
diff --git a/robotest-internal.mk b/robotest-internal.mk
index 77e173024..34db668c7 100644
--- a/robotest-internal.mk
+++ b/robotest-internal.mk
@@ -25,7 +25,7 @@ $(my_target_output): PRIVATE_MODULE := $(LOCAL_MODULE)
$(my_target_output): PRIVATE_TESTS := $(my_tests)
$(my_target_output): PRIVATE_JARS := $(my_jars)
$(my_target_output): PRIVATE_JAVA_ARGS := $(my_java_args)
-$(my_target_output): PRIVATE_JAVA_PATH := $(ANDROID_JAVA11_HOME)/bin:
+$(my_target_output): PRIVATE_JAVA_PATH := $(ANDROID_JAVA17_HOME)/bin:
$(my_target_output): PRIVATE_ROBOLECTRIC_PATH := $(my_robolectric_path)
$(my_target_output): PRIVATE_ROBOLECTRIC_SCRIPT_PATH := $(my_robolectric_script_path)
$(my_target_output): PRIVATE_TARGET_MESSAGE := $(my_target_message)
diff --git a/robotest.sh b/robotest.sh
index e95f09df3..df5570bcf 100755
--- a/robotest.sh
+++ b/robotest.sh
@@ -73,6 +73,8 @@ function junit() {
# Remove the timeout so Robolectric doesn't get killed while debugging
local debug_timeout="0"
fi
+ # For --add-opens jdk.internal.util.random see b/238100560.
+ # For --add-opens java.io see b/251387255.
local command=(
"${PRIVATE_ROBOLECTRIC_SCRIPT_PATH}/java-timeout"
"${debug_timeout:-${PRIVATE_TIMEOUT}}"
@@ -84,6 +86,10 @@ function junit() {
-Drobolectric.conscryptMode=OFF
-Drobolectric.logging.enabled=true
-cp "$classpath"
+ --add-opens=java.base/java.lang=ALL-UNNAMED
+ --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
+ --add-opens=java.base/jdk.internal.util.random=ALL-UNNAMED
+ --add-opens=java.base/java.io=ALL-UNNAMED
com.android.junitxml.JUnitXmlRunner
)
echo "${command[@]}" "$@"
diff --git a/run_robolectric_module_tests.mk b/run_robolectric_module_tests.mk
index 96f1cb59b..0050c7326 100644
--- a/run_robolectric_module_tests.mk
+++ b/run_robolectric_module_tests.mk
@@ -51,9 +51,11 @@ copy_android_all_jar_pairs := \
$(android_all_source_dir)/android-all-8.0.0_r4-robolectric-r1.jar:$(android_all_target_dir)/android-all-8.0.0_r4-robolectric-r1.jar \
$(android_all_source_dir)/android-all-8.1.0-robolectric-4611349.jar:$(android_all_target_dir)/android-all-8.1.0-robolectric-4611349.jar \
$(android_all_source_dir)/android-all-9-robolectric-4913185-2.jar:$(android_all_target_dir)/android-all-9-robolectric-4913185-2.jar \
- $(android_all_source_dir)/android-all-9plus-robolectric-5616371.jar:$(android_all_target_dir)/android-all-9plus-robolectric-5616371.jar \
- $(android_all_source_dir)/android-all-R-beta2-robolectric-6625208.jar:$(android_all_target_dir)/android-all-R-beta2-robolectric-6625208.jar \
- $(android_all_source_dir)/android-all-S-beta3-robolectric-7541949.jar:$(android_all_target_dir)/android-all-S-beta3-robolectric-7541949.jar \
+ $(android_all_source_dir)/android-all-10-robolectric-5803371.jar:$(android_all_target_dir)/android-all-10-robolectric-5803371.jar \
+ $(android_all_source_dir)/android-all-11-robolectric-6757853.jar:$(android_all_target_dir)/android-all-11-robolectric-6757853.jar \
+ $(android_all_source_dir)/android-all-12-robolectric-7732740.jar:$(android_all_target_dir)/android-all-12-robolectric-7732740.jar \
+ $(android_all_source_dir)/android-all-12.1-robolectric-8229987.jar:$(android_all_target_dir)/android-all-12.1-robolectric-8229987.jar \
+ $(android_all_source_dir)/android-all-13-robolectric-9030017.jar:$(android_all_target_dir)/android-all-13-robolectric-9030017.jar \
$(local_android_all_source_jar):$(android_all_target_dir)/android-all-current-robolectric-r0.jar
copy_android_all_jars := $(call copy-many-files, $(copy_android_all_jar_pairs))
@@ -91,6 +93,9 @@ $(LOCAL_BUILT_MODULE): $(copy_test_resource_files) $(copy_android_all_jars) $(cl
-Drobolectric.resourcesMode=binary \
-Drobolectric-tests.base-dir=$(private_test_base_dir) \
-Drobolectric.dependency.dir=$(private_android_all_dir) \
+ --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
+ --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
+ --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
$(private_debug_test_args) \
-cp $(private_host_jdk_tools_jar):$(private_test_base_dir):$(private_classpath_jars) \
org.junit.runner.JUnitCore \
diff --git a/run_robotests.mk b/run_robotests.mk
index b5a6ee44e..cb0db1b74 100644
--- a/run_robotests.mk
+++ b/run_robotests.mk
@@ -135,8 +135,10 @@ ifneq ($(DISABLE_ROBO_RUN_TESTS),true)
$(android_all_lib_path)/android-all-8.1.0-robolectric-4611349.jar:$(my_robolectric_path)/android-all-8.1.0-robolectric-4611349.jar \
$(android_all_lib_path)/android-all-9-robolectric-4913185-2.jar:$(my_robolectric_path)/android-all-9-robolectric-4913185-2.jar \
$(android_all_lib_path)/android-all-10-robolectric-5803371.jar:$(my_robolectric_path)/android-all-10-robolectric-5803371.jar \
- $(android_all_lib_path)/android-all-R-beta2-robolectric-6625208.jar:$(my_robolectric_path)/android-all-R-beta2-robolectric-6625208.jar \
- $(android_all_lib_path)/android-all-S-beta3-robolectric-7541949.jar:$(my_robolectric_path)/android-all-S-beta3-robolectric-7541949.jar \
+ $(android_all_lib_path)/android-all-11-robolectric-6757853.jar:$(my_robolectric_path)/android-all-11-robolectric-6757853.jar \
+ $(android_all_lib_path)/android-all-12-robolectric-7732740.jar:$(my_robolectric_path)/android-all-12-robolectric-7732740.jar \
+ $(android_all_lib_path)/android-all-12.1-robolectric-8229987.jar:$(my_robolectric_path)/android-all-12.1-robolectric-8229987.jar \
+ $(android_all_lib_path)/android-all-13-robolectric-9030017.jar:$(my_robolectric_path)/android-all-13-robolectric-9030017.jar \
$(local_android_all_source_jar):$(my_robolectric_path)/android-all-current-robolectric-r0.jar
copy_android_all_jars := $(call copy-many-files, $(copy_android_all_jar_pairs))
diff --git a/sandbox/Android.bp b/sandbox/Android.bp
index ae6aa36cf..fafcdef53 100644
--- a/sandbox/Android.bp
+++ b/sandbox/Android.bp
@@ -18,10 +18,10 @@ java_library_host {
"Robolectric_annotations",
"Robolectric_shadowapi",
"Robolectric_utils",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"guava",
- "asm-tree-9.2",
- "asm-9.2",
+ "ow2-asm-tree",
+ "ow2-asm",
"jsr305",
],
}
@@ -41,14 +41,19 @@ java_test_host {
"Robolectric_utils",
"mockito",
"hamcrest",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"guava",
"objenesis",
- "asm-tree-9.2",
+ "ow2-asm-tree",
"junit",
"truth-prebuilt",
- "asm-9.2",
+ "ow2-asm",
"jsr305",
],
test_suites: ["general-tests"],
+ errorprone: {
+ javacflags: [
+ "-Xep:ReturnValueIgnored:WARN",
+ ],
+ },
}
diff --git a/sandbox/AndroidTest.xml b/sandbox/AndroidTest.xml
index 932f08385..f8f3c8780 100644
--- a/sandbox/AndroidTest.xml
+++ b/sandbox/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="jar" value="Robolectric_sandbox_tests.jar" />
<option name="java-flags" value="-Drobolectric.offline=true" />
<option name="java-flags" value="-Drobolectric.resourcesMode=binary" />
+ <option name="java-flags" value="--add-opens=java.base/java.lang=ALL-UNNAMED"/>
<option name="exclude-paths" value="java/" />
</test>
</configuration>
diff --git a/sandbox/src/main/java/org/robolectric/internal/bytecode/ClassInstrumentor.java b/sandbox/src/main/java/org/robolectric/internal/bytecode/ClassInstrumentor.java
index 8997be4b2..ebe36c66f 100644
--- a/sandbox/src/main/java/org/robolectric/internal/bytecode/ClassInstrumentor.java
+++ b/sandbox/src/main/java/org/robolectric/internal/bytecode/ClassInstrumentor.java
@@ -42,7 +42,7 @@ public abstract class ClassInstrumentor {
final InstrumentationConfiguration config,
ClassNodeProvider classNodeProvider) {
ClassNode classNode =
- new ClassNode(Opcodes.ASM4) {
+ new ClassNode(Opcodes.ASM9) {
@Override
public FieldVisitor visitField(
int access, String name, String desc, String signature, Object value) {
@@ -366,7 +366,7 @@ public abstract class ClassInstrumentor {
//todo rename
private MethodNode redirectorMethod(MutableClass mutableClass, MethodNode method, String newName) {
- MethodNode redirector = new MethodNode(Opcodes.ASM4, newName, method.desc, method.signature, exceptionArray(method));
+ MethodNode redirector = new MethodNode(Opcodes.ASM9, newName, method.desc, method.signature, exceptionArray(method));
redirector.access = method.access & ~(Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_FINAL);
makeMethodPrivate(redirector);
RobolectricGeneratorAdapter generator = new RobolectricGeneratorAdapter(redirector);
diff --git a/sandbox/src/main/java/org/robolectric/internal/bytecode/ProxyMaker.java b/sandbox/src/main/java/org/robolectric/internal/bytecode/ProxyMaker.java
index 9cf0c829d..67dbdf2d7 100644
--- a/sandbox/src/main/java/org/robolectric/internal/bytecode/ProxyMaker.java
+++ b/sandbox/src/main/java/org/robolectric/internal/bytecode/ProxyMaker.java
@@ -6,6 +6,9 @@ import static org.objectweb.asm.Opcodes.ACC_SUPER;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.V1_7;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.objectweb.asm.ClassWriter;
@@ -16,18 +19,68 @@ import sun.misc.Unsafe;
public class ProxyMaker {
private static final String TARGET_FIELD = "__proxy__";
+ private static final Class UNSAFE_CLASS = Unsafe.class;
+ private static final Class LOOKUP_CLASS = MethodHandles.Lookup.class;
private static final Unsafe UNSAFE;
+ private static final java.lang.reflect.Method DEFINE_ANONYMOUS_CLASS;
+
+ private static final MethodHandles.Lookup LOOKUP;
+ private static final java.lang.reflect.Method HIDDEN_DEFINE_METHOD;
+ private static final Object HIDDEN_CLASS_OPTIONS;
+
static {
try {
- Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ Field unsafeField = UNSAFE_CLASS.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
UNSAFE = (Unsafe) unsafeField.get(null);
- } catch (NoSuchFieldException | IllegalAccessException e) {
+
+ // Unsafe.defineAnonymousClass() has been deprecated in Java 15 and removed in Java 17. Its
+ // usage should be replace by MethodHandles.Lookup.defineHiddenClass() which was introduced in
+ // Java 15. For now, try and support both older and newer Java versions.
+ DEFINE_ANONYMOUS_CLASS = getDefineAnonymousClass();
+ if (DEFINE_ANONYMOUS_CLASS == null) {
+ LOOKUP = getTrustedLookup();
+
+ Class classOptionClass = Class.forName(LOOKUP_CLASS.getName() + "$ClassOption");
+ HIDDEN_CLASS_OPTIONS = Array.newInstance(classOptionClass, 1);
+ Array.set(HIDDEN_CLASS_OPTIONS, 0, Enum.valueOf(classOptionClass, "NESTMATE"));
+ HIDDEN_DEFINE_METHOD = LOOKUP_CLASS.getMethod("defineHiddenClass", byte[].class,
+ boolean.class,
+ HIDDEN_CLASS_OPTIONS.getClass());
+ } else {
+ LOOKUP = null;
+ HIDDEN_DEFINE_METHOD = null;
+ HIDDEN_CLASS_OPTIONS = null;
+ }
+ } catch (ReflectiveOperationException e) {
throw new AssertionError(e);
}
}
+ private static java.lang.reflect.Method getDefineAnonymousClass() {
+ try {
+ return UNSAFE_CLASS.getMethod("defineAnonymousClass", Class.class,
+ byte[].class, Object[].class);
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ private static MethodHandles.Lookup getTrustedLookup() throws ReflectiveOperationException {
+ Field trustedLookupField = LOOKUP_CLASS.getDeclaredField("IMPL_LOOKUP");
+ java.lang.reflect.Method baseMethod = UNSAFE_CLASS.getMethod("staticFieldBase",
+ Field.class);
+ Object lookupBase = baseMethod.invoke(UNSAFE, trustedLookupField);
+ java.lang.reflect.Method offsetMethod = UNSAFE_CLASS.getMethod("staticFieldOffset",
+ Field.class);
+ Object lookupOffset = offsetMethod.invoke(UNSAFE, trustedLookupField);
+
+ java.lang.reflect.Method getObjectMethod = UNSAFE_CLASS.getMethod("getObject",
+ Object.class, long.class);
+ return (MethodHandles.Lookup) getObjectMethod.invoke(UNSAFE, lookupBase, lookupOffset);
+ }
+
private final MethodMapper methodMapper;
private final ClassValueMap<Factory> factories;
@@ -74,9 +127,8 @@ public class ProxyMaker {
writer.visitEnd();
- final Class<?> proxyClass = UNSAFE.defineAnonymousClass(targetClass, writer.toByteArray(), null);
-
try {
+ final Class<?> proxyClass = defineHiddenClass(targetClass, writer.toByteArray());
final Field field = proxyClass.getDeclaredField(TARGET_FIELD);
return new Factory() {
@Override public <E> E createProxy(Class<E> targetClass, E target) {
@@ -91,11 +143,24 @@ public class ProxyMaker {
}
}
};
- } catch (NoSuchFieldException e) {
+ } catch (ReflectiveOperationException e) {
throw new AssertionError(e);
}
}
+ private static Class<?> defineHiddenClass(Class<?> targetClass,
+ byte[] bytes) throws ReflectiveOperationException {
+ if (DEFINE_ANONYMOUS_CLASS != null) {
+ return (Class<?>) DEFINE_ANONYMOUS_CLASS.invoke(UNSAFE, targetClass,
+ bytes, (Object[]) null);
+ } else {
+ MethodHandles.Lookup lookup = (MethodHandles.Lookup) LOOKUP.in(targetClass);
+ MethodHandles.Lookup definedLookup = (MethodHandles.Lookup)
+ HIDDEN_DEFINE_METHOD.invoke(lookup, bytes, false, HIDDEN_CLASS_OPTIONS);
+ return definedLookup.lookupClass();
+ }
+ }
+
private static boolean shouldProxy(java.lang.reflect.Method method) {
int modifiers = method.getModifiers();
return !Modifier.isAbstract(modifiers) && !Modifier.isFinal(modifiers) && !Modifier.isPrivate(
diff --git a/sandbox/src/main/java/org/robolectric/internal/bytecode/RobolectricGeneratorAdapter.java b/sandbox/src/main/java/org/robolectric/internal/bytecode/RobolectricGeneratorAdapter.java
index 1569c379c..14ab0415d 100644
--- a/sandbox/src/main/java/org/robolectric/internal/bytecode/RobolectricGeneratorAdapter.java
+++ b/sandbox/src/main/java/org/robolectric/internal/bytecode/RobolectricGeneratorAdapter.java
@@ -18,7 +18,7 @@ class RobolectricGeneratorAdapter extends GeneratorAdapter {
private final String desc;
public RobolectricGeneratorAdapter(MethodNode methodNode) {
- super(Opcodes.ASM4, methodNode, methodNode.access, methodNode.name, methodNode.desc);
+ super(Opcodes.ASM9, methodNode, methodNode.access, methodNode.name, methodNode.desc);
this.isStatic = Modifier.isStatic(methodNode.access);
this.desc = methodNode.desc;
}
diff --git a/shadowapi/Android.bp b/shadowapi/Android.bp
index ad3841e2f..a46f8ca03 100644
--- a/shadowapi/Android.bp
+++ b/shadowapi/Android.bp
@@ -15,6 +15,11 @@ java_library_host {
name: "Robolectric_shadowapi",
libs: ["jsr305"],
srcs: ["src/main/java/**/*.java"],
+ openjdk9: {
+ javacflags: [
+ "--add-opens=java.base/java.lang=ALL-UNNAMED",
+ ],
+ },
}
//#############################################
diff --git a/shadowapi/AndroidTest.xml b/shadowapi/AndroidTest.xml
index 16368dd43..c0ef7cad5 100644
--- a/shadowapi/AndroidTest.xml
+++ b/shadowapi/AndroidTest.xml
@@ -18,6 +18,8 @@
<option name="jar" value="Robolectric_shadowapi_tests.jar" />
<option name="java-flags" value="-Drobolectric.offline=true" />
<option name="java-flags" value="-Drobolectric.resourcesMode=binary" />
+ <option name="java-flags" value="--add-opens=java.base/java.lang=ALL-UNNAMED"/>
+ <option name="java-flags" value="--add-opens=java.base/java.lang.reflect=ALL-UNNAMED"/>
<option name="exclude-paths" value="java/" />
</test>
</configuration>
diff --git a/shadowapi/src/main/java/org/robolectric/shadow/api/Shadow.java b/shadowapi/src/main/java/org/robolectric/shadow/api/Shadow.java
index 0ae7c85a1..0d54e52d3 100644
--- a/shadowapi/src/main/java/org/robolectric/shadow/api/Shadow.java
+++ b/shadowapi/src/main/java/org/robolectric/shadow/api/Shadow.java
@@ -5,7 +5,7 @@ import org.robolectric.util.ReflectionHelpers.ClassParameter;
public class Shadow {
@SuppressWarnings("unused")
- private final static IShadow SHADOW_IMPL;
+ private static IShadow SHADOW_IMPL;
static {
try {
diff --git a/shadowapi/src/main/java/org/robolectric/util/ReflectionHelpers.java b/shadowapi/src/main/java/org/robolectric/util/ReflectionHelpers.java
index 8fdfdcb37..1c2e52dab 100644
--- a/shadowapi/src/main/java/org/robolectric/util/ReflectionHelpers.java
+++ b/shadowapi/src/main/java/org/robolectric/util/ReflectionHelpers.java
@@ -411,18 +411,37 @@ public class ReflectionHelpers {
private static void makeFieldVeryAccessible(Field field) {
field.setAccessible(true);
-
- try {
- Field modifiersField = Field.class.getDeclaredField("modifiers");
+ // remove 'final' modifier if present
+ if ((field.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
+ Field modifiersField = getModifiersField();
modifiersField.setAccessible(true);
try {
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (IllegalAccessException e) {
- throw new RuntimeException(e);
+
+ throw new AssertionError(e);
}
+ }
+ }
+
+ private static Field getModifiersField() {
+ try {
+ return Field.class.getDeclaredField("modifiers");
} catch (NoSuchFieldException e) {
- // ignore missing fields
+ try {
+ Method getFieldsMethod = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
+ getFieldsMethod.setAccessible(true);
+ Field[] fields = (Field[]) getFieldsMethod.invoke(Field.class, false);
+ for (Field modifiersField : fields) {
+ if ("modifiers".equals(modifiersField.getName())) {
+ return modifiersField;
+ }
+ }
+ } catch (ReflectiveOperationException innerE) {
+ throw new AssertionError(innerE);
+ }
}
+ throw new AssertionError();
}
public static Object defaultValueForType(String returnType) {
diff --git a/shadowapi/src/test/java/org/robolectric/util/ReflectionHelpersTest.java b/shadowapi/src/test/java/org/robolectric/util/ReflectionHelpersTest.java
index 40c007f5b..96306d43d 100644
--- a/shadowapi/src/test/java/org/robolectric/util/ReflectionHelpersTest.java
+++ b/shadowapi/src/test/java/org/robolectric/util/ReflectionHelpersTest.java
@@ -84,6 +84,19 @@ public class ReflectionHelpersTest {
}
@Test
+ public void getFinalStaticFieldReflectively_withField_getsStaticField() throws Exception {
+ Field field = ExampleBase.class.getDeclaredField("BASE");
+
+ int result = ReflectionHelpers.getStaticField(field);
+ assertThat(result).isEqualTo(8);
+ }
+
+ @Test
+ public void getFinalStaticFieldReflectively_withFieldName_getsStaticField() throws Exception {
+ assertThat((int) ReflectionHelpers.getStaticField(ExampleBase.class, "BASE")).isEqualTo(8);
+ }
+
+ @Test
public void setStaticFieldReflectively_withField_setsStaticFields() throws Exception {
Field field = ExampleDescendant.class.getDeclaredField("DESCENDANT");
int startingValue = ReflectionHelpers.getStaticField(field);
@@ -109,6 +122,20 @@ public class ReflectionHelpersTest {
}
@Test
+ public void setFinalStaticFieldReflectively_withFieldName_setsStaticFields() {
+ int startingValue = ReflectionHelpers.getStaticField(ExampleWithFinalStatic.class, "FIELD");
+
+ ReflectionHelpers.setStaticField(ExampleWithFinalStatic.class, "FIELD", 101);
+ assertWithMessage("startingValue").that(startingValue).isEqualTo(100);
+ assertWithMessage("BASE")
+ .that((int) ReflectionHelpers.getStaticField(ExampleWithFinalStatic.class, "FIELD"))
+ .isEqualTo(101);
+
+ // Reset the value to avoid test pollution
+ ReflectionHelpers.setStaticField(ExampleWithFinalStatic.class, "FIELD", startingValue);
+ }
+
+ @Test
public void callInstanceMethodReflectively_callsPrivateMethods() {
ExampleDescendant example = new ExampleDescendant();
assertThat((int) ReflectionHelpers.callInstanceMethod(example, "returnNumber")).isEqualTo(1337);
@@ -339,6 +366,11 @@ public class ReflectionHelpersTest {
}
}
+ @SuppressWarnings("unused")
+ private static class ExampleWithFinalStatic {
+ private static final int FIELD = 100;
+ }
+
private static class ThrowsError {
@SuppressWarnings("unused")
public ThrowsError() {
diff --git a/shadows/framework/Android.bp b/shadows/framework/Android.bp
index 28a7108ba..2eddf8b28 100644
--- a/shadows/framework/Android.bp
+++ b/shadows/framework/Android.bp
@@ -32,4 +32,11 @@ java_library_host {
javacflags: ["-Aorg.robolectric.annotation.processing.shadowPackage=org.robolectric"],
srcs: ["src/main/java/**/*.java"],
java_resource_dirs: ["src/main/resources"],
+ errorprone: {
+ javacflags: [
+ "-Xep:XorPower:WARN",
+ "-Xep:EmptyTopLevelDeclaration:WARN",
+ "-Xep:ReturnValueIgnored:WARN",
+ ],
+ },
}
diff --git a/shadows/framework/src/main/java/org/robolectric/android/controller/ActivityController.java b/shadows/framework/src/main/java/org/robolectric/android/controller/ActivityController.java
index 3f173dcb8..b41ca9cee 100644
--- a/shadows/framework/src/main/java/org/robolectric/android/controller/ActivityController.java
+++ b/shadows/framework/src/main/java/org/robolectric/android/controller/ActivityController.java
@@ -16,6 +16,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.os.Build;
import android.os.Bundle;
import android.view.ViewRootImpl;
import org.robolectric.RuntimeEnvironment;
@@ -160,9 +161,14 @@ public class ActivityController<T extends Activity> extends ComponentController<
callDispatchResized(root);
}
- ReflectionHelpers.callInstanceMethod(root, "windowFocusChanged",
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ ReflectionHelpers.callInstanceMethod(root, "windowFocusChanged",
+ from(boolean.class, hasFocus));
+ } else {
+ ReflectionHelpers.callInstanceMethod(root, "windowFocusChanged",
from(boolean.class, hasFocus), /* hasFocus */
from(boolean.class, false) /* inTouchMode */);
+ }
return this;
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ImageUtil.java b/shadows/framework/src/main/java/org/robolectric/shadows/ImageUtil.java
index 534a0eebc..83ed5a7b9 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ImageUtil.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ImageUtil.java
@@ -21,7 +21,25 @@ import javax.imageio.stream.ImageOutputStream;
public class ImageUtil {
private static boolean initialized;
+ public static class ImageInfo {
+
+ public final int width;
+ public final int height;
+ public final String mimeType;
+
+ ImageInfo(int width, int height, String mimeType) {
+ this.width = width;
+ this.height = height;
+ this.mimeType = mimeType;
+ }
+ }
+
public static Point getImageSizeFromStream(InputStream is) {
+ ImageInfo info = getImageInfoFromStream(is);
+ return new Point(info.width, info.height);
+ }
+
+ public static ImageInfo getImageInfoFromStream(InputStream is) {
if (!initialized) {
// Stops ImageIO from creating temp files when reading images
// from input stream.
@@ -37,7 +55,7 @@ public class ImageUtil {
ImageReader reader = readers.next();
try {
reader.setInput(imageStream);
- return new Point(reader.getWidth(0), reader.getHeight(0));
+ return new ImageInfo(reader.getWidth(0), reader.getHeight(0), "image/" + reader.getFormatName());
} finally {
reader.dispose();
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAlarmManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAlarmManager.java
index bea306d2e..0ec2bc838 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAlarmManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAlarmManager.java
@@ -5,6 +5,7 @@ import static android.os.Build.VERSION_CODES.KITKAT;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.N;
+import static android.os.Build.VERSION_CODES.S;
import android.annotation.TargetApi;
import android.app.AlarmManager;
@@ -29,6 +30,7 @@ public class ShadowAlarmManager {
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getDefault();
+ private static boolean canScheduleExactAlarms;
private final List<ScheduledAlarm> scheduledAlarms = new ArrayList<>();
@RealObject private AlarmManager realObject;
@@ -36,6 +38,7 @@ public class ShadowAlarmManager {
@Resetter
public static void reset() {
TimeZone.setDefault(DEFAULT_TIMEZONE);
+ canScheduleExactAlarms = false;
}
@Implementation
@@ -196,6 +199,20 @@ public class ShadowAlarmManager {
}
}
+ /** Returns the schedule exact alarm state set by {@link #setCanScheduleExactAlarms}. */
+ @Implementation(minSdk = S)
+ protected boolean canScheduleExactAlarms() {
+ return canScheduleExactAlarms;
+ }
+
+ /**
+ * Sets the schedule exact alarm state reported by {@link AlarmManager#canScheduleExactAlarms},
+ * but has no effect otherwise.
+ */
+ public static void setCanScheduleExactAlarms(boolean scheduleExactAlarms) {
+ canScheduleExactAlarms = scheduleExactAlarms;
+ }
+
/**
* Container object to hold a PendingIntent and parameters describing when to send it.
*/
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormat.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormat.java
index abbed64fb..83d5235c0 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormat.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormat.java
@@ -2,16 +2,17 @@ package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.KITKAT;
import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
import java.text.FieldPosition;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
-import libcore.icu.DateIntervalFormat;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
-@Implements(value = DateIntervalFormat.class, isInAndroidSdk = false, minSdk = KITKAT)
+@Implements(className = "libcore.icu.DateIntervalFormat", isInAndroidSdk = false, minSdk = KITKAT,
+ maxSdk = TIRAMISU)
public class ShadowDateIntervalFormat {
private static long address;
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormatU.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormatU.java
new file mode 100644
index 000000000..ac435c46f
--- /dev/null
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDateIntervalFormatU.java
@@ -0,0 +1,42 @@
+package org.robolectric.shadows;
+
+import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+
+import java.text.FieldPosition;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import android.text.format.DateIntervalFormat;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(value = DateIntervalFormat.class, isInAndroidSdk = false, minSdk = UPSIDE_DOWN_CAKE)
+public class ShadowDateIntervalFormatU {
+
+ private static long address;
+ private static Map<Long, com.ibm.icu.text.DateIntervalFormat> INTERVAL_CACHE = new HashMap<>();
+
+ @Implementation
+ public static long createDateIntervalFormat(String skeleton, String localeName, String tzName) {
+ address++;
+ INTERVAL_CACHE.put(address, com.ibm.icu.text.DateIntervalFormat.getInstance(skeleton, new Locale(localeName)));
+ return address;
+ }
+
+ @Implementation
+ public static void destroyDateIntervalFormat(long address) {
+ INTERVAL_CACHE.remove(address);
+ }
+
+ @Implementation
+ @SuppressWarnings("JdkObsolete")
+ public static String formatDateInterval(long address, long fromDate, long toDate) {
+ StringBuffer buffer = new StringBuffer();
+
+ FieldPosition pos = new FieldPosition(0);
+ INTERVAL_CACHE.get(address).format(new com.ibm.icu.util.DateInterval(fromDate, toDate), buffer, pos);
+
+ return buffer.toString();
+ }
+}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowImageDecoder.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowImageDecoder.java
index fbe48ac8b..b7efad575 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowImageDecoder.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowImageDecoder.java
@@ -39,12 +39,14 @@ public class ShadowImageDecoder {
private final int height;
private final boolean animated = false;
private final boolean ninePatch;
+ private final String mimeType;
ImgStream() {
InputStream inputStream = getInputStream();
- final Point size = ImageUtil.getImageSizeFromStream(inputStream);
- this.width = size == null ? 10 : size.x;
- this.height = size == null ? 10 : size.y;
+ final ImageUtil.ImageInfo info = ImageUtil.getImageInfoFromStream(inputStream);
+ this.width = info == null ? 10 : info.width;
+ this.height = info == null ? 10 : info.height;
+ this.mimeType = info == null ? "" : info.mimeType;
if (inputStream instanceof AssetManager.AssetInputStream) {
ShadowAssetInputStream sis = Shadow.extract(inputStream);
this.ninePatch = sis.isNinePatch();
@@ -70,6 +72,10 @@ public class ShadowImageDecoder {
boolean isNinePatch() {
return ninePatch;
}
+
+ String getMimeType() {
+ return mimeType;
+ }
}
private static final class CppImageDecoder {
@@ -80,6 +86,9 @@ public class ShadowImageDecoder {
this.imgStream = imgStream;
}
+ public String getMimeType() {
+ return imgStream.getMimeType();
+ }
}
private static final NativeObjRegistry<CppImageDecoder> NATIVE_IMAGE_DECODER_REGISTRY =
@@ -238,8 +247,7 @@ public class ShadowImageDecoder {
static String ImageDecoder_nGetMimeType(long nativePtr) {
CppImageDecoder decoder = NATIVE_IMAGE_DECODER_REGISTRY.getNativeObject(nativePtr);
- // return encodedFormatToString(decoder.mCodec.getEncodedFormat());
- throw new UnsupportedOperationException();
+ return decoder.getMimeType();
}
static ColorSpace ImageDecoder_nGetColorSpace(long nativePtr) {
@@ -247,7 +255,7 @@ public class ShadowImageDecoder {
// auto colorType = codec.computeOutputColorType(codec.getInfo().colorType());
// sk_sp<SkColorSpace> colorSpace = codec.computeOutputColorSpace(colorType);
// return GraphicsJNI.getColorSpace(colorSpace, colorType);
- throw new UnsupportedOperationException();
+ return null;
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInputManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInputManager.java
index 4c8ebf509..867c72033 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInputManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInputManager.java
@@ -3,6 +3,7 @@ package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.KITKAT;
import android.hardware.input.InputManager;
+import android.hardware.input.InputManagerGlobal;
import android.view.InputEvent;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -25,6 +26,7 @@ public class ShadowInputManager {
@Resetter
public static void reset() {
- ReflectionHelpers.setStaticField(InputManager.class, "sInstance", null);
+ ReflectionHelpers.setStaticField(InputManagerGlobal.class,
+ "sInstance", null);
}
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSQLiteConnection.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSQLiteConnection.java
index d4b8a1db7..ce65e8ef6 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSQLiteConnection.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSQLiteConnection.java
@@ -1,5 +1,6 @@
package org.robolectric.shadows;
+import static android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
import static android.os.Build.VERSION_CODES.KITKAT_WATCH;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.O;
@@ -158,11 +159,16 @@ public class ShadowSQLiteConnection {
nativeExecute((long) connectionPtr, (long) statementPtr);
}
- @Implementation(minSdk = LOLLIPOP)
+ @Implementation(minSdk = LOLLIPOP, maxSdk = 32)
public static void nativeExecute(final long connectionPtr, final long statementPtr) {
CONNECTIONS.executeStatement(connectionPtr, statementPtr);
}
+ @Implementation(minSdk = CUR_DEVELOPMENT)
+ public static void nativeExecute(final long connectionPtr, final long statementPtr, boolean isPragmaStmt){
+ CONNECTIONS.executeStatement(connectionPtr, statementPtr);
+ }
+
@Implementation(maxSdk = KITKAT_WATCH)
public static String nativeExecuteForString(int connectionPtr, int statementPtr) {
return nativeExecuteForString((long) connectionPtr, (long) statementPtr);
@@ -668,7 +674,7 @@ static class Connections {
@Override
public Long call() throws Exception {
statement.stepThrough();
- return connection.getLastInsertId();
+ return connection.getChanges() > 0 ? connection.getLastInsertId() : -1L;
}
});
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensor.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensor.java
index c37ca3a3d..00fea9483 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensor.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensor.java
@@ -1,27 +1,51 @@
package org.robolectric.shadows;
-
import android.hardware.Sensor;
import android.os.Build.VERSION_CODES;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.RealObject;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.ReflectionHelpers;
-import org.robolectric.util.ReflectionHelpers.ClassParameter;
@Implements(Sensor.class)
public class ShadowSensor {
- /**
- * Constructs a {@link Sensor} with a given type.
- */
+ @RealObject private Sensor realSensor;
+
+ /** Constructs a {@link Sensor} with a given type. */
public static Sensor newInstance(int type) {
Sensor sensor = Shadow.newInstanceOf(Sensor.class);
if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.M) {
- Shadow.directlyOn(sensor, Sensor.class, "setType", ClassParameter.from(int.class, type));
+ Shadow.directlyOn(sensor, Sensor.class, "setType", ReflectionHelpers.ClassParameter.from(int.class, type));
} else {
ReflectionHelpers.setField(Sensor.class, sensor, "mType", type);
}
return sensor;
}
+
+ /** Controls the return value of {@link Sensor#isWakeUpSensor()}. */
+ public void setWakeUpFlag(boolean wakeup) {
+ int wakeUpSensorFlag = getWakeUpSensorFlag();
+
+ if(wakeup) {
+ setMask(wakeUpSensorFlag);
+ } else {
+ clearMask(wakeUpSensorFlag);
+ }
+ }
+
+ private void setMask(int mask) {
+ int value = ReflectionHelpers.getField(realSensor, "mFlags");
+ ReflectionHelpers.setField(realSensor, "mFlags", (value | mask));
+ }
+
+ private void clearMask(int mask) {
+ int value = ReflectionHelpers.getField(realSensor, "mFlags");
+ ReflectionHelpers.setField(realSensor, "mFlags", (value & ~mask));
+ }
+
+ private int getWakeUpSensorFlag() {
+ return ReflectionHelpers.getStaticField(Sensor.class, "SENSOR_FLAG_WAKE_UP_SENSOR");
+ }
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensorManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensorManager.java
index 68a80cd43..05a4b9574 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensorManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensorManager.java
@@ -53,6 +53,12 @@ public class ShadowSensorManager {
return sensorMap.get(type);
}
+ @Implementation
+ protected Sensor getDefaultSensor(int type, boolean wakeUp) {
+ Sensor typedSensor = sensorMap.get(type);
+ return (typedSensor != null && typedSensor.isWakeUpSensor() == wakeUp) ? typedSensor : null;
+ }
+
/** @param handler is ignored. */
@Implementation
protected boolean registerListener(
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 3c4afdab6..facd5a5b6 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowServiceManager.java
@@ -55,6 +55,7 @@ import android.os.ServiceManager;
import android.os.storage.IStorageManager;
import android.permission.IPermissionManager;
import android.service.persistentdata.IPersistentDataBlockService;
+import android.view.IWindowManager;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
@@ -133,6 +134,9 @@ public class ShadowServiceManager {
map.put(
Context.APPWIDGET_SERVICE,
createBinder(IAppWidgetService.class, "com.android.internal.appwidget.IAppWidgetService"));
+ map.put(
+ Context.WINDOW_SERVICE,
+ createBinder(IWindowManager.class, "android.view.IWindowManager"));
if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR1) {
map.put(Context.USER_SERVICE, createBinder(IUserManager.class, "android.os.IUserManager"));
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 b925f4317..3de5456a9 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSettings.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSettings.java
@@ -6,6 +6,7 @@ import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.P;
+import android.app.ActivityThread;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Build;
@@ -265,11 +266,21 @@ public class ShadowSettings {
return true;
}
+ @Implementation(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ protected static boolean putString(String name, String value) {
+ return putString(ActivityThread.currentApplication().getContentResolver(), name, value);
+ }
+
@Implementation
protected static String getString(ContentResolver cr, String name) {
return get(cr).get(name);
}
+ @Implementation(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ protected static String getString(String name) {
+ return getString(ActivityThread.currentApplication().getContentResolver(), name);
+ }
+
// BEGIN-INTERNAL
@Implementation(minSdk = Build.VERSION_CODES.R)
protected static Map<String, String> getStrings(ContentResolver cr, String prefix,
@@ -288,6 +299,12 @@ public class ShadowSettings {
}
return arrayMap;
}
+
+ @Implementation(minSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ protected static Map<String, String> getStrings(String prefix,
+ List<String> names) {
+ return getStrings(ActivityThread.currentApplication().getContentResolver(), prefix, names);
+ }
// END-INTERNAL
private static Map<String, String> get(ContentResolver cr) {
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsbManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsbManager.java
index d5dd186b4..52a83e9f7 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsbManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsbManager.java
@@ -4,6 +4,7 @@ import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.N;
import static android.os.Build.VERSION_CODES.N_MR1;
import static android.os.Build.VERSION_CODES.P;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
import static org.robolectric.RuntimeEnvironment.application;
import static org.robolectric.util.ReflectionHelpers.ClassParameter.from;
import static org.robolectric.util.ReflectionHelpers.callConstructor;
@@ -261,6 +262,15 @@ public class ShadowUsbManager {
from(UsbManager.class, usbManager),
from(String.class, id),
from(int.class, supportedModes));
+ } else if (RuntimeEnvironment.getApiLevel() <= TIRAMISU) {
+ return new UsbPort(
+ usbManager,
+ id,
+ supportedModes,
+ 0,
+ false,
+ false
+ );
}
// BEGIN-INTERNAL
return new UsbPort(
@@ -269,7 +279,9 @@ public class ShadowUsbManager {
supportedModes,
0,
false,
- false
+ false,
+ false,
+ 0
);
// END-INTERNAL
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUserManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUserManager.java
index e1625d159..f4598aaa3 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUserManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUserManager.java
@@ -8,6 +8,7 @@ import static android.os.Build.VERSION_CODES.N;
import static android.os.Build.VERSION_CODES.N_MR1;
import static android.os.Build.VERSION_CODES.R;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
import static org.robolectric.shadow.api.Shadow.directlyOn;
@@ -17,6 +18,7 @@ import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.content.pm.UserProperties;
import android.os.Bundle;
import android.os.IUserManager;
import android.os.Process;
@@ -64,6 +66,10 @@ public class ShadowUserManager {
private boolean userUnlocked = true;
private boolean managedProfile = false;
private boolean isSystemUser = true;
+ private static boolean isHeadlessSystemUserMode = false;
+ private static boolean isMultipleAdminEnabled = false;
+
+
private Map<Integer, Bundle> userRestrictions = new HashMap<>();
private BiMap<UserHandle, Long> userProfiles = HashBiMap.create();
private Map<String, Bundle> applicationRestrictions = new HashMap<>();
@@ -72,6 +78,7 @@ public class ShadowUserManager {
private Map<Integer, UserInfo> userInfoMap = new HashMap<>();
private Map<Integer, List<UserInfo>> profiles = new HashMap<>();
private Map<Integer, Integer> profileToParent = new HashMap<>();
+ private Map<Integer, UserProperties> mUserPropertiesMap = new HashMap<>();
private Context context;
private boolean enforcePermissions;
@@ -341,6 +348,24 @@ public class ShadowUserManager {
return context.getPackageManager().checkPermission(permission.MANAGE_USERS, context.getPackageName()) == PackageManager.PERMISSION_GRANTED;
}
+ public static void setIsMultipleAdminEnabled(boolean enableMultipleAdmin) {
+ isMultipleAdminEnabled = enableMultipleAdmin;
+ }
+
+ @Implementation(minSdk = UPSIDE_DOWN_CAKE)
+ protected static boolean isMultipleAdminEnabled() {
+ return isMultipleAdminEnabled;
+ }
+
+ public static void setIsHeadlessSystemUserMode(boolean isHSUM) {
+ isHeadlessSystemUserMode = isHSUM;
+ }
+
+ @Implementation
+ protected static boolean isHeadlessSystemUserMode() {
+ return isHeadlessSystemUserMode;
+ }
+
private void checkPermissions() {
// TODO Ensure permisions
// throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS
@@ -636,5 +661,18 @@ public class ShadowUserManager {
userPidMap.clear();
userPidMap.put(UserHandle.USER_SYSTEM, Process.myUid());
}
+ isMultipleAdminEnabled = false;
+ }
+
+ public void setupUserProperty(int userId, int showInSettings) {
+ UserProperties userProperties = new UserProperties(new UserProperties.Builder()
+ .setShowInSettings(showInSettings).build());
+ mUserPropertiesMap.putIfAbsent(userId, userProperties);
+ }
+
+ @Implementation(minSdk = UPSIDE_DOWN_CAKE)
+ protected UserProperties getUserProperties(UserHandle user) {
+ return mUserPropertiesMap.getOrDefault(user.getIdentifier(),
+ new UserProperties(new UserProperties.Builder().build()));
}
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowViewRootImpl.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowViewRootImpl.java
index ad17119d4..5e6719c24 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowViewRootImpl.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowViewRootImpl.java
@@ -163,7 +163,7 @@ public class ShadowViewRootImpl {
ClassParameter.from(boolean.class, false),
ClassParameter.from(int.class, 0));
// END-INTERNAL
- } else if (apiLevel >= Build.VERSION_CODES.TIRAMISU) {
+ } else if (apiLevel <= Build.VERSION_CODES.TIRAMISU) {
// BEGIN-INTERNAL
ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized",
ClassParameter.from(ClientWindowFrames.class, clientWindowFrame),
@@ -176,6 +176,19 @@ public class ShadowViewRootImpl {
ClassParameter.from(int.class, 0),
ClassParameter.from(int.class, 0));
// END-INTERNAL
+ } else if (apiLevel >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ // BEGIN-INTERNAL
+ ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized",
+ ClassParameter.from(ClientWindowFrames.class, clientWindowFrame),
+ ClassParameter.from(boolean.class, true),
+ ClassParameter.from(MergedConfiguration.class, new MergedConfiguration()),
+ ClassParameter.from(InsetsState.class, new InsetsState()),
+ ClassParameter.from(boolean.class, false),
+ ClassParameter.from(boolean.class, false),
+ ClassParameter.from(int.class, 0),
+ ClassParameter.from(int.class, 0),
+ ClassParameter.from(boolean.class, false));
+ // END-INTERNAL
} else {
throw new RuntimeException("Could not find AndroidRuntimeAdapter for API level: " + apiLevel);
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java
index a6aeaf2a9..a23dab947 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java
@@ -3,7 +3,10 @@ package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
+import android.content.Context;
import android.os.Looper;
+import android.os.ServiceManager;
+import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -32,7 +35,7 @@ public class ShadowWindowManagerGlobal {
@Implementation
public static Object getWindowManagerService() {
- return null;
+ return IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
}
} \ No newline at end of file
diff --git a/shadows/httpclient/Android.bp b/shadows/httpclient/Android.bp
index 39d57a8be..d3ca43f56 100644
--- a/shadows/httpclient/Android.bp
+++ b/shadows/httpclient/Android.bp
@@ -55,14 +55,14 @@ java_test_host {
"bouncycastle-unbundled",
"hamcrest",
"robolectric-httpclient-4.0.3",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"robolectric-httpcore-4.0.1",
"guava",
- "asm-tree-9.2",
+ "ow2-asm-tree",
"junit",
"truth-prebuilt",
"robolectric-ant-1.8.0",
- "asm-9.2",
+ "ow2-asm",
"jsr305",
"robolectric-host-android_all",
"robolectric-host-org_apache_http_legacy",
diff --git a/shadows/supportv4/Android.bp b/shadows/supportv4/Android.bp
index 04714e520..c2fd48036 100644
--- a/shadows/supportv4/Android.bp
+++ b/shadows/supportv4/Android.bp
@@ -53,14 +53,14 @@ java_test_host {
"mockito",
"bouncycastle-unbundled",
"hamcrest",
- "asm-commons-9.2",
+ "ow2-asm-commons",
"guava",
"objenesis",
- "asm-tree-9.2",
+ "ow2-asm-tree",
"junit",
"truth-prebuilt",
"robolectric-ant-1.8.0",
- "asm-9.2",
+ "ow2-asm",
"jsr305",
],
libs: ["robolectric-host-android_all"],