diff --git a/annotations/src/main/java/org/robolectric/annotation/ClassName.java b/annotations/src/main/java/org/robolectric/annotation/ClassName.java new file mode 100644 index 00000000000..8b4a429ef15 --- /dev/null +++ b/annotations/src/main/java/org/robolectric/annotation/ClassName.java @@ -0,0 +1,20 @@ +package org.robolectric.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Parameters with types that can't be resolved at compile time may be annotated @ClassName. */ +@Target({ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ClassName { + + /** + * The class name intended for this parameter. + * + *

Use the value as returned from {@link Class#getName()}, not {@link + * Class#getCanonicalName()}; e.g. {@code Foo$Bar} instead of {@code Foo.Bar}. + */ + String value(); +} 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 e08b3acd1b7..94c1f80b154 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 @@ -38,6 +38,7 @@ import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; +import org.robolectric.annotation.ClassName; import org.robolectric.annotation.Implementation; import org.robolectric.versioning.AndroidVersionInitTools; @@ -162,7 +163,7 @@ public String verifyMethod( MethodExtraInfo sdkMethod = classInfo.findMethod(methodElement, looseSignatures); if (sdkMethod == null) { - return "No such method in " + className; + return "No such method " + methodElement + " in " + className; } MethodExtraInfo implMethod = new MethodExtraInfo(methodElement); @@ -372,8 +373,14 @@ public MethodInfo(ExecutableElement methodElement) { for (VariableElement variableElement : methodElement.getParameters()) { TypeMirror varTypeMirror = variableElement.asType(); String paramType = canonicalize(varTypeMirror); - String paramTypeWithoutGenerics = typeWithoutGenerics(paramType); - paramTypes.add(paramTypeWithoutGenerics); + ClassName className = variableElement.getAnnotation(ClassName.class); + if (className != null) { + // If this parameter has ClassName annotation, we need to save its type + // based on ClassName value. + paramTypes.add(typeWithoutGenerics(className.value())); + } else { + paramTypes.add(typeWithoutGenerics(paramType)); + } } } @@ -433,7 +440,15 @@ public MethodExtraInfo(MethodNode method) { public MethodExtraInfo(ExecutableElement methodElement) { this.isStatic = methodElement.getModifiers().contains(Modifier.STATIC); - this.returnType = typeWithoutGenerics(canonicalize(methodElement.getReturnType())); + TypeMirror typeMirror = methodElement.getReturnType(); + WithType withType = methodElement.getAnnotation(WithType.class); + if (withType != null) { + // If this return type has WithType annotation, we need to save its type + // based on WithType value. + this.returnType = typeWithoutGenerics(withType.value()); + } else { + this.returnType = typeWithoutGenerics(canonicalize(methodElement.getReturnType())); + } } @Override diff --git a/sandbox/src/main/java/org/robolectric/internal/bytecode/ShadowWrangler.java b/sandbox/src/main/java/org/robolectric/internal/bytecode/ShadowWrangler.java index 5e03aa945d7..2529d1b90f3 100644 --- a/sandbox/src/main/java/org/robolectric/internal/bytecode/ShadowWrangler.java +++ b/sandbox/src/main/java/org/robolectric/internal/bytecode/ShadowWrangler.java @@ -8,6 +8,7 @@ import static org.robolectric.util.reflector.Reflector.reflector; import com.google.auto.service.AutoService; +import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -21,6 +22,7 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Priority; +import org.robolectric.annotation.ClassName; import org.robolectric.annotation.RealObject; import org.robolectric.annotation.ReflectorObject; import org.robolectric.sandbox.NativeMethodNotFoundException; @@ -320,13 +322,23 @@ private Method findShadowMethod( Class[] types, ShadowInfo shadowInfo, Class shadowClass) { + // Try to find the shadow method with the exact method signature first. Method method = findShadowMethodDeclaredOnClass(shadowClass, name, types); + // Try to find shadow method with fallback looseSignature mechanism. if (method == null && shadowInfo.looseSignatures) { + // If user sets looseSignatures for shadow class, we will try to find method with generic + // types by following origin full looseSignatures definition. Class[] genericTypes = MethodType.genericMethodType(types.length).parameterArray(); method = findShadowMethodDeclaredOnClass(shadowClass, name, genericTypes); } + // Try to find shadow method with another fallback WithType mechanism with a lower priority. + if (method == null && !shadowInfo.looseSignatures) { + // Otherwise, we will try to find method with WithType annotation that can match signature. + method = findShadowMethodHasWithTypeDeclaredOnClass(shadowClass, name, types); + } + if (method != null) { return method; } else { @@ -348,6 +360,76 @@ private Method findShadowMethod( return method; } + private ClassName findClassNameAnnotation(Annotation[] annotations) { + for (Annotation annotation : annotations) { + if (ClassName.class.isAssignableFrom(annotation.annotationType())) { + return (ClassName) annotation; + } + } + return null; + } + + private boolean hasClassNameAnnotation(Annotation[][] annotations) { + for (Annotation[] parameterAnnotations : annotations) { + for (Annotation annotation : parameterAnnotations) { + if (ClassName.class.isAssignableFrom(annotation.annotationType())) { + return true; + } + } + } + return false; + } + + private Method findShadowMethodHasWithTypeDeclaredOnClass( + Class shadowClass, String methodName, Class[] paramClasses) { + // We don't process the method without input parameters now. + if (paramClasses == null || paramClasses.length == 0) { + return null; + } + Method[] methods = shadowClass.getDeclaredMethods(); + // TODO try to find methods with the same name first + for (Method method : methods) { + if (method == null + || !method.getName().equals(methodName) + || method.getParameterCount() != paramClasses.length + || !isValidShadowMethod(method)) { + continue; + } + Class[] parameterTypes = method.getParameterTypes(); + Annotation[][] allAnnotations = method.getParameterAnnotations(); + if (!hasClassNameAnnotation(allAnnotations)) { + continue; + } + boolean matched = true; + for (int i = 0; i < parameterTypes.length; i++) { + // If method's parameter type is superclass of input parameter, we can pass checking for + // this parameter. + if (parameterTypes[i].isAssignableFrom(paramClasses[i])) { + continue; + } + if (allAnnotations.length <= i) { + matched = false; + break; + } + ClassName className = findClassNameAnnotation(allAnnotations[i]); + // If developer uses WithType for an input parameter, we need ensure it is the same + // type of the real method to avoid unexpected method override/overwrite result. + if (className != null + && paramClasses[i] != null + && className.value().equals(paramClasses[i].getCanonicalName())) { + continue; + } + matched = false; + break; + } + // TODO identify why above logic will affect __constructor__ without WithType + if (matched) { + return method; + } + } + return null; + } + private Method findShadowMethodDeclaredOnClass( Class shadowClass, String methodName, Class[] paramClasses) { try { 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 56b0f4c77e1..21fb6508239 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 @@ -29,6 +29,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import javax.annotation.Nullable; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.ClassName; import org.robolectric.shadow.api.Shadow; import org.robolectric.shadows.ShadowActivity; import org.robolectric.shadows.ShadowContextThemeWrapper; @@ -39,7 +40,6 @@ import org.robolectric.util.ReflectionHelpers.ClassParameter; import org.robolectric.util.reflector.Accessor; import org.robolectric.util.reflector.ForType; -import org.robolectric.util.reflector.WithType; /** * ActivityController provides low-level APIs to control activity's lifecycle. @@ -99,7 +99,7 @@ private ActivityController attach(@Nullable Bundle activityOptions) { private ActivityController attach( @Nullable Bundle activityOptions, - @Nullable @WithType("android.app.Activity$NonConfigurationInstances") + @Nullable @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, @Nullable Configuration overrideConfig) { if (attached) { diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/CellInfoLteBuilder.java b/shadows/framework/src/main/java/org/robolectric/shadows/CellInfoLteBuilder.java index 06396e05053..5ffa79158f3 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/CellInfoLteBuilder.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/CellInfoLteBuilder.java @@ -12,7 +12,6 @@ import org.robolectric.util.reflector.Accessor; import org.robolectric.util.reflector.Constructor; import org.robolectric.util.reflector.ForType; -import org.robolectric.util.reflector.WithType; /** Builder for {@link android.telephony.CellInfoLte}. */ public class CellInfoLteBuilder { @@ -113,7 +112,7 @@ CellInfoLte newCellInfoLte( long timeStamp, CellIdentityLte cellIdentity, CellSignalStrengthLte cellSignalStrength, - @WithType("android.telephony.CellConfigLte") Object cellConfigLte); + @ClassName("android.telephony.CellConfigLte") Object cellConfigLte); @Accessor("mCellIdentityLte") void setCellIdentity(CellIdentityLte cellIdentity); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivity.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivity.java index b5e962b2e09..f0dd88ea8a7 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivity.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivity.java @@ -76,10 +76,9 @@ import org.robolectric.shadows.ShadowLoadedApk._LoadedApk_; import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.reflector.ForType; -import org.robolectric.util.reflector.WithType; @SuppressWarnings("NewApi") -@Implements(value = Activity.class, looseSignatures = true) +@Implements(value = Activity.class) public class ShadowActivity extends ShadowContextThemeWrapper { @RealObject protected Activity realActivity; @@ -130,7 +129,7 @@ public void callAttach(Intent intent, @Nullable Bundle activityOptions) { public void callAttach( Intent intent, @Nullable Bundle activityOptions, - @Nullable @WithType("android.app.Activity$NonConfigurationInstances") + @Nullable @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances) { callAttach( intent, @@ -142,7 +141,7 @@ public void callAttach( public void callAttach( Intent intent, @Nullable Bundle activityOptions, - @Nullable @WithType("android.app.Activity$NonConfigurationInstances") + @Nullable @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, @Nullable Configuration overrideConfig) { Application application = RuntimeEnvironment.getApplication(); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivityThread.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivityThread.java index 8b55be12417..d8af12ccc18 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivityThread.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowActivityThread.java @@ -42,7 +42,7 @@ import org.robolectric.util.reflector.ForType; import org.robolectric.util.reflector.Reflector; -@Implements(value = ActivityThread.class, isInAndroidSdk = false, looseSignatures = true) +@Implements(value = ActivityThread.class, isInAndroidSdk = false) public class ShadowActivityThread { private static ApplicationInfo applicationInfo; @RealObject protected ActivityThread realActivityThread; diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAppOpsManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAppOpsManager.java index f2e0f74f4a0..714ef720d78 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAppOpsManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAppOpsManager.java @@ -64,7 +64,7 @@ import org.robolectric.util.reflector.ForType; /** Shadow for {@link AppOpsManager}. */ -@Implements(value = AppOpsManager.class, looseSignatures = true) +@Implements(value = AppOpsManager.class) public class ShadowAppOpsManager { // OpEntry fields that the shadow doesn't currently allow the test to configure. @@ -415,18 +415,18 @@ protected int noteProxyOpNoThrow( @RequiresApi(api = S) @Implementation(minSdk = S) protected int noteProxyOpNoThrow( - Object op, Object attributionSource, Object message, Object ignoredSkipProxyOperation) { - Preconditions.checkArgument(op instanceof Integer); + int op, + @ClassName(value = "android.content.AttributionSource") Object attributionSource, + String message, + boolean ignoredSkipProxyOperation) { Preconditions.checkArgument(attributionSource instanceof AttributionSource); - Preconditions.checkArgument(message == null || message instanceof String); - Preconditions.checkArgument(ignoredSkipProxyOperation instanceof Boolean); AttributionSource castedAttributionSource = (AttributionSource) attributionSource; return noteProxyOpNoThrow( - (int) op, + op, castedAttributionSource.getNextPackageName(), castedAttributionSource.getNextUid(), castedAttributionSource.getNextAttributionTag(), - (String) message); + message); } @Implementation diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowArscApkAssets9.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowArscApkAssets9.java index 9ab0887c72a..b8cbc46711b 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowArscApkAssets9.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowArscApkAssets9.java @@ -37,8 +37,7 @@ value = ApkAssets.class, minSdk = P, shadowPicker = Picker.class, - isInAndroidSdk = false, - looseSignatures = true) + isInAndroidSdk = false) public class ShadowArscApkAssets9 extends ShadowApkAssets { // #define ATRACE_TAG ATRACE_TAG_RESOURCES // @@ -149,12 +148,16 @@ protected static long nativeLoad( } @Implementation(minSdk = R) - protected static Object nativeLoad( - Object format, Object javaPath, Object flags, Object assetsProvider) throws IOException { - boolean system = ((int) flags & PROPERTY_SYSTEM) == PROPERTY_SYSTEM; - boolean overlay = ((int) flags & PROPERTY_OVERLAY) == PROPERTY_OVERLAY; - boolean forceSharedLib = ((int) flags & PROPERTY_DYNAMIC) == PROPERTY_DYNAMIC; - return nativeLoad((String) javaPath, system, forceSharedLib, overlay); + protected static long nativeLoad( + int format, + String javaPath, + int flags, + @ClassName(value = "android.content.res.loader.AssetsProvider") Object assetsProvider) + throws IOException { + boolean system = (flags & PROPERTY_SYSTEM) == PROPERTY_SYSTEM; + boolean overlay = (flags & PROPERTY_OVERLAY) == PROPERTY_OVERLAY; + boolean forceSharedLib = (flags & PROPERTY_DYNAMIC) == PROPERTY_DYNAMIC; + return nativeLoad(javaPath, system, forceSharedLib, overlay); } // static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, jobject file_descriptor, diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioManager.java index 317341315b8..4c62ccbbb3e 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioManager.java @@ -50,7 +50,7 @@ import org.robolectric.util.reflector.ForType; @SuppressWarnings({"UnusedDeclaration"}) -@Implements(value = AudioManager.class, looseSignatures = true) +@Implements(value = AudioManager.class) public class ShadowAudioManager { @RealObject AudioManager realAudioManager; @@ -883,7 +883,8 @@ public AudioRecordingConfiguration createActiveRecordingConfiguration( @HiddenApi @Implementation(minSdk = P) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) - protected int registerAudioPolicy(@NonNull Object audioPolicy) { + protected int registerAudioPolicy( + @NonNull @ClassName(value = "android.media.audiopolicy.AudioPolicy") Object audioPolicy) { Preconditions.checkNotNull(audioPolicy, "Illegal null AudioPolicy argument"); AudioPolicy policy = (AudioPolicy) audioPolicy; String id = getIdForAudioPolicy(audioPolicy); @@ -897,7 +898,8 @@ protected int registerAudioPolicy(@NonNull Object audioPolicy) { @HiddenApi @Implementation(minSdk = Q) - protected void unregisterAudioPolicy(@NonNull Object audioPolicy) { + protected void unregisterAudioPolicy( + @NonNull @ClassName(value = "android.media.audiopolicy.AudioPolicy") Object audioPolicy) { Preconditions.checkNotNull(audioPolicy, "Illegal null AudioPolicy argument"); AudioPolicy policy = (AudioPolicy) audioPolicy; registeredAudioPolicies.remove(getIdForAudioPolicy(policy)); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioTrack.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioTrack.java index ecf5f16ea25..54bd428ce91 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioTrack.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAudioTrack.java @@ -44,7 +44,7 @@ * other methods are expected run through the real class. The two {@link WriteMode} are treated the * same. */ -@Implements(value = AudioTrack.class, looseSignatures = true) +@Implements(value = AudioTrack.class) public class ShadowAudioTrack { /** 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 1a70cf3b17f..1d979fd50e2 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothAdapter.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothAdapter.java @@ -58,7 +58,7 @@ import org.robolectric.util.reflector.Static; @SuppressWarnings({"UnusedDeclaration"}) -@Implements(value = BluetoothAdapter.class, looseSignatures = true) +@Implements(value = BluetoothAdapter.class) public class ShadowBluetoothAdapter { @RealObject private BluetoothAdapter realAdapter; @@ -129,9 +129,9 @@ protected static BluetoothAdapter getDefaultAdapter() { return reflector(BluetoothAdapterReflector.class).getDefaultAdapter(); } - /** Requires LooseSignatures because of {@link AttributionSource} parameter */ @Implementation(minSdk = VERSION_CODES.TIRAMISU) - protected static Object createAdapter(Object attributionSource) { + protected static Object createAdapter( + @ClassName(value = "android.content.AttributionSource") Object attributionSource) { IBluetoothManager service = ReflectionHelpers.createDelegatingProxy( IBluetoothManager.class, new BluetoothManagerDelegate()); @@ -355,10 +355,7 @@ protected boolean setName(String name) { return true; } - /** - * Needs looseSignatures because in Android T the return value of this method was changed from - * bool to int. - */ + /** T return value changed from {@code int} to {@link Duration} starting in T. */ @Implementation protected Object setScanMode(int scanMode) { boolean result = true; @@ -394,10 +391,7 @@ protected int getScanMode() { return scanMode; } - /** - * Needs looseSignatures because the return value changed from {@code int} to {@link Duration} - * starting in T. - */ + /** In Android T the return value of this method was changed from bool to int. */ @Implementation protected Object getDiscoverableTimeout() { if (RuntimeEnvironment.getApiLevel() <= S_V2) { diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayEventReceiver.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayEventReceiver.java index 50a53d9d3e7..e26a9db2b0d 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayEventReceiver.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayEventReceiver.java @@ -32,7 +32,6 @@ import org.robolectric.util.reflector.Constructor; import org.robolectric.util.reflector.Direct; import org.robolectric.util.reflector.ForType; -import org.robolectric.util.reflector.WithType; import org.robolectric.versioning.AndroidVersions.U; /** @@ -284,7 +283,7 @@ void onVsync( long timestampNanos, long physicalDisplayId, int frame, - @WithType("android.view.DisplayEventReceiver$VsyncEventData") Object vsyncEventData); + @ClassName("android.view.DisplayEventReceiver$VsyncEventData") Object vsyncEventData); @Accessor("mCloseGuard") CloseGuard getCloseGuard(); @@ -300,14 +299,14 @@ interface VsyncEventDataReflector { @Constructor Object newVsyncEventData( - @WithType("[Landroid.view.DisplayEventReceiver$VsyncEventData$FrameTimeline;") + @ClassName("[Landroid.view.DisplayEventReceiver$VsyncEventData$FrameTimeline;") Object frameTimelineArray, int preferredFrameTimelineIndex, long frameInterval); @Constructor Object newVsyncEventData( - @WithType("[Landroid.view.DisplayEventReceiver$VsyncEventData$FrameTimeline;") + @ClassName("[Landroid.view.DisplayEventReceiver$VsyncEventData$FrameTimeline;") Object frameTimelineArray, int preferredFrameTimelineIndex, int timelineArrayLength, diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManager.java index 85a421a1a64..3d00f1c19d7 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManager.java @@ -42,7 +42,7 @@ * For tests, display properties may be changed and devices may be added or removed * programmatically. */ -@Implements(value = DisplayManager.class, looseSignatures = true) +@Implements(value = DisplayManager.class) public class ShadowDisplayManager { @RealObject private DisplayManager realDisplayManager; @@ -315,14 +315,17 @@ public void setSaturationLevel(float level) { @Implementation(minSdk = P) @HiddenApi - protected void setBrightnessConfiguration(Object config) { + protected void setBrightnessConfiguration( + @ClassName(value = "android.hardware.display.BrightnessConfiguration") Object config) { setBrightnessConfigurationForUser(config, 0, context.getPackageName()); } @Implementation(minSdk = P) @HiddenApi protected void setBrightnessConfigurationForUser( - Object config, Object userId, Object packageName) { + @ClassName(value = "android.hardware.display.BrightnessConfiguration") Object config, + int userId, + String packageName) { getShadowDisplayManagerGlobal().setBrightnessConfigurationForUser(config, userId, packageName); } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManagerGlobal.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManagerGlobal.java index 5681eb2185e..55201339de7 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManagerGlobal.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDisplayManagerGlobal.java @@ -34,10 +34,7 @@ import org.robolectric.util.reflector.ForType; /** Shadow for {@link DisplayManagerGlobal}. */ -@Implements( - value = DisplayManagerGlobal.class, - isInAndroidSdk = false, - looseSignatures = true) +@Implements(value = DisplayManagerGlobal.class, isInAndroidSdk = false) public class ShadowDisplayManagerGlobal { private static DisplayManagerGlobal instance; @@ -234,9 +231,11 @@ float getSaturationLevel() { @Implementation(minSdk = P) @HiddenApi protected void setBrightnessConfigurationForUser( - Object configObject, Object userId, Object packageName) { + @ClassName("android.hardware.display.BrightnessConfiguration") Object configObject, + int userId, + String packageName) { BrightnessConfiguration config = (BrightnessConfiguration) configObject; - brightnessConfiguration.put((int) userId, config); + brightnessConfiguration.put(userId, config); } @Implementation(minSdk = P) diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowHardwareRenderer.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowHardwareRenderer.java index 7b86dc2f487..f37e38f8761 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowHardwareRenderer.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowHardwareRenderer.java @@ -40,6 +40,7 @@ protected static long nCreateProxy( // need to use loose signatures here to account for signature changes @Implementation(minSdk = S) protected static long nCreateProxy(Object translucent, Object rootRenderNode) { + // TODO Find an approach to support the same method with disconnected range return nCreateProxy((boolean) translucent, (long) rootRenderNode); } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInstrumentation.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInstrumentation.java index 68d5b317373..5276e496512 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInstrumentation.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowInstrumentation.java @@ -71,7 +71,6 @@ import org.robolectric.util.ReflectionHelpers.ClassParameter; import org.robolectric.util.reflector.Direct; import org.robolectric.util.reflector.ForType; -import org.robolectric.util.reflector.WithType; @Implements(value = Instrumentation.class) public class ShadowInstrumentation { @@ -1068,8 +1067,8 @@ void init( Context instrContext, Context appContext, ComponentName component, - @WithType("android.app.IInstrumentationWatcher") Object watcher, - @WithType("android.app.IUiAutomationConnection") Object uiAutomationConnection); + @ClassName("android.app.IInstrumentationWatcher") Object watcher, + @ClassName("android.app.IUiAutomationConnection") Object uiAutomationConnection); @Direct ActivityResult execStartActivity( diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPackageParser.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPackageParser.java index 0f31e379cfd..04717251ca9 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPackageParser.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPackageParser.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Set; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.ClassName; import org.robolectric.annotation.Implements; import org.robolectric.res.Fs; import org.robolectric.shadows.ShadowLog.LogItem; @@ -24,7 +25,6 @@ import org.robolectric.util.reflector.Accessor; import org.robolectric.util.reflector.ForType; import org.robolectric.util.reflector.Static; -import org.robolectric.util.reflector.WithType; @Implements(value = PackageParser.class, isInAndroidSdk = false) @SuppressWarnings("NewApi") @@ -108,8 +108,7 @@ PackageInfo generatePackageInfo( long firstInstallTime, long lastUpdateTime, HashSet grantedPermissions, - @WithType("android.content.pm.PackageUserState") - Object state); + @ClassName("android.content.pm.PackageUserState") Object state); // LOLLIPOP_MR1 @Static @@ -120,8 +119,7 @@ PackageInfo generatePackageInfo( long firstInstallTime, long lastUpdateTime, ArraySet grantedPermissions, - @WithType("android.content.pm.PackageUserState") - Object state); + @ClassName("android.content.pm.PackageUserState") Object state); @Static PackageInfo generatePackageInfo( @@ -131,7 +129,7 @@ PackageInfo generatePackageInfo( long firstInstallTime, long lastUpdateTime, Set grantedPermissions, - @WithType("android.content.pm.PackageUserState") Object state); + @ClassName("android.content.pm.PackageUserState") Object state); default PackageInfo generatePackageInfo( PackageParser.Package p, 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 db5d39ebfc2..e53d6c8bcfa 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPaint.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPaint.java @@ -33,7 +33,7 @@ import org.robolectric.versioning.AndroidVersions.V; @SuppressWarnings({"UnusedDeclaration"}) -@Implements(value = Paint.class, looseSignatures = true) +@Implements(value = Paint.class) public class ShadowPaint { private int color; @@ -533,8 +533,11 @@ protected static int nGetFontMetricsInt( } @Implementation(minSdk = N, maxSdk = N_MR1) - protected int nGetFontMetricsInt(Object nativePaint, Object nativeTypeface, Object fmi) { - return nGetFontMetricsInt((long) nativePaint, (FontMetricsInt) fmi); + protected int nGetFontMetricsInt( + long nativePaint, + long nativeTypeface, + @ClassName(value = "android.graphics.Paint$FontMetricsInt") Object fmi) { + return nGetFontMetricsInt(nativePaint, (FontMetricsInt) fmi); } @Implementation(maxSdk = M) diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindow.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindow.java index 9411ff1c82e..0ebfd2663d5 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindow.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindow.java @@ -13,11 +13,11 @@ import org.robolectric.annotation.RealObject; import org.robolectric.util.reflector.ForType; -/** - * Shadow for PhoneWindow for APIs 23+ - */ -@Implements(className = "com.android.internal.policy.PhoneWindow", isInAndroidSdk = false, - minSdk = M, looseSignatures = true) +/** Shadow for PhoneWindow for APIs 23+ */ +@Implements( + className = "com.android.internal.policy.PhoneWindow", + isInAndroidSdk = false, + minSdk = M) public class ShadowPhoneWindow extends ShadowWindow { protected @RealObject Window realWindow; protected boolean decorFitsSystemWindows = true; diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindowFor22.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindowFor22.java index f39f66e693b..6fae3dd26c5 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindowFor22.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPhoneWindowFor22.java @@ -8,11 +8,11 @@ import org.robolectric.annotation.Implements; import org.robolectric.util.reflector.ForType; -/** - * Shadow for the API 16-22 PhoneWindow.li - */ -@Implements(className = "com.android.internal.policy.impl.PhoneWindow", maxSdk = LOLLIPOP_MR1, - looseSignatures = true, isInAndroidSdk = false) +/** Shadow for the API 16-22 PhoneWindow.li */ +@Implements( + className = "com.android.internal.policy.impl.PhoneWindow", + maxSdk = LOLLIPOP_MR1, + isInAndroidSdk = false) public class ShadowPhoneWindowFor22 extends ShadowPhoneWindow { @Override @Implementation(maxSdk = LOLLIPOP_MR1) diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPowerManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPowerManager.java index cc6e427a7da..5dcbd48580a 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPowerManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowPowerManager.java @@ -53,7 +53,7 @@ import org.robolectric.util.reflector.ForType; /** Shadow of PowerManager */ -@Implements(value = PowerManager.class, looseSignatures = true) +@Implements(value = PowerManager.class) public class ShadowPowerManager { @RealObject private PowerManager realPowerManager; @@ -219,7 +219,9 @@ protected int getCurrentThermalStatus() { /** This function adds a listener for thermal status change. */ @Implementation(minSdk = Q) - protected void addThermalStatusListener(Object listener) { + protected void addThermalStatusListener( + @ClassName(value = "android.os.PowerManager$OnThermalStatusChangedListener") + Object listener) { checkState( listener instanceof PowerManager.OnThermalStatusChangedListener, "Listener must implement PowerManager.OnThermalStatusChangedListener"); @@ -233,7 +235,9 @@ public ImmutableSet getThermalStatusListeners() { /** This function removes a listener for thermal status change. */ @Implementation(minSdk = Q) - protected void removeThermalStatusListener(Object listener) { + protected void removeThermalStatusListener( + @ClassName(value = "android.os.PowerManager$OnThermalStatusChangedListener") + Object listener) { checkState( listener instanceof PowerManager.OnThermalStatusChangedListener, "Listener must implement PowerManager.OnThermalStatusChangedListener"); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowRotationWatcherFor22.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowRotationWatcherFor22.java index b27c7d61f4d..d744faed48f 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowRotationWatcherFor22.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowRotationWatcherFor22.java @@ -5,15 +5,16 @@ import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; -/** - * Shadow for RotationWatcher for API 16-22 - */ -@Implements(className = "com.android.internal.policy.impl.PhoneWindow$RotationWatcher", - isInAndroidSdk = false, maxSdk = LOLLIPOP_MR1, looseSignatures = true) +/** Shadow for RotationWatcher for API 16-22 */ +@Implements( + className = "com.android.internal.policy.impl.PhoneWindow$RotationWatcher", + isInAndroidSdk = false, + maxSdk = LOLLIPOP_MR1) public class ShadowRotationWatcherFor22 { @Implementation - protected void addWindow(Object phoneWindow) { + protected void addWindow( + @ClassName(value = "com.android.internal.policy.impl.PhoneWindow") Object phoneWindow) { // ignore } } 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 4cea614d234..baa931a955a 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensorManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSensorManager.java @@ -27,7 +27,7 @@ import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers.ClassParameter; -@Implements(value = SensorManager.class, looseSignatures = true) +@Implements(value = SensorManager.class) public class ShadowSensorManager { public boolean forceListenersToFail = false; private final Multimap sensorMap = @@ -241,7 +241,8 @@ public static SensorEvent createSensorEvent(int valueArraySize, int sensorType) } @Implementation(minSdk = O) - protected Object createDirectChannel(MemoryFile mem) { + protected @ClassName("android.hardware.SensorDirectChannel") Object createDirectChannel( + MemoryFile mem) { return ReflectionHelpers.callConstructor(SensorDirectChannel.class, ClassParameter.from(SensorManager.class, realObject), ClassParameter.from(int.class, 0), diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStaticLayout.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStaticLayout.java index 5a08de4eb16..c81d40a4738 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStaticLayout.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowStaticLayout.java @@ -19,7 +19,7 @@ import org.robolectric.util.reflector.ForType; /** Shadow for android.text.StaticLayout */ -@Implements(value = StaticLayout.class, looseSignatures = true) +@Implements(value = StaticLayout.class) public class ShadowStaticLayout { @ForType(className = "android.text.StaticLayout$LineBreaks") @@ -46,37 +46,37 @@ public static int[] nLineBreakOpportunities( @HiddenApi @Implementation(minSdk = M, maxSdk = O_MR1) public static int nComputeLineBreaks( - Object nativePtr, - Object recycle, - Object recycleBreaks, - Object recycleWidths, - Object recycleFlags, - Object recycleLength) { + long nativePtr, + @ClassName(value = "android.text.StaticLayout$LineBreaks") Object recycle, + int[] recycleBreaks, + float[] recycleWidths, + int[] recycleFlags, + int recycleLength) { return 1; } @HiddenApi @Implementation(minSdk = P, maxSdk = P) protected static int nComputeLineBreaks( - Object nativePtr, - Object text, - Object measuredTextPtr, - Object length, - Object firstWidth, - Object firstWidthLineCount, - Object restWidth, - Object variableTabStops, - Object defaultTabStop, - Object indentsOffset, - Object recycle, - Object recycleLength, - Object recycleBreaks, - Object recycleWidths, - Object recycleAscents, - Object recycleDescents, - Object recycleFlags, - Object charWidths) { - reflector(LineBreaksReflector.class, recycle).setBreaks(new int[] {((char[]) text).length}); + long nativePtr, + char[] text, + long measuredTextPtr, + int length, + float firstWidth, + int firstWidthLineCount, + float restWidth, + int[] variableTabStops, + int defaultTabStop, + int indentsOffset, + @ClassName(value = "android.text.StaticLayout$LineBreaks") Object recycle, + int recycleLength, + int[] recycleBreaks, + float[] recycleWidths, + float[] recycleAscents, + float[] recycleDescents, + int[] recycleFlags, + float[] charWidths) { + reflector(LineBreaksReflector.class, recycle).setBreaks(new int[] {text.length}); return 1; } } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemClock.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemClock.java index bba7005c431..09d4bd1de18 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemClock.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemClock.java @@ -17,12 +17,11 @@ /** * The shadow API for {@link SystemClock}. * - * The behavior of SystemClock in Robolectric will differ based on the current {@link + *

The behavior of SystemClock in Robolectric will differ based on the current {@link * LooperMode}. See {@link ShadowLegacySystemClock} and {@link ShadowPausedSystemClock} for more * details. */ -@Implements(value = SystemClock.class, shadowPicker = ShadowSystemClock.Picker.class, - looseSignatures = true) +@Implements(value = SystemClock.class, shadowPicker = ShadowSystemClock.Picker.class) public abstract class ShadowSystemClock { protected static boolean networkTimeAvailable = true; private static boolean gnssTimeAvailable = true; @@ -96,7 +95,7 @@ public static void simulateDeepSleep(Duration duration) { } @Implementation(minSdk = Q) - protected static Object currentGnssTimeClock() { + protected static @ClassName("java.time.Clock") Object currentGnssTimeClock() { if (gnssTimeAvailable) { return new SimpleClock(UTC) { @Override diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemServiceRegistry.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemServiceRegistry.java index 9ab967edaf6..bd471b855fe 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemServiceRegistry.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowSystemServiceRegistry.java @@ -15,7 +15,6 @@ @Implements( className = "android.app.SystemServiceRegistry", isInAndroidSdk = false, - looseSignatures = true, minSdk = Build.VERSION_CODES.M ) public class ShadowSystemServiceRegistry { @@ -128,7 +127,8 @@ public interface _ServiceFetcherN_ extends _ServiceFetcher_ { } @Implementation(minSdk = O) - protected static void onServiceNotFound(/* ServiceNotFoundException */ Object e0) { + protected static void onServiceNotFound( + @ClassName(value = "android.os.ServiceManager.ServiceNotFoundException") Object e0) { // otherwise the full stacktrace might be swallowed... Exception e = (Exception) e0; e.printStackTrace(); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelephonyManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelephonyManager.java index 1893ae8dc0f..7b76fb5adab 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelephonyManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTelephonyManager.java @@ -81,7 +81,7 @@ import org.robolectric.versioning.AndroidVersions.U; import org.robolectric.versioning.AndroidVersions.V; -@Implements(value = TelephonyManager.class, looseSignatures = true) +@Implements(value = TelephonyManager.class) public class ShadowTelephonyManager { @RealObject protected TelephonyManager realTelephonyManager; @@ -205,12 +205,13 @@ public Object getBootstrapAuthenticationCallback() { @Implementation(minSdk = S) @HiddenApi public void bootstrapAuthenticationRequest( - Object appType, - Object nafId, - Object securityProtocol, - Object forceBootStrapping, - Object e, - Object callback) { + int appType, + Uri nafId, + @ClassName(value = "android.telephony.gba.UaSecurityProtocolIdentifier") + Object securityProtocol, + boolean forceBootStrapping, + Executor e, + @ClassName(value = "android.telephony.BootstrapAuthenticationCallback") Object callback) { this.callback = callback; } @@ -261,7 +262,8 @@ public int getEventFlags() { @Implementation(minSdk = S) public void registerTelephonyCallback( - /*Executor*/ Object executor, /*TelephonyCallback*/ Object callback) { + @ClassName(value = "java.util.concurrent.Executor") Object executor, + @ClassName(value = "android.telephony.TelephonyCallback") Object callback) { Preconditions.checkArgument(executor instanceof Executor); Preconditions.checkArgument(callback instanceof TelephonyCallback); lastTelephonyCallback = callback; @@ -271,15 +273,15 @@ public void registerTelephonyCallback( @Implementation(minSdk = TIRAMISU) protected void registerTelephonyCallback( - /*int*/ Object includeLocationData, /*Executor*/ - Object executor, /*TelephonyCallback*/ - Object callback) { - Preconditions.checkArgument(includeLocationData instanceof Integer); + int includeLocationData, + @ClassName(value = "java.util.concurrent.Executor") Object executor, + @ClassName(value = "android.telephony.TelephonyCallback") Object callback) { registerTelephonyCallback(executor, callback); } @Implementation(minSdk = S) - public void unregisterTelephonyCallback(/*TelephonyCallback*/ Object callback) { + public void unregisterTelephonyCallback( + @ClassName(value = "android.telephony.TelephonyCallback") Object callback) { telephonyCallbackRegistrations.remove(callback); } @@ -733,8 +735,9 @@ public void setAllCellInfo(List allCellInfo) { * TelephonyManager#NETWORK_TYPE_UNKNOWN} if it was never called. */ @Implementation(minSdk = Q) - protected void requestCellInfoUpdate(Object cellInfoExecutor, Object cellInfoCallback) { - Executor executor = (Executor) cellInfoExecutor; + protected void requestCellInfoUpdate( + Executor executor, + @ClassName(value = "android.telephony.CellInfoCallback") Object cellInfoCallback) { if (callbackCellInfos == null) { // ignore } else if (requestCellInfoUpdateErrorCode != 0 || requestCellInfoUpdateDetail != null) { @@ -827,7 +830,8 @@ protected void initListener(PhoneStateListener listener, int flags) { } @CallSuper - protected void initTelephonyCallback(Object callback) { + protected void initTelephonyCallback( + @ClassName(value = "android.telephony.TelephonyCallback") Object callback) { if (VERSION.SDK_INT < S) { return; } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowThreadedRenderer.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowThreadedRenderer.java index 7675c9996ff..db19924d890 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowThreadedRenderer.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowThreadedRenderer.java @@ -12,15 +12,14 @@ @Implements( className = "android.view.ThreadedRenderer", isInAndroidSdk = false, - looseSignatures = true, minSdk = O, maxSdk = P) public class ShadowThreadedRenderer { @Implementation protected static Bitmap createHardwareBitmap( - /*RenderNode*/ Object node, /*int*/ Object width, /*int*/ Object height) { - return createHardwareBitmap((int) width, (int) height); + @ClassName(value = "android.view.RenderNode") Object node, int width, int height) { + return createHardwareBitmap(width, height); } private static Bitmap createHardwareBitmap(int width, int height) { diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinder.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinder.java index 926ae6e8d2b..9f1df6aef81 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinder.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinder.java @@ -18,8 +18,7 @@ className = "libcore.util.TimeZoneFinder", minSdk = O, maxSdk = P, - isInAndroidSdk = false, - looseSignatures = true) + isInAndroidSdk = false) public class ShadowTimeZoneFinder { private static final String TZLOOKUP_PATH = "/usr/share/zoneinfo/tzlookup.xml"; diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderQ.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderQ.java index 97134bd4268..74ee1fa27c0 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderQ.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderQ.java @@ -14,8 +14,7 @@ className = "libcore.timezone.TimeZoneFinder", minSdk = Q, maxSdk = R, - isInAndroidSdk = false, - looseSignatures = true) + isInAndroidSdk = false) public class ShadowTimeZoneFinderQ { @Implementation diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderS.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderS.java index f28a12edfb2..6f31fef5f2e 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderS.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowTimeZoneFinderS.java @@ -12,17 +12,13 @@ import org.robolectric.annotation.Implements; /** Shadow for TimeZoneFinder on S or above. */ -@Implements( - value = TimeZoneFinder.class, - minSdk = S, - isInAndroidSdk = false, - looseSignatures = true) +@Implements(className = "android.timezone.TimeZoneFinder", minSdk = S, isInAndroidSdk = false) public class ShadowTimeZoneFinderS { private static final String TZLOOKUP_PATH = "/usr/share/zoneinfo/tzlookup.xml"; @Implementation - protected static Object getInstance() { + protected static @ClassName("android.timezone.TimeZoneFinder") Object getInstance() { return TimeZoneFinder.createInstanceForTests(readTzlookup()); } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsageStatsManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsageStatsManager.java index 40dc52690ec..0cb7489b479 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsageStatsManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsageStatsManager.java @@ -45,10 +45,7 @@ import org.robolectric.annotation.Resetter; /** Shadow of {@link UsageStatsManager}. */ -@Implements( - value = UsageStatsManager.class, - minSdk = Build.VERSION_CODES.LOLLIPOP, - looseSignatures = true) +@Implements(value = UsageStatsManager.class, minSdk = Build.VERSION_CODES.LOLLIPOP) public class ShadowUsageStatsManager { private static @StandbyBuckets int currentAppStandbyBucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE; @@ -596,7 +593,7 @@ public void setUsageSource(@UsageSource int usageSource) { @SuppressWarnings("unchecked") @Implementation(minSdk = TIRAMISU) protected Object /* List */ queryBroadcastResponseStats( - @Nullable Object packageName, Object id) { + @Nullable String packageName, long id) { List result = new ArrayList<>(); for (Map.Entry> entry : appBroadcastStats.entrySet()) { 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 6e7ab58403e..1703265636b 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsbManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowUsbManager.java @@ -32,7 +32,7 @@ import org.robolectric.util.reflector.ForType; /** Robolectric implementation of {@link android.hardware.usb.UsbManager}. */ -@Implements(value = UsbManager.class, looseSignatures = true) +@Implements(value = UsbManager.class) public class ShadowUsbManager { @RealObject private UsbManager realUsbManager; @@ -261,22 +261,23 @@ public void addPort( @Implementation(minSdk = M) @HiddenApi - protected /* UsbPortStatus */ Object getPortStatus(/* UsbPort */ Object port) { + protected /* UsbPortStatus */ Object getPortStatus( + @ClassName(value = "android.hardware.usb.UsbPort") Object port) { return usbPortStatuses.get(port); } @Implementation(minSdk = M) @HiddenApi protected void setPortRoles( - /* UsbPort */ Object port, /* int */ Object powerRole, /* int */ Object dataRole) { + @ClassName(value = "android.hardware.usb.UsbPort") Object port, int powerRole, int dataRole) { UsbPortStatus status = usbPortStatuses.get(port); usbPortStatuses.put( (UsbPort) port, (UsbPortStatus) createUsbPortStatus( status.getCurrentMode(), - (int) powerRole, - (int) dataRole, + powerRole, + dataRole, status.getSupportedRoleCombinations())); RuntimeEnvironment.getApplication() .sendBroadcast(new Intent(UsbManager.ACTION_USB_PORT_CHANGED)); 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 744b1c02e3d..c9413089c50 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowViewRootImpl.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowViewRootImpl.java @@ -40,7 +40,6 @@ import org.robolectric.util.reflector.Direct; import org.robolectric.util.reflector.ForType; import org.robolectric.util.reflector.Static; -import org.robolectric.util.reflector.WithType; @Implements(value = ViewRootImpl.class, isInAndroidSdk = false) public class ShadowViewRootImpl { @@ -401,7 +400,7 @@ void dispatchResized( Rect stableInsets, Rect outsets, boolean reportDraw, - @WithType("android.util.MergedConfiguration") Object mergedConfiguration, + @ClassName("android.util.MergedConfiguration") Object mergedConfiguration, Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, @@ -416,12 +415,12 @@ void dispatchResized( Rect stableInsets, Rect outsets, boolean reportDraw, - @WithType("android.util.MergedConfiguration") Object mergedConfiguration, + @ClassName("android.util.MergedConfiguration") Object mergedConfiguration, Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId, - @WithType("android.view.DisplayCutout$ParcelableWrapper") Object displayCutout); + @ClassName("android.view.DisplayCutout$ParcelableWrapper") Object displayCutout); default void dispatchResized(Rect frame) { Rect emptyRect = new Rect(0, 0, 0, 0); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiInfo.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiInfo.java index 18363716755..3421b606762 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiInfo.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiInfo.java @@ -14,7 +14,6 @@ import org.robolectric.util.reflector.Direct; import org.robolectric.util.reflector.ForType; import org.robolectric.util.reflector.Static; -import org.robolectric.util.reflector.WithType; @Implements(WifiInfo.class) public class ShadowWifiInfo { @@ -91,7 +90,7 @@ interface WifiInfoReflector { @Direct void setSSID(String ssid); - void setSSID(@WithType("android.net.wifi.WifiSsid") Object ssid); + void setSSID(@ClassName("android.net.wifi.WifiSsid") Object ssid); @Direct void setBSSID(String bssid); diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiManager.java index 9e17e353142..91a26972a24 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWifiManager.java @@ -55,7 +55,7 @@ import org.robolectric.util.ReflectionHelpers; /** Shadow for {@link android.net.wifi.WifiManager}. */ -@Implements(value = WifiManager.class, looseSignatures = true) +@Implements(value = WifiManager.class) @SuppressWarnings("AndroidConcurrentHashMap") public class ShadowWifiManager { private static final int LOCAL_HOST = 2130706433; @@ -578,8 +578,10 @@ public WifiConfiguration getWifiConfiguration(int netId) { @Implementation(minSdk = Q) @HiddenApi - protected void addOnWifiUsabilityStatsListener(Object executorObject, Object listenerObject) { - Executor executor = (Executor) executorObject; + protected void addOnWifiUsabilityStatsListener( + Executor executor, + @ClassName(value = "android.net.wifi.WifiManager$OnWifiUsabilityStatsListener") + Object listenerObject) { WifiManager.OnWifiUsabilityStatsListener listener = (WifiManager.OnWifiUsabilityStatsListener) listenerObject; wifiUsabilityStatsListeners.put(listener, executor); @@ -587,7 +589,9 @@ protected void addOnWifiUsabilityStatsListener(Object executorObject, Object lis @Implementation(minSdk = Q) @HiddenApi - protected void removeOnWifiUsabilityStatsListener(Object listenerObject) { + protected void removeOnWifiUsabilityStatsListener( + @ClassName(value = "android.net.wifi.WifiManager$OnWifiUsabilityStatsListener") + Object listenerObject) { WifiManager.OnWifiUsabilityStatsListener listener = (WifiManager.OnWifiUsabilityStatsListener) listenerObject; wifiUsabilityStatsListeners.remove(listener); @@ -607,7 +611,9 @@ protected void updateWifiUsabilityScore(int seqNum, int score, int predictionHor */ @Implementation(minSdk = R) @HiddenApi - protected boolean setWifiConnectedNetworkScorer(Object executorObject, Object scorerObject) { + protected boolean setWifiConnectedNetworkScorer( + Executor executorObject, + @ClassName("android.net.wifi.WifiManager$WifiConnectedNetworkScorer") Object scorerObject) { if (networkScorer == null) { networkScorer = scorerObject; return true; @@ -850,15 +856,19 @@ public void networksFoundFromPnoScan(List scanResults) { @Implementation(minSdk = TIRAMISU) @HiddenApi protected void setExternalPnoScanRequest( - Object ssids, Object frequencies, Object executor, Object callback) { + // TODO How to support List with generics + @ClassName("java.util.List") Object ssids, + int[] frequencies, + Executor executor, + @ClassName("android.net.wifi.WifiManager$PnoScanResultsCallback") Object callback) { synchronized (pnoRequestLock) { if (callback == null) { throw new IllegalArgumentException("callback cannot be null"); } List pnoSsids = (List) ssids; - int[] pnoFrequencies = (int[]) frequencies; - Executor pnoExecutor = (Executor) executor; + int[] pnoFrequencies = frequencies; + Executor pnoExecutor = executor; InternalPnoScanResultsCallback pnoCallback = new InternalPnoScanResultsCallback(callback); if (pnoExecutor == null) { 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 7438b1bb0ad..d82da062a01 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java @@ -31,10 +31,7 @@ /** Shadow for {@link WindowManagerGlobal}. */ @SuppressWarnings("unused") // Unused params are implementations of Android SDK methods. -@Implements( - value = WindowManagerGlobal.class, - isInAndroidSdk = false, - looseSignatures = true) +@Implements(value = WindowManagerGlobal.class, isInAndroidSdk = false) public class ShadowWindowManagerGlobal { private static WindowSessionDelegate windowSessionDelegate = new WindowSessionDelegate(); private static IWindowSession windowSession; diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/_Activity_.java b/shadows/framework/src/main/java/org/robolectric/shadows/_Activity_.java index fcfcfda7cfa..ec9a0c92e65 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/_Activity_.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/_Activity_.java @@ -19,7 +19,6 @@ import org.robolectric.shadow.api.Shadow; import org.robolectric.util.reflector.Accessor; import org.robolectric.util.reflector.ForType; -import org.robolectric.util.reflector.WithType; /** Accessor interface for {@link Activity}'s internals. */ @ForType(Activity.class) @@ -41,7 +40,7 @@ void attach( CharSequence title, Activity parent, String id, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, Configuration configuration); @@ -58,10 +57,10 @@ void attach( CharSequence title, Activity parent, String id, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, Configuration configuration, - @WithType("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor); + @ClassName("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor); // <= M void attach( @@ -76,11 +75,11 @@ void attach( CharSequence title, Activity parent, String id, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, Configuration configuration, String referer, - @WithType("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor); + @ClassName("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor); // <= N_MR1 void attach( @@ -95,11 +94,11 @@ void attach( CharSequence title, Activity parent, String id, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, Configuration configuration, String referer, - @WithType("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, + @ClassName("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, Window window); // <= P @@ -115,13 +114,13 @@ void attach( CharSequence title, Activity parent, String id, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, Configuration configuration, String referer, - @WithType("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, + @ClassName("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, Window window, - @WithType("android.view.ViewRootImpl$ActivityConfigCallback") Object activityConfigCallback); + @ClassName("android.view.ViewRootImpl$ActivityConfigCallback") Object activityConfigCallback); // <= R void attach( @@ -136,13 +135,13 @@ void attach( CharSequence title, Activity parent, String id, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, Configuration configuration, String referer, - @WithType("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, + @ClassName("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, Window window, - @WithType("android.view.ViewRootImpl$ActivityConfigCallback") Object activityConfigCallback, + @ClassName("android.view.ViewRootImpl$ActivityConfigCallback") Object activityConfigCallback, IBinder assistToken); // >= S @@ -158,13 +157,13 @@ void attach( CharSequence title, Activity parent, String id, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances, Configuration configuration, String referer, - @WithType("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, + @ClassName("com.android.internal.app.IVoiceInteractor") Object iVoiceInteractor, Window window, - @WithType("android.view.ViewRootImpl$ActivityConfigCallback") Object activityConfigCallback, + @ClassName("android.view.ViewRootImpl$ActivityConfigCallback") Object activityConfigCallback, IBinder assistToken, IBinder shareableActivityToken); @@ -178,7 +177,7 @@ default void callAttach( ActivityInfo activityInfo, IBinder token, CharSequence activityTitle, - @WithType("android.app.Activity$NonConfigurationInstances") + @ClassName("android.app.Activity$NonConfigurationInstances") Object lastNonConfigurationInstances) { int apiLevel = RuntimeEnvironment.getApiLevel(); if (apiLevel == Build.VERSION_CODES.KITKAT) { @@ -380,7 +379,7 @@ void dispatchActivityResult( void setLastNonConfigurationInstances(Object nonConfigInstance); void setVoiceInteractor( - @WithType("com.android.internal.app.IVoiceInteractor") Object voiceInteractor); + @ClassName("com.android.internal.app.IVoiceInteractor") Object voiceInteractor); @Accessor("mWindowAdded") boolean getWindowAdded(); diff --git a/utils/reflector/src/main/java/org/robolectric/util/reflector/WithType.java b/utils/reflector/src/main/java/org/robolectric/util/reflector/WithType.java index 6befd71a510..a34e57b16c5 100644 --- a/utils/reflector/src/main/java/org/robolectric/util/reflector/WithType.java +++ b/utils/reflector/src/main/java/org/robolectric/util/reflector/WithType.java @@ -6,7 +6,7 @@ import java.lang.annotation.Target; /** Parameters with types that can't be resolved at compile time may be annotated @WithType. */ -@Target(ElementType.PARAMETER) +@Target({ElementType.METHOD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface WithType {