Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 688b3aea authored by Anna Trostanetski's avatar Anna Trostanetski Committed by Gerrit Code Review
Browse files

Merge "Make CompatConfig be package private."

parents 2cc5a852 f69bbe1a
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ interface IPlatformCompat
    boolean isChangeEnabledByUid(long changeId, int uid);

    /**
     * Add overrides to compatibility changes.
     * Add overrides to compatibility changes. 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.
@@ -142,7 +142,28 @@ interface IPlatformCompat
    void setOverrides(in CompatibilityChangeConfig overrides, in String packageName);

    /**
     * Revert overrides to compatibility changes.
     * Add overrides to compatibility changes. Doesn't 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.
     *
     */
    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.
     *
     * @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 clearOverride(long changeId, String packageName);

    /**
     * Revert overrides to compatibility changes. Kills the app to allow the changes to take effect.
     *
     * @param packageName The package name of the app whose overrides will be cleared.
     *
+2 −2
Original line number Diff line number Diff line
@@ -349,7 +349,6 @@ import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
import com.android.server.appop.AppOpsService;
import com.android.server.compat.CompatConfig;
import com.android.server.compat.PlatformCompat;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.firewall.IntentFirewall;
@@ -5049,8 +5048,9 @@ public class ActivityManagerService extends IActivityManager.Stub
            bindApplicationTimeMillis = SystemClock.elapsedRealtime();
            mAtmInternal.preBindApplication(app.getWindowProcessController());
            final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
            long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
            long[] disabledCompatChanges = {};
            if (mPlatformCompat != null) {
                disabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
                mPlatformCompat.resetReporting(app.info);
            }
            if (app.isolatedEntryPoint != null) {
+25 −29
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.app.usage.AppStandbyInfo;
import android.app.usage.ConfigurationStats;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageStatsManager;
import android.compat.Compatibility;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Context;
@@ -80,15 +81,17 @@ import android.os.UserManager;
import android.text.TextUtils;
import android.text.format.Time;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.DisplayMetrics;
import android.util.proto.ProtoOutputStream;
import android.view.Display;

import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.util.HexDump;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import com.android.server.compat.CompatConfig;
import com.android.server.compat.PlatformCompat;

import java.io.BufferedReader;
import java.io.File;
@@ -2868,56 +2871,49 @@ final class ActivityManagerShellCommand extends ShellCommand {
        return 0;
    }

    private void killPackage(String packageName, PrintWriter pw) throws RemoteException {
        int uid = mPm.getPackageUid(packageName, 0, mUserId);
        if (uid < 0) {
            // uid is negative if the package wasn't found.
            pw.println("Didn't find package " + packageName + " on device.");
        } else {
            pw.println("Killing package " + packageName + " (UID " + uid + ").");
            final long origId = Binder.clearCallingIdentity();
            mInterface.killUid(UserHandle.getAppId(uid),
                    UserHandle.USER_ALL, "killPackage");
            Binder.restoreCallingIdentity(origId);
        }
    }

    private int runCompat(PrintWriter pw) throws RemoteException {
        final CompatConfig config = CompatConfig.get();
        final PlatformCompat platformCompat = (PlatformCompat)
                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
        String toggleValue = getNextArgRequired();
        long changeId;
        String changeIdString = getNextArgRequired();
        try {
            changeId = Long.parseLong(changeIdString);
        } catch (NumberFormatException e) {
            changeId = config.lookupChangeId(changeIdString);
            changeId = platformCompat.lookupChangeId(changeIdString);
        }
        if (changeId == -1) {
            pw.println("Unknown or invalid change: '" + changeIdString + "'.");
            return -1;
        }
        String packageName = getNextArgRequired();
        switch (toggleValue) {
            case "enable":
                if (!config.addOverride(changeId, packageName, true)) {
                    pw.println("Warning! Change " + changeId + " is not known yet. Enabling it"
        if (!platformCompat.isKnownChangeId(changeId)) {
            pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it"
                    + " could have no effect.");
        }
        ArraySet<Long> enabled = new ArraySet<>();
        ArraySet<Long> disabled = new ArraySet<>();
        switch (toggleValue) {
            case "enable":
                enabled.add(changeId);
                pw.println("Enabled change " + changeId + " for " + packageName + ".");
                killPackage(packageName, pw);
                CompatibilityChangeConfig overrides =
                        new CompatibilityChangeConfig(
                                new Compatibility.ChangeConfig(enabled, disabled));
                platformCompat.setOverrides(overrides, packageName);
                return 0;
            case "disable":
                if (!config.addOverride(changeId, packageName, false)) {
                    pw.println("Warning! Change " + changeId + " is not known yet. Disabling it"
                            + " could have no effect.");
                }
                disabled.add(changeId);
                pw.println("Disabled change " + changeId + " for " + packageName + ".");
                killPackage(packageName, pw);
                overrides =
                        new CompatibilityChangeConfig(
                                new Compatibility.ChangeConfig(enabled, disabled));
                platformCompat.setOverrides(overrides, packageName);
                return 0;
            case "reset":
                if (config.removeOverride(changeId, packageName)) {
                if (platformCompat.clearOverride(changeId, packageName)) {
                    pw.println("Reset change " + changeId + " for " + packageName
                            + " to default value.");
                    killPackage(packageName, pw);
                } else {
                    pw.println("No override exists for changeId " + changeId + ".");
                }
+49 −35
Original line number Diff line number Diff line
@@ -43,13 +43,14 @@ import java.util.HashSet;
import java.util.Set;

import javax.xml.datatype.DatatypeConfigurationException;

/**
 * This class maintains state relating to platform compatibility changes.
 *
 * <p>It stores the default configuration for each change, and any per-package overrides that have
 * been configured.
 */
public final class CompatConfig {
final class CompatConfig {

    private static final String TAG = "CompatConfig";

@@ -61,13 +62,13 @@ public final class CompatConfig {
    private final LongSparseArray<CompatChange> mChanges = new LongSparseArray<>();

    @VisibleForTesting
    public CompatConfig() {
    CompatConfig() {
    }

    /**
     * @return The static instance of this class to be used within the system server.
     */
    public static CompatConfig get() {
    static CompatConfig get() {
        return sInstance;
    }

@@ -77,7 +78,7 @@ public final class CompatConfig {
     *
     * @param change The change to add. Any change with the same ID will be overwritten.
     */
    public void addChange(CompatChange change) {
    void addChange(CompatChange change) {
        synchronized (mChanges) {
            mChanges.put(change.getId(), change);
        }
@@ -92,7 +93,7 @@ public final class CompatConfig {
     * footprint: Every app process will store this array statically so we aim to reduce
     * overhead as much as possible.
     */
    public long[] getDisabledChanges(ApplicationInfo app) {
    long[] getDisabledChanges(ApplicationInfo app) {
        LongArray disabled = new LongArray();
        synchronized (mChanges) {
            for (int i = 0; i < mChanges.size(); ++i) {
@@ -113,7 +114,7 @@ public final class CompatConfig {
     * @param name Name of the change to look up
     * @return The change ID, or {@code -1} if no change with that name exists.
     */
    public long lookupChangeId(String name) {
    long lookupChangeId(String name) {
        synchronized (mChanges) {
            for (int i = 0; i < mChanges.size(); ++i) {
                if (TextUtils.equals(mChanges.valueAt(i).getName(), name)) {
@@ -132,7 +133,7 @@ public final class CompatConfig {
     * @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.
     */
    public boolean isChangeEnabled(long changeId, ApplicationInfo app) {
    boolean isChangeEnabled(long changeId, ApplicationInfo app) {
        synchronized (mChanges) {
            CompatChange c = mChanges.get(changeId);
            if (c == null) {
@@ -150,14 +151,15 @@ public final class CompatConfig {
     *
     * <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
     * @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.
     */
    public boolean addOverride(long changeId, String packageName, boolean enabled) {
    boolean addOverride(long changeId, String packageName, boolean enabled) {
        boolean alreadyKnown = true;
        synchronized (mChanges) {
            CompatChange c = mChanges.get(changeId);
@@ -171,6 +173,18 @@ public final class CompatConfig {
        return alreadyKnown;
    }

    /**
     * Check whether the change is known to the compat config.
     *
     * @return {@code true} if the change is known.
     */
    boolean isKnownChangeId(long changeId) {
        synchronized (mChanges) {
            CompatChange c = mChanges.get(changeId);
            return c != null;
        }
    }

    /**
     * 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
@@ -180,7 +194,7 @@ public final class CompatConfig {
     * @param packageName The app package name that was overridden.
     * @return {@code true} if an override existed;
     */
    public boolean removeOverride(long changeId, String packageName) {
    boolean removeOverride(long changeId, String packageName) {
        boolean overrideExists = false;
        synchronized (mChanges) {
            CompatChange c = mChanges.get(changeId);
@@ -191,6 +205,7 @@ public final class CompatConfig {
        }
        return overrideExists;
    }

    /**
     * Overrides the enabled state for a given change and app. This method is intended to be used
     * *only* for debugging purposes.
@@ -200,8 +215,7 @@ public final class CompatConfig {
     * @param overrides   list of overrides to default changes config.
     * @param packageName app for which the overrides will be applied.
     */
    public void addOverrides(
            CompatibilityChangeConfig overrides, String packageName) {
    void addOverrides(CompatibilityChangeConfig overrides, String packageName) {
        synchronized (mChanges) {
            for (Long changeId : overrides.enabledChanges()) {
                addOverride(changeId, packageName, true);
@@ -221,7 +235,7 @@ public final class CompatConfig {
     *
     * @param packageName The package for which the overrides should be purged.
     */
    public void removePackageOverrides(String packageName) {
    void removePackageOverrides(String packageName) {
        synchronized (mChanges) {
            for (int i = 0; i < mChanges.size(); ++i) {
                mChanges.valueAt(i).removePackageOverride(packageName);
@@ -234,7 +248,7 @@ public final class CompatConfig {
     *
     * @param pw The {@link PrintWriter} instance to which the information will be dumped.
     */
    public void dumpConfig(PrintWriter pw) {
    void dumpConfig(PrintWriter pw) {
        synchronized (mChanges) {
            if (mChanges.size() == 0) {
                pw.println("No compat overrides.");
@@ -255,7 +269,7 @@ public final class CompatConfig {
     * given app.
     */

    public CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
    CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
        Set<Long> enabled = new HashSet<>();
        Set<Long> disabled = new HashSet<>();
        synchronized (mChanges) {
@@ -276,7 +290,7 @@ public final class CompatConfig {
     *
     * @return An array of {@link CompatibilityChangeInfo} with the current changes.
     */
    public CompatibilityChangeInfo[] dumpChanges() {
    CompatibilityChangeInfo[] dumpChanges() {
        synchronized (mChanges) {
            CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()];
            for (int i = 0; i < mChanges.size(); ++i) {
+81 −0
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@

package com.android.server.compat;

import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import android.util.StatsLog;
@@ -106,12 +110,26 @@ public class PlatformCompat extends IPlatformCompat.Stub {
    @Override
    public void setOverrides(CompatibilityChangeConfig overrides, String packageName) {
        CompatConfig.get().addOverrides(overrides, packageName);
        killPackage(packageName);
    }

    @Override
    public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
        CompatConfig.get().addOverrides(overrides, packageName);
    }

    @Override
    public void clearOverrides(String packageName) {
        CompatConfig config = CompatConfig.get();
        config.removePackageOverrides(packageName);
        killPackage(packageName);
    }

    @Override
    public boolean clearOverride(long changeId, String packageName) {
        boolean existed = CompatConfig.get().removeOverride(changeId, packageName);
        killPackage(packageName);
        return existed;
    }

    @Override
@@ -124,6 +142,39 @@ public class PlatformCompat extends IPlatformCompat.Stub {
        return CompatConfig.get().dumpChanges();
    }

    /**
     * Check whether the change is known to the compat config.
     * @param changeId
     * @return {@code true} if the change is known.
     */
    public boolean isKnownChangeId(long changeId) {
        return CompatConfig.get().isKnownChangeId(changeId);

    }

    /**
     * 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.
     *
     * @param appInfo 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.
     */
    public long[] getDisabledChanges(ApplicationInfo appInfo) {
        return CompatConfig.get().getDisabledChanges(appInfo);
    }

    /**
     * Look 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.
     */
    public long lookupChangeId(String name) {
        return CompatConfig.get().lookupChangeId(name);
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
@@ -151,4 +202,34 @@ public class PlatformCompat extends IPlatformCompat.Stub {
    private void reportChange(long changeId, int uid, int state) {
        mChangeReporter.reportChange(uid, changeId, state);
    }

    private void killPackage(String packageName) {
        int uid = -1;
        try {
            uid = mContext.getPackageManager().getPackageUid(packageName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            Slog.w(TAG, "Didn't find package " + packageName + " on device.", e);
            return;
        }

        Slog.d(TAG, "Killing package " + packageName + " (UID " + uid + ").");
        killUid(UserHandle.getAppId(uid),
                UserHandle.USER_ALL, "PlatformCompat overrides");
    }

    private void killUid(int appId, int userId, String reason) {
        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 */
                }
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }
}