Merge "Add an API method for clearing compat overrides on release builds"
This commit is contained in:
@@ -1124,10 +1124,11 @@ package android.app.backup {
|
||||
package android.app.compat {
|
||||
|
||||
public final class CompatChanges {
|
||||
method @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public static void addPackageOverrides(@NonNull String, @NonNull java.util.Map<java.lang.Long,android.app.compat.PackageOverride>);
|
||||
method public static boolean isChangeEnabled(long);
|
||||
method @RequiresPermission(allOf={"android.permission.READ_COMPAT_CHANGE_CONFIG", "android.permission.LOG_COMPAT_CHANGE"}) public static boolean isChangeEnabled(long, @NonNull String, @NonNull android.os.UserHandle);
|
||||
method @RequiresPermission(allOf={"android.permission.READ_COMPAT_CHANGE_CONFIG", "android.permission.LOG_COMPAT_CHANGE"}) public static boolean isChangeEnabled(long, int);
|
||||
method @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public static void setPackageOverride(@NonNull String, @NonNull java.util.Map<java.lang.Long,android.app.compat.PackageOverride>);
|
||||
method @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD) public static void removePackageOverrides(@NonNull String, @NonNull java.util.Set<java.lang.Long>);
|
||||
}
|
||||
|
||||
public final class PackageOverride {
|
||||
|
||||
@@ -26,9 +26,11 @@ import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.compat.CompatibilityOverrideConfig;
|
||||
import com.android.internal.compat.CompatibilityOverridesToRemoveConfig;
|
||||
import com.android.internal.compat.IPlatformCompat;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* CompatChanges APIs - to be used by platform code only (including mainline
|
||||
@@ -98,15 +100,19 @@ public final class CompatChanges {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an app compat override for a given package. This will check whether the caller is allowed
|
||||
* Adds app compat overrides for a given package. This will check whether the caller is allowed
|
||||
* to perform this operation on the given apk and build. Only the installer package is allowed
|
||||
* to set overrides on a non-debuggable final build and a non-test apk.
|
||||
*
|
||||
* <p>Note that calling this method doesn't remove previously added overrides for the given
|
||||
* package if their change ID isn't in the given map, only replaces those that have the same
|
||||
* change ID.
|
||||
*
|
||||
* @param packageName The package name of the app in question.
|
||||
* @param overrides A map from changeId to the override applied for this change id.
|
||||
* @param overrides A map from change ID to the override applied for this change ID.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD)
|
||||
public static void setPackageOverride(@NonNull String packageName,
|
||||
public static void addPackageOverrides(@NonNull String packageName,
|
||||
@NonNull Map<Long, PackageOverride> overrides) {
|
||||
IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
|
||||
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
||||
@@ -117,4 +123,29 @@ public final class CompatChanges {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes app compat overrides for a given package. This will check whether the caller is
|
||||
* allowed to perform this operation on the given apk and build. Only the installer package is
|
||||
* allowed to clear overrides on a non-debuggable final build and a non-test apk.
|
||||
*
|
||||
* <p>Note that calling this method with an empty set is a no-op and no overrides will be
|
||||
* removed for the given package.
|
||||
*
|
||||
* @param packageName The package name of the app in question.
|
||||
* @param overridesToRemove A set of change IDs for which to remove overrides.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD)
|
||||
public static void removePackageOverrides(@NonNull String packageName,
|
||||
@NonNull Set<Long> overridesToRemove) {
|
||||
IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
|
||||
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
||||
CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig(
|
||||
overridesToRemove);
|
||||
try {
|
||||
platformCompat.removeOverridesOnReleaseBuilds(config, packageName);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.internal.compat;
|
||||
|
||||
parcelable CompatibilityOverridesToRemoveConfig;
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.internal.compat;
|
||||
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Parcelable containing compat config change IDs for which to remove overrides for a given
|
||||
* application.
|
||||
* @hide
|
||||
*/
|
||||
public final class CompatibilityOverridesToRemoveConfig implements Parcelable {
|
||||
public final Set<Long> changeIds;
|
||||
|
||||
public CompatibilityOverridesToRemoveConfig(Set<Long> changeIds) {
|
||||
this.changeIds = changeIds;
|
||||
}
|
||||
|
||||
private CompatibilityOverridesToRemoveConfig(Parcel in) {
|
||||
int keyCount = in.readInt();
|
||||
changeIds = new HashSet<>();
|
||||
for (int i = 0; i < keyCount; i++) {
|
||||
changeIds.add(in.readLong());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(changeIds.size());
|
||||
for (Long changeId : changeIds) {
|
||||
dest.writeLong(changeId);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Creator<CompatibilityOverridesToRemoveConfig> CREATOR =
|
||||
new Creator<CompatibilityOverridesToRemoveConfig>() {
|
||||
|
||||
@Override
|
||||
public CompatibilityOverridesToRemoveConfig createFromParcel(Parcel in) {
|
||||
return new CompatibilityOverridesToRemoveConfig(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatibilityOverridesToRemoveConfig[] newArray(int size) {
|
||||
return new CompatibilityOverridesToRemoveConfig[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import java.util.Map;
|
||||
|
||||
parcelable CompatibilityChangeConfig;
|
||||
parcelable CompatibilityOverrideConfig;
|
||||
parcelable CompatibilityOverridesToRemoveConfig;
|
||||
parcelable CompatibilityChangeInfo;
|
||||
/**
|
||||
* Platform private API for talking with the PlatformCompat service.
|
||||
@@ -203,6 +204,27 @@ interface IPlatformCompat {
|
||||
*/
|
||||
void clearOverrideForTest(long changeId, String packageName);
|
||||
|
||||
/**
|
||||
* Restores the default behaviour for compatibility changes on release builds.
|
||||
*
|
||||
* <p>The caller to this API needs to hold
|
||||
* {@code android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD} and all change ids
|
||||
* in {@code overridesToRemove} need to annotated with
|
||||
* {@link android.compat.annotation.Overridable}.
|
||||
*
|
||||
* A release build in this definition means that {@link android.os.Build#IS_DEBUGGABLE} needs to
|
||||
* be {@code false}.
|
||||
*
|
||||
* <p>Note that this does not kill the app, and therefore overrides read from the app process
|
||||
* will not be updated. Overrides read from the system process do take effect.
|
||||
*
|
||||
* @param overridesToRemove parcelable containing the compat change overrides to be removed
|
||||
* @param packageName the package name of the app whose changes will be restored to the
|
||||
* default behaviour
|
||||
* @throws SecurityException if overriding changes is not permitted
|
||||
*/
|
||||
void removeOverridesOnReleaseBuilds(in CompatibilityOverridesToRemoveConfig overridesToRemove, in String packageName);
|
||||
|
||||
/**
|
||||
* Enables all compatibility changes that have enabledSinceTargetSdk ==
|
||||
* {@param targetSdkVersion} for an app, subject to the policy.
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.android.internal.compat.AndroidBuildClassifier;
|
||||
import com.android.internal.compat.CompatibilityChangeConfig;
|
||||
import com.android.internal.compat.CompatibilityChangeInfo;
|
||||
import com.android.internal.compat.CompatibilityOverrideConfig;
|
||||
import com.android.internal.compat.CompatibilityOverridesToRemoveConfig;
|
||||
import com.android.internal.compat.IOverrideValidator;
|
||||
import com.android.internal.compat.OverrideAllowedState;
|
||||
import com.android.server.compat.config.Change;
|
||||
@@ -370,6 +371,27 @@ final class CompatConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes overrides whose change ID is specified in {@code overridesToRemove} that were
|
||||
* previously added via {@link #addOverride(long, String, boolean)} or
|
||||
* {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
|
||||
*
|
||||
* <p>This restores the default behaviour for the given change IDs and app.
|
||||
*
|
||||
* @param overridesToRemove list of change IDs for which to restore the default behaviour.
|
||||
* @param packageName the package for which the overrides should be purged
|
||||
*/
|
||||
void removePackageOverrides(CompatibilityOverridesToRemoveConfig overridesToRemove,
|
||||
String packageName) {
|
||||
synchronized (mChanges) {
|
||||
for (Long changeId : overridesToRemove.changeIds) {
|
||||
removeOverrideUnsafe(changeId, packageName);
|
||||
}
|
||||
saveOverrides();
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
|
||||
int targetSdkVersion) {
|
||||
LongArray allowed = new LongArray();
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.android.internal.compat.ChangeReporter;
|
||||
import com.android.internal.compat.CompatibilityChangeConfig;
|
||||
import com.android.internal.compat.CompatibilityChangeInfo;
|
||||
import com.android.internal.compat.CompatibilityOverrideConfig;
|
||||
import com.android.internal.compat.CompatibilityOverridesToRemoveConfig;
|
||||
import com.android.internal.compat.IOverrideValidator;
|
||||
import com.android.internal.compat.IPlatformCompat;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
@@ -54,6 +55,7 @@ import com.android.server.LocalServices;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -187,7 +189,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
String packageName) {
|
||||
// TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
|
||||
checkCompatChangeOverrideOverridablePermission();
|
||||
checkAllCompatOverridesAreOverridable(overrides);
|
||||
checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
|
||||
mCompatConfig.addOverrides(overrides, packageName);
|
||||
}
|
||||
|
||||
@@ -250,6 +252,16 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
mCompatConfig.removeOverride(changeId, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOverridesOnReleaseBuilds(
|
||||
CompatibilityOverridesToRemoveConfig overridesToRemove,
|
||||
String packageName) {
|
||||
// TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
|
||||
checkCompatChangeOverrideOverridablePermission();
|
||||
checkAllCompatOverridesAreOverridable(overridesToRemove.changeIds);
|
||||
mCompatConfig.removePackageOverrides(overridesToRemove, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
|
||||
checkCompatChangeReadAndLogPermission();
|
||||
@@ -396,8 +408,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAllCompatOverridesAreOverridable(CompatibilityOverrideConfig overrides) {
|
||||
for (Long changeId : overrides.overrides.keySet()) {
|
||||
private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) {
|
||||
for (Long changeId : changeIds) {
|
||||
if (!mCompatConfig.isOverridable(changeId)) {
|
||||
throw new SecurityException("Only change ids marked as Overridable can be "
|
||||
+ "overridden.");
|
||||
|
||||
@@ -115,7 +115,12 @@ class CompatConfigBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
CompatConfigBuilder addOverridableChangeWithId(long id) {
|
||||
CompatConfigBuilder addEnabledOverridableChangeWithId(long id) {
|
||||
mChanges.add(new CompatChange(id, "", -1, -1, false, false, "", true));
|
||||
return this;
|
||||
}
|
||||
|
||||
CompatConfigBuilder addDisabledOverridableChangeWithId(long id) {
|
||||
mChanges.add(new CompatChange(id, "", -1, -1, true, false, "", true));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.compat.AndroidBuildClassifier;
|
||||
import com.android.internal.compat.CompatibilityOverrideConfig;
|
||||
import com.android.internal.compat.CompatibilityOverridesToRemoveConfig;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -50,6 +51,10 @@ import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -249,7 +254,7 @@ public class CompatConfigTest {
|
||||
when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
// Force the validator to prevent overriding the change by using a user build.
|
||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
@@ -261,10 +266,12 @@ public class CompatConfigTest {
|
||||
|
||||
@Test
|
||||
public void testInstallerCanSetOverrides() throws Exception {
|
||||
final long changeId = 1234L;
|
||||
final int installerUid = 23;
|
||||
final long disabledChangeId1 = 1234L;
|
||||
final long disabledChangeId2 = 1235L;
|
||||
// We make disabledChangeId2 non-overridable to make sure it is ignored.
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addOverridableChangeWithId(1234L)
|
||||
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
||||
.addDisabledChangeWithId(disabledChangeId2)
|
||||
.build();
|
||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.some.package")
|
||||
@@ -274,19 +281,56 @@ public class CompatConfigTest {
|
||||
when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
// Force the validator to prevent overriding the change by using a user build.
|
||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(
|
||||
Collections.singletonMap(1234L,
|
||||
Collections.singletonMap(disabledChangeId1,
|
||||
new PackageOverride.Builder()
|
||||
.setMaxVersionCode(99L)
|
||||
.setEnabled(true)
|
||||
.build()));
|
||||
|
||||
compatConfig.addOverrides(config, "com.some.package");
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreventInstallerSetNonOverridable() throws Exception {
|
||||
final long disabledChangeId1 = 1234L;
|
||||
final long disabledChangeId2 = 1235L;
|
||||
final long disabledChangeId3 = 1236L;
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
||||
.addDisabledChangeWithId(disabledChangeId2)
|
||||
.addDisabledOverridableChangeWithId(disabledChangeId3)
|
||||
.build();
|
||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.some.package")
|
||||
.build();
|
||||
PackageManager packageManager = mock(PackageManager.class);
|
||||
when(mContext.getPackageManager()).thenReturn(packageManager);
|
||||
when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
Map<Long, PackageOverride> overrides = new HashMap<>();
|
||||
overrides.put(disabledChangeId1, new PackageOverride.Builder().setEnabled(true).build());
|
||||
overrides.put(disabledChangeId2, new PackageOverride.Builder().setEnabled(true).build());
|
||||
overrides.put(disabledChangeId3, new PackageOverride.Builder().setEnabled(true).build());
|
||||
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> compatConfig.addOverrides(config, "com.some.package")
|
||||
);
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId3, applicationInfo)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -459,7 +503,7 @@ public class CompatConfigTest {
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
||||
|
||||
// Reject all override attempts.
|
||||
// Force the validator to prevent overriding the change by using a user build.
|
||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(false);
|
||||
// Try to turn off change, but validator prevents it.
|
||||
@@ -481,7 +525,7 @@ public class CompatConfigTest {
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
// Reject all override attempts.
|
||||
// Force the validator to prevent overriding the change by using a user build.
|
||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
// Try to remove a non existing override, and it doesn't fail.
|
||||
@@ -508,6 +552,90 @@ public class CompatConfigTest {
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallerCanRemoveOverrides() throws Exception {
|
||||
final long disabledChangeId1 = 1234L;
|
||||
final long disabledChangeId2 = 1235L;
|
||||
final long enabledChangeId = 1236L;
|
||||
// We make disabledChangeId2 non-overridable to make sure it is ignored.
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
||||
.addDisabledChangeWithId(disabledChangeId2)
|
||||
.addEnabledOverridableChangeWithId(enabledChangeId)
|
||||
.build();
|
||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.some.package")
|
||||
.build();
|
||||
when(mPackageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
assertThat(compatConfig.addOverride(disabledChangeId1, "com.some.package", true)).isTrue();
|
||||
assertThat(compatConfig.addOverride(disabledChangeId2, "com.some.package", true)).isTrue();
|
||||
assertThat(compatConfig.addOverride(enabledChangeId, "com.some.package", false)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(enabledChangeId, applicationInfo)).isFalse();
|
||||
|
||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
Set<Long> overridesToRemove = new HashSet<>();
|
||||
overridesToRemove.add(disabledChangeId1);
|
||||
overridesToRemove.add(enabledChangeId);
|
||||
CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig(
|
||||
overridesToRemove);
|
||||
|
||||
compatConfig.removePackageOverrides(config, "com.some.package");
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isFalse();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(enabledChangeId, applicationInfo)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreventInstallerRemoveNonOverridable() throws Exception {
|
||||
final long disabledChangeId1 = 1234L;
|
||||
final long disabledChangeId2 = 1235L;
|
||||
final long disabledChangeId3 = 1236L;
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledOverridableChangeWithId(disabledChangeId1)
|
||||
.addDisabledChangeWithId(disabledChangeId2)
|
||||
.addDisabledOverridableChangeWithId(disabledChangeId3)
|
||||
.build();
|
||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.some.package")
|
||||
.build();
|
||||
PackageManager packageManager = mock(PackageManager.class);
|
||||
when(mContext.getPackageManager()).thenReturn(packageManager);
|
||||
when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
assertThat(compatConfig.addOverride(disabledChangeId1, "com.some.package", true)).isTrue();
|
||||
assertThat(compatConfig.addOverride(disabledChangeId2, "com.some.package", true)).isTrue();
|
||||
assertThat(compatConfig.addOverride(disabledChangeId3, "com.some.package", true)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId3, applicationInfo)).isTrue();
|
||||
|
||||
// Force the validator to prevent overriding non-overridable changes by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
Set<Long> overridesToRemove = new HashSet<>();
|
||||
overridesToRemove.add(disabledChangeId1);
|
||||
overridesToRemove.add(disabledChangeId2);
|
||||
overridesToRemove.add(disabledChangeId3);
|
||||
CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig(
|
||||
overridesToRemove);
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> compatConfig.removePackageOverrides(config, "com.some.package")
|
||||
);
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isFalse();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
|
||||
assertThat(compatConfig.isChangeEnabled(disabledChangeId3, applicationInfo)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableTargetSdkChangesForPackage() throws Exception {
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
|
||||
@@ -98,7 +98,7 @@ public class PlatformCompatTest {
|
||||
.addEnableAfterSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
|
||||
.addEnableAfterSdkChangeWithId(Build.VERSION_CODES.R, 6L)
|
||||
.addLoggingOnlyChangeWithId(7L)
|
||||
.addOverridableChangeWithId(8L)
|
||||
.addDisabledOverridableChangeWithId(8L)
|
||||
.build();
|
||||
mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier);
|
||||
assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly(
|
||||
|
||||
Reference in New Issue
Block a user