Merge "Create a new permission to override Overridable change ids" am: 44008b63fb
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1599153 Change-Id: I903139aedc745ce8fbf3f5614319f81ca1d69586
This commit is contained in:
@@ -161,6 +161,7 @@ package android {
|
|||||||
field public static final String OBSERVE_NETWORK_POLICY = "android.permission.OBSERVE_NETWORK_POLICY";
|
field public static final String OBSERVE_NETWORK_POLICY = "android.permission.OBSERVE_NETWORK_POLICY";
|
||||||
field public static final String OBSERVE_ROLE_HOLDERS = "android.permission.OBSERVE_ROLE_HOLDERS";
|
field public static final String OBSERVE_ROLE_HOLDERS = "android.permission.OBSERVE_ROLE_HOLDERS";
|
||||||
field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS";
|
field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS";
|
||||||
|
field public static final String OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD = "android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD";
|
||||||
field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
|
field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
|
||||||
field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
|
field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
|
||||||
field public static final String PACKET_KEEPALIVE_OFFLOAD = "android.permission.PACKET_KEEPALIVE_OFFLOAD";
|
field public static final String PACKET_KEEPALIVE_OFFLOAD = "android.permission.PACKET_KEEPALIVE_OFFLOAD";
|
||||||
@@ -1125,6 +1126,21 @@ package android.app.compat {
|
|||||||
method public static boolean isChangeEnabled(long);
|
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, @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(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>);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class PackageOverride {
|
||||||
|
method public long getMaxVersionCode();
|
||||||
|
method public long getMinVersionCode();
|
||||||
|
method public boolean isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class PackageOverride.Builder {
|
||||||
|
ctor public PackageOverride.Builder();
|
||||||
|
method @NonNull public android.app.compat.PackageOverride build();
|
||||||
|
method @NonNull public android.app.compat.PackageOverride.Builder setEnabled(boolean);
|
||||||
|
method @NonNull public android.app.compat.PackageOverride.Builder setMaxVersionCode(long);
|
||||||
|
method @NonNull public android.app.compat.PackageOverride.Builder setMinVersionCode(long);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,16 +104,15 @@ public final class CompatChanges {
|
|||||||
*
|
*
|
||||||
* @param packageName The package name of the app in question.
|
* @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 changeId to the override applied for this change id.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG)
|
@RequiresPermission(android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD)
|
||||||
public static void setPackageOverride(String packageName,
|
public static void setPackageOverride(@NonNull String packageName,
|
||||||
Map<Long, PackageOverride> overrides) {
|
@NonNull Map<Long, PackageOverride> overrides) {
|
||||||
IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
|
IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
|
||||||
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
||||||
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
|
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
|
||||||
try {
|
try {
|
||||||
platformCompat.setOverridesFromInstaller(config, packageName);
|
platformCompat.setOverridesOnReleaseBuilds(config, packageName);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
e.rethrowFromSystemServer();
|
e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
package android.app.compat;
|
package android.app.compat;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.SystemApi;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@@ -32,15 +33,16 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public class PackageOverride implements Parcelable {
|
@SystemApi
|
||||||
|
public final class PackageOverride {
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
@IntDef({
|
@IntDef({
|
||||||
VALUE_UNDEFINED,
|
VALUE_UNDEFINED,
|
||||||
VALUE_ENABLED,
|
VALUE_ENABLED,
|
||||||
VALUE_DISABLED
|
VALUE_DISABLED
|
||||||
})
|
})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
/** @hide */
|
|
||||||
public @interface EvaluatedOverride {
|
public @interface EvaluatedOverride {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,10 +77,6 @@ public class PackageOverride implements Parcelable {
|
|||||||
this.mEnabled = enabled;
|
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
|
* Evaluate the override for the given {@code versionCode}. If no override is defined for
|
||||||
* the specified version code, {@link #VALUE_UNDEFINED} is returned.
|
* the specified version code, {@link #VALUE_UNDEFINED} is returned.
|
||||||
@@ -114,24 +112,22 @@ public class PackageOverride implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the enabled value for the override. */
|
/** Returns the enabled value for the override. */
|
||||||
public boolean getEnabled() {
|
public boolean isEnabled() {
|
||||||
return mEnabled;
|
return mEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@Override
|
public void writeToParcel(Parcel dest) {
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeLong(mMinVersionCode);
|
dest.writeLong(mMinVersionCode);
|
||||||
dest.writeLong(mMaxVersionCode);
|
dest.writeLong(mMaxVersionCode);
|
||||||
dest.writeBoolean(mEnabled);
|
dest.writeBoolean(mEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public static PackageOverride createFromParcel(Parcel in) {
|
||||||
|
return new PackageOverride(in.readLong(), in.readLong(), in.readBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -141,25 +137,10 @@ public class PackageOverride implements Parcelable {
|
|||||||
return String.format("[%d,%d,%b]", mMinVersionCode, mMaxVersionCode, 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.
|
* Builder to construct a PackageOverride.
|
||||||
*/
|
*/
|
||||||
public static class Builder {
|
public static final class Builder {
|
||||||
private long mMinVersionCode = Long.MIN_VALUE;
|
private long mMinVersionCode = Long.MIN_VALUE;
|
||||||
private long mMaxVersionCode = Long.MAX_VALUE;
|
private long mMaxVersionCode = Long.MAX_VALUE;
|
||||||
private boolean mEnabled;
|
private boolean mEnabled;
|
||||||
@@ -169,6 +150,7 @@ public class PackageOverride implements Parcelable {
|
|||||||
*
|
*
|
||||||
* default value: {@code Long.MIN_VALUE}.
|
* default value: {@code Long.MIN_VALUE}.
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
public Builder setMinVersionCode(long minVersionCode) {
|
public Builder setMinVersionCode(long minVersionCode) {
|
||||||
mMinVersionCode = minVersionCode;
|
mMinVersionCode = minVersionCode;
|
||||||
return this;
|
return this;
|
||||||
@@ -179,6 +161,7 @@ public class PackageOverride implements Parcelable {
|
|||||||
*
|
*
|
||||||
* default value: {@code Long.MAX_VALUE}.
|
* default value: {@code Long.MAX_VALUE}.
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
public Builder setMaxVersionCode(long maxVersionCode) {
|
public Builder setMaxVersionCode(long maxVersionCode) {
|
||||||
mMaxVersionCode = maxVersionCode;
|
mMaxVersionCode = maxVersionCode;
|
||||||
return this;
|
return this;
|
||||||
@@ -189,6 +172,7 @@ public class PackageOverride implements Parcelable {
|
|||||||
*
|
*
|
||||||
* default value: {@code false}.
|
* default value: {@code false}.
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
public Builder setEnabled(boolean enabled) {
|
public Builder setEnabled(boolean enabled) {
|
||||||
mEnabled = enabled;
|
mEnabled = enabled;
|
||||||
return this;
|
return this;
|
||||||
@@ -200,6 +184,7 @@ public class PackageOverride implements Parcelable {
|
|||||||
* @throws IllegalArgumentException if {@code minVersionCode} is larger than
|
* @throws IllegalArgumentException if {@code minVersionCode} is larger than
|
||||||
* {@code maxVersionCode}.
|
* {@code maxVersionCode}.
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
public PackageOverride build() {
|
public PackageOverride build() {
|
||||||
if (mMinVersionCode > mMaxVersionCode) {
|
if (mMinVersionCode > mMaxVersionCode) {
|
||||||
throw new IllegalArgumentException("minVersionCode must not be larger than "
|
throw new IllegalArgumentException("minVersionCode must not be larger than "
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ public final class CompatibilityOverrideConfig implements Parcelable {
|
|||||||
overrides = new HashMap<>();
|
overrides = new HashMap<>();
|
||||||
for (int i = 0; i < keyCount; i++) {
|
for (int i = 0; i < keyCount; i++) {
|
||||||
long key = in.readLong();
|
long key = in.readLong();
|
||||||
PackageOverride override = in.readParcelable(PackageOverride.class.getClassLoader());
|
overrides.put(key, PackageOverride.createFromParcel(in));
|
||||||
overrides.put(key, override);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +54,7 @@ public final class CompatibilityOverrideConfig implements Parcelable {
|
|||||||
dest.writeInt(overrides.size());
|
dest.writeInt(overrides.size());
|
||||||
for (Long key : overrides.keySet()) {
|
for (Long key : overrides.keySet()) {
|
||||||
dest.writeLong(key);
|
dest.writeLong(key);
|
||||||
dest.writeParcelable(overrides.get(key), 0);
|
overrides.get(key).writeToParcel(dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,15 +151,23 @@ interface IPlatformCompat {
|
|||||||
void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);
|
void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds overrides to compatibility changes.
|
* Adds overrides to compatibility changes on release builds.
|
||||||
*
|
*
|
||||||
* <p>Kills the app to allow the changes to take effect.
|
* <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 overrides} 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 overrides parcelable containing the compat change overrides to be applied
|
* @param overrides parcelable containing the compat change overrides to be applied
|
||||||
* @param packageName the package name of the app whose changes will be overridden
|
* @param packageName the package name of the app whose changes will be overridden
|
||||||
* @throws SecurityException if overriding changes is not permitted
|
* @throws SecurityException if overriding changes is not permitted
|
||||||
*/
|
*/
|
||||||
void setOverridesFromInstaller(in CompatibilityOverrideConfig overrides, in String packageName);
|
void setOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds overrides to compatibility changes.
|
* Adds overrides to compatibility changes.
|
||||||
|
|||||||
@@ -5123,9 +5123,16 @@
|
|||||||
<permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
|
<permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
|
||||||
android:protectionLevel="signature|privileged" />
|
android:protectionLevel="signature|privileged" />
|
||||||
<!-- Allows an app to override compat change config.
|
<!-- Allows an app to override compat change config.
|
||||||
|
This permission only allows to override config on debuggable builds or test-apks and is
|
||||||
|
therefore a less powerful version of OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD.
|
||||||
@hide <p>Not for use by third-party applications.</p> -->
|
@hide <p>Not for use by third-party applications.</p> -->
|
||||||
<permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
|
<permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
|
||||||
android:protectionLevel="signature|privileged" />
|
android:protectionLevel="signature|privileged" />
|
||||||
|
<!-- @SystemApi Allows an app to override compat change config on release builds.
|
||||||
|
Only ChangeIds that are annotated as @Overridable can be overridden on release builds.
|
||||||
|
@hide -->
|
||||||
|
<permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"
|
||||||
|
android:protectionLevel="signature|privileged" />
|
||||||
|
|
||||||
<!-- Allows input events to be monitored. Very dangerous! @hide -->
|
<!-- Allows input events to be monitored. Very dangerous! @hide -->
|
||||||
<permission android:name="android.permission.MONITOR_INPUT"
|
<permission android:name="android.permission.MONITOR_INPUT"
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ import static android.app.compat.PackageOverride.VALUE_UNDEFINED;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.compat.PackageOverride;
|
import android.app.compat.PackageOverride;
|
||||||
import android.compat.annotation.ChangeId;
|
import android.compat.annotation.ChangeId;
|
||||||
|
import android.compat.annotation.Disabled;
|
||||||
import android.compat.annotation.EnabledSince;
|
import android.compat.annotation.EnabledSince;
|
||||||
|
import android.compat.annotation.Overridable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -59,6 +61,15 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
|||||||
@EnabledSince(targetSdkVersion = 31) // Needs to be > test APK targetSdkVersion.
|
@EnabledSince(targetSdkVersion = 31) // Needs to be > test APK targetSdkVersion.
|
||||||
static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id.
|
static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An overridable change ID to be used only in the CTS test for this SystemApi
|
||||||
|
*/
|
||||||
|
@ChangeId
|
||||||
|
@Disabled
|
||||||
|
@Overridable
|
||||||
|
static final long CTS_SYSTEM_API_OVERRIDABLE_CHANGEID = 174043039; // This is a bug id.
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback listener for when compat changes are updated for a package.
|
* Callback listener for when compat changes are updated for a package.
|
||||||
* See {@link #registerListener(ChangeListener)} for more details.
|
* See {@link #registerListener(ChangeListener)} for more details.
|
||||||
@@ -211,6 +222,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
|||||||
boolean hasPackageOverride(String pname) {
|
boolean hasPackageOverride(String pname) {
|
||||||
return mRawOverrides.containsKey(pname);
|
return mRawOverrides.containsKey(pname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove any package override for the given package name, restoring the default behaviour.
|
* Remove any package override for the given package name, restoring the default behaviour.
|
||||||
*
|
*
|
||||||
@@ -355,7 +367,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
|||||||
override.setPackageName(entry.getKey());
|
override.setPackageName(entry.getKey());
|
||||||
override.setMinVersionCode(entry.getValue().getMinVersionCode());
|
override.setMinVersionCode(entry.getValue().getMinVersionCode());
|
||||||
override.setMaxVersionCode(entry.getValue().getMaxVersionCode());
|
override.setMaxVersionCode(entry.getValue().getMaxVersionCode());
|
||||||
override.setEnabled(entry.getValue().getEnabled());
|
override.setEnabled(entry.getValue().isEnabled());
|
||||||
rawList.add(override);
|
rawList.add(override);
|
||||||
}
|
}
|
||||||
changeOverrides.setRaw(rawOverrides);
|
changeOverrides.setRaw(rawOverrides);
|
||||||
|
|||||||
@@ -303,6 +303,16 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the change is overridable.
|
||||||
|
*/
|
||||||
|
boolean isOverridable(long changeId) {
|
||||||
|
synchronized (mChanges) {
|
||||||
|
CompatChange c = mChanges.get(changeId);
|
||||||
|
return c != null && c.getOverridable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an override previously added via {@link #addOverride(long, String, boolean)}.
|
* Removes an override previously added via {@link #addOverride(long, String, boolean)}.
|
||||||
*
|
*
|
||||||
@@ -343,7 +353,7 @@ final class CompatConfig {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
|
* Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
|
||||||
* {@link #addOverrides(CompatibilityChangeConfig, String)} for a certain package.
|
* {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
|
||||||
*
|
*
|
||||||
* <p>This restores the default behaviour for the given app.
|
* <p>This restores the default behaviour for the given app.
|
||||||
*
|
*
|
||||||
@@ -632,8 +642,11 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
boolean shouldInvalidateCache = false;
|
boolean shouldInvalidateCache = false;
|
||||||
for (CompatChange c: changes) {
|
for (CompatChange c: changes) {
|
||||||
|
if (!c.hasPackageOverride(packageName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
OverrideAllowedState allowedState =
|
OverrideAllowedState allowedState =
|
||||||
mOverrideValidator.getOverrideAllowedState(c.getId(), packageName);
|
mOverrideValidator.getOverrideAllowedStateForRecheck(c.getId(), packageName);
|
||||||
shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, mContext);
|
shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, mContext);
|
||||||
}
|
}
|
||||||
if (shouldInvalidateCache) {
|
if (shouldInvalidateCache) {
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.server.compat;
|
package com.android.server.compat;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
||||||
import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
|
import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
|
||||||
import static com.android.internal.compat.OverrideAllowedState.DEFERRED_VERIFICATION;
|
import static com.android.internal.compat.OverrideAllowedState.DEFERRED_VERIFICATION;
|
||||||
import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARGET_SDK;
|
import static com.android.internal.compat.OverrideAllowedState.DISABLED_NON_TARGET_SDK;
|
||||||
@@ -24,6 +27,7 @@ import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_S
|
|||||||
import static com.android.internal.compat.OverrideAllowedState.LOGGING_ONLY_CHANGE;
|
import static com.android.internal.compat.OverrideAllowedState.LOGGING_ONLY_CHANGE;
|
||||||
import static com.android.internal.compat.OverrideAllowedState.PLATFORM_TOO_OLD;
|
import static com.android.internal.compat.OverrideAllowedState.PLATFORM_TOO_OLD;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -69,8 +73,25 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
|||||||
mForceNonDebuggableFinalBuild = false;
|
mForceNonDebuggableFinalBuild = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the allowed state for the given changeId and packageName on a recheck.
|
||||||
|
*
|
||||||
|
* <p>Recheck happens when the given app is getting updated. In this case we cannot do a
|
||||||
|
* permission check on the caller, so we're using the fact that the override was present as
|
||||||
|
* proof that the original caller was allowed to set this override.
|
||||||
|
*/
|
||||||
|
OverrideAllowedState getOverrideAllowedStateForRecheck(long changeId,
|
||||||
|
@NonNull String packageName) {
|
||||||
|
return getOverrideAllowedStateInternal(changeId, packageName, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OverrideAllowedState getOverrideAllowedState(long changeId, String packageName) {
|
public OverrideAllowedState getOverrideAllowedState(long changeId, String packageName) {
|
||||||
|
return getOverrideAllowedStateInternal(changeId, packageName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OverrideAllowedState getOverrideAllowedStateInternal(long changeId, String packageName,
|
||||||
|
boolean isRecheck) {
|
||||||
if (mCompatConfig.isLoggingOnly(changeId)) {
|
if (mCompatConfig.isLoggingOnly(changeId)) {
|
||||||
return new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1);
|
return new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1);
|
||||||
}
|
}
|
||||||
@@ -99,6 +120,16 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
|||||||
} catch (NameNotFoundException e) {
|
} catch (NameNotFoundException e) {
|
||||||
return new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1);
|
return new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1);
|
||||||
}
|
}
|
||||||
|
// If the change is annotated as @Overridable, apps with the specific permission can
|
||||||
|
// set the override even on production builds. When rechecking the override, e.g. during an
|
||||||
|
// app update we can bypass this check, as it wouldn't have been here in the first place.
|
||||||
|
if (mCompatConfig.isOverridable(changeId)
|
||||||
|
&& (isRecheck
|
||||||
|
|| mContext.checkCallingOrSelfPermission(
|
||||||
|
OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD)
|
||||||
|
== PERMISSION_GRANTED)) {
|
||||||
|
return new OverrideAllowedState(ALLOWED, -1, -1);
|
||||||
|
}
|
||||||
int appTargetSdk = applicationInfo.targetSdkVersion;
|
int appTargetSdk = applicationInfo.targetSdkVersion;
|
||||||
// Only allow overriding debuggable apps.
|
// Only allow overriding debuggable apps.
|
||||||
if ((applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
|
if ((applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
|
||||||
@@ -130,5 +161,4 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
|||||||
void forceNonDebuggableFinalForTest(boolean value) {
|
void forceNonDebuggableFinalForTest(boolean value) {
|
||||||
mForceNonDebuggableFinalBuild = value;
|
mForceNonDebuggableFinalBuild = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.server.compat;
|
|||||||
|
|
||||||
import static android.Manifest.permission.LOG_COMPAT_CHANGE;
|
import static android.Manifest.permission.LOG_COMPAT_CHANGE;
|
||||||
import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
|
import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
|
||||||
|
import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD;
|
||||||
import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
|
import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
import static android.os.Process.SYSTEM_UID;
|
import static android.os.Process.SYSTEM_UID;
|
||||||
@@ -182,11 +183,12 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOverridesFromInstaller(CompatibilityOverrideConfig overrides,
|
public void setOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides,
|
||||||
String packageName) {
|
String packageName) {
|
||||||
checkCompatChangeOverridePermission();
|
// TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
|
||||||
|
checkCompatChangeOverrideOverridablePermission();
|
||||||
|
checkAllCompatOverridesAreOverridable(overrides);
|
||||||
mCompatConfig.addOverrides(overrides, packageName);
|
mCompatConfig.addOverrides(overrides, packageName);
|
||||||
killPackage(packageName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -383,6 +385,26 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkCompatChangeOverrideOverridablePermission() {
|
||||||
|
// Don't check for permissions within the system process
|
||||||
|
if (Binder.getCallingUid() == SYSTEM_UID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD)
|
||||||
|
!= PERMISSION_GRANTED) {
|
||||||
|
throw new SecurityException("Cannot override compat change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAllCompatOverridesAreOverridable(CompatibilityOverrideConfig overrides) {
|
||||||
|
for (Long changeId : overrides.overrides.keySet()) {
|
||||||
|
if (!mCompatConfig.isOverridable(changeId)) {
|
||||||
|
throw new SecurityException("Only change ids marked as Overridable can be "
|
||||||
|
+ "overridden.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkCompatChangeReadAndLogPermission() {
|
private void checkCompatChangeReadAndLogPermission() {
|
||||||
checkCompatChangeReadPermission();
|
checkCompatChangeReadPermission();
|
||||||
checkCompatChangeLogPermission();
|
checkCompatChangeLogPermission();
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class CompatConfigBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompatConfigBuilder addOverridableChangeWithId(long id) {
|
CompatConfigBuilder addOverridableChangeWithId(long id) {
|
||||||
mChanges.add(new CompatChange(id, "", -1, -1, false, true, "", true));
|
mChanges.add(new CompatChange(id, "", -1, -1, true, false, "", true));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -259,6 +259,36 @@ public class CompatConfigTest {
|
|||||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInstallerCanSetOverrides() throws Exception {
|
||||||
|
final long changeId = 1234L;
|
||||||
|
final int installerUid = 23;
|
||||||
|
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||||
|
.addOverridableChangeWithId(1234L)
|
||||||
|
.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 the change by using a user build.
|
||||||
|
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||||
|
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||||
|
|
||||||
|
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(
|
||||||
|
Collections.singletonMap(1234L,
|
||||||
|
new PackageOverride.Builder()
|
||||||
|
.setMaxVersionCode(99L)
|
||||||
|
.setEnabled(true)
|
||||||
|
.build()));
|
||||||
|
|
||||||
|
compatConfig.addOverrides(config, "com.some.package");
|
||||||
|
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApplyDeferredOverridesAfterInstallingApp() throws Exception {
|
public void testApplyDeferredOverridesAfterInstallingApp() throws Exception {
|
||||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||||
@@ -639,9 +669,18 @@ public class CompatConfigTest {
|
|||||||
.build());
|
.build());
|
||||||
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
|
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
|
||||||
.thenThrow(new NameNotFoundException());
|
.thenThrow(new NameNotFoundException());
|
||||||
|
compatConfig.addOverrides(
|
||||||
compatConfig.addOverride(1L, "foo.bar", true);
|
new CompatibilityOverrideConfig(
|
||||||
compatConfig.addOverride(2L, "bar.baz", false);
|
Collections.singletonMap(
|
||||||
|
1L,
|
||||||
|
new PackageOverride.Builder().setEnabled(true).build())),
|
||||||
|
"foo.bar");
|
||||||
|
compatConfig.addOverrides(
|
||||||
|
new CompatibilityOverrideConfig(
|
||||||
|
Collections.singletonMap(
|
||||||
|
2L,
|
||||||
|
new PackageOverride.Builder().setEnabled(false).build())),
|
||||||
|
"bar.baz");
|
||||||
|
|
||||||
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||||
+ "<overrides>\n"
|
+ "<overrides>\n"
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public class PlatformCompatTest {
|
|||||||
new CompatibilityChangeInfo(
|
new CompatibilityChangeInfo(
|
||||||
6L, "", Build.VERSION_CODES.R, -1, false, false, "", false),
|
6L, "", Build.VERSION_CODES.R, -1, false, false, "", false),
|
||||||
new CompatibilityChangeInfo(7L, "", -1, -1, false, true, "", false),
|
new CompatibilityChangeInfo(7L, "", -1, -1, false, true, "", false),
|
||||||
new CompatibilityChangeInfo(8L, "", -1, -1, false, true, "", true));
|
new CompatibilityChangeInfo(8L, "", -1, -1, true, false, "", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user