summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorBenjamin Franz <bfranz@google.com>2021-02-16 12:21:08 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-02-16 12:21:08 +0000
commit4fb9af6ceda3e7ddcfce0bbe0bfdcaa12a99ea0c (patch)
treecfd7331cd3a56d232fc266cffdd5143f30186931 /core/java/android
parentee109d8f3b15345f7d2b138c199efc9e55acd858 (diff)
parent80bbdfd100a4143154dfe17f4258b74806d5b749 (diff)
Merge "Add versioning to app compat framework" am: 80bbdfd100
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1585009 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Ib4796325c84396082256cec7c66fd1efdc623d36
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/compat/CompatChanges.java29
-rw-r--r--core/java/android/app/compat/PackageOverride.java211
2 files changed, 240 insertions, 0 deletions
diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java
index 28b73406b877..ab38832458d6 100644
--- a/core/java/android/app/compat/CompatChanges.java
+++ b/core/java/android/app/compat/CompatChanges.java
@@ -20,8 +20,16 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.compat.Compatibility;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
+import com.android.internal.compat.CompatibilityOverrideConfig;
+import com.android.internal.compat.IPlatformCompat;
+
+import java.util.Map;
+
/**
* CompatChanges APIs - to be used by platform code only (including mainline
* modules).
@@ -89,4 +97,25 @@ public final class CompatChanges {
return QUERY_CACHE.query(ChangeIdStateQuery.byUid(changeId, uid));
}
+ /**
+ * Set an app compat override 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.
+ *
+ * @param packageName The package name of the app in question.
+ * @param overrides A map from changeId to the override applied for this change id.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG)
+ public static void setPackageOverride(String packageName,
+ Map<Long, PackageOverride> overrides) {
+ IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+ CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
+ try {
+ platformCompat.setOverridesFromInstaller(config, packageName);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/compat/PackageOverride.java b/core/java/android/app/compat/PackageOverride.java
new file mode 100644
index 000000000000..9f97cd41128a
--- /dev/null
+++ b/core/java/android/app/compat/PackageOverride.java
@@ -0,0 +1,211 @@
+/*
+ * 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 android.app.compat;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An app compat override applied to a given package and change id pairing.
+ *
+ * A package override contains a list of version ranges with the desired boolean value of
+ * the override for the app in this version range. Ranges can be open ended in either direction.
+ * An instance of PackageOverride gets created via {@link Builder} and is immutable once created.
+ *
+ * @hide
+ */
+public class PackageOverride implements Parcelable {
+
+ @IntDef({
+ VALUE_UNDEFINED,
+ VALUE_ENABLED,
+ VALUE_DISABLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ /** @hide */
+ public @interface EvaluatedOverride {
+ }
+
+ /**
+ * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that
+ * this PackageOverride does not define the value of the override for the given version.
+ * @hide
+ */
+ public static final int VALUE_UNDEFINED = 0;
+ /**
+ * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that
+ * the override evaluates to {@code true} for the given version.
+ * @hide
+ */
+ public static final int VALUE_ENABLED = 1;
+ /**
+ * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that
+ * the override evaluates to {@code fakse} for the given version.
+ * @hide
+ */
+ public static final int VALUE_DISABLED = 2;
+
+ private final long mMinVersionCode;
+ private final long mMaxVersionCode;
+ private final boolean mEnabled;
+
+ private PackageOverride(long minVersionCode,
+ long maxVersionCode,
+ boolean enabled) {
+ this.mMinVersionCode = minVersionCode;
+ this.mMaxVersionCode = maxVersionCode;
+ this.mEnabled = enabled;
+ }
+
+ private PackageOverride(Parcel in) {
+ this(in.readLong(), in.readLong(), in.readBoolean());
+ }
+
+ /**
+ * Evaluate the override for the given {@code versionCode}. If no override is defined for
+ * the specified version code, {@link #VALUE_UNDEFINED} is returned.
+ * @hide
+ */
+ public @EvaluatedOverride int evaluate(long versionCode) {
+ if (versionCode >= mMinVersionCode && versionCode <= mMaxVersionCode) {
+ return mEnabled ? VALUE_ENABLED : VALUE_DISABLED;
+ }
+ return VALUE_UNDEFINED;
+ }
+
+ /**
+ * Evaluate the override independent of version code, i.e. only return an evaluated value if
+ * this range covers all versions, otherwise {@link #VALUE_UNDEFINED} is returned.
+ * @hide
+ */
+ public int evaluateForAllVersions() {
+ if (mMinVersionCode == Long.MIN_VALUE && mMaxVersionCode == Long.MAX_VALUE) {
+ return mEnabled ? VALUE_ENABLED : VALUE_DISABLED;
+ }
+ return VALUE_UNDEFINED;
+ }
+
+ /** Returns the minimum version code the override applies to. */
+ public long getMinVersionCode() {
+ return mMinVersionCode;
+ }
+
+ /** Returns the minimum version code the override applies from. */
+ public long getMaxVersionCode() {
+ return mMaxVersionCode;
+ }
+
+ /** Returns the enabled value for the override. */
+ public boolean getEnabled() {
+ return mEnabled;
+ }
+
+ /** @hide */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mMinVersionCode);
+ dest.writeLong(mMaxVersionCode);
+ dest.writeBoolean(mEnabled);
+ }
+
+ /** @hide */
+ @Override
+ public String toString() {
+ if (mMinVersionCode == Long.MIN_VALUE && mMaxVersionCode == Long.MAX_VALUE) {
+ return Boolean.toString(mEnabled);
+ }
+ return String.format("[%d,%d,%b]", mMinVersionCode, mMaxVersionCode, mEnabled);
+ }
+
+ /** @hide */
+ public static final Creator<PackageOverride> CREATOR =
+ new Creator<PackageOverride>() {
+
+ @Override
+ public PackageOverride createFromParcel(Parcel in) {
+ return new PackageOverride(in);
+ }
+
+ @Override
+ public PackageOverride[] newArray(int size) {
+ return new PackageOverride[size];
+ }
+ };
+
+ /**
+ * Builder to construct a PackageOverride.
+ */
+ public static class Builder {
+ private long mMinVersionCode = Long.MIN_VALUE;
+ private long mMaxVersionCode = Long.MAX_VALUE;
+ private boolean mEnabled;
+
+ /**
+ * Sets the minimum version code the override should apply from.
+ *
+ * default value: {@code Long.MIN_VALUE}.
+ */
+ public Builder setMinVersionCode(long minVersionCode) {
+ mMinVersionCode = minVersionCode;
+ return this;
+ }
+
+ /**
+ * Sets the maximum version code the override should apply to.
+ *
+ * default value: {@code Long.MAX_VALUE}.
+ */
+ public Builder setMaxVersionCode(long maxVersionCode) {
+ mMaxVersionCode = maxVersionCode;
+ return this;
+ }
+
+ /**
+ * Sets whether the override should be enabled for the given version range.
+ *
+ * default value: {@code false}.
+ */
+ public Builder setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Build the {@link PackageOverride}.
+ *
+ * @throws IllegalArgumentException if {@code minVersionCode} is larger than
+ * {@code maxVersionCode}.
+ */
+ public PackageOverride build() {
+ if (mMinVersionCode > mMaxVersionCode) {
+ throw new IllegalArgumentException("minVersionCode must not be larger than "
+ + "maxVersionCode");
+ }
+ return new PackageOverride(mMinVersionCode, mMaxVersionCode, mEnabled);
+ }
+ };
+}