Merge changes from topic "preinstall-overrides" am: 29ed176b46 am: d1ebbf5086
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1520701 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I94c9aca60ff8d5eec190434a2a22338cb04d5922
This commit is contained in:
committed by
Automerger Merge Worker
commit
dd1d1cbacc
@@ -13289,6 +13289,16 @@ public final class Settings {
|
||||
@TestApi
|
||||
public static final String HIDDEN_API_POLICY = "hidden_api_policy";
|
||||
|
||||
/**
|
||||
* Flag for forcing {@link com.android.server.compat.OverrideValidatorImpl}
|
||||
* to consider this a non-debuggable build.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT =
|
||||
"force_non_debuggable_final_build_for_compat";
|
||||
|
||||
|
||||
/**
|
||||
* Current version of signed configuration applied.
|
||||
*
|
||||
|
||||
@@ -33,7 +33,7 @@ public final class OverrideAllowedState implements Parcelable {
|
||||
DISABLED_NOT_DEBUGGABLE,
|
||||
DISABLED_NON_TARGET_SDK,
|
||||
DISABLED_TARGET_SDK_TOO_HIGH,
|
||||
PACKAGE_DOES_NOT_EXIST,
|
||||
DEFERRED_VERIFICATION,
|
||||
LOGGING_ONLY_CHANGE
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -57,10 +57,10 @@ public final class OverrideAllowedState implements Parcelable {
|
||||
* Change cannot be overridden, due to the app's targetSdk being above the change's targetSdk.
|
||||
*/
|
||||
public static final int DISABLED_TARGET_SDK_TOO_HIGH = 3;
|
||||
/**
|
||||
* Package does not exist.
|
||||
/**
|
||||
* Change override decision is currently being deferred, due to the app not being installed yet.
|
||||
*/
|
||||
public static final int PACKAGE_DOES_NOT_EXIST = 4;
|
||||
public static final int DEFERRED_VERIFICATION = 4;
|
||||
/**
|
||||
* Change is marked as logging only, and cannot be toggled.
|
||||
*/
|
||||
@@ -106,6 +106,7 @@ public final class OverrideAllowedState implements Parcelable {
|
||||
throws SecurityException {
|
||||
switch (state) {
|
||||
case ALLOWED:
|
||||
case DEFERRED_VERIFICATION:
|
||||
return;
|
||||
case DISABLED_NOT_DEBUGGABLE:
|
||||
throw new SecurityException(
|
||||
@@ -118,11 +119,6 @@ public final class OverrideAllowedState implements Parcelable {
|
||||
"Cannot override %1$d for %2$s because the app's targetSdk (%3$d) is "
|
||||
+ "above the change's targetSdk threshold (%4$d)",
|
||||
changeId, packageName, appTargetSdk, changeIdTargetSdk));
|
||||
case PACKAGE_DOES_NOT_EXIST:
|
||||
throw new SecurityException(String.format(
|
||||
"Cannot override %1$d for %2$s because the package does not exist, and "
|
||||
+ "the change is targetSdk gated.",
|
||||
changeId, packageName));
|
||||
case LOGGING_ONLY_CHANGE:
|
||||
throw new SecurityException(String.format(
|
||||
"Cannot override %1$d because it is marked as a logging-only change.",
|
||||
@@ -170,8 +166,8 @@ public final class OverrideAllowedState implements Parcelable {
|
||||
return "DISABLED_NON_TARGET_SDK";
|
||||
case DISABLED_TARGET_SDK_TOO_HIGH:
|
||||
return "DISABLED_TARGET_SDK_TOO_HIGH";
|
||||
case PACKAGE_DOES_NOT_EXIST:
|
||||
return "PACKAGE_DOES_NOT_EXIST";
|
||||
case DEFERRED_VERIFICATION:
|
||||
return "DEFERRED_VERIFICATION";
|
||||
case LOGGING_ONLY_CHANGE:
|
||||
return "LOGGING_ONLY_CHANGE";
|
||||
}
|
||||
|
||||
@@ -300,6 +300,7 @@ public class SettingsBackupTest {
|
||||
Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
|
||||
Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
|
||||
Settings.Global.HIDDEN_API_POLICY,
|
||||
Settings.Global.FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT,
|
||||
Settings.Global.HIDE_ERROR_DIALOGS,
|
||||
Settings.Global.HTTP_PROXY,
|
||||
HYBRID_SYSUI_BATTERY_WARNING_FLAGS,
|
||||
|
||||
@@ -9482,6 +9482,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
final long waitForNetworkTimeoutMs = Settings.Global.getLong(resolver,
|
||||
NETWORK_ACCESS_TIMEOUT_MS, NETWORK_ACCESS_TIMEOUT_DEFAULT_MS);
|
||||
mHiddenApiBlacklist.registerObserver();
|
||||
mPlatformCompat.registerContentObserver();
|
||||
|
||||
final long pssDeferralMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
ACTIVITY_START_PSS_DEFER_CONFIG, 0L);
|
||||
|
||||
@@ -61,6 +61,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
||||
ChangeListener mListener = null;
|
||||
|
||||
private Map<String, Boolean> mPackageOverrides;
|
||||
private Map<String, Boolean> mDeferredOverrides;
|
||||
|
||||
public CompatChange(long changeId) {
|
||||
this(changeId, null, -1, -1, false, false, null);
|
||||
@@ -120,6 +121,56 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
||||
notifyListener(pname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tentatively set the state of this change for a given package name.
|
||||
* The override will only take effect after that package is installed, if applicable.
|
||||
*
|
||||
* <p>Note, this method is not thread safe so callers must ensure thread safety.
|
||||
*
|
||||
* @param packageName Package name to tentatively enable the change for.
|
||||
* @param enabled Whether or not to enable the change.
|
||||
*/
|
||||
void addPackageDeferredOverride(String packageName, boolean enabled) {
|
||||
if (getLoggingOnly()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't add overrides for a logging only change " + toString());
|
||||
}
|
||||
if (mDeferredOverrides == null) {
|
||||
mDeferredOverrides = new HashMap<>();
|
||||
}
|
||||
mDeferredOverrides.put(packageName, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rechecks an existing (and possibly deferred) override.
|
||||
*
|
||||
* <p>For deferred overrides, check if they can be promoted to a regular override. For regular
|
||||
* overrides, check if they need to be demoted to deferred.</p>
|
||||
*
|
||||
* @param packageName Package name to apply deferred overrides for.
|
||||
* @param allowed Whether the override is allowed.
|
||||
*
|
||||
* @return {@code true} if the recheck yielded a result that requires invalidating caches
|
||||
* (a deferred override was consolidated or a regular override was removed).
|
||||
*/
|
||||
boolean recheckOverride(String packageName, boolean allowed) {
|
||||
// A deferred override now is allowed by the policy, so promote it to a regular override.
|
||||
if (hasDeferredOverride(packageName) && allowed) {
|
||||
boolean overrideValue = mDeferredOverrides.remove(packageName);
|
||||
addPackageOverride(packageName, overrideValue);
|
||||
return true;
|
||||
}
|
||||
// A previously set override is no longer allowed by the policy, so make it deferred.
|
||||
if (hasOverride(packageName) && !allowed) {
|
||||
boolean overrideValue = mPackageOverrides.remove(packageName);
|
||||
addPackageDeferredOverride(packageName, overrideValue);
|
||||
// Notify because the override was removed.
|
||||
notifyListener(packageName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any package override for the given package name, restoring the default behaviour.
|
||||
*
|
||||
@@ -133,6 +184,9 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
||||
notifyListener(pname);
|
||||
}
|
||||
}
|
||||
if (mDeferredOverrides != null) {
|
||||
mDeferredOverrides.remove(pname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,6 +230,15 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
||||
return mPackageOverrides != null && mPackageOverrides.containsKey(packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a change has a deferred override for a package.
|
||||
* @param packageName name of the package
|
||||
* @return true if there is such a deferred override
|
||||
*/
|
||||
boolean hasDeferredOverride(String packageName) {
|
||||
return mDeferredOverrides != null && mDeferredOverrides.containsKey(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("ChangeId(")
|
||||
@@ -195,6 +258,9 @@ public final class CompatChange extends CompatibilityChangeInfo {
|
||||
if (mPackageOverrides != null && mPackageOverrides.size() > 0) {
|
||||
sb.append("; packageOverrides=").append(mPackageOverrides);
|
||||
}
|
||||
if (mDeferredOverrides != null && mDeferredOverrides.size() > 0) {
|
||||
sb.append("; deferredOverrides=").append(mDeferredOverrides);
|
||||
}
|
||||
return sb.append(")").toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ final class CompatConfig {
|
||||
@GuardedBy("mChanges")
|
||||
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
|
||||
|
||||
private IOverrideValidator mOverrideValidator;
|
||||
private OverrideValidatorImpl mOverrideValidator;
|
||||
|
||||
@VisibleForTesting
|
||||
CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
|
||||
@@ -161,7 +161,7 @@ final class CompatConfig {
|
||||
* @return {@code true} if the change existed before adding the override.
|
||||
*/
|
||||
boolean addOverride(long changeId, String packageName, boolean enabled)
|
||||
throws RemoteException, SecurityException {
|
||||
throws SecurityException {
|
||||
boolean alreadyKnown = true;
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
|
||||
@@ -173,7 +173,17 @@ final class CompatConfig {
|
||||
c = new CompatChange(changeId);
|
||||
addChange(c);
|
||||
}
|
||||
c.addPackageOverride(packageName, enabled);
|
||||
switch (allowedState.state) {
|
||||
case OverrideAllowedState.ALLOWED:
|
||||
c.addPackageOverride(packageName, enabled);
|
||||
break;
|
||||
case OverrideAllowedState.DEFERRED_VERIFICATION:
|
||||
c.addPackageDeferredOverride(packageName, enabled);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Should only be able to override changes that "
|
||||
+ "are allowed or can be deferred.");
|
||||
}
|
||||
invalidateCache();
|
||||
}
|
||||
return alreadyKnown;
|
||||
@@ -244,26 +254,26 @@ final class CompatConfig {
|
||||
* @return {@code true} if an override existed;
|
||||
*/
|
||||
boolean removeOverride(long changeId, String packageName)
|
||||
throws RemoteException, SecurityException {
|
||||
throws SecurityException {
|
||||
boolean overrideExists = false;
|
||||
synchronized (mChanges) {
|
||||
CompatChange c = mChanges.get(changeId);
|
||||
try {
|
||||
if (c != null) {
|
||||
overrideExists = c.hasOverride(packageName);
|
||||
if (overrideExists) {
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
|
||||
allowedState.enforce(changeId, packageName);
|
||||
c.removePackageOverride(packageName);
|
||||
}
|
||||
if (c != null) {
|
||||
// Always allow removing a deferred override.
|
||||
if (c.hasDeferredOverride(packageName)) {
|
||||
c.removePackageOverride(packageName);
|
||||
overrideExists = true;
|
||||
} else if (c.hasOverride(packageName)) {
|
||||
// Regular overrides need to pass the policy.
|
||||
overrideExists = true;
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
|
||||
allowedState.enforce(changeId, packageName);
|
||||
c.removePackageOverride(packageName);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Should never occur, since validator is in the same process.
|
||||
throw new RuntimeException("Unable to call override validator!", e);
|
||||
}
|
||||
invalidateCache();
|
||||
}
|
||||
invalidateCache();
|
||||
return overrideExists;
|
||||
}
|
||||
|
||||
@@ -293,29 +303,15 @@ final class CompatConfig {
|
||||
* Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
|
||||
* {@link #addOverrides(CompatibilityChangeConfig, String)} for a certain package.
|
||||
*
|
||||
* <p>This restores the default behaviour for the given change and app, once any app
|
||||
* processes have been restarted.
|
||||
* <p>This restores the default behaviour for the given app.
|
||||
*
|
||||
* @param packageName The package for which the overrides should be purged.
|
||||
*/
|
||||
void removePackageOverrides(String packageName) throws RemoteException, SecurityException {
|
||||
void removePackageOverrides(String packageName) throws SecurityException {
|
||||
synchronized (mChanges) {
|
||||
for (int i = 0; i < mChanges.size(); ++i) {
|
||||
try {
|
||||
CompatChange change = mChanges.valueAt(i);
|
||||
if (change.hasOverride(packageName)) {
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(change.getId(),
|
||||
packageName);
|
||||
allowedState.enforce(change.getId(), packageName);
|
||||
if (change != null) {
|
||||
mChanges.valueAt(i).removePackageOverride(packageName);
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Should never occur, since validator is in the same process.
|
||||
throw new RuntimeException("Unable to call override validator!", e);
|
||||
}
|
||||
CompatChange change = mChanges.valueAt(i);
|
||||
removeOverride(change.getId(), packageName);
|
||||
}
|
||||
invalidateCache();
|
||||
}
|
||||
@@ -327,20 +323,15 @@ final class CompatConfig {
|
||||
LongArray allowed = new LongArray();
|
||||
synchronized (mChanges) {
|
||||
for (int i = 0; i < mChanges.size(); ++i) {
|
||||
try {
|
||||
CompatChange change = mChanges.valueAt(i);
|
||||
if (change.getEnableSinceTargetSdk() != targetSdkVersion) {
|
||||
continue;
|
||||
}
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(change.getId(),
|
||||
packageName);
|
||||
if (allowedState.state == OverrideAllowedState.ALLOWED) {
|
||||
allowed.add(change.getId());
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Should never occur, since validator is in the same process.
|
||||
throw new RuntimeException("Unable to call override validator!", e);
|
||||
CompatChange change = mChanges.valueAt(i);
|
||||
if (change.getEnableSinceTargetSdk() != targetSdkVersion) {
|
||||
continue;
|
||||
}
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(change.getId(),
|
||||
packageName);
|
||||
if (allowedState.state == OverrideAllowedState.ALLOWED) {
|
||||
allowed.add(change.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,6 +391,11 @@ final class CompatConfig {
|
||||
return c.defaultValue();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void forceNonDebuggableFinalForTest(boolean value) {
|
||||
mOverrideValidator.forceNonDebuggableFinalForTest(value);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void clearChanges() {
|
||||
synchronized (mChanges) {
|
||||
@@ -511,4 +507,26 @@ final class CompatConfig {
|
||||
private void invalidateCache() {
|
||||
ChangeIdStateCache.invalidate();
|
||||
}
|
||||
/**
|
||||
* Rechecks all the existing overrides for a package.
|
||||
*/
|
||||
void recheckOverrides(String packageName) {
|
||||
synchronized (mChanges) {
|
||||
boolean shouldInvalidateCache = false;
|
||||
for (int idx = 0; idx < mChanges.size(); ++idx) {
|
||||
CompatChange c = mChanges.valueAt(idx);
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(c.getId(), packageName);
|
||||
boolean allowedOverride = (allowedState.state == OverrideAllowedState.ALLOWED);
|
||||
shouldInvalidateCache |= c.recheckOverride(packageName, allowedOverride);
|
||||
}
|
||||
if (shouldInvalidateCache) {
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void registerContentObserver() {
|
||||
mOverrideValidator.registerContentObserver();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,19 @@
|
||||
package com.android.server.compat;
|
||||
|
||||
import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
|
||||
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_NOT_DEBUGGABLE;
|
||||
import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH;
|
||||
import static com.android.internal.compat.OverrideAllowedState.LOGGING_ONLY_CHANGE;
|
||||
import static com.android.internal.compat.OverrideAllowedState.PACKAGE_DOES_NOT_EXIST;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.compat.AndroidBuildClassifier;
|
||||
@@ -41,6 +44,20 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
||||
private AndroidBuildClassifier mAndroidBuildClassifier;
|
||||
private Context mContext;
|
||||
private CompatConfig mCompatConfig;
|
||||
private boolean mForceNonDebuggableFinalBuild;
|
||||
|
||||
private class SettingsObserver extends ContentObserver {
|
||||
SettingsObserver() {
|
||||
super(new Handler());
|
||||
}
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
mForceNonDebuggableFinalBuild = Settings.Global.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Global.FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT,
|
||||
0) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
OverrideValidatorImpl(AndroidBuildClassifier androidBuildClassifier,
|
||||
@@ -48,6 +65,7 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
||||
mAndroidBuildClassifier = androidBuildClassifier;
|
||||
mContext = context;
|
||||
mCompatConfig = config;
|
||||
mForceNonDebuggableFinalBuild = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,8 +74,10 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
||||
return new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1);
|
||||
}
|
||||
|
||||
boolean debuggableBuild = mAndroidBuildClassifier.isDebuggableBuild();
|
||||
boolean finalBuild = mAndroidBuildClassifier.isFinalBuild();
|
||||
boolean debuggableBuild = mAndroidBuildClassifier.isDebuggableBuild()
|
||||
&& !mForceNonDebuggableFinalBuild;
|
||||
boolean finalBuild = mAndroidBuildClassifier.isFinalBuild()
|
||||
|| mForceNonDebuggableFinalBuild;
|
||||
int maxTargetSdk = mCompatConfig.maxTargetSdkForChangeIdOptIn(changeId);
|
||||
boolean disabled = mCompatConfig.isDisabled(changeId);
|
||||
|
||||
@@ -73,7 +93,7 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
||||
try {
|
||||
applicationInfo = packageManager.getApplicationInfo(packageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
return new OverrideAllowedState(PACKAGE_DOES_NOT_EXIST, -1, -1);
|
||||
return new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1);
|
||||
}
|
||||
int appTargetSdk = applicationInfo.targetSdkVersion;
|
||||
// Only allow overriding debuggable apps.
|
||||
@@ -94,4 +114,17 @@ public class OverrideValidatorImpl extends IOverrideValidator.Stub {
|
||||
}
|
||||
return new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, appTargetSdk, maxTargetSdk);
|
||||
}
|
||||
|
||||
void registerContentObserver() {
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Global.getUriFor(
|
||||
Settings.Global.FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT),
|
||||
false,
|
||||
new SettingsObserver());
|
||||
}
|
||||
|
||||
void forceNonDebuggableFinalForTest(boolean value) {
|
||||
mForceNonDebuggableFinalBuild = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,9 +25,13 @@ import static android.os.Process.SYSTEM_UID;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.IActivityManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
@@ -74,6 +78,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
mChangeReporter = new ChangeReporter(
|
||||
ChangeReporter.SOURCE_SYSTEM_SERVER);
|
||||
mCompatConfig = compatConfig;
|
||||
registerPackageReceiver(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -389,4 +394,42 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a broadcast receiver that listens for package install, replace or remove.
|
||||
* @param context the context where the receiver should be registered.
|
||||
*/
|
||||
public void registerPackageReceiver(Context context) {
|
||||
final BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
final Uri packageData = intent.getData();
|
||||
if (packageData == null) {
|
||||
return;
|
||||
}
|
||||
final String packageName = packageData.getSchemeSpecificPart();
|
||||
if (packageName == null) {
|
||||
return;
|
||||
}
|
||||
mCompatConfig.recheckOverrides(packageName);
|
||||
}
|
||||
};
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addDataScheme("package");
|
||||
context.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the observer for
|
||||
* {@link android.provider.Settings.Global#FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT}
|
||||
*/
|
||||
public void registerContentObserver() {
|
||||
mCompatConfig.registerContentObserver();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,6 +912,9 @@ public final class SystemServer {
|
||||
mActivityManagerService.setSystemProcess();
|
||||
t.traceEnd();
|
||||
|
||||
// The package receiver depends on the activity service in order to get registered.
|
||||
platformCompat.registerPackageReceiver(mSystemContext);
|
||||
|
||||
// Complete the watchdog setup with an ActivityManager instance and listen for reboots
|
||||
// Do this only after the ActivityManagerService is properly started as a system process
|
||||
t.traceBegin("InitWatchdog");
|
||||
|
||||
@@ -117,6 +117,7 @@ class CompatConfigBuilder {
|
||||
|
||||
CompatConfig build() {
|
||||
CompatConfig config = new CompatConfig(mBuildClassifier, mContext);
|
||||
config.forceNonDebuggableFinalForTest(false);
|
||||
for (CompatChange change : mChanges) {
|
||||
config.addChange(change);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.app.compat.ChangeIdStateCache;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
@@ -81,6 +82,8 @@ public class CompatConfigTest {
|
||||
@Test
|
||||
public void testUnknownChangeEnabled() throws Exception {
|
||||
CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
|
||||
compatConfig.forceNonDebuggableFinalForTest(false);
|
||||
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, ApplicationInfoBuilder.create().build()))
|
||||
.isTrue();
|
||||
}
|
||||
@@ -180,6 +183,8 @@ public class CompatConfigTest {
|
||||
@Test
|
||||
public void testPackageOverrideUnknownPackage() throws Exception {
|
||||
CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
|
||||
compatConfig.forceNonDebuggableFinalForTest(false);
|
||||
|
||||
|
||||
compatConfig.addOverride(1234L, "com.some.package", false);
|
||||
|
||||
@@ -229,6 +234,83 @@ public class CompatConfigTest {
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyDeferredOverridesAfterInstallingApp() throws Exception {
|
||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.notinstalled.foo")
|
||||
.debuggable().build();
|
||||
when(mPackageManager.getApplicationInfo(eq("com.notinstalled.foo"), anyInt()))
|
||||
.thenThrow(new NameNotFoundException());
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledChangeWithId(1234L).build();
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
// Add override before the app is available.
|
||||
compatConfig.addOverride(1234L, "com.notinstalled.foo", true);
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
||||
|
||||
// Pretend the app is now installed.
|
||||
when(mPackageManager.getApplicationInfo(eq("com.notinstalled.foo"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
compatConfig.recheckOverrides("com.notinstalled.foo");
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyDeferredOverrideClearsOverrideAfterUninstall() throws Exception {
|
||||
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.installedapp.foo")
|
||||
.debuggable().build();
|
||||
when(mPackageManager.getApplicationInfo(eq("com.installedapp.foo"), anyInt()))
|
||||
.thenReturn(applicationInfo);
|
||||
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledChangeWithId(1234L).build();
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
// Add override when app is installed.
|
||||
compatConfig.addOverride(1234L, "com.installedapp.foo", true);
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
|
||||
|
||||
// Pretend the app is now uninstalled.
|
||||
when(mPackageManager.getApplicationInfo(eq("com.installedapp.foo"), anyInt()))
|
||||
.thenThrow(new NameNotFoundException());
|
||||
|
||||
compatConfig.recheckOverrides("com.installedapp.foo");
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyDeferredOverrideClearsOverrideAfterChange() throws Exception {
|
||||
ApplicationInfo debuggableApp = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.installedapp.foo")
|
||||
.debuggable().build();
|
||||
ApplicationInfo releaseApp = ApplicationInfoBuilder.create()
|
||||
.withPackageName("com.installedapp.foo")
|
||||
.build();
|
||||
when(mPackageManager.getApplicationInfo(eq("com.installedapp.foo"), anyInt()))
|
||||
.thenReturn(debuggableApp);
|
||||
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
.addDisabledChangeWithId(1234L).build();
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
|
||||
// Add override for debuggable app.
|
||||
compatConfig.addOverride(1234L, "com.installedapp.foo", true);
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, debuggableApp)).isTrue();
|
||||
|
||||
// Pretend the app now is no longer debuggable, but has the same package.
|
||||
when(mPackageManager.getApplicationInfo(eq("com.installedapp.foo"), anyInt()))
|
||||
.thenReturn(releaseApp);
|
||||
|
||||
compatConfig.recheckOverrides("com.installedapp.foo");
|
||||
assertThat(compatConfig.isChangeEnabled(1234L, releaseApp)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoggingOnlyChangePreventAddOverride() throws Exception {
|
||||
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
|
||||
@@ -259,7 +341,7 @@ public class CompatConfigTest {
|
||||
// Reject all override attempts.
|
||||
// Force the validator to prevent overriding the change by using a user build.
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(false);
|
||||
// Try to turn off change, but validator prevents it.
|
||||
assertThrows(SecurityException.class,
|
||||
() -> compatConfig.removeOverride(1234L, "com.some.package"));
|
||||
@@ -360,6 +442,8 @@ public class CompatConfigTest {
|
||||
@Test
|
||||
public void testLookupChangeIdNotPresent() throws Exception {
|
||||
CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
|
||||
compatConfig.forceNonDebuggableFinalForTest(false);
|
||||
|
||||
assertThat(compatConfig.lookupChangeId("MY_CHANGE")).isEqualTo(-1L);
|
||||
}
|
||||
|
||||
@@ -374,6 +458,8 @@ public class CompatConfigTest {
|
||||
File dir = createTempDir();
|
||||
writeToFile(dir, "platform_compat_config.xml", configXml);
|
||||
CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
|
||||
compatConfig.forceNonDebuggableFinalForTest(false);
|
||||
|
||||
compatConfig.initConfigFromLib(dir);
|
||||
|
||||
assertThat(compatConfig.isChangeEnabled(1234L,
|
||||
@@ -400,6 +486,8 @@ public class CompatConfigTest {
|
||||
writeToFile(dir, "libcore_platform_compat_config.xml", configXml1);
|
||||
writeToFile(dir, "frameworks_platform_compat_config.xml", configXml2);
|
||||
CompatConfig compatConfig = new CompatConfig(mBuildClassifier, mContext);
|
||||
compatConfig.forceNonDebuggableFinalForTest(false);
|
||||
|
||||
compatConfig.initConfigFromLib(dir);
|
||||
|
||||
assertThat(compatConfig.isChangeEnabled(1234L,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.compat;
|
||||
|
||||
import static com.android.internal.compat.OverrideAllowedState.ALLOWED;
|
||||
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_NOT_DEBUGGABLE;
|
||||
import static com.android.internal.compat.OverrideAllowedState.DISABLED_TARGET_SDK_TOO_HIGH;
|
||||
@@ -31,6 +32,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
@@ -409,4 +411,216 @@ public class OverrideValidatorImplTest {
|
||||
assertThat(stateDLoggingOnlyChange)
|
||||
.isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1));
|
||||
}
|
||||
@Test
|
||||
public void getOverrideAllowedState_finalBuildAnyChangeNotInstalledApp_deferOverride()
|
||||
throws Exception {
|
||||
CompatConfig config = CompatConfigBuilder.create(finalBuild(), mContext)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
|
||||
.addEnabledChangeWithId(4)
|
||||
.addDisabledChangeWithId(5)
|
||||
.addLoggingOnlyChangeWithId(6).build();
|
||||
IOverrideValidator overrideValidator = config.getOverrideValidator();
|
||||
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
|
||||
.thenThrow(new NameNotFoundException());
|
||||
|
||||
OverrideAllowedState stateTargetSdkLessChange =
|
||||
overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
|
||||
OverrideAllowedState stateTargetSdkEqualChange =
|
||||
overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
|
||||
OverrideAllowedState stateTargetSdkAfterChange =
|
||||
overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
|
||||
OverrideAllowedState stateEnabledChange =
|
||||
overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
|
||||
OverrideAllowedState stateDisabledChange =
|
||||
overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
|
||||
OverrideAllowedState stateDLoggingOnlyChange =
|
||||
overrideValidator.getOverrideAllowedState(6, PACKAGE_NAME);
|
||||
|
||||
assertThat(stateTargetSdkLessChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateTargetSdkEqualChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateTargetSdkAfterChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateEnabledChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateDisabledChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateDLoggingOnlyChange)
|
||||
.isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getOverrideAllowedState_forceFinalBuildTargetSdkChangeDebugAppOptin_allowOverride()
|
||||
throws Exception {
|
||||
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 1)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK, 2).build();
|
||||
config.forceNonDebuggableFinalForTest(true);
|
||||
IOverrideValidator overrideValidator = config.getOverrideValidator();
|
||||
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
|
||||
.thenReturn(ApplicationInfoBuilder.create()
|
||||
.debuggable()
|
||||
.withTargetSdk(TARGET_SDK)
|
||||
.withPackageName(PACKAGE_NAME).build());
|
||||
|
||||
OverrideAllowedState stateTargetSdkGreaterChange =
|
||||
overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
|
||||
OverrideAllowedState stateTargetSdkEqualChange =
|
||||
overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
|
||||
|
||||
assertThat(stateTargetSdkGreaterChange)
|
||||
.isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK_AFTER));
|
||||
|
||||
assertThat(stateTargetSdkEqualChange)
|
||||
.isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, TARGET_SDK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getOverrideAllowedState_forceFinalBldTargetSdkChangeDebugAppOptout_rejectOverride()
|
||||
throws Exception {
|
||||
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1).build();
|
||||
config.forceNonDebuggableFinalForTest(true);
|
||||
IOverrideValidator overrideValidator = config.getOverrideValidator();
|
||||
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
|
||||
.thenReturn(ApplicationInfoBuilder.create()
|
||||
.withPackageName(PACKAGE_NAME)
|
||||
.withTargetSdk(TARGET_SDK)
|
||||
.debuggable()
|
||||
.build());
|
||||
|
||||
OverrideAllowedState stateTargetSdkLessChange =
|
||||
overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
|
||||
|
||||
assertThat(stateTargetSdkLessChange).isEqualTo(
|
||||
new OverrideAllowedState(DISABLED_TARGET_SDK_TOO_HIGH, TARGET_SDK,
|
||||
TARGET_SDK_BEFORE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getOverrideAllowedState_forceFinalBuildEnabledChangeDebugApp_rejectOverride()
|
||||
throws Exception {
|
||||
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
|
||||
.addEnabledChangeWithId(1).build();
|
||||
config.forceNonDebuggableFinalForTest(true);
|
||||
IOverrideValidator overrideValidator = config.getOverrideValidator();
|
||||
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
|
||||
.thenReturn(ApplicationInfoBuilder.create()
|
||||
.withPackageName(PACKAGE_NAME)
|
||||
.debuggable().build());
|
||||
|
||||
OverrideAllowedState allowedState =
|
||||
overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
|
||||
|
||||
assertThat(allowedState)
|
||||
.isEqualTo(new OverrideAllowedState(DISABLED_NON_TARGET_SDK, -1, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getOverrideAllowedState_forceFinalBuildDisabledChangeDebugApp_allowOverride()
|
||||
throws Exception {
|
||||
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
|
||||
.addDisabledChangeWithId(1).build();
|
||||
config.forceNonDebuggableFinalForTest(true);
|
||||
IOverrideValidator overrideValidator = config.getOverrideValidator();
|
||||
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
|
||||
.thenReturn(ApplicationInfoBuilder.create()
|
||||
.withPackageName(PACKAGE_NAME)
|
||||
.withTargetSdk(TARGET_SDK)
|
||||
.debuggable().build());
|
||||
|
||||
OverrideAllowedState allowedState =
|
||||
overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
|
||||
|
||||
assertThat(allowedState)
|
||||
.isEqualTo(new OverrideAllowedState(ALLOWED, TARGET_SDK, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getOverrideAllowedState_forceFinalBuildAnyChangeReleaseApp_rejectOverride()
|
||||
throws Exception {
|
||||
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
|
||||
.addEnabledChangeWithId(4)
|
||||
.addDisabledChangeWithId(5)
|
||||
.addLoggingOnlyChangeWithId(6).build();
|
||||
config.forceNonDebuggableFinalForTest(true);
|
||||
IOverrideValidator overrideValidator = config.getOverrideValidator();
|
||||
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
|
||||
.thenReturn(ApplicationInfoBuilder.create()
|
||||
.withPackageName(PACKAGE_NAME)
|
||||
.withTargetSdk(TARGET_SDK).build());
|
||||
|
||||
OverrideAllowedState stateTargetSdkLessChange =
|
||||
overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
|
||||
OverrideAllowedState stateTargetSdkEqualChange =
|
||||
overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
|
||||
OverrideAllowedState stateTargetSdkAfterChange =
|
||||
overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
|
||||
OverrideAllowedState stateEnabledChange =
|
||||
overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
|
||||
OverrideAllowedState stateDisabledChange =
|
||||
overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
|
||||
OverrideAllowedState stateDLoggingOnlyChange =
|
||||
overrideValidator.getOverrideAllowedState(6, PACKAGE_NAME);
|
||||
|
||||
assertThat(stateTargetSdkLessChange)
|
||||
.isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
|
||||
assertThat(stateTargetSdkEqualChange)
|
||||
.isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
|
||||
assertThat(stateTargetSdkAfterChange)
|
||||
.isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
|
||||
assertThat(stateEnabledChange)
|
||||
.isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
|
||||
assertThat(stateDisabledChange)
|
||||
.isEqualTo(new OverrideAllowedState(DISABLED_NOT_DEBUGGABLE, -1, -1));
|
||||
assertThat(stateDLoggingOnlyChange)
|
||||
.isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1));
|
||||
}
|
||||
@Test
|
||||
public void getOverrideAllowedState_forceFinalBuildAnyChangeNotInstalledApp_deferOverride()
|
||||
throws Exception {
|
||||
CompatConfig config = CompatConfigBuilder.create(debuggableBuild(), mContext)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_BEFORE, 1)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK, 2)
|
||||
.addEnableAfterSdkChangeWithId(TARGET_SDK_AFTER, 3)
|
||||
.addEnabledChangeWithId(4)
|
||||
.addDisabledChangeWithId(5)
|
||||
.addLoggingOnlyChangeWithId(6).build();
|
||||
config.forceNonDebuggableFinalForTest(true);
|
||||
IOverrideValidator overrideValidator = config.getOverrideValidator();
|
||||
when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt()))
|
||||
.thenThrow(new NameNotFoundException());
|
||||
|
||||
OverrideAllowedState stateTargetSdkLessChange =
|
||||
overrideValidator.getOverrideAllowedState(1, PACKAGE_NAME);
|
||||
OverrideAllowedState stateTargetSdkEqualChange =
|
||||
overrideValidator.getOverrideAllowedState(2, PACKAGE_NAME);
|
||||
OverrideAllowedState stateTargetSdkAfterChange =
|
||||
overrideValidator.getOverrideAllowedState(3, PACKAGE_NAME);
|
||||
OverrideAllowedState stateEnabledChange =
|
||||
overrideValidator.getOverrideAllowedState(4, PACKAGE_NAME);
|
||||
OverrideAllowedState stateDisabledChange =
|
||||
overrideValidator.getOverrideAllowedState(5, PACKAGE_NAME);
|
||||
OverrideAllowedState stateDLoggingOnlyChange =
|
||||
overrideValidator.getOverrideAllowedState(6, PACKAGE_NAME);
|
||||
|
||||
assertThat(stateTargetSdkLessChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateTargetSdkEqualChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateTargetSdkAfterChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateEnabledChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateDisabledChange)
|
||||
.isEqualTo(new OverrideAllowedState(DEFERRED_VERIFICATION, -1, -1));
|
||||
assertThat(stateDLoggingOnlyChange)
|
||||
.isEqualTo(new OverrideAllowedState(LOGGING_ONLY_CHANGE, -1, -1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ public class PlatformCompatTest {
|
||||
mCompatConfig = new CompatConfig(mBuildClassifier, mContext);
|
||||
mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
|
||||
// Assume userdebug/eng non-final build
|
||||
mCompatConfig.forceNonDebuggableFinalForTest(false);
|
||||
when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
|
||||
when(mBuildClassifier.isFinalBuild()).thenReturn(false);
|
||||
LocalServices.removeServiceForTest(PackageManagerInternal.class);
|
||||
|
||||
Reference in New Issue
Block a user