1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.compat; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.content.pm.PackageInfo; 23 import android.os.Parcel; 24 25 import java.lang.annotation.Retention; 26 import java.lang.annotation.RetentionPolicy; 27 28 /** 29 * An app compat override applied to a given package and change id pairing. 30 * 31 * A package override contains a list of version ranges with the desired boolean value of 32 * the override for the app in this version range. Ranges can be open ended in either direction. 33 * An instance of PackageOverride gets created via {@link Builder} and is immutable once created. 34 * 35 * @hide 36 */ 37 @SystemApi 38 public final class PackageOverride { 39 40 /** @hide */ 41 @IntDef({ 42 VALUE_UNDEFINED, 43 VALUE_ENABLED, 44 VALUE_DISABLED 45 }) 46 @Retention(RetentionPolicy.SOURCE) 47 public @interface EvaluatedOverride { 48 } 49 50 /** 51 * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that 52 * this PackageOverride does not define the value of the override for the given version. 53 * @hide 54 */ 55 public static final int VALUE_UNDEFINED = 0; 56 /** 57 * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that 58 * the override evaluates to {@code true} for the given version. 59 * @hide 60 */ 61 public static final int VALUE_ENABLED = 1; 62 /** 63 * Return value of {@link #evaluate(long)} and {@link #evaluateForAllVersions()} indicating that 64 * the override evaluates to {@code fakse} for the given version. 65 * @hide 66 */ 67 public static final int VALUE_DISABLED = 2; 68 69 private final long mMinVersionCode; 70 private final long mMaxVersionCode; 71 private final boolean mEnabled; 72 PackageOverride(long minVersionCode, long maxVersionCode, boolean enabled)73 private PackageOverride(long minVersionCode, 74 long maxVersionCode, 75 boolean enabled) { 76 this.mMinVersionCode = minVersionCode; 77 this.mMaxVersionCode = maxVersionCode; 78 this.mEnabled = enabled; 79 } 80 81 /** 82 * Evaluate the override for the given {@code versionCode}. If no override is defined for 83 * the specified version code, {@link #VALUE_UNDEFINED} is returned. 84 * @hide 85 */ evaluate(long versionCode)86 public @EvaluatedOverride int evaluate(long versionCode) { 87 if (versionCode >= mMinVersionCode && versionCode <= mMaxVersionCode) { 88 return mEnabled ? VALUE_ENABLED : VALUE_DISABLED; 89 } 90 return VALUE_UNDEFINED; 91 } 92 93 /** 94 * Evaluate the override independent of version code, i.e. only return an evaluated value if 95 * this range covers all versions, otherwise {@link #VALUE_UNDEFINED} is returned. 96 * @hide 97 */ evaluateForAllVersions()98 public int evaluateForAllVersions() { 99 if (mMinVersionCode == Long.MIN_VALUE && mMaxVersionCode == Long.MAX_VALUE) { 100 return mEnabled ? VALUE_ENABLED : VALUE_DISABLED; 101 } 102 return VALUE_UNDEFINED; 103 } 104 105 /** 106 * Returns the minimum APK version code the override applies to. 107 * 108 * @see PackageInfo#getLongVersionCode() 109 */ getMinVersionCode()110 public long getMinVersionCode() { 111 return mMinVersionCode; 112 } 113 114 /** 115 * Returns the maximum APK version code the override applies from. 116 * 117 * @see PackageInfo#getLongVersionCode() 118 */ getMaxVersionCode()119 public long getMaxVersionCode() { 120 return mMaxVersionCode; 121 } 122 123 /** Returns the enabled value for the override. */ isEnabled()124 public boolean isEnabled() { 125 return mEnabled; 126 } 127 128 /** @hide */ writeToParcel(Parcel dest)129 public void writeToParcel(Parcel dest) { 130 dest.writeLong(mMinVersionCode); 131 dest.writeLong(mMaxVersionCode); 132 dest.writeBoolean(mEnabled); 133 } 134 135 /** @hide */ createFromParcel(Parcel in)136 public static PackageOverride createFromParcel(Parcel in) { 137 return new PackageOverride(in.readLong(), in.readLong(), in.readBoolean()); 138 } 139 140 /** @hide */ 141 @Override toString()142 public String toString() { 143 if (mMinVersionCode == Long.MIN_VALUE && mMaxVersionCode == Long.MAX_VALUE) { 144 return Boolean.toString(mEnabled); 145 } 146 return String.format("[%d,%d,%b]", mMinVersionCode, mMaxVersionCode, mEnabled); 147 } 148 149 /** 150 * Builder to construct a PackageOverride. 151 */ 152 public static final class Builder { 153 private long mMinVersionCode = Long.MIN_VALUE; 154 private long mMaxVersionCode = Long.MAX_VALUE; 155 private boolean mEnabled; 156 157 /** 158 * Sets the minimum APK version code the override should apply from. 159 * 160 * default value: {@code Long.MIN_VALUE}. 161 * 162 * @see PackageInfo#getLongVersionCode() 163 */ 164 @NonNull setMinVersionCode(long minVersionCode)165 public Builder setMinVersionCode(long minVersionCode) { 166 mMinVersionCode = minVersionCode; 167 return this; 168 } 169 170 /** 171 * Sets the maximum APK version code the override should apply to. 172 * 173 * default value: {@code Long.MAX_VALUE}. 174 * 175 * @see PackageInfo#getLongVersionCode() 176 */ 177 @NonNull setMaxVersionCode(long maxVersionCode)178 public Builder setMaxVersionCode(long maxVersionCode) { 179 mMaxVersionCode = maxVersionCode; 180 return this; 181 } 182 183 /** 184 * Sets whether the override should be enabled for the given version range. 185 * 186 * default value: {@code false}. 187 */ 188 @NonNull setEnabled(boolean enabled)189 public Builder setEnabled(boolean enabled) { 190 mEnabled = enabled; 191 return this; 192 } 193 194 /** 195 * Build the {@link PackageOverride}. 196 * 197 * @throws IllegalArgumentException if {@code minVersionCode} is larger than 198 * {@code maxVersionCode}. 199 */ 200 @NonNull build()201 public PackageOverride build() { 202 if (mMinVersionCode > mMaxVersionCode) { 203 throw new IllegalArgumentException("minVersionCode must not be larger than " 204 + "maxVersionCode"); 205 } 206 return new PackageOverride(mMinVersionCode, mMaxVersionCode, mEnabled); 207 } 208 }; 209 } 210