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

Commit 57d083db authored by Anna Trostanetski's avatar Anna Trostanetski Committed by android-build-merger
Browse files

Merge "Make CompatConfig be package private." am: 688b3aea

am: eec638da

Change-Id: I7c5fec41bd74e19bffcdcbb6a096197f365936a4
parents 592274ed eec638da
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);
        }
    }
}