diff options
author | 2024-10-29 11:18:38 -0700 | |
---|---|---|
committer | 2024-11-13 14:59:56 -0800 | |
commit | 97f3b8a5e6ec83afe6e6f1a19d7cdac0dc5b67e3 (patch) | |
tree | 05d9a10b48b9a58b499e5dd4ad9b0d084dde3145 | |
parent | 9fe82166333c1d0418909b8e41013487b82fe991 (diff) |
Compat-framework on ravenwood
Flag: EXEMPT host test change only
Bug: 367706429
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Merged-In: Ibef0180fe3e5acb919cb6cbab09574c508e6d894
Change-Id: Ia6cd79b9468542ed845b028317ae967e48ea8e88
35 files changed, 292 insertions, 24 deletions
diff --git a/core/java/android/app/AppCompatCallbacks.java b/core/java/android/app/AppCompatCallbacks.java index f2debfcfa6b1..4ef8eb7b93d6 100644 --- a/core/java/android/app/AppCompatCallbacks.java +++ b/core/java/android/app/AppCompatCallbacks.java @@ -28,6 +28,7 @@ import java.util.Arrays; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class AppCompatCallbacks implements Compatibility.BehaviorChangeDelegate { private final long[] mDisabledChanges; private final long[] mLoggableChanges; diff --git a/core/java/android/app/compat/ChangeIdStateCache.java b/core/java/android/app/compat/ChangeIdStateCache.java index dea4e9c82f56..a185d6a48a62 100644 --- a/core/java/android/app/compat/ChangeIdStateCache.java +++ b/core/java/android/app/compat/ChangeIdStateCache.java @@ -29,13 +29,24 @@ import com.android.internal.compat.IPlatformCompat; * Handles caching of calls to {@link com.android.internal.compat.IPlatformCompat} * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class ChangeIdStateCache extends PropertyInvalidatedCache<ChangeIdStateQuery, Boolean> { private static final String CACHE_KEY = "cache_key.is_compat_change_enabled"; private static final int MAX_ENTRIES = 64; - private static boolean sDisabled = false; + private static boolean sDisabled = getDefaultDisabled(); private volatile IPlatformCompat mPlatformCompat; + + @android.ravenwood.annotation.RavenwoodReplace + private static boolean getDefaultDisabled() { + return false; + } + + private static boolean getDefaultDisabled$ravenwood() { + return true; // TODO(b/376676753) Disable the cache for now. + } + /** @hide */ public ChangeIdStateCache() { super(MAX_ENTRIES, CACHE_KEY); diff --git a/core/java/android/app/compat/ChangeIdStateQuery.java b/core/java/android/app/compat/ChangeIdStateQuery.java index 7598d6c90d3d..26d9ab65417e 100644 --- a/core/java/android/app/compat/ChangeIdStateQuery.java +++ b/core/java/android/app/compat/ChangeIdStateQuery.java @@ -35,6 +35,7 @@ import java.util.Objects; * @hide */ @Immutable +@android.ravenwood.annotation.RavenwoodKeepWholeClass final class ChangeIdStateQuery { static final int QUERY_BY_PACKAGE_NAME = 0; diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java index d7b2ab4351a4..643d4c96f7b9 100644 --- a/core/java/android/app/compat/CompatChanges.java +++ b/core/java/android/app/compat/CompatChanges.java @@ -39,6 +39,7 @@ import java.util.Set; * @hide */ @SystemApi +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatChanges { private static final ChangeIdStateCache QUERY_CACHE = new ChangeIdStateCache(); diff --git a/core/java/android/app/compat/PackageOverride.java b/core/java/android/app/compat/PackageOverride.java index ebc2945fb1a0..ffc1eec05667 100644 --- a/core/java/android/app/compat/PackageOverride.java +++ b/core/java/android/app/compat/PackageOverride.java @@ -36,6 +36,7 @@ import java.util.Objects; * @hide */ @SystemApi +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class PackageOverride { /** @hide */ diff --git a/core/java/com/android/internal/compat/AndroidBuildClassifier.java b/core/java/com/android/internal/compat/AndroidBuildClassifier.java index 364db06976a0..19f8889996dc 100644 --- a/core/java/com/android/internal/compat/AndroidBuildClassifier.java +++ b/core/java/com/android/internal/compat/AndroidBuildClassifier.java @@ -22,6 +22,7 @@ import android.os.Build; * Platform private class for determining the type of Android build installed. * */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class AndroidBuildClassifier { public boolean isDebuggableBuild() { diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java index ded142ce49e5..bfa122b8aa6d 100644 --- a/core/java/com/android/internal/compat/ChangeReporter.java +++ b/core/java/com/android/internal/compat/ChangeReporter.java @@ -42,6 +42,7 @@ import java.util.function.Function; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class ChangeReporter { private static final String TAG = "CompatChangeReporter"; private static final Function<Integer, Set<ChangeReport>> NEW_CHANGE_REPORT_SET = diff --git a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java index 182dba71d0d7..8fd914aecf55 100644 --- a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java @@ -28,6 +28,7 @@ import java.util.Set; * Parcelable containing compat config overrides for a given application. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityChangeConfig implements Parcelable { private final ChangeConfig mChangeConfig; diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java index 03fe4551c249..505fd2319a6b 100644 --- a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java @@ -25,6 +25,7 @@ import android.os.Parcelable; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class CompatibilityChangeInfo implements Parcelable { private final long mChangeId; private final @Nullable String mName; diff --git a/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java index 9a02b7b7aae9..32206c9950dd 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java @@ -28,6 +28,7 @@ import java.util.Map; * Parcelable containing compat config overrides for a given application. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverrideConfig implements Parcelable { public final Map<Long, PackageOverride> overrides; diff --git a/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java b/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java index 8652bb6d05e4..998b48a8a76e 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java @@ -26,6 +26,7 @@ import java.util.Map; * Parcelable containing compat config overrides by application. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverridesByPackageConfig implements Parcelable { public final Map<String, CompatibilityOverrideConfig> packageNameToOverrides; diff --git a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java index b408d6440070..c0e2217d509e 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java @@ -29,6 +29,7 @@ import java.util.Map; * IDs. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverridesToRemoveByPackageConfig implements Parcelable { public final Map<String, CompatibilityOverridesToRemoveConfig> packageNameToOverridesToRemove; diff --git a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java index e85afefdc39a..10461ec0b4c6 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java @@ -30,6 +30,7 @@ import java.util.Set; * <p>This class is separate from CompatibilityOverrideConfig since we only need change IDs. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverridesToRemoveConfig implements Parcelable { public final Set<Long> changeIds; diff --git a/core/java/com/android/internal/compat/OverrideAllowedState.java b/core/java/com/android/internal/compat/OverrideAllowedState.java index e408be2ab471..f018c3a830bd 100644 --- a/core/java/com/android/internal/compat/OverrideAllowedState.java +++ b/core/java/com/android/internal/compat/OverrideAllowedState.java @@ -27,6 +27,7 @@ import java.lang.annotation.RetentionPolicy; /** * This class contains all the possible override allowed states. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class OverrideAllowedState implements Parcelable { @IntDef({ ALLOWED, diff --git a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java index a69d2e4f4dca..8df3f2abcafd 100644 --- a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java +++ b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java @@ -15,6 +15,12 @@ */ package com.android.internal.ravenwood; +import static android.os.Build.VERSION_CODES.S; +import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; + +import android.compat.annotation.ChangeId; +import android.compat.annotation.Disabled; +import android.compat.annotation.EnabledAfter; import android.ravenwood.annotation.RavenwoodKeepWholeClass; import android.ravenwood.annotation.RavenwoodRedirect; import android.ravenwood.annotation.RavenwoodRedirectionClass; @@ -78,4 +84,24 @@ public final class RavenwoodEnvironment { public String getRavenwoodRuntimePath() { throw notSupportedOnDevice(); } + + /** @hide */ + public static class CompatIdsForTest { + // Enabled by default + /** Used for testing */ + @ChangeId + public static final long TEST_COMPAT_ID_1 = 368131859L; + + /** Used for testing */ + @Disabled + @ChangeId public static final long TEST_COMPAT_ID_2 = 368131701L; + + /** Used for testing */ + @EnabledAfter(targetSdkVersion = S) + @ChangeId public static final long TEST_COMPAT_ID_3 = 368131659L; + + /** Used for testing */ + @EnabledAfter(targetSdkVersion = UPSIDE_DOWN_CAKE) + @ChangeId public static final long TEST_COMPAT_ID_4 = 368132057L; + } } diff --git a/ravenwood/Framework.bp b/ravenwood/Framework.bp index d20773844df3..99fc31b258e9 100644 --- a/ravenwood/Framework.bp +++ b/ravenwood/Framework.bp @@ -214,7 +214,8 @@ java_genrule { java_genrule { name: "services.core.ravenwood", - defaults: ["ravenwood-internal-only-visibility-genrule"], + // This is used by unit tests too (so tests will be able to access HSG-processed implementation) + // so it's visible to all. cmd: "cp $(in) $(out)", srcs: [ ":services.core.ravenwood-base{ravenwood.jar}", diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING index a1243e37003e..607592b4cbbe 100644 --- a/ravenwood/TEST_MAPPING +++ b/ravenwood/TEST_MAPPING @@ -117,7 +117,11 @@ "host": true }, { - "name": "FrameworksServicesTestsRavenwood", + "name": "FrameworksServicesTestsRavenwood_Compat", + "host": true + }, + { + "name": "FrameworksServicesTestsRavenwood_Uri", "host": true }, { diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java index c5a9c7b28ad3..678a97be60a2 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java @@ -30,9 +30,12 @@ import static org.mockito.Mockito.mock; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.AppCompatCallbacks; import android.app.Instrumentation; import android.app.ResourcesManager; import android.app.UiAutomation; +import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.os.Binder; import android.os.Build; @@ -41,6 +44,7 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.Process_ravenwood; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemProperties; import android.provider.DeviceConfig_host; import android.system.ErrnoException; @@ -58,6 +62,7 @@ import com.android.ravenwood.common.RavenwoodCommonUtils; import com.android.ravenwood.common.RavenwoodRuntimeException; import com.android.ravenwood.common.SneakyThrow; import com.android.server.LocalServices; +import com.android.server.compat.PlatformCompat; import org.junit.runner.Description; @@ -331,6 +336,8 @@ public class RavenwoodRuntimeEnvironmentController { RavenwoodSystemServer.init(config); + initializeCompatIds(config); + if (ENABLE_TIMEOUT_STACKS) { sPendingTimeout = sTimeoutExecutor.schedule( RavenwoodRuntimeEnvironmentController::dumpStacks, @@ -346,6 +353,31 @@ public class RavenwoodRuntimeEnvironmentController { Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid)); } + private static void initializeCompatIds(RavenwoodConfig config) { + // Set up compat-IDs for the app side. + // TODO: Inside the system server, all the compat-IDs should be enabled, + // Due to the `AppCompatCallbacks.install(new long[0], new long[0])` call in + // SystemServer. + + // Compat framework only uses the package name and the target SDK level. + ApplicationInfo appInfo = new ApplicationInfo(); + appInfo.packageName = config.mTargetPackageName; + appInfo.targetSdkVersion = config.mTargetSdkLevel; + + PlatformCompat platformCompat = null; + try { + platformCompat = (PlatformCompat) ServiceManager.getServiceOrThrow( + Context.PLATFORM_COMPAT_SERVICE); + } catch (ServiceNotFoundException e) { + throw new RuntimeException(e); + } + + var disabledChanges = platformCompat.getDisabledChanges(appInfo); + var loggableChanges = platformCompat.getLoggableChanges(appInfo); + + AppCompatCallbacks.install(disabledChanges, loggableChanges); + } + /** * De-initialize. */ diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java index f198a08a50e3..438a2bfa7a14 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java @@ -17,7 +17,9 @@ package android.platform.test.ravenwood; import android.content.ClipboardManager; +import android.content.Context; import android.hardware.SerialManager; +import android.os.ServiceManager; import android.os.SystemClock; import android.ravenwood.example.BlueManager; import android.ravenwood.example.RedManager; @@ -27,6 +29,8 @@ import android.util.ArraySet; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; +import com.android.server.compat.PlatformCompat; +import com.android.server.compat.PlatformCompatNative; import com.android.server.utils.TimingsTraceAndSlog; import java.util.List; @@ -65,6 +69,14 @@ public class RavenwoodSystemServer { private static SystemServiceManager sServiceManager; public static void init(RavenwoodConfig config) { + // Always start PlatformCompat, regardless of the requested services. + // PlatformCompat is not really a SystemService, so it won't receive boot phases / etc. + // This initialization code is copied from SystemServer.java. + PlatformCompat platformCompat = new PlatformCompat(config.mState.mSystemServerContext); + ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat); + ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE, + new PlatformCompatNative(platformCompat)); + // Avoid overhead if no services required if (config.mServicesRequired.isEmpty()) return; diff --git a/ravenwood/tests/bivalenttest/Android.bp b/ravenwood/tests/bivalenttest/Android.bp index 4895a1a6d1a2..40e6672a3c63 100644 --- a/ravenwood/tests/bivalenttest/Android.bp +++ b/ravenwood/tests/bivalenttest/Android.bp @@ -58,6 +58,9 @@ java_defaults { java_defaults { name: "ravenwood-bivalent-device-defaults", defaults: ["ravenwood-bivalent-defaults"], + + target_sdk_version: "34", // For compat-framework tests + // TODO(b/371215487): migrate bivalenttest.ravenizer tests to another architecture exclude_srcs: [ "test/**/ravenizer/*.java", diff --git a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt new file mode 100644 index 000000000000..a95760db1a61 --- /dev/null +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.ravenwoodtest.bivalenttest.compat + +import android.app.compat.CompatChanges +import android.os.Build +import android.platform.test.ravenwood.RavenwoodConfig +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.internal.ravenwood.RavenwoodEnvironment.CompatIdsForTest +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class RavenwoodCompatFrameworkTest { + companion object { + @JvmField // Expose as a raw field, not as a property. + @RavenwoodConfig.Config + val config = RavenwoodConfig.Builder() + .setTargetSdkLevel(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + .build() + } + + @Test + fun testEnabled() { + Assert.assertTrue(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_1)) + } + + @Test + fun testDisabled() { + Assert.assertFalse(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_2)) + } + + @Test + fun testEnabledAfterSForUApps() { + Assert.assertTrue(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_3)) + } + + @Test + fun testEnabledAfterUForUApps() { + Assert.assertFalse(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_4)) + } +}
\ No newline at end of file diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt index 5d24c3aea728..39e0cf90698e 100644 --- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt +++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt @@ -366,3 +366,9 @@ com.android.server.utils.TimingsTraceAndSlog android.os.IpcDataCache android.app.PropertyInvalidatedCache + +android.app.compat.* +com.android.server.compat.* +com.android.internal.compat.* +android.app.AppCompatCallbacks + diff --git a/ravenwood/texts/ravenwood-services-policies.txt b/ravenwood/texts/ravenwood-services-policies.txt index cc2fa602b3c3..530e5c8f5986 100644 --- a/ravenwood/texts/ravenwood-services-policies.txt +++ b/ravenwood/texts/ravenwood-services-policies.txt @@ -1 +1,12 @@ # Ravenwood "policy" file for services.core. + +# Auto-generated from XSD +class com.android.server.compat.config.Change keepclass +class com.android.server.compat.config.Config keepclass +class com.android.server.compat.config.XmlParser keepclass +class com.android.server.compat.overrides.ChangeOverrides keepclass +class com.android.server.compat.overrides.OverrideValue keepclass +class com.android.server.compat.overrides.Overrides keepclass +class com.android.server.compat.overrides.RawOverrideValue keepclass +class com.android.server.compat.overrides.XmlParser keepclass +class com.android.server.compat.overrides.XmlWriter keepclass
\ No newline at end of file diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index a40dd7919402..c3d88e3e6eb1 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -50,6 +50,7 @@ import java.util.concurrent.ConcurrentHashMap; * * <p>Note, this class is not thread safe so callers must ensure thread safety. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatChange extends CompatibilityChangeInfo { /** diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 79025d00d128..e89f43bd7196 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -42,6 +42,7 @@ import com.android.internal.compat.CompatibilityOverridesToRemoveByPackageConfig import com.android.internal.compat.CompatibilityOverridesToRemoveConfig; import com.android.internal.compat.IOverrideValidator; import com.android.internal.compat.OverrideAllowedState; +import com.android.internal.ravenwood.RavenwoodEnvironment; import com.android.server.compat.config.Change; import com.android.server.compat.config.Config; import com.android.server.compat.overrides.ChangeOverrides; @@ -63,6 +64,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; import javax.xml.datatype.DatatypeConfigurationException; @@ -72,12 +74,16 @@ import javax.xml.datatype.DatatypeConfigurationException; * <p>It stores the default configuration for each change, and any per-package overrides that have * been configured. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass final class CompatConfig { private static final String TAG = "CompatConfig"; private static final String APP_COMPAT_DATA_DIR = "/data/misc/appcompat"; private static final String STATIC_OVERRIDES_PRODUCT_DIR = "/product/etc/appcompat"; private static final String OVERRIDES_FILE = "compat_framework_overrides.xml"; + private static final String APP_COMPAT_DATA_DIR_RAVENWOOD = "/ravenwood-data/"; + private static final String OVERRIDES_FILE_RAVENWOOD = "compat-config.xml"; + private final ConcurrentHashMap<Long, CompatChange> mChanges = new ConcurrentHashMap<>(); private final OverrideValidatorImpl mOverrideValidator; @@ -98,19 +104,32 @@ final class CompatConfig { static CompatConfig create(AndroidBuildClassifier androidBuildClassifier, Context context) { CompatConfig config = new CompatConfig(androidBuildClassifier, context); - config.initConfigFromLib(Environment.buildPath( + config.loadConfigFiles(); + config.initOverrides(); + config.invalidateCache(); + return config; + } + + @android.ravenwood.annotation.RavenwoodReplace + private void loadConfigFiles() { + initConfigFromLib(Environment.buildPath( Environment.getRootDirectory(), "etc", "compatconfig")); - config.initConfigFromLib(Environment.buildPath( + initConfigFromLib(Environment.buildPath( Environment.getRootDirectory(), "system_ext", "etc", "compatconfig")); List<ApexManager.ActiveApexInfo> apexes = ApexManager.getInstance().getActiveApexInfos(); for (ApexManager.ActiveApexInfo apex : apexes) { - config.initConfigFromLib(Environment.buildPath( + initConfigFromLib(Environment.buildPath( apex.apexDirectory, "etc", "compatconfig")); } - config.initOverrides(); - config.invalidateCache(); - return config; + } + + @SuppressWarnings("unused") + private void loadConfigFiles$ravenwood() { + final var configDir = new File( + RavenwoodEnvironment.getInstance().getRavenwoodRuntimePath() + + APP_COMPAT_DATA_DIR_RAVENWOOD); + initConfigFromLib(configDir, (file) -> file.getName().endsWith(OVERRIDES_FILE_RAVENWOOD)); } /** @@ -678,12 +697,25 @@ final class CompatConfig { return changeInfos; } + /** + * Load all config files in a given directory. + */ void initConfigFromLib(File libraryDir) { + initConfigFromLib(libraryDir, (file) -> true); + } + + /** + * Load config files in a given directory, but only the ones that match {@code includingFilter}. + */ + void initConfigFromLib(File libraryDir, Predicate<File> includingFilter) { if (!libraryDir.exists() || !libraryDir.isDirectory()) { Slog.d(TAG, "No directory " + libraryDir + ", skipping"); return; } for (File f : libraryDir.listFiles()) { + if (!includingFilter.test(f)) { + continue; + } Slog.d(TAG, "Found a config file: " + f.getPath()); //TODO(b/138222363): Handle duplicate ids across config files. readConfig(f); diff --git a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java index e3b6d032b7f0..362c69797161 100644 --- a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java +++ b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java @@ -45,6 +45,7 @@ import com.android.internal.compat.OverrideAllowedState; /** * Implementation of the policy for allowing compat change overrides. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class OverrideValidatorImpl extends IOverrideValidator.Stub { private AndroidBuildClassifier mAndroidBuildClassifier; diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index df49affa4d6f..2186e2a397c5 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -36,6 +36,7 @@ import android.content.pm.PackageManagerInternal; import android.net.Uri; import android.os.Binder; import android.os.Build; +import android.os.PermissionEnforcer; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; @@ -65,6 +66,7 @@ import java.util.Map; /** * System server internal API for gating and reporting compatibility changes. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class PlatformCompat extends IPlatformCompat.Stub { private static final String TAG = "Compatibility"; @@ -75,6 +77,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { private final AndroidBuildClassifier mBuildClassifier; public PlatformCompat(Context context) { + super(PermissionEnforcer.fromContext(context)); mContext = context; mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER); mBuildClassifier = new AndroidBuildClassifier(); @@ -84,6 +87,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @VisibleForTesting PlatformCompat(Context context, CompatConfig compatConfig, AndroidBuildClassifier buildClassifier) { + super(PermissionEnforcer.fromContext(context)); mContext = context; mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER); mCompatConfig = compatConfig; @@ -492,6 +496,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { packageName, 0, Process.myUid(), userId); } + @android.ravenwood.annotation.RavenwoodReplace private void killPackage(String packageName) { int uid = LocalServices.getService(PackageManagerInternal.class).getPackageUid(packageName, 0, UserHandle.myUserId()); @@ -505,6 +510,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { killUid(UserHandle.getAppId(uid)); } + @SuppressWarnings("unused") + private void killPackage$ravenwood(String packageName) { + // TODO Maybe crash if the package is the self. + Slog.w(TAG, "killPackage() is ignored on Ravenwood: packageName=" + packageName); + } + + @android.ravenwood.annotation.RavenwoodReplace private void killUid(int appId) { final long identity = Binder.clearCallingIdentity(); try { @@ -519,6 +531,12 @@ public class PlatformCompat extends IPlatformCompat.Stub { } } + @SuppressWarnings("unused") + private void killUid$ravenwood(int appId) { + // TODO Maybe crash if the UID is the self. + Slog.w(TAG, "killUid() is ignored on Ravenwood: appId=" + appId); + } + private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) { for (Long changeId : changeIds) { if (isKnownChangeId(changeId) && !mCompatConfig.isOverridable(changeId)) { diff --git a/services/core/java/com/android/server/compat/PlatformCompatNative.java b/services/core/java/com/android/server/compat/PlatformCompatNative.java index 5d7af650db0b..7a3feb515706 100644 --- a/services/core/java/com/android/server/compat/PlatformCompatNative.java +++ b/services/core/java/com/android/server/compat/PlatformCompatNative.java @@ -23,6 +23,7 @@ import com.android.internal.compat.IPlatformCompatNative; /** * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class PlatformCompatNative extends IPlatformCompatNative.Stub { private final PlatformCompat mPlatformCompat; diff --git a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java index e8762a3e935c..0ec68792a886 100644 --- a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java +++ b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java @@ -46,6 +46,7 @@ import java.util.regex.Pattern; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass final class AppCompatOverridesParser { /** * Flag for specifying all compat change IDs owned by a namespace. See {@link diff --git a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java index fe002ce00d32..8637d2dfe565 100644 --- a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java +++ b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java @@ -68,6 +68,7 @@ import java.util.Set; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class AppCompatOverridesService { private static final String TAG = "AppCompatOverridesService"; diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index d336c9962c17..c09886807884 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -149,21 +149,49 @@ android_test { resource_zips: [":FrameworksServicesTests_apks_as_resources"], } -android_ravenwood_test { - name: "FrameworksServicesTestsRavenwood", +java_defaults { + name: "FrameworksServicesTestsRavenwood-defaults", libs: [ "android.test.mock.stubs.system", ], static_libs: [ "androidx.annotation_annotation", "androidx.test.rules", - "services.core", "flag-junit", ], + auto_gen_config: true, +} + +// Unit tests for UriGrantManager, running on ravenwood. +// Note UriGrantManager does not support Ravenwood (yet). We're just running the original +// unit tests as is on Ravenwood. So here, we use the original "services.core", because +// "services.core.ravenwood" doesn't have the target code. +// (Compare to FrameworksServicesTestsRavenwood_Compat, which does support Ravenwood.) +android_ravenwood_test { + name: "FrameworksServicesTestsRavenwood_Uri", + defaults: ["FrameworksServicesTestsRavenwood-defaults"], + team: "trendy_team_ravenwood", + static_libs: [ + "services.core", + ], srcs: [ "src/com/android/server/uri/**/*.java", ], - auto_gen_config: true, +} + +// Unit tests for compat-framework. +// Compat-framework does support Ravenwood, and it uses the ravenwood anottations, +// so we link "services.core.ravenwood". +android_ravenwood_test { + name: "FrameworksServicesTestsRavenwood_Compat", + defaults: ["FrameworksServicesTestsRavenwood-defaults"], + team: "trendy_team_ravenwood", + static_libs: [ + "services.core.ravenwood", + ], + srcs: [ + "src/com/android/server/compat/**/*.java", + ], } java_library { diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java index 36b163ec84b6..3d695a68f1f9 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java @@ -18,12 +18,12 @@ package com.android.server.compat; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.testng.Assert.assertThrows; import android.app.compat.ChangeIdStateCache; import android.app.compat.PackageOverride; diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java index 9accd49bc392..79f0673d91bd 100644 --- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java @@ -18,6 +18,7 @@ package com.android.server.compat; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.never; @@ -25,13 +26,15 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.internal.verification.VerificationModeFactory.times; -import static org.testng.Assert.assertThrows; import android.compat.Compatibility.ChangeConfig; +import android.content.AttributionSource; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.os.Build; +import android.os.PermissionEnforcer; +import android.permission.PermissionCheckerManager; import androidx.test.runner.AndroidJUnit4; @@ -77,6 +80,22 @@ public class PlatformCompatTest { .thenReturn(-1); when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) .thenThrow(new PackageManager.NameNotFoundException()); + + var allGrantingPermissionEnforcer = new PermissionEnforcer() { + @Override + protected int checkPermission(String permission, AttributionSource source) { + return PermissionCheckerManager.PERMISSION_GRANTED; + } + + @Override + protected int checkPermission(String permission, int pid, int uid) { + return PermissionCheckerManager.PERMISSION_GRANTED; + } + }; + + when(mContext.getSystemService(eq(Context.PERMISSION_ENFORCER_SERVICE))) + .thenReturn(allGrantingPermissionEnforcer); + mCompatConfig = new CompatConfig(mBuildClassifier, mContext); mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); // Assume userdebug/eng non-final build diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java index 24abc183cad1..f5494534716a 100644 --- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java @@ -61,7 +61,6 @@ import android.os.Process; import android.os.UserHandle; import android.platform.test.flag.junit.FlagsParameterization; import android.platform.test.flag.junit.SetFlagsRule; -import android.platform.test.ravenwood.RavenwoodRule; import android.util.ArraySet; import org.junit.Before; @@ -77,9 +76,6 @@ import java.util.Set; @RunWith(Parameterized.class) public class UriGrantsManagerServiceTest { - @Rule - public final RavenwoodRule mRavenwood = new RavenwoodRule(); - /** * Why this class needs to test all combinations of * {@link android.security.Flags#FLAG_CONTENT_URI_PERMISSION_APIS}: diff --git a/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java b/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java index 611c51463246..fe66f738487d 100644 --- a/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java +++ b/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java @@ -37,18 +37,13 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import android.os.SystemClock; -import android.platform.test.ravenwood.RavenwoodRule; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class UriPermissionTest { - @Rule - public final RavenwoodRule mRavenwood = new RavenwoodRule(); - @Mock private UriGrantsManagerInternal mService; |