From 155ef8928c9c69b83d98e2bacfe71c68496e7f6b Mon Sep 17 00:00:00 2001 From: utzcoz Date: Thu, 25 Nov 2021 00:11:48 +0800 Subject: [PATCH 1/3] Bump AGP to 7.1.0-beta04 Signed-off-by: utzcoz --- build.gradle | 2 +- buildSrc/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 910f217a910..22640ad8ada 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { dependencies { gradle - classpath 'com.android.tools.build:gradle:7.1.0-beta03' + classpath 'com.android.tools.build:gradle:7.1.0-beta04' classpath 'net.ltgt.gradle:gradle-errorprone-plugin:1.3.0' classpath 'com.netflix.nebula:gradle-aggregate-javadocs-plugin:3.0.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31" diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index fc6e7d19252..c2e33d1aaa1 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -14,5 +14,5 @@ dependencies { api "com.google.guava:guava:27.0.1-jre" api 'org.jetbrains:annotations:16.0.2' implementation "org.ow2.asm:asm-tree:9.2" - implementation 'com.android.tools.build:gradle:7.1.0-beta03' + implementation 'com.android.tools.build:gradle:7.1.0-beta04' } From bb36cda71131b177cf3d06f4a90b433662c957bf Mon Sep 17 00:00:00 2001 From: utzcoz Date: Thu, 25 Nov 2021 00:25:45 +0800 Subject: [PATCH 2/3] Only using AttributionSource for compile SDK 31 and above We have tried to use Object to replace AttributionSource as type of second input parameter for noteProxyOpNoThrow(int, AttributeSource, String, bool) to make sure ShadowAppOpsManager can be loaded and used when compile SDK is less than 31. But changed method's siganture doesn't match origin method signature, and it will be used as shadow method. To fix this problem, this CL uses looseSignatures for ShadowAppOpsManager, and chagnes all input parameters' type to Object to meet looseSignatures' requirement. Signed-off-by: utzcoz --- .../compat-target29/build.gradle | 2 +- .../target29/Target29CompatibilityTest.kt | 10 +++++++- .../shadows/ShadowAppOpsManager.java | 25 +++++++++++-------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/integration_tests/compat-target29/build.gradle b/integration_tests/compat-target29/build.gradle index 414cebd09b5..f452c2d6060 100644 --- a/integration_tests/compat-target29/build.gradle +++ b/integration_tests/compat-target29/build.gradle @@ -13,7 +13,7 @@ dependencies { testCompileOnly AndroidSdk.Q.coordinates testRuntime AndroidSdk.Q.coordinates - testImplementation("androidx.test:core:$axtVersion") + testImplementation "androidx.test:core:$axtVersion" testImplementation "junit:junit:$junitVersion" testImplementation "com.google.truth:truth:$truthVersion" } \ No newline at end of file diff --git a/integration_tests/compat-target29/src/test/java/org/robolectric/integration/compat/target29/Target29CompatibilityTest.kt b/integration_tests/compat-target29/src/test/java/org/robolectric/integration/compat/target29/Target29CompatibilityTest.kt index a44accf2be2..2bea90de386 100644 --- a/integration_tests/compat-target29/src/test/java/org/robolectric/integration/compat/target29/Target29CompatibilityTest.kt +++ b/integration_tests/compat-target29/src/test/java/org/robolectric/integration/compat/target29/Target29CompatibilityTest.kt @@ -5,14 +5,22 @@ import androidx.test.core.app.ApplicationProvider import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith +import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class Target29CompatibilityTest { + private val application = ApplicationProvider.getApplicationContext(); + @Test fun `Initialize LocationManager succeed`() { - val application = ApplicationProvider.getApplicationContext() val locationManager = application.getSystemService(Context.LOCATION_SERVICE) assertThat(locationManager).isNotNull() } + + @Test + fun `Initialize AppOpsManager succeed`() { + val appOpsManager = application.getSystemService(Context.APP_OPS_SERVICE); + assertThat(appOpsManager).isNotNull(); + } } 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 0891a016300..d2222d676c7 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAppOpsManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowAppOpsManager.java @@ -30,8 +30,10 @@ import android.util.ArrayMap; import android.util.LongSparseArray; import android.util.LongSparseLongArray; +import androidx.annotation.RequiresApi; import com.android.internal.app.IAppOpsService; import com.google.auto.value.AutoValue; +import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.Multimap; @@ -57,7 +59,7 @@ import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers.ClassParameter; -@Implements(value = AppOpsManager.class) +@Implements(value = AppOpsManager.class, looseSignatures = true) public class ShadowAppOpsManager { // OpEntry fields that the shadow doesn't currently allow the test to configure. @@ -394,18 +396,21 @@ protected int noteProxyOpNoThrow( return checkOpNoThrow(op, proxiedUid, proxiedPackageName); } + @RequiresApi(api = Build.VERSION_CODES.S) @Implementation(minSdk = Build.VERSION_CODES.S) protected int noteProxyOpNoThrow( - int op, - AttributionSource attributionSource, - String message, - boolean ignoredSkipProxyOperation) { + Object op, Object attributionSource, Object message, Object ignoredSkipProxyOperation) { + Preconditions.checkArgument(op instanceof Integer); + Preconditions.checkArgument(attributionSource instanceof AttributionSource); + Preconditions.checkArgument(message == null || message instanceof String); + Preconditions.checkArgument(ignoredSkipProxyOperation instanceof Boolean); + AttributionSource castedAttributionSource = (AttributionSource) attributionSource; return noteProxyOpNoThrow( - op, - attributionSource.getNextPackageName(), - attributionSource.getNextUid(), - attributionSource.getNextAttributionTag(), - message); + (int) op, + castedAttributionSource.getNextPackageName(), + castedAttributionSource.getNextUid(), + castedAttributionSource.getNextAttributionTag(), + (String) message); } @Implementation(minSdk = KITKAT) From e54a4cc9af0208f9c396e48323a750bfdef4657a Mon Sep 17 00:00:00 2001 From: utzcoz Date: Sat, 27 Nov 2021 14:01:08 +0800 Subject: [PATCH 3/3] Simply looseSignatures checking Signed-off-by: utzcoz --- .../annotation/processing/validator/ImplementsValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processor/src/main/java/org/robolectric/annotation/processing/validator/ImplementsValidator.java b/processor/src/main/java/org/robolectric/annotation/processing/validator/ImplementsValidator.java index 71b49419125..9f467694e34 100644 --- a/processor/src/main/java/org/robolectric/annotation/processing/validator/ImplementsValidator.java +++ b/processor/src/main/java/org/robolectric/annotation/processing/validator/ImplementsValidator.java @@ -156,7 +156,7 @@ public Void visitType(TypeElement shadowType, Element parent) { AnnotationValue looseSignaturesAttr = Helpers.getAnnotationTypeMirrorValue(am, "looseSignatures"); boolean looseSignatures = - looseSignaturesAttr == null ? false : (Boolean) looseSignaturesAttr.getValue(); + looseSignaturesAttr != null && (Boolean) looseSignaturesAttr.getValue(); validateShadowMethods(actualType, shadowType, minSdk, maxSdk, looseSignatures); modelBuilder.addShadowType(shadowType, actualType,