Merge "Refactor PlatformCompat and related files." am: 5d37ff2d33
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1553536 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I662e0813ca02ec8a0fa569a4afde2a7db00a9e6d
This commit is contained in:
@@ -22,17 +22,16 @@ import java.util.Map;
|
||||
|
||||
parcelable CompatibilityChangeConfig;
|
||||
parcelable CompatibilityChangeInfo;
|
||||
|
||||
/**
|
||||
* Platform private API for talking with the PlatformCompat service.
|
||||
*
|
||||
* <p> Should be used for gating and logging from non-app processes.
|
||||
* For app processes please use android.compat.Compatibility API.
|
||||
* <p>Should be used for gating and logging from non-app processes.
|
||||
*
|
||||
* <p>Note: for app processes please use {@code android.compat.Compatibility} API.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IPlatformCompat
|
||||
{
|
||||
interface IPlatformCompat {
|
||||
|
||||
/**
|
||||
* 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)},
|
||||
* 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 appInfo Representing the affected app.
|
||||
* @param changeId the ID of the compatibility change taking effect
|
||||
* @param appInfo representing the affected app
|
||||
* @throws SecurityException if logging is not allowed
|
||||
*/
|
||||
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)},
|
||||
* 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 userId The ID of the user that the operation is done for.
|
||||
* @param packageName The package name of the app in question.
|
||||
* @param changeId the ID of the compatibility change taking effect
|
||||
* @param userId the ID of the user that the operation is done for
|
||||
* @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.
|
||||
@@ -63,13 +64,14 @@ interface IPlatformCompat
|
||||
* <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.
|
||||
*
|
||||
* @param changeId The ID of the compatibility change taking effect.
|
||||
* @param uid The UID of the app in question.
|
||||
* @param changeId the ID of the compatibility change taking effect
|
||||
* @param uid the UID of the app in question
|
||||
* @throws SecurityException if logging is not allowed
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* <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
|
||||
* there is no need to call that method directly.
|
||||
*
|
||||
* @param changeId The ID of the compatibility change in question.
|
||||
* @param appInfo Representing the app in question.
|
||||
* @return {@code true} if the change is enabled for the current app.
|
||||
* @param changeId the ID of the compatibility change in question
|
||||
* @param appInfo representing the app in question
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <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
|
||||
* no need to call that method directly.
|
||||
*
|
||||
* @param changeId The ID of the compatibility change 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.
|
||||
* @return {@code true} if the change is enabled for the current app.
|
||||
* @param changeId the ID of the compatibility change 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
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <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
|
||||
* no need to call that method directly.
|
||||
*
|
||||
* @param changeId The ID of the compatibility change in question.
|
||||
* @param uid The UID of the app in question.
|
||||
* @return {@code true} if the change is enabled for the current app.
|
||||
* @param changeId the ID of the compatibility change in question
|
||||
* @param uid the UID of the app in question
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param packageName The package name of the app whose changes will be overridden.
|
||||
* <p>Kills the app to allow the changes to take effect.
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param packageName The package name of the app whose changes will be overridden.
|
||||
* <p>Does not kill the app, to be only used in tests.
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Removes an override previously added via {@link #setOverrides(CompatibilityChangeConfig,
|
||||
* 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.
|
||||
* Restores the default behaviour for the given change and app.
|
||||
*
|
||||
* @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;
|
||||
* <p>Kills the app to allow the changes to take effect.
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* Enable all compatibility changes which have enabledSinceTargetSdk ==
|
||||
* {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
|
||||
* changes to take effect.
|
||||
* Enables all compatibility changes that have enabledSinceTargetSdk ==
|
||||
* {@param targetSdkVersion} for an app, subject to the policy.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return The number of changes that were enabled.
|
||||
* @throws SecurityException if overriding changes is not permitted.
|
||||
*/
|
||||
int enableTargetSdkChanges(in String packageName, int targetSdkVersion);
|
||||
|
||||
/**
|
||||
* Disable all compatibility changes which have enabledAfterTargetSdk ==
|
||||
* {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
|
||||
* changes to take effect.
|
||||
* Disables all compatibility changes that have enabledAfterTargetSdk ==
|
||||
* {@param targetSdkVersion} for an app, subject to the policy.
|
||||
*
|
||||
* @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.
|
||||
* <p>Kills the app to allow the changes to take effect.
|
||||
*
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
* Get configs for an application.
|
||||
*
|
||||
* @param appInfo The application whose config will be returned.
|
||||
*
|
||||
* @return A {@link CompatibilityChangeConfig}, representing whether a change is enabled for
|
||||
* the given app or not.
|
||||
* @param appInfo the application whose config will be returned
|
||||
* @return a {@link CompatibilityChangeConfig}, representing whether a change is enabled for
|
||||
* the given app or not
|
||||
*/
|
||||
CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* List the compatibility changes that should be present in the UI.
|
||||
* Filters out certain changes like e.g. logging only.
|
||||
*
|
||||
* @return An array of {@link CompatChangeInfo}.
|
||||
*/
|
||||
* List the compatibility changes that should be present in the UI.
|
||||
* Filters out certain changes like e.g. logging only.
|
||||
*
|
||||
* @return an array of {@link CompatibilityChangeInfo}
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.compat.Compatibility.ChangeConfig;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Environment;
|
||||
import android.os.RemoteException;
|
||||
import android.text.TextUtils;
|
||||
import android.util.LongArray;
|
||||
import android.util.LongSparseArray;
|
||||
@@ -53,7 +52,7 @@ import java.util.Set;
|
||||
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
|
||||
* been configured.
|
||||
@@ -65,18 +64,38 @@ final class CompatConfig {
|
||||
@GuardedBy("mChanges")
|
||||
private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();
|
||||
|
||||
private OverrideValidatorImpl mOverrideValidator;
|
||||
private final OverrideValidatorImpl mOverrideValidator;
|
||||
|
||||
@VisibleForTesting
|
||||
CompatConfig(AndroidBuildClassifier androidBuildClassifier, Context context) {
|
||||
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
|
||||
* filesystem. This should be done at system startup time.
|
||||
* Adds a change.
|
||||
*
|
||||
* @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) {
|
||||
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
|
||||
* array is by default enabled for the app.
|
||||
* Retrieves the set of disabled changes for a given app.
|
||||
*
|
||||
* @param app The app in question
|
||||
* @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
|
||||
* overhead as much as possible.
|
||||
* <p>Any change ID not in the returned array is by default enabled for the app.
|
||||
*
|
||||
* <p>We use a primitive array to minimize memory footprint: every app process will store this
|
||||
* 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) {
|
||||
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
|
||||
* @return The change ID, or {@code -1} if no change with that name exists.
|
||||
* @param name name of the change to look up
|
||||
* @return the change ID, or {@code -1} if no change with that name exists
|
||||
*/
|
||||
long lookupChangeId(String name) {
|
||||
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 app App to check for
|
||||
* @param changeId the ID of the change in question
|
||||
* @param app app to check for
|
||||
* @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.
|
||||
*/
|
||||
@@ -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 packageName Package name to check for
|
||||
* @param changeId the ID of the change in question
|
||||
* @param packageName package name to check for
|
||||
* @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.
|
||||
*/
|
||||
@@ -165,22 +186,22 @@ final class CompatConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the enabled state for a given change and app. This method is intended to be used
|
||||
* *only* for debugging purposes, ultimately invoked either by an adb command, or from some
|
||||
* developer settings UI.
|
||||
* 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>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
|
||||
* if
|
||||
* this change is not known; it will only have any effect if any code in the
|
||||
* platform is gated on the ID given.
|
||||
* @param packageName The app package name to override the change for.
|
||||
* @param enabled If the change should be enabled or disabled.
|
||||
* @return {@code true} if the change existed before adding the override.
|
||||
* <p>Note: package overrides are not persistent and will be lost on system or runtime restart.
|
||||
*
|
||||
* @param changeId the ID of the change to be overridden. Note, this call will succeed even
|
||||
* if this change is not known; it will only have any effect if any code in
|
||||
* the platform is gated on the ID given.
|
||||
* @param packageName the app package name to override the change for
|
||||
* @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)
|
||||
throws SecurityException {
|
||||
boolean addOverride(long changeId, String packageName, boolean enabled) {
|
||||
boolean alreadyKnown = true;
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
|
||||
@@ -201,18 +222,14 @@ final class CompatConfig {
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Should only be able to override changes that "
|
||||
+ "are allowed or can be deferred.");
|
||||
+ "are allowed or can be deferred.");
|
||||
}
|
||||
invalidateCache();
|
||||
}
|
||||
return alreadyKnown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the change is known to the compat config.
|
||||
*
|
||||
* @return {@code true} if the change is known.
|
||||
*/
|
||||
/** Checks whether the change is known to the compat config. */
|
||||
boolean isKnownChangeId(long changeId) {
|
||||
synchronized (mChanges) {
|
||||
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
|
||||
* target sdk gated).
|
||||
* Returns the maximum SDK version for which this change can be opted in (or -1 if it is not
|
||||
* target SDK gated).
|
||||
*/
|
||||
int maxTargetSdkForChangeIdOptIn(long changeId) {
|
||||
synchronized (mChanges) {
|
||||
CompatChange c = mChanges.get(changeId);
|
||||
if (c == null) {
|
||||
return -1;
|
||||
}
|
||||
if (c.getEnableSinceTargetSdk() != -1) {
|
||||
if (c != null && c.getEnableSinceTargetSdk() != -1) {
|
||||
return c.getEnableSinceTargetSdk() - 1;
|
||||
}
|
||||
return -1;
|
||||
@@ -243,10 +257,7 @@ final class CompatConfig {
|
||||
boolean isLoggingOnly(long changeId) {
|
||||
synchronized (mChanges) {
|
||||
CompatChange c = mChanges.get(changeId);
|
||||
if (c == null) {
|
||||
return false;
|
||||
}
|
||||
return c.getLoggingOnly();
|
||||
return c != null && c.getLoggingOnly();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,24 +267,21 @@ final class CompatConfig {
|
||||
boolean isDisabled(long changeId) {
|
||||
synchronized (mChanges) {
|
||||
CompatChange c = mChanges.get(changeId);
|
||||
if (c == null) {
|
||||
return false;
|
||||
}
|
||||
return c.getDisabled();
|
||||
return c != null && c.getDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an override previously added via {@link #addOverride(long, String, boolean)}. This
|
||||
* restores the default behaviour for the given change and app, once any app processes have been
|
||||
* restarted.
|
||||
* Removes an override previously added via {@link #addOverride(long, String, boolean)}.
|
||||
*
|
||||
* @param changeId The ID of the change that was overridden.
|
||||
* @param packageName The app package name that was overridden.
|
||||
* <p>This 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
|
||||
* @param packageName the app package name that was overridden
|
||||
* @return {@code true} if an override existed;
|
||||
*/
|
||||
boolean removeOverride(long changeId, String packageName)
|
||||
throws SecurityException {
|
||||
boolean removeOverride(long changeId, String packageName) {
|
||||
boolean overrideExists = false;
|
||||
synchronized (mChanges) {
|
||||
CompatChange c = mChanges.get(changeId);
|
||||
@@ -299,13 +307,12 @@ final class CompatConfig {
|
||||
/**
|
||||
* 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 packageName app for which the overrides will be applied.
|
||||
* @param overrides list of overrides to default changes config
|
||||
* @param packageName app for which the overrides will be applied
|
||||
*/
|
||||
void addOverrides(CompatibilityChangeConfig overrides, String packageName)
|
||||
throws RemoteException, SecurityException {
|
||||
void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
|
||||
synchronized (mChanges) {
|
||||
for (Long changeId : overrides.enabledChanges()) {
|
||||
addOverride(changeId, packageName, true);
|
||||
@@ -324,9 +331,9 @@ final class CompatConfig {
|
||||
*
|
||||
* <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) {
|
||||
for (int i = 0; i < mChanges.size(); ++i) {
|
||||
CompatChange change = mChanges.valueAt(i);
|
||||
@@ -337,8 +344,7 @@ final class CompatConfig {
|
||||
}
|
||||
|
||||
private long[] getAllowedChangesSinceTargetSdkForPackage(String packageName,
|
||||
int targetSdkVersion)
|
||||
throws RemoteException {
|
||||
int targetSdkVersion) {
|
||||
LongArray allowed = new LongArray();
|
||||
synchronized (mChanges) {
|
||||
for (int i = 0; i < mChanges.size(); ++i) {
|
||||
@@ -348,7 +354,7 @@ final class CompatConfig {
|
||||
}
|
||||
OverrideAllowedState allowedState =
|
||||
mOverrideValidator.getOverrideAllowedState(change.getId(),
|
||||
packageName);
|
||||
packageName);
|
||||
if (allowedState.state == OverrideAllowedState.ALLOWED) {
|
||||
allowed.add(change.getId());
|
||||
}
|
||||
@@ -361,10 +367,9 @@ final class CompatConfig {
|
||||
* Enables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
|
||||
* {@param packageName}.
|
||||
*
|
||||
* @return The number of changes that were toggled.
|
||||
* @return the number of changes that were toggled
|
||||
*/
|
||||
int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
|
||||
throws RemoteException {
|
||||
int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) {
|
||||
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
||||
for (long changeId : changes) {
|
||||
addOverride(changeId, packageName, true);
|
||||
@@ -372,15 +377,13 @@ final class CompatConfig {
|
||||
return changes.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disables all changes with enabledSinceTargetSdk == {@param targetSdkVersion} for
|
||||
* {@param packageName}.
|
||||
*
|
||||
* @return The number of changes that were toggled.
|
||||
* @return the number of changes that were toggled
|
||||
*/
|
||||
int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
|
||||
throws RemoteException {
|
||||
int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion) {
|
||||
long[] changes = getAllowedChangesSinceTargetSdkForPackage(packageName, targetSdkVersion);
|
||||
for (long changeId : changes) {
|
||||
addOverride(changeId, packageName, false);
|
||||
@@ -425,7 +428,7 @@ final class CompatConfig {
|
||||
/**
|
||||
* 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) {
|
||||
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.
|
||||
* @return A {@link CompatibilityChangeConfig} which contains the compat config info for the
|
||||
* given app.
|
||||
* @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped
|
||||
*/
|
||||
|
||||
CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
|
||||
Set<Long> enabled = new HashSet<>();
|
||||
Set<Long> disabled = new HashSet<>();
|
||||
@@ -467,7 +467,7 @@ final class CompatConfig {
|
||||
/**
|
||||
* 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() {
|
||||
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) {
|
||||
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
|
||||
Slog.d(TAG, "No directory " + libraryDir + ", skipping");
|
||||
@@ -526,6 +510,7 @@ final class CompatConfig {
|
||||
private void invalidateCache() {
|
||||
ChangeIdStateCache.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rechecks all the existing overrides for a package.
|
||||
*/
|
||||
|
||||
@@ -63,45 +63,43 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
private final ChangeReporter mChangeReporter;
|
||||
private final CompatConfig mCompatConfig;
|
||||
|
||||
private static int sMinTargetSdk = Build.VERSION_CODES.Q;
|
||||
|
||||
public PlatformCompat(Context context) {
|
||||
mContext = context;
|
||||
mChangeReporter = new ChangeReporter(
|
||||
ChangeReporter.SOURCE_SYSTEM_SERVER);
|
||||
mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER);
|
||||
mCompatConfig = CompatConfig.create(new AndroidBuildClassifier(), mContext);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
PlatformCompat(Context context, CompatConfig compatConfig) {
|
||||
mContext = context;
|
||||
mChangeReporter = new ChangeReporter(
|
||||
ChangeReporter.SOURCE_SYSTEM_SERVER);
|
||||
mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER);
|
||||
mCompatConfig = compatConfig;
|
||||
|
||||
registerPackageReceiver(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportChange(long changeId, ApplicationInfo appInfo) {
|
||||
checkCompatChangeLogPermission();
|
||||
reportChange(changeId, appInfo.uid,
|
||||
ChangeReporter.STATE_LOGGED);
|
||||
reportChangeByUid(changeId, appInfo.uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportChangeByPackageName(long changeId, String packageName, int userId) {
|
||||
checkCompatChangeLogPermission();
|
||||
public void reportChangeByPackageName(long changeId, String packageName,
|
||||
@UserIdInt int userId) {
|
||||
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
|
||||
if (appInfo == null) {
|
||||
return;
|
||||
if (appInfo != null) {
|
||||
reportChangeByUid(changeId, appInfo.uid);
|
||||
}
|
||||
reportChange(changeId, appInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportChangeByUid(long changeId, int uid) {
|
||||
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
|
||||
@@ -110,28 +108,6 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
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
|
||||
public boolean isChangeEnabledByPackageName(long changeId, String packageName,
|
||||
@UserIdInt int userId) {
|
||||
@@ -140,7 +116,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
if (appInfo == null) {
|
||||
return mCompatConfig.willChangeBeEnabled(changeId, packageName);
|
||||
}
|
||||
return isChangeEnabled(changeId, appInfo);
|
||||
return isChangeEnabledInternal(changeId, appInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,81 +128,82 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
}
|
||||
boolean enabled = true;
|
||||
for (String packageName : packages) {
|
||||
enabled = enabled && isChangeEnabledByPackageName(changeId, packageName,
|
||||
enabled &= isChangeEnabledByPackageName(changeId, packageName,
|
||||
UserHandle.getUserId(uid));
|
||||
}
|
||||
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
|
||||
* 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.
|
||||
* @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.
|
||||
* <p>Does not perform costly permission check.
|
||||
* TODO(b/167551701): Remove this method and add 'loggability' as a changeid property.
|
||||
*/
|
||||
public boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
|
||||
return mCompatConfig.registerListener(changeId, listener);
|
||||
public boolean isChangeEnabledInternalNoLogging(long changeId, ApplicationInfo appInfo) {
|
||||
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
|
||||
public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
|
||||
throws RemoteException, SecurityException {
|
||||
public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
|
||||
checkCompatChangeOverridePermission();
|
||||
mCompatConfig.addOverrides(overrides, packageName);
|
||||
killPackage(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
|
||||
throws RemoteException, SecurityException {
|
||||
public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
|
||||
checkCompatChangeOverridePermission();
|
||||
mCompatConfig.addOverrides(overrides, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int enableTargetSdkChanges(String packageName, int targetSdkVersion)
|
||||
throws RemoteException, SecurityException {
|
||||
public int enableTargetSdkChanges(String packageName, int targetSdkVersion) {
|
||||
checkCompatChangeOverridePermission();
|
||||
int numChanges = mCompatConfig.enableTargetSdkChangesForPackage(packageName,
|
||||
targetSdkVersion);
|
||||
int numChanges =
|
||||
mCompatConfig.enableTargetSdkChangesForPackage(packageName, targetSdkVersion);
|
||||
killPackage(packageName);
|
||||
return numChanges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int disableTargetSdkChanges(String packageName, int targetSdkVersion)
|
||||
throws RemoteException, SecurityException {
|
||||
public int disableTargetSdkChanges(String packageName, int targetSdkVersion) {
|
||||
checkCompatChangeOverridePermission();
|
||||
int numChanges = mCompatConfig.disableTargetSdkChangesForPackage(packageName,
|
||||
targetSdkVersion);
|
||||
int numChanges =
|
||||
mCompatConfig.disableTargetSdkChangesForPackage(packageName, targetSdkVersion);
|
||||
killPackage(packageName);
|
||||
return numChanges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearOverrides(String packageName) throws RemoteException, SecurityException {
|
||||
public void clearOverrides(String packageName) {
|
||||
checkCompatChangeOverridePermission();
|
||||
mCompatConfig.removePackageOverrides(packageName);
|
||||
killPackage(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearOverridesForTest(String packageName)
|
||||
throws RemoteException, SecurityException {
|
||||
public void clearOverridesForTest(String packageName) {
|
||||
checkCompatChangeOverridePermission();
|
||||
mCompatConfig.removePackageOverrides(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearOverride(long changeId, String packageName)
|
||||
throws RemoteException, SecurityException {
|
||||
public boolean clearOverride(long changeId, String packageName) {
|
||||
checkCompatChangeOverridePermission();
|
||||
boolean existed = mCompatConfig.removeOverride(changeId, packageName);
|
||||
killPackage(packageName);
|
||||
@@ -247,18 +224,13 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
|
||||
@Override
|
||||
public CompatibilityChangeInfo[] listUIChanges() {
|
||||
return Arrays.stream(listAllChanges()).filter(
|
||||
x -> isShownInUI(x)).toArray(CompatibilityChangeInfo[]::new);
|
||||
return Arrays.stream(listAllChanges()).filter(this::isShownInUI).toArray(
|
||||
CompatibilityChangeInfo[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the change is known to the compat config.
|
||||
*
|
||||
* @return {@code true} if the change is known.
|
||||
*/
|
||||
/** Checks whether the change is known to the compat config. */
|
||||
public boolean isKnownChangeId(long changeId) {
|
||||
return mCompatConfig.isKnownChangeId(changeId);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +258,9 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
|
||||
@Override
|
||||
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();
|
||||
mCompatConfig.dumpConfig(pw);
|
||||
}
|
||||
@@ -298,7 +272,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@@ -311,13 +286,9 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
packageName, 0, userId, userId);
|
||||
}
|
||||
|
||||
private void reportChange(long changeId, int uid, int state) {
|
||||
mChangeReporter.reportChange(uid, changeId, state);
|
||||
}
|
||||
|
||||
private void killPackage(String packageName) {
|
||||
int uid = LocalServices.getService(PackageManagerInternal.class).getPackageUid(packageName,
|
||||
0, UserHandle.myUserId());
|
||||
0, UserHandle.myUserId());
|
||||
|
||||
if (uid < 0) {
|
||||
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 + ").");
|
||||
killUid(UserHandle.getAppId(uid),
|
||||
UserHandle.USER_ALL, "PlatformCompat overrides");
|
||||
killUid(UserHandle.getAppId(uid));
|
||||
}
|
||||
|
||||
private void killUid(int appId, int userId, String reason) {
|
||||
private void killUid(int appId) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
IActivityManager am = ActivityManager.getService();
|
||||
if (am != null) {
|
||||
try {
|
||||
am.killUid(appId, userId, reason);
|
||||
} catch (RemoteException e) {
|
||||
/* ignore - same process */
|
||||
}
|
||||
am.killUid(appId, UserHandle.USER_ALL, "PlatformCompat overrides");
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
/* ignore - same process */
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
@@ -350,13 +318,12 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
if (Binder.getCallingUid() == SYSTEM_UID) {
|
||||
return;
|
||||
}
|
||||
if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE)
|
||||
!= PERMISSION_GRANTED) {
|
||||
if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE) != PERMISSION_GRANTED) {
|
||||
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
|
||||
if (Binder.getCallingUid() == SYSTEM_UID) {
|
||||
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
|
||||
if (Binder.getCallingUid() == SYSTEM_UID) {
|
||||
return;
|
||||
@@ -378,7 +345,7 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCompatChangeReadAndLogPermission() throws SecurityException {
|
||||
private void checkCompatChangeReadAndLogPermission() {
|
||||
checkCompatChangeReadPermission();
|
||||
checkCompatChangeLogPermission();
|
||||
}
|
||||
@@ -391,16 +358,34 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
return false;
|
||||
}
|
||||
if (change.getEnableSinceTargetSdk() > 0) {
|
||||
if (change.getEnableSinceTargetSdk() < sMinTargetSdk) {
|
||||
return false;
|
||||
}
|
||||
return change.getEnableSinceTargetSdk() >= Build.VERSION_CODES.Q;
|
||||
}
|
||||
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.
|
||||
* @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) {
|
||||
final BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||
@@ -429,8 +414,8 @@ public class PlatformCompat extends IPlatformCompat.Stub {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the observer for
|
||||
* {@link android.provider.Settings.Global#FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT}
|
||||
* Registers the observer for
|
||||
* {@link android.provider.Settings.Global#FORCE_NON_DEBUGGABLE_FINAL_BUILD_FOR_COMPAT}.
|
||||
*/
|
||||
public void registerContentObserver() {
|
||||
mCompatConfig.registerContentObserver();
|
||||
|
||||
Reference in New Issue
Block a user