Merge "Refactor PlatformCompat and related files."
This commit is contained in:
@@ -22,17 +22,16 @@ import java.util.Map;
|
|||||||
|
|
||||||
parcelable CompatibilityChangeConfig;
|
parcelable CompatibilityChangeConfig;
|
||||||
parcelable CompatibilityChangeInfo;
|
parcelable CompatibilityChangeInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform private API for talking with the PlatformCompat service.
|
* Platform private API for talking with the PlatformCompat service.
|
||||||
*
|
*
|
||||||
* <p> Should be used for gating and logging from non-app processes.
|
* <p>Should be used for gating and logging from non-app processes.
|
||||||
* For app processes please use android.compat.Compatibility API.
|
*
|
||||||
|
* <p>Note: for app processes please use {@code android.compat.Compatibility} API.
|
||||||
*
|
*
|
||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
interface IPlatformCompat
|
interface IPlatformCompat {
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports that a compatibility change is affecting an app process now.
|
* Reports that a compatibility change is affecting an app process now.
|
||||||
@@ -40,8 +39,9 @@ interface IPlatformCompat
|
|||||||
* <p>Note: for changes that are gated using {@link #isChangeEnabled(long, ApplicationInfo)},
|
* <p>Note: for changes that are gated using {@link #isChangeEnabled(long, ApplicationInfo)},
|
||||||
* you do not need to call this API directly. The change will be reported for you.
|
* you do not need to call this API directly. The change will be reported for you.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the compatibility change taking effect.
|
* @param changeId the ID of the compatibility change taking effect
|
||||||
* @param appInfo Representing the affected app.
|
* @param appInfo representing the affected app
|
||||||
|
* @throws SecurityException if logging is not allowed
|
||||||
*/
|
*/
|
||||||
void reportChange(long changeId, in ApplicationInfo appInfo);
|
void reportChange(long changeId, in ApplicationInfo appInfo);
|
||||||
|
|
||||||
@@ -51,11 +51,12 @@ interface IPlatformCompat
|
|||||||
* <p>Note: for changes that are gated using {@link #isChangeEnabled(long, String)},
|
* <p>Note: for changes that are gated using {@link #isChangeEnabled(long, String)},
|
||||||
* you do not need to call this API directly. The change will be reported for you.
|
* you do not need to call this API directly. The change will be reported for you.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the compatibility change taking effect.
|
* @param changeId the ID of the compatibility change taking effect
|
||||||
* @param userId The ID of the user that the operation is done for.
|
* @param userId the ID of the user that the operation is done for
|
||||||
* @param packageName The package name of the app in question.
|
* @param packageName the package name of the app in question
|
||||||
|
* @throws SecurityException if logging is not allowed
|
||||||
*/
|
*/
|
||||||
void reportChangeByPackageName(long changeId, in String packageName, int userId);
|
void reportChangeByPackageName(long changeId, in String packageName, int userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports that a compatibility change is affecting an app process now.
|
* Reports that a compatibility change is affecting an app process now.
|
||||||
@@ -63,13 +64,14 @@ interface IPlatformCompat
|
|||||||
* <p>Note: for changes that are gated using {@link #isChangeEnabled(long, int)},
|
* <p>Note: for changes that are gated using {@link #isChangeEnabled(long, int)},
|
||||||
* you do not need to call this API directly. The change will be reported for you.
|
* you do not need to call this API directly. The change will be reported for you.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the compatibility change taking effect.
|
* @param changeId the ID of the compatibility change taking effect
|
||||||
* @param uid The UID of the app in question.
|
* @param uid the UID of the app in question
|
||||||
|
* @throws SecurityException if logging is not allowed
|
||||||
*/
|
*/
|
||||||
void reportChangeByUid(long changeId, int uid);
|
void reportChangeByUid(long changeId, int uid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query if a given compatibility change is enabled for an app process. This method should
|
* Queries if a given compatibility change is enabled for an app process. This method should
|
||||||
* be called when implementing functionality on behalf of the affected app.
|
* be called when implementing functionality on behalf of the affected app.
|
||||||
*
|
*
|
||||||
* <p>If this method returns {@code true}, the calling code should implement the compatibility
|
* <p>If this method returns {@code true}, the calling code should implement the compatibility
|
||||||
@@ -79,14 +81,15 @@ interface IPlatformCompat
|
|||||||
* <p>It will also report the change as {@link #reportChange(long, ApplicationInfo)} would, so
|
* <p>It will also report the change as {@link #reportChange(long, ApplicationInfo)} would, so
|
||||||
* there is no need to call that method directly.
|
* there is no need to call that method directly.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the compatibility change in question.
|
* @param changeId the ID of the compatibility change in question
|
||||||
* @param appInfo Representing the app in question.
|
* @param appInfo representing the app in question
|
||||||
* @return {@code true} if the change is enabled for the current app.
|
* @return {@code true} if the change is enabled for the current app
|
||||||
|
* @throws SecurityException if logging or reading compat confis is not allowed
|
||||||
*/
|
*/
|
||||||
boolean isChangeEnabled(long changeId, in ApplicationInfo appInfo);
|
boolean isChangeEnabled(long changeId, in ApplicationInfo appInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query if a given compatibility change is enabled for an app process. This method should
|
* Queries if a given compatibility change is enabled for an app process. This method should
|
||||||
* be called when implementing functionality on behalf of the affected app.
|
* be called when implementing functionality on behalf of the affected app.
|
||||||
*
|
*
|
||||||
* <p>Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a package name
|
* <p>Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a package name
|
||||||
@@ -102,15 +105,16 @@ interface IPlatformCompat
|
|||||||
* <p>It will also report the change as {@link #reportChange(long, String)} would, so there is
|
* <p>It will also report the change as {@link #reportChange(long, String)} would, so there is
|
||||||
* no need to call that method directly.
|
* no need to call that method directly.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the compatibility change in question.
|
* @param changeId the ID of the compatibility change in question
|
||||||
* @param packageName The package name of the app in question.
|
* @param packageName the package name of the app in question
|
||||||
* @param userId The ID of the user that the operation is done for.
|
* @param userId the ID of the user that the operation is done for
|
||||||
* @return {@code true} if the change is enabled for the current app.
|
* @return {@code true} if the change is enabled for the current app
|
||||||
|
* @throws SecurityException if logging or reading compat confis is not allowed
|
||||||
*/
|
*/
|
||||||
boolean isChangeEnabledByPackageName(long changeId, in String packageName, int userId);
|
boolean isChangeEnabledByPackageName(long changeId, in String packageName, int userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query if a given compatibility change is enabled for an app process. This method should
|
* Queries if a given compatibility change is enabled for an app process. This method should
|
||||||
* be called when implementing functionality on behalf of the affected app.
|
* be called when implementing functionality on behalf of the affected app.
|
||||||
*
|
*
|
||||||
* <p>Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a uid
|
* <p>Same as {@link #isChangeEnabled(long, ApplicationInfo)}, except it receives a uid
|
||||||
@@ -127,110 +131,121 @@ interface IPlatformCompat
|
|||||||
* <p>It will also report the change as {@link #reportChange(long, int)} would, so there is
|
* <p>It will also report the change as {@link #reportChange(long, int)} would, so there is
|
||||||
* no need to call that method directly.
|
* no need to call that method directly.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the compatibility change in question.
|
* @param changeId the ID of the compatibility change in question
|
||||||
* @param uid The UID of the app in question.
|
* @param uid the UID of the app in question
|
||||||
* @return {@code true} if the change is enabled for the current app.
|
* @return {@code true} if the change is enabled for the current app
|
||||||
|
* @throws SecurityException if logging or reading compat confis is not allowed
|
||||||
*/
|
*/
|
||||||
boolean isChangeEnabledByUid(long changeId, int uid);
|
boolean isChangeEnabledByUid(long changeId, int uid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add overrides to compatibility changes. Kills the app to allow the changes to take effect.
|
* Adds overrides to compatibility changes.
|
||||||
*
|
*
|
||||||
* @param overrides Parcelable containing the compat change overrides to be applied.
|
* <p>Kills the app to allow the changes to take effect.
|
||||||
* @param packageName The package name of the app whose changes will be overridden.
|
|
||||||
*
|
*
|
||||||
|
* @param overrides parcelable containing the compat change overrides to be applied
|
||||||
|
* @param packageName the package name of the app whose changes will be overridden
|
||||||
|
* @throws SecurityException if overriding changes is not permitted
|
||||||
*/
|
*/
|
||||||
void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);
|
void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add overrides to compatibility changes. Doesn't kill the app, to be only used in tests.
|
* Adds overrides to compatibility changes.
|
||||||
*
|
*
|
||||||
* @param overrides Parcelable containing the compat change overrides to be applied.
|
* <p>Does not kill the app, to be only used in tests.
|
||||||
* @param packageName The package name of the app whose changes will be overridden.
|
|
||||||
*
|
*
|
||||||
|
* @param overrides parcelable containing the compat change overrides to be applied
|
||||||
|
* @param packageName the package name of the app whose changes will be overridden
|
||||||
|
* @throws SecurityException if overriding changes is not permitted.
|
||||||
*/
|
*/
|
||||||
void setOverridesForTest(in CompatibilityChangeConfig overrides, in String packageName);
|
void setOverridesForTest(in CompatibilityChangeConfig overrides, in String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an override previously added via {@link #setOverrides(CompatibilityChangeConfig,
|
* Restores the default behaviour for the given change and app.
|
||||||
* String)}. This restores the default behaviour for the given change and app, once any app
|
|
||||||
* processes have been restarted.
|
|
||||||
* Kills the app to allow the changes to take effect.
|
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the change that was overridden.
|
* <p>Kills the app to allow the changes to take effect.
|
||||||
* @param packageName The app package name that was overridden.
|
*
|
||||||
* @return {@code true} if an override existed;
|
* @param changeId the ID of the change that was overridden
|
||||||
|
* @param packageName the app package name that was overridden
|
||||||
|
* @return {@code true} if an override existed
|
||||||
|
* @throws SecurityException if overriding changes is not permitted
|
||||||
*/
|
*/
|
||||||
boolean clearOverride(long changeId, String packageName);
|
boolean clearOverride(long changeId, String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable all compatibility changes which have enabledSinceTargetSdk ==
|
* Enables all compatibility changes that have enabledSinceTargetSdk ==
|
||||||
* {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
|
* {@param targetSdkVersion} for an app, subject to the policy.
|
||||||
* changes to take effect.
|
|
||||||
*
|
*
|
||||||
* @param packageName The package name of the app whose compatibility changes will be enabled.
|
* <p>Kills the app to allow the changes to take effect.
|
||||||
|
*
|
||||||
|
* @param packageName The package name of the app whose compatibility changes will be
|
||||||
|
* enabled.
|
||||||
* @param targetSdkVersion The targetSdkVersion for filtering the changes to be enabled.
|
* @param targetSdkVersion The targetSdkVersion for filtering the changes to be enabled.
|
||||||
*
|
|
||||||
* @return The number of changes that were enabled.
|
* @return The number of changes that were enabled.
|
||||||
|
* @throws SecurityException if overriding changes is not permitted.
|
||||||
*/
|
*/
|
||||||
int enableTargetSdkChanges(in String packageName, int targetSdkVersion);
|
int enableTargetSdkChanges(in String packageName, int targetSdkVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable all compatibility changes which have enabledAfterTargetSdk ==
|
* Disables all compatibility changes that have enabledAfterTargetSdk ==
|
||||||
* {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
|
* {@param targetSdkVersion} for an app, subject to the policy.
|
||||||
* changes to take effect.
|
|
||||||
*
|
*
|
||||||
* @param packageName The package name of the app whose compatibility changes will be disabled.
|
* <p>Kills the app to allow the changes to take effect.
|
||||||
* @param targetSdkVersion The targetSdkVersion for filtering the changes to be disabled.
|
|
||||||
*
|
*
|
||||||
* @return The number of changes that were disabled.
|
* @param packageName the package name of the app whose compatibility changes will be
|
||||||
|
* disabled
|
||||||
|
* @param targetSdkVersion the targetSdkVersion for filtering the changes to be disabled
|
||||||
|
* @return the number of changes that were disabled
|
||||||
|
* @throws SecurityException if overriding changes is not permitted.
|
||||||
*/
|
*/
|
||||||
int disableTargetSdkChanges(in String packageName, int targetSdkVersion);
|
int disableTargetSdkChanges(in String packageName, int targetSdkVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revert overrides to compatibility changes. Kills the app to allow the changes to take effect.
|
* Restores the default behaviour for the given app.
|
||||||
*
|
*
|
||||||
* @param packageName The package name of the app whose overrides will be cleared.
|
* <p>Kills the app to allow the changes to take effect.
|
||||||
*
|
*
|
||||||
|
* @param packageName the package name of the app whose overrides will be cleared
|
||||||
|
* @throws SecurityException if overriding changes is not permitted
|
||||||
*/
|
*/
|
||||||
void clearOverrides(in String packageName);
|
void clearOverrides(in String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revert overrides to compatibility changes. Doesn't kill the app, to be only used in tests.
|
* Restores the default behaviour for the given app.
|
||||||
*
|
*
|
||||||
* @param packageName The package name of the app whose overrides will be cleared.
|
* <p>Does not kill the app; to be only used in tests.
|
||||||
*
|
*
|
||||||
|
* @param packageName the package name of the app whose overrides will be cleared
|
||||||
|
* @throws SecurityException if overriding changes is not permitted
|
||||||
*/
|
*/
|
||||||
void clearOverridesForTest(in String packageName);
|
void clearOverridesForTest(in String packageName);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get configs for an application.
|
* Get configs for an application.
|
||||||
*
|
*
|
||||||
* @param appInfo The application whose config will be returned.
|
* @param appInfo the application whose config will be returned
|
||||||
*
|
* @return a {@link CompatibilityChangeConfig}, representing whether a change is enabled for
|
||||||
* @return A {@link CompatibilityChangeConfig}, representing whether a change is enabled for
|
* the given app or not
|
||||||
* the given app or not.
|
|
||||||
*/
|
*/
|
||||||
CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo);
|
CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all compatibility changes.
|
* List all compatibility changes.
|
||||||
*
|
*
|
||||||
* @return An array of {@link CompatChangeInfo} known to the service.
|
* @return an array of {@link CompatibilityChangeInfo} known to the service
|
||||||
*/
|
*/
|
||||||
CompatibilityChangeInfo[] listAllChanges();
|
CompatibilityChangeInfo[] listAllChanges();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List the compatibility changes that should be present in the UI.
|
* List the compatibility changes that should be present in the UI.
|
||||||
* Filters out certain changes like e.g. logging only.
|
* Filters out certain changes like e.g. logging only.
|
||||||
*
|
*
|
||||||
* @return An array of {@link CompatChangeInfo}.
|
* @return an array of {@link CompatibilityChangeInfo}
|
||||||
*/
|
*/
|
||||||
CompatibilityChangeInfo[] listUIChanges();
|
CompatibilityChangeInfo[] listUIChanges();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an instance that can determine whether a changeid can be overridden for a package name.
|
* Gets an instance that can determine whether a changeid can be overridden for a package name.
|
||||||
*/
|
*/
|
||||||
IOverrideValidator getOverrideValidator();
|
IOverrideValidator getOverrideValidator();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import android.compat.Compatibility.ChangeConfig;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.LongArray;
|
import android.util.LongArray;
|
||||||
import android.util.LongSparseArray;
|
import android.util.LongSparseArray;
|
||||||
@@ -53,7 +52,7 @@ import java.util.Set;
|
|||||||
import javax.xml.datatype.DatatypeConfigurationException;
|
import javax.xml.datatype.DatatypeConfigurationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class maintains state relating to platform compatibility changes.
|
* CompatConfig maintains state related to the platform compatibility changes.
|
||||||
*
|
*
|
||||||
* <p>It stores the default configuration for each change, and any per-package overrides that have
|
* <p>It stores the default configuration for each change, and any per-package overrides that have
|
||||||
* been configured.
|
* been configured.
|
||||||
@@ -65,18 +64,38 @@ final class CompatConfig {
|
|||||||
@GuardedBy("mChanges")
|
@GuardedBy("mChanges")
|
||||||
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
|
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
|
||||||
|
|
||||||
private OverrideValidatorImpl mOverrideValidator;
|
private final OverrideValidatorImpl mOverrideValidator;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
|
CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
|
||||||
mOverrideValidator = new OverrideValidatorImpl(androidBuildClassifier, context, this);
|
mOverrideValidator = new OverrideValidatorImpl(androidBuildClassifier, context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CompatConfig create(AndroidBuildClassifier androidBuildClassifier, Context context) {
|
||||||
|
CompatConfig config = new CompatConfig(androidBuildClassifier, context);
|
||||||
|
config.initConfigFromLib(Environment.buildPath(
|
||||||
|
Environment.getRootDirectory(), "etc", "compatconfig"));
|
||||||
|
config.initConfigFromLib(Environment.buildPath(
|
||||||
|
Environment.getRootDirectory(), "system_ext", "etc", "compatconfig"));
|
||||||
|
|
||||||
|
List<ApexManager.ActiveApexInfo> apexes = ApexManager.getInstance().getActiveApexInfos();
|
||||||
|
for (ApexManager.ActiveApexInfo apex : apexes) {
|
||||||
|
config.initConfigFromLib(Environment.buildPath(
|
||||||
|
apex.apexDirectory, "etc", "compatconfig"));
|
||||||
|
}
|
||||||
|
config.invalidateCache();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a change. This is intended to be used by code that reads change config from the
|
* Adds a change.
|
||||||
* filesystem. This should be done at system startup time.
|
|
||||||
*
|
*
|
||||||
* @param change The change to add. Any change with the same ID will be overwritten.
|
* <p>This is intended to be used by code that reads change config from the filesystem. This
|
||||||
|
* should be done at system startup time.
|
||||||
|
*
|
||||||
|
* <p>Any change with the same ID will be overwritten.
|
||||||
|
*
|
||||||
|
* @param change the change to add
|
||||||
*/
|
*/
|
||||||
void addChange(CompatChange change) {
|
void addChange(CompatChange change) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
@@ -86,13 +105,15 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the set of disabled changes for a given app. Any change ID not in the returned
|
* Retrieves the set of disabled changes for a given app.
|
||||||
* array is by default enabled for the app.
|
|
||||||
*
|
*
|
||||||
* @param app The app in question
|
* <p>Any change ID not in the returned array is by default enabled for the app.
|
||||||
* @return A sorted long array of change IDs. We use a primitive array to minimize memory
|
*
|
||||||
* footprint: Every app process will store this array statically so we aim to reduce
|
* <p>We use a primitive array to minimize memory footprint: every app process will store this
|
||||||
* overhead as much as possible.
|
* array statically so we aim to reduce overhead as much as possible.
|
||||||
|
*
|
||||||
|
* @param app the app in question
|
||||||
|
* @return a sorted long array of change IDs
|
||||||
*/
|
*/
|
||||||
long[] getDisabledChanges(ApplicationInfo app) {
|
long[] getDisabledChanges(ApplicationInfo app) {
|
||||||
LongArray disabled = new LongArray();
|
LongArray disabled = new LongArray();
|
||||||
@@ -110,10 +131,10 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up a change ID by name.
|
* Looks up a change ID by name.
|
||||||
*
|
*
|
||||||
* @param name Name of the change to look up
|
* @param name name of the change to look up
|
||||||
* @return The change ID, or {@code -1} if no change with that name exists.
|
* @return the change ID, or {@code -1} if no change with that name exists
|
||||||
*/
|
*/
|
||||||
long lookupChangeId(String name) {
|
long lookupChangeId(String name) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
@@ -127,10 +148,10 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find if a given change is enabled for a given application.
|
* Checks if a given change is enabled for a given application.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the change in question
|
* @param changeId the ID of the change in question
|
||||||
* @param app App to check for
|
* @param app app to check for
|
||||||
* @return {@code true} if the change is enabled for this app. Also returns {@code true} if the
|
* @return {@code true} if the change is enabled for this app. Also returns {@code true} if the
|
||||||
* change ID is not known, as unknown changes are enabled by default.
|
* change ID is not known, as unknown changes are enabled by default.
|
||||||
*/
|
*/
|
||||||
@@ -146,10 +167,10 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find if a given change will be enabled for a given package name, prior to installation.
|
* Checks if a given change will be enabled for a given package name after the installation.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the change in question
|
* @param changeId the ID of the change in question
|
||||||
* @param packageName Package name to check for
|
* @param packageName package name to check for
|
||||||
* @return {@code true} if the change would be enabled for this package name. Also returns
|
* @return {@code true} if the change would be enabled for this package name. Also returns
|
||||||
* {@code true} if the change ID is not known, as unknown changes are enabled by default.
|
* {@code true} if the change ID is not known, as unknown changes are enabled by default.
|
||||||
*/
|
*/
|
||||||
@@ -165,22 +186,22 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides the enabled state for a given change and app. This method is intended to be used
|
* Overrides the enabled state for a given change and app.
|
||||||
* *only* for debugging purposes, ultimately invoked either by an adb command, or from some
|
|
||||||
* developer settings UI.
|
|
||||||
*
|
*
|
||||||
* <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
|
* <p>This method is intended to be used *only* for debugging purposes, ultimately invoked
|
||||||
|
* either by an adb command, or from some developer settings UI.
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the change to be overridden. Note, this call will succeed even
|
* <p>Note: package overrides are not persistent and will be lost on system or runtime restart.
|
||||||
* if
|
*
|
||||||
* this change is not known; it will only have any effect if any code in the
|
* @param changeId the ID of the change to be overridden. Note, this call will succeed even
|
||||||
* platform is gated on the ID given.
|
* if this change is not known; it will only have any effect if any code in
|
||||||
* @param packageName The app package name to override the change for.
|
* the platform is gated on the ID given.
|
||||||
* @param enabled If the change should be enabled or disabled.
|
* @param packageName the app package name to override the change for
|
||||||
* @return {@code true} if the change existed before adding the override.
|
* @param enabled if the change should be enabled or disabled
|
||||||
|
* @return {@code true} if the change existed before adding the override
|
||||||
|
* @throws IllegalStateException if overriding is not allowed
|
||||||
*/
|
*/
|
||||||
boolean addOverride(long changeId, String packageName, boolean enabled)
|
boolean addOverride(long changeId, String packageName, boolean enabled) {
|
||||||
throws SecurityException {
|
|
||||||
boolean alreadyKnown = true;
|
boolean alreadyKnown = true;
|
||||||
OverrideAllowedState allowedState =
|
OverrideAllowedState allowedState =
|
||||||
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
|
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
|
||||||
@@ -201,18 +222,14 @@ final class CompatConfig {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Should only be able to override changes that "
|
throw new IllegalStateException("Should only be able to override changes that "
|
||||||
+ "are allowed or can be deferred.");
|
+ "are allowed or can be deferred.");
|
||||||
}
|
}
|
||||||
invalidateCache();
|
invalidateCache();
|
||||||
}
|
}
|
||||||
return alreadyKnown;
|
return alreadyKnown;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Checks whether the change is known to the compat config. */
|
||||||
* Check whether the change is known to the compat config.
|
|
||||||
*
|
|
||||||
* @return {@code true} if the change is known.
|
|
||||||
*/
|
|
||||||
boolean isKnownChangeId(long changeId) {
|
boolean isKnownChangeId(long changeId) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
CompatChange c = mChanges.get(changeId);
|
CompatChange c = mChanges.get(changeId);
|
||||||
@@ -221,16 +238,13 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the maximum sdk version for which this change can be opted in (or -1 if it is not
|
* Returns the maximum SDK version for which this change can be opted in (or -1 if it is not
|
||||||
* target sdk gated).
|
* target SDK gated).
|
||||||
*/
|
*/
|
||||||
int maxTargetSdkForChangeIdOptIn(long changeId) {
|
int maxTargetSdkForChangeIdOptIn(long changeId) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
CompatChange c = mChanges.get(changeId);
|
CompatChange c = mChanges.get(changeId);
|
||||||
if (c == null) {
|
if (c != null && c.getEnableSinceTargetSdk() != -1) {
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (c.getEnableSinceTargetSdk() != -1) {
|
|
||||||
return c.getEnableSinceTargetSdk() - 1;
|
return c.getEnableSinceTargetSdk() - 1;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -243,10 +257,7 @@ final class CompatConfig {
|
|||||||
boolean isLoggingOnly(long changeId) {
|
boolean isLoggingOnly(long changeId) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
CompatChange c = mChanges.get(changeId);
|
CompatChange c = mChanges.get(changeId);
|
||||||
if (c == null) {
|
return c != null && c.getLoggingOnly();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return c.getLoggingOnly();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,24 +267,21 @@ final class CompatConfig {
|
|||||||
boolean isDisabled(long changeId) {
|
boolean isDisabled(long changeId) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
CompatChange c = mChanges.get(changeId);
|
CompatChange c = mChanges.get(changeId);
|
||||||
if (c == null) {
|
return c != null && c.getDisabled();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return c.getDisabled();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an override previously added via {@link #addOverride(long, String, boolean)}. This
|
* Removes an override previously added via {@link #addOverride(long, String, boolean)}.
|
||||||
* restores the default behaviour for the given change and app, once any app processes have been
|
|
||||||
* restarted.
|
|
||||||
*
|
*
|
||||||
* @param changeId The ID of the change that was overridden.
|
* <p>This restores the default behaviour for the given change and app, once any app processes
|
||||||
* @param packageName The app package name that was overridden.
|
* have been restarted.
|
||||||
|
*
|
||||||
|
* @param changeId the ID of the change that was overridden
|
||||||
|
* @param packageName the app package name that was overridden
|
||||||
* @return {@code true} if an override existed;
|
* @return {@code true} if an override existed;
|
||||||
*/
|
*/
|
||||||
boolean removeOverride(long changeId, String packageName)
|
boolean removeOverride(long changeId, String packageName) {
|
||||||
throws SecurityException {
|
|
||||||
boolean overrideExists = false;
|
boolean overrideExists = false;
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
CompatChange c = mChanges.get(changeId);
|
CompatChange c = mChanges.get(changeId);
|
||||||
@@ -299,13 +307,12 @@ final class CompatConfig {
|
|||||||
/**
|
/**
|
||||||
* Overrides the enabled state for a given change and app.
|
* Overrides the enabled state for a given change and app.
|
||||||
*
|
*
|
||||||
* <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
|
* <p>Note: package overrides are not persistent and will be lost on system or runtime restart.
|
||||||
*
|
*
|
||||||
* @param overrides list of overrides to default changes config.
|
* @param overrides list of overrides to default changes config
|
||||||
* @param packageName app for which the overrides will be applied.
|
* @param packageName app for which the overrides will be applied
|
||||||
*/
|
*/
|
||||||
void addOverrides(CompatibilityChangeConfig overrides, String packageName)
|
void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
|
||||||
throws RemoteException, SecurityException {
|
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
for (Long changeId : overrides.enabledChanges()) {
|
for (Long changeId : overrides.enabledChanges()) {
|
||||||
addOverride(changeId, packageName, true);
|
addOverride(changeId, packageName, true);
|
||||||
@@ -324,9 +331,9 @@ final class CompatConfig {
|
|||||||
*
|
*
|
||||||
* <p>This restores the default behaviour for the given app.
|
* <p>This restores the default behaviour for the given app.
|
||||||
*
|
*
|
||||||
* @param packageName The package for which the overrides should be purged.
|
* @param packageName the package for which the overrides should be purged
|
||||||
*/
|
*/
|
||||||
void removePackageOverrides(String packageName) throws SecurityException {
|
void removePackageOverrides(String packageName) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
for (int i = 0; i < mChanges.size(); ++i) {
|
for (int i = 0; i < mChanges.size(); ++i) {
|
||||||
CompatChange change = mChanges.valueAt(i);
|
CompatChange change = mChanges.valueAt(i);
|
||||||
@@ -337,8 +344,7 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
|
private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
|
||||||
int targetSdkVersion)
|
int targetSdkVersion) {
|
||||||
throws RemoteException {
|
|
||||||
LongArray allowed = new LongArray();
|
LongArray allowed = new LongArray();
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
for (int i = 0; i < mChanges.size(); ++i) {
|
for (int i = 0; i < mChanges.size(); ++i) {
|
||||||
@@ -348,7 +354,7 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
OverrideAllowedState allowedState =
|
OverrideAllowedState allowedState =
|
||||||
mOverrideValidator.getOverrideAllowedState(change.getId(),
|
mOverrideValidator.getOverrideAllowedState(change.getId(),
|
||||||
packageName);
|
packageName);
|
||||||
if (allowedState.state == OverrideAllowedState.ALLOWED) {
|
if (allowedState.state == OverrideAllowedState.ALLOWED) {
|
||||||
allowed.add(change.getId());
|
allowed.add(change.getId());
|
||||||
}
|
}
|
||||||
@@ -361,10 +367,9 @@ final class CompatConfig {
|
|||||||
* Enables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
|
* Enables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
|
||||||
* {@param packageName}.
|
* {@param packageName}.
|
||||||
*
|
*
|
||||||
* @return The number of changes that were toggled.
|
* @return the number of changes that were toggled
|
||||||
*/
|
*/
|
||||||
int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
|
int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) {
|
||||||
throws RemoteException {
|
|
||||||
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
||||||
for (long changeId : changes) {
|
for (long changeId : changes) {
|
||||||
addOverride(changeId, packageName, true);
|
addOverride(changeId, packageName, true);
|
||||||
@@ -372,15 +377,13 @@ final class CompatConfig {
|
|||||||
return changes.length;
|
return changes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
|
* Disables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
|
||||||
* {@param packageName}.
|
* {@param packageName}.
|
||||||
*
|
*
|
||||||
* @return The number of changes that were toggled.
|
* @return the number of changes that were toggled
|
||||||
*/
|
*/
|
||||||
int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
|
int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) {
|
||||||
throws RemoteException {
|
|
||||||
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
||||||
for (long changeId : changes) {
|
for (long changeId : changes) {
|
||||||
addOverride(changeId, packageName, false);
|
addOverride(changeId, packageName, false);
|
||||||
@@ -425,7 +428,7 @@ final class CompatConfig {
|
|||||||
/**
|
/**
|
||||||
* Dumps the current list of compatibility config information.
|
* Dumps the current list of compatibility config information.
|
||||||
*
|
*
|
||||||
* @param pw The {@link PrintWriter} instance to which the information will be dumped.
|
* @param pw {@link PrintWriter} instance to which the information will be dumped
|
||||||
*/
|
*/
|
||||||
void dumpConfig(PrintWriter pw) {
|
void dumpConfig(PrintWriter pw) {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
@@ -441,13 +444,10 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the config for a given app.
|
* Returns config for a given app.
|
||||||
*
|
*
|
||||||
* @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped.
|
* @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped
|
||||||
* @return A {@link CompatibilityChangeConfig} which contains the compat config info for the
|
|
||||||
* given app.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
|
CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
|
||||||
Set<Long> enabled = new HashSet<>();
|
Set<Long> enabled = new HashSet<>();
|
||||||
Set<Long> disabled = new HashSet<>();
|
Set<Long> disabled = new HashSet<>();
|
||||||
@@ -467,7 +467,7 @@ final class CompatConfig {
|
|||||||
/**
|
/**
|
||||||
* Dumps all the compatibility change information.
|
* Dumps all the compatibility change information.
|
||||||
*
|
*
|
||||||
* @return An array of {@link CompatibilityChangeInfo} with the current changes.
|
* @return an array of {@link CompatibilityChangeInfo} with the current changes
|
||||||
*/
|
*/
|
||||||
CompatibilityChangeInfo[] dumpChanges() {
|
CompatibilityChangeInfo[] dumpChanges() {
|
||||||
synchronized (mChanges) {
|
synchronized (mChanges) {
|
||||||
@@ -480,22 +480,6 @@ final class CompatConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static CompatConfig create(AndroidBuildClassifier androidBuildClassifier, Context context) {
|
|
||||||
CompatConfig config = new CompatConfig(androidBuildClassifier, context);
|
|
||||||
config.initConfigFromLib(Environment.buildPath(
|
|
||||||
Environment.getRootDirectory(), "etc", "compatconfig"));
|
|
||||||
config.initConfigFromLib(Environment.buildPath(
|
|
||||||
Environment.getRootDirectory(), "system_ext", "etc", "compatconfig"));
|
|
||||||
|
|
||||||
List<ApexManager.ActiveApexInfo> apexes = ApexManager.getInstance().getActiveApexInfos();
|
|
||||||
for (ApexManager.ActiveApexInfo apex : apexes) {
|
|
||||||
config.initConfigFromLib(Environment.buildPath(
|
|
||||||
apex.apexDirectory, "etc", "compatconfig"));
|
|
||||||
}
|
|
||||||
config.invalidateCache();
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initConfigFromLib(File libraryDir) {
|
void initConfigFromLib(File libraryDir) {
|
||||||
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
|
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
|
||||||
Slog.d(TAG, "No directory " + libraryDir + ", skipping");
|
Slog.d(TAG, "No directory " + libraryDir + ", skipping");
|
||||||
@@ -526,6 +510,7 @@ final class CompatConfig {
|
|||||||
private void invalidateCache() {
|
private void invalidateCache() {
|
||||||
ChangeIdStateCache.invalidate();
|
ChangeIdStateCache.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rechecks all the existing overrides for a package.
|
* Rechecks all the existing overrides for a package.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -63,45 +63,43 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
private final ChangeReporter mChangeReporter;
|
private final ChangeReporter mChangeReporter;
|
||||||
private final CompatConfig mCompatConfig;
|
private final CompatConfig mCompatConfig;
|
||||||
|
|
||||||
private static int sMinTargetSdk = Build.VERSION_CODES.Q;
|
|
||||||
|
|
||||||
public PlatformCompat(Context context) {
|
public PlatformCompat(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mChangeReporter = new ChangeReporter(
|
mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER);
|
||||||
ChangeReporter.SOURCE_SYSTEM_SERVER);
|
|
||||||
mCompatConfig = CompatConfig.create(new AndroidBuildClassifier(), mContext);
|
mCompatConfig = CompatConfig.create(new AndroidBuildClassifier(), mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
PlatformCompat(Context context, CompatConfig compatConfig) {
|
PlatformCompat(Context context, CompatConfig compatConfig) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mChangeReporter = new ChangeReporter(
|
mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER);
|
||||||
ChangeReporter.SOURCE_SYSTEM_SERVER);
|
|
||||||
mCompatConfig = compatConfig;
|
mCompatConfig = compatConfig;
|
||||||
|
|
||||||
registerPackageReceiver(context);
|
registerPackageReceiver(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportChange(long changeId, ApplicationInfo appInfo) {
|
public void reportChange(long changeId, ApplicationInfo appInfo) {
|
||||||
checkCompatChangeLogPermission();
|
reportChangeByUid(changeId, appInfo.uid);
|
||||||
reportChange(changeId, appInfo.uid,
|
|
||||||
ChangeReporter.STATE_LOGGED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportChangeByPackageName(long changeId, String packageName, int userId) {
|
public void reportChangeByPackageName(long changeId, String packageName,
|
||||||
checkCompatChangeLogPermission();
|
@UserIdInt int userId) {
|
||||||
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
|
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
|
||||||
if (appInfo == null) {
|
if (appInfo != null) {
|
||||||
return;
|
reportChangeByUid(changeId, appInfo.uid);
|
||||||
}
|
}
|
||||||
reportChange(changeId, appInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reportChangeByUid(long changeId, int uid) {
|
public void reportChangeByUid(long changeId, int uid) {
|
||||||
checkCompatChangeLogPermission();
|
checkCompatChangeLogPermission();
|
||||||
reportChange(changeId, uid, ChangeReporter.STATE_LOGGED);
|
reportChangeInternal(changeId, uid, ChangeReporter.STATE_LOGGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reportChangeInternal(long changeId, int uid, int state) {
|
||||||
|
mChangeReporter.reportChange(uid, changeId, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -110,28 +108,6 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
return isChangeEnabledInternal(changeId, appInfo);
|
return isChangeEnabledInternal(changeId, appInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal version of the above method, without logging. Does not perform costly permission
|
|
||||||
* check.
|
|
||||||
* TODO(b/167551701): Remove this method and add 'loggability' as a changeid property.
|
|
||||||
*/
|
|
||||||
public boolean isChangeEnabledInternalNoLogging(long changeId, ApplicationInfo appInfo) {
|
|
||||||
return mCompatConfig.isChangeEnabled(changeId, appInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal version of {@link #isChangeEnabled(long, ApplicationInfo)}. Does not perform costly
|
|
||||||
* permission check.
|
|
||||||
*/
|
|
||||||
public boolean isChangeEnabledInternal(long changeId, ApplicationInfo appInfo) {
|
|
||||||
boolean enabled = isChangeEnabledInternalNoLogging(changeId, appInfo);
|
|
||||||
if (appInfo != null) {
|
|
||||||
reportChange(changeId, appInfo.uid,
|
|
||||||
enabled ? ChangeReporter.STATE_ENABLED : ChangeReporter.STATE_DISABLED);
|
|
||||||
}
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChangeEnabledByPackageName(long changeId, String packageName,
|
public boolean isChangeEnabledByPackageName(long changeId, String packageName,
|
||||||
@UserIdInt int userId) {
|
@UserIdInt int userId) {
|
||||||
@@ -140,7 +116,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
if (appInfo == null) {
|
if (appInfo == null) {
|
||||||
return mCompatConfig.willChangeBeEnabled(changeId, packageName);
|
return mCompatConfig.willChangeBeEnabled(changeId, packageName);
|
||||||
}
|
}
|
||||||
return isChangeEnabled(changeId, appInfo);
|
return isChangeEnabledInternal(changeId, appInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -152,81 +128,82 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
}
|
}
|
||||||
boolean enabled = true;
|
boolean enabled = true;
|
||||||
for (String packageName : packages) {
|
for (String packageName : packages) {
|
||||||
enabled = enabled && isChangeEnabledByPackageName(changeId, packageName,
|
enabled &= isChangeEnabledByPackageName(changeId, packageName,
|
||||||
UserHandle.getUserId(uid));
|
UserHandle.getUserId(uid));
|
||||||
}
|
}
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a listener for change state overrides. Only one listener per change is allowed.
|
* Internal version of the above method, without logging.
|
||||||
*
|
*
|
||||||
* <p>{@code listener.onCompatChange(String)} method is guaranteed to be called with
|
* <p>Does not perform costly permission check.
|
||||||
* packageName before the app is killed upon an override change. The state of a change is not
|
* TODO(b/167551701): Remove this method and add 'loggability' as a changeid property.
|
||||||
* guaranteed to change when {@code listener.onCompatChange(String)} is called.
|
|
||||||
*
|
|
||||||
* @param changeId to get updates for
|
|
||||||
* @param listener the listener that will be called upon a potential change for package.
|
|
||||||
* @throws IllegalStateException if a listener was already registered for changeId
|
|
||||||
* @returns {@code true} if a change with changeId was already known, or (@code false}
|
|
||||||
* otherwise.
|
|
||||||
*/
|
*/
|
||||||
public boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
|
public boolean isChangeEnabledInternalNoLogging(long changeId, ApplicationInfo appInfo) {
|
||||||
return mCompatConfig.registerListener(changeId, listener);
|
return mCompatConfig.isChangeEnabled(changeId, appInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal version of {@link #isChangeEnabled(long, ApplicationInfo)}.
|
||||||
|
*
|
||||||
|
* <p>Does not perform costly permission check.
|
||||||
|
*/
|
||||||
|
public boolean isChangeEnabledInternal(long changeId, ApplicationInfo appInfo) {
|
||||||
|
boolean enabled = isChangeEnabledInternalNoLogging(changeId, appInfo);
|
||||||
|
if (appInfo != null) {
|
||||||
|
reportChangeInternal(changeId, appInfo.uid,
|
||||||
|
enabled ? ChangeReporter.STATE_ENABLED : ChangeReporter.STATE_DISABLED);
|
||||||
|
}
|
||||||
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
|
public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
|
||||||
throws RemoteException, SecurityException {
|
|
||||||
checkCompatChangeOverridePermission();
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.addOverrides(overrides, packageName);
|
mCompatConfig.addOverrides(overrides, packageName);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
|
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
|
||||||
throws RemoteException, SecurityException {
|
|
||||||
checkCompatChangeOverridePermission();
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.addOverrides(overrides, packageName);
|
mCompatConfig.addOverrides(overrides, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int enableTargetSdkChanges(String packageName, int targetSdkVersion)
|
public int enableTargetSdkChanges(String packageName, int targetSdkVersion) {
|
||||||
throws RemoteException, SecurityException {
|
|
||||||
checkCompatChangeOverridePermission();
|
checkCompatChangeOverridePermission();
|
||||||
int numChanges = mCompatConfig.enableTargetSdkChangesForPackage(packageName,
|
int numChanges =
|
||||||
targetSdkVersion);
|
mCompatConfig.enableTargetSdkChangesForPackage(packageName, targetSdkVersion);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
return numChanges;
|
return numChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int disableTargetSdkChanges(String packageName, int targetSdkVersion)
|
public int disableTargetSdkChanges(String packageName, int targetSdkVersion) {
|
||||||
throws RemoteException, SecurityException {
|
|
||||||
checkCompatChangeOverridePermission();
|
checkCompatChangeOverridePermission();
|
||||||
int numChanges = mCompatConfig.disableTargetSdkChangesForPackage(packageName,
|
int numChanges =
|
||||||
targetSdkVersion);
|
mCompatConfig.disableTargetSdkChangesForPackage(packageName, targetSdkVersion);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
return numChanges;
|
return numChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearOverrides(String packageName) throws RemoteException, SecurityException {
|
public void clearOverrides(String packageName) {
|
||||||
checkCompatChangeOverridePermission();
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.removePackageOverrides(packageName);
|
mCompatConfig.removePackageOverrides(packageName);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearOverridesForTest(String packageName)
|
public void clearOverridesForTest(String packageName) {
|
||||||
throws RemoteException, SecurityException {
|
|
||||||
checkCompatChangeOverridePermission();
|
checkCompatChangeOverridePermission();
|
||||||
mCompatConfig.removePackageOverrides(packageName);
|
mCompatConfig.removePackageOverrides(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clearOverride(long changeId, String packageName)
|
public boolean clearOverride(long changeId, String packageName) {
|
||||||
throws RemoteException, SecurityException {
|
|
||||||
checkCompatChangeOverridePermission();
|
checkCompatChangeOverridePermission();
|
||||||
boolean existed = mCompatConfig.removeOverride(changeId, packageName);
|
boolean existed = mCompatConfig.removeOverride(changeId, packageName);
|
||||||
killPackage(packageName);
|
killPackage(packageName);
|
||||||
@@ -247,18 +224,13 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompatibilityChangeInfo[] listUIChanges() {
|
public CompatibilityChangeInfo[] listUIChanges() {
|
||||||
return Arrays.stream(listAllChanges()).filter(
|
return Arrays.stream(listAllChanges()).filter(this::isShownInUI).toArray(
|
||||||
x -> isShownInUI(x)).toArray(CompatibilityChangeInfo[]::new);
|
CompatibilityChangeInfo[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Checks whether the change is known to the compat config. */
|
||||||
* Check whether the change is known to the compat config.
|
|
||||||
*
|
|
||||||
* @return {@code true} if the change is known.
|
|
||||||
*/
|
|
||||||
public boolean isKnownChangeId(long changeId) {
|
public boolean isKnownChangeId(long changeId) {
|
||||||
return mCompatConfig.isKnownChangeId(changeId);
|
return mCompatConfig.isKnownChangeId(changeId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -286,7 +258,9 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
|
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
checkCompatChangeReadAndLogPermission();
|
checkCompatChangeReadAndLogPermission();
|
||||||
mCompatConfig.dumpConfig(pw);
|
mCompatConfig.dumpConfig(pw);
|
||||||
}
|
}
|
||||||
@@ -298,7 +272,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears information stored about events reported on behalf of an app.
|
* Clears information stored about events reported on behalf of an app.
|
||||||
* To be called once upon app start or end. A second call would be a no-op.
|
*
|
||||||
|
* <p>To be called once upon app start or end. A second call would be a no-op.
|
||||||
*
|
*
|
||||||
* @param appInfo the app to reset
|
* @param appInfo the app to reset
|
||||||
*/
|
*/
|
||||||
@@ -311,13 +286,9 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
packageName, 0, userId, userId);
|
packageName, 0, userId, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportChange(long changeId, int uid, int state) {
|
|
||||||
mChangeReporter.reportChange(uid, changeId, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void killPackage(String packageName) {
|
private void killPackage(String packageName) {
|
||||||
int uid = LocalServices.getService(PackageManagerInternal.class).getPackageUid(packageName,
|
int uid = LocalServices.getService(PackageManagerInternal.class).getPackageUid(packageName,
|
||||||
0, UserHandle.myUserId());
|
0, UserHandle.myUserId());
|
||||||
|
|
||||||
if (uid < 0) {
|
if (uid < 0) {
|
||||||
Slog.w(TAG, "Didn't find package " + packageName + " on device.");
|
Slog.w(TAG, "Didn't find package " + packageName + " on device.");
|
||||||
@@ -325,21 +296,18 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Slog.d(TAG, "Killing package " + packageName + " (UID " + uid + ").");
|
Slog.d(TAG, "Killing package " + packageName + " (UID " + uid + ").");
|
||||||
killUid(UserHandle.getAppId(uid),
|
killUid(UserHandle.getAppId(uid));
|
||||||
UserHandle.USER_ALL, "PlatformCompat overrides");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void killUid(int appId, int userId, String reason) {
|
private void killUid(int appId) {
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
IActivityManager am = ActivityManager.getService();
|
IActivityManager am = ActivityManager.getService();
|
||||||
if (am != null) {
|
if (am != null) {
|
||||||
try {
|
am.killUid(appId, UserHandle.USER_ALL, "PlatformCompat overrides");
|
||||||
am.killUid(appId, userId, reason);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
/* ignore - same process */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
/* ignore - same process */
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
@@ -350,13 +318,12 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
if (Binder.getCallingUid() == SYSTEM_UID) {
|
if (Binder.getCallingUid() == SYSTEM_UID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE)
|
if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE) != PERMISSION_GRANTED) {
|
||||||
!= PERMISSION_GRANTED) {
|
|
||||||
throw new SecurityException("Cannot log compat change usage");
|
throw new SecurityException("Cannot log compat change usage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCompatChangeReadPermission() throws SecurityException {
|
private void checkCompatChangeReadPermission() {
|
||||||
// Don't check for permissions within the system process
|
// Don't check for permissions within the system process
|
||||||
if (Binder.getCallingUid() == SYSTEM_UID) {
|
if (Binder.getCallingUid() == SYSTEM_UID) {
|
||||||
return;
|
return;
|
||||||
@@ -367,7 +334,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCompatChangeOverridePermission() throws SecurityException {
|
private void checkCompatChangeOverridePermission() {
|
||||||
// Don't check for permissions within the system process
|
// Don't check for permissions within the system process
|
||||||
if (Binder.getCallingUid() == SYSTEM_UID) {
|
if (Binder.getCallingUid() == SYSTEM_UID) {
|
||||||
return;
|
return;
|
||||||
@@ -378,7 +345,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCompatChangeReadAndLogPermission() throws SecurityException {
|
private void checkCompatChangeReadAndLogPermission() {
|
||||||
checkCompatChangeReadPermission();
|
checkCompatChangeReadPermission();
|
||||||
checkCompatChangeLogPermission();
|
checkCompatChangeLogPermission();
|
||||||
}
|
}
|
||||||
@@ -391,16 +358,34 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (change.getEnableSinceTargetSdk() > 0) {
|
if (change.getEnableSinceTargetSdk() > 0) {
|
||||||
if (change.getEnableSinceTargetSdk() < sMinTargetSdk) {
|
return change.getEnableSinceTargetSdk() >= Build.VERSION_CODES.Q;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a listener for change state overrides.
|
||||||
|
*
|
||||||
|
* <p>Only one listener per change is allowed.
|
||||||
|
*
|
||||||
|
* <p>{@code listener.onCompatChange(String)} method is guaranteed to be called with
|
||||||
|
* packageName before the app is killed upon an override change. The state of a change is not
|
||||||
|
* guaranteed to change when {@code listener.onCompatChange(String)} is called.
|
||||||
|
*
|
||||||
|
* @param changeId to get updates for
|
||||||
|
* @param listener the listener that will be called upon a potential change for package
|
||||||
|
* @return {@code true} if a change with changeId was already known, or (@code false}
|
||||||
|
* otherwise
|
||||||
|
* @throws IllegalStateException if a listener was already registered for changeId
|
||||||
|
*/
|
||||||
|
public boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
|
||||||
|
return mCompatConfig.registerListener(changeId, listener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a broadcast receiver that listens for package install, replace or remove.
|
* Registers a broadcast receiver that listens for package install, replace or remove.
|
||||||
* @param context the context where the receiver should be registered.
|
*
|
||||||
|
* @param context the context where the receiver should be registered
|
||||||
*/
|
*/
|
||||||
public void registerPackageReceiver(Context context) {
|
public void registerPackageReceiver(Context context) {
|
||||||
final BroadcastReceiver receiver = new BroadcastReceiver() {
|
final BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||||
@@ -429,8 +414,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the observer for
|
* Registers the observer for
|
||||||
* {@link android.provider.Settings.Global#FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT}
|
* {@link android.provider.Settings.Global#FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT}.
|
||||||
*/
|
*/
|
||||||
public void registerContentObserver() {
|
public void registerContentObserver() {
|
||||||
mCompatConfig.registerContentObserver();
|
mCompatConfig.registerContentObserver();
|
||||||
|
|||||||
Reference in New Issue
Block a user