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

Commit 4fc1e2c4 authored by Andrei Onea's avatar Andrei Onea
Browse files

Add option to toggle all changes

This change adds the ability of enabling and disabling all allowed
changes for a given package and target sdk through adb.

Bug: 149980515
Test: adb shell am enable-all 28 foo.bar && \
	adb shell dumpsys platform_compat
Test: adb shell am disable-all 28 foo.bar && \
	adb shell dumpsys platform_compat
Test: atest CompatConfigTest
Change-Id: Ia84d8e1162ea0b3f4c6afe87e63db56256236940
parent 0ab50898
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -163,6 +163,30 @@ interface IPlatformCompat
     */
    boolean clearOverride(long changeId, String packageName);

    /**
     * Enable 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.
     *
     * @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.
     */
    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.
     *
     * @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.
     */
    int disableTargetSdkChanges(in String packageName, int targetSdkVersion);

    /**
     * Revert overrides to compatibility changes. Kills the app to allow the changes to take effect.
     *
+68 −29
Original line number Diff line number Diff line
@@ -2875,13 +2875,22 @@ final class ActivityManagerShellCommand extends ShellCommand {
        final PlatformCompat platformCompat = (PlatformCompat)
                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
        String toggleValue = getNextArgRequired();
        if (toggleValue.equals("reset-all")) {
            final String packageName = getNextArgRequired();
            pw.println("Reset all changes for " + packageName + " to default value.");
            platformCompat.clearOverrides(packageName);
            return 0;
        boolean toggleAll = false;
        int targetSdkVersion = -1;
        long changeId = -1;

        if (toggleValue.endsWith("-all")) {
            toggleValue = toggleValue.substring(0, toggleValue.lastIndexOf("-all"));
            toggleAll = true;
            if (!toggleValue.equals("reset")) {
                try {
                    targetSdkVersion = Integer.parseInt(getNextArgRequired());
                } catch (NumberFormatException e) {
                    pw.println("Invalid targetSdkVersion!");
                    return -1;
                }
        long changeId;
            }
        } else {
            String changeIdString = getNextArgRequired();
            try {
                changeId = Long.parseLong(changeIdString);
@@ -2892,8 +2901,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
                pw.println("Unknown or invalid change: '" + changeIdString + "'.");
                return -1;
            }
        }
        String packageName = getNextArgRequired();
        if (!platformCompat.isKnownChangeId(changeId)) {
        if (!toggleAll && !platformCompat.isKnownChangeId(changeId)) {
            pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it"
                    + " could have no effect.");
        }
@@ -2902,22 +2912,49 @@ final class ActivityManagerShellCommand extends ShellCommand {
        try {
            switch (toggleValue) {
                case "enable":
                    if (toggleAll) {
                        int numChanges = platformCompat.enableTargetSdkChanges(packageName,
                                                                               targetSdkVersion);
                        if (numChanges == 0) {
                            pw.println("No changes were enabled.");
                            return -1;
                        }
                        pw.println("Enabled " + numChanges + " changes gated by targetSdkVersion "
                                + targetSdkVersion + " for " + packageName + ".");
                    } else {
                        enabled.add(changeId);
                        CompatibilityChangeConfig overrides =
                                new CompatibilityChangeConfig(
                                        new Compatibility.ChangeConfig(enabled, disabled));
                        platformCompat.setOverrides(overrides, packageName);
                        pw.println("Enabled change " + changeId + " for " + packageName + ".");
                    }
                    return 0;
                case "disable":
                    if (toggleAll) {
                        int numChanges = platformCompat.disableTargetSdkChanges(packageName,
                                                                                targetSdkVersion);
                        if (numChanges == 0) {
                            pw.println("No changes were disabled.");
                            return -1;
                        }
                        pw.println("Disabled " + numChanges + " changes gated by targetSdkVersion "
                                + targetSdkVersion + " for " + packageName + ".");
                    } else {
                        disabled.add(changeId);
                    overrides =
                        CompatibilityChangeConfig overrides =
                                new CompatibilityChangeConfig(
                                        new Compatibility.ChangeConfig(enabled, disabled));
                        platformCompat.setOverrides(overrides, packageName);
                        pw.println("Disabled change " + changeId + " for " + packageName + ".");
                    }
                    return 0;
                case "reset":
                    if (toggleAll) {
                        platformCompat.clearOverrides(packageName);
                        pw.println("Reset all changes for " + packageName + " to default value.");
                        return 0;
                    }
                    if (platformCompat.clearOverride(changeId, packageName)) {
                        pw.println("Reset change " + changeId + " for " + packageName
                                + " to default value.");
@@ -3247,6 +3284,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
            pw.println("         enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
            pw.println("            Toggles a change either by id or by name for <PACKAGE_NAME>.");
            pw.println("            It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
            pw.println("         enable-all|disable-all <targetSdkVersion> <PACKAGE_NAME");
            pw.println("            Toggles all changes that are gated by <targetSdkVersion>.");
            pw.println("         reset-all <PACKAGE_NAME>");
            pw.println("            Removes all existing overrides for all changes for ");
            pw.println("            <PACKAGE_NAME> (back to default behaviour).");
+57 −0
Original line number Diff line number Diff line
@@ -280,6 +280,63 @@ final class CompatConfig {
        }
    }

    private long[] getAllowedChangesAfterTargetSdkForPackage(String packageName,
                                                             int targetSdkVersion)
                    throws RemoteException {
        LongArray allowed = new LongArray();
        synchronized (mChanges) {
            for (int i = 0; i < mChanges.size(); ++i) {
                try {
                    CompatChange change = mChanges.valueAt(i);
                    if (change.getEnableAfterTargetSdk() != targetSdkVersion) {
                        continue;
                    }
                    OverrideAllowedState allowedState =
                            mOverrideValidator.getOverrideAllowedState(change.getId(),
                                                                       packageName);
                    if (allowedState.state == OverrideAllowedState.ALLOWED) {
                        allowed.add(change.getId());
                    }
                } catch (RemoteException e) {
                    // Should never occur, since validator is in the same process.
                    throw new RuntimeException("Unable to call override validator!", e);
                }
            }
        }
        return allowed.toArray();
    }

    /**
     * Enables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
     * {@param packageName}.
     *
     * @return The number of changes that were toggled.
     */
    int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
            throws RemoteException {
        long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
        for (long changeId : changes) {
            addOverride(changeId, packageName, true);
        }
        return changes.length;
    }


    /**
     * Disables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
     * {@param packageName}.
     *
     * @return The number of changes that were toggled.
     */
    int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
            throws RemoteException {
        long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
        for (long changeId : changes) {
            addOverride(changeId, packageName, false);
        }
        return changes.length;
    }

    boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
        boolean alreadyKnown = true;
        synchronized (mChanges) {
+20 −0
Original line number Diff line number Diff line
@@ -164,6 +164,26 @@ public class PlatformCompat extends IPlatformCompat.Stub {
        mCompatConfig.addOverrides(overrides, packageName);
    }

    @Override
    public int enableTargetSdkChanges(String packageName, int targetSdkVersion)
            throws RemoteException, SecurityException {
        checkCompatChangeOverridePermission();
        int numChanges = mCompatConfig.enableTargetSdkChangesForPackage(packageName,
                                                                        targetSdkVersion);
        killPackage(packageName);
        return numChanges;
    }

    @Override
    public int disableTargetSdkChanges(String packageName, int targetSdkVersion)
            throws RemoteException, SecurityException {
        checkCompatChangeOverridePermission();
        int numChanges = mCompatConfig.disableTargetSdkChangesForPackage(packageName,
                                                                         targetSdkVersion);
        killPackage(packageName);
        return numChanges;
    }

    @Override
    public void clearOverrides(String packageName) throws RemoteException, SecurityException {
        checkCompatChangeOverridePermission();
+43 −0
Original line number Diff line number Diff line
@@ -253,6 +253,49 @@ public class CompatConfigTest {
        assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
    }

    @Test
    public void testEnableTargetSdkChangesForPackage() throws Exception {
        CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                .addEnabledChangeWithId(1L)
                .addDisabledChangeWithId(2L)
                .addTargetSdkChangeWithId(3, 3L)
                .addTargetSdkChangeWithId(4, 4L)
                .build();
        ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
                .withPackageName("foo.bar")
                .withTargetSdk(2)
                .build();

        assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isFalse();
        assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();

        assertThat(compatConfig.enableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
        assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isTrue();
        assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
    }

    @Test
    public void testDisableTargetSdkChangesForPackage() throws Exception {
        CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                .addEnabledChangeWithId(1L)
                .addDisabledChangeWithId(2L)
                .addTargetSdkChangeWithId(3, 3L)
                .addTargetSdkChangeWithId(4, 4L)
                .build();
        ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
                .withPackageName("foo.bar")
                .withTargetSdk(2)
                .build();

        assertThat(compatConfig.enableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
        assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isTrue();
        assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();

        assertThat(compatConfig.disableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
        assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isFalse();
        assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
    }

    @Test
    public void testLookupChangeId() throws Exception {
        CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)