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

Commit 7de701f8 authored by Brandon Liu's avatar Brandon Liu
Browse files

Allow Activities to handle configuration changes

Make CONFIG_ASSETS_PATHS to public to allow activity itself to handle
assets paths config changes.
Introduce CONFIG_RESOURCES_UNUSED for applications that do not use
Resources at all like games to disabled all activity restart triggered
by any kind of configuration change.
Adding aapt2 support to allow app to handle all kinds of config change
based on the targeting SDK for more general cases.
Adding Framework host tests to test against non activity restart after
building and enabling frro.

Bug: b/180625460
Flag: android.content.res.handle_all_config_changes
Test: Added unit and CTS tests and verified all affected tests passed
Change-Id: I816df3604149ed337974ace83aef20d3d3566338
parent 9df00b18
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -12040,6 +12040,7 @@ package android.content.pm {
    field public static final int COLOR_MODE_DEFAULT = 0; // 0x0
    field public static final int COLOR_MODE_HDR = 2; // 0x2
    field public static final int COLOR_MODE_WIDE_COLOR_GAMUT = 1; // 0x1
    field @FlaggedApi("android.content.res.handle_all_config_changes") public static final int CONFIG_ASSETS_PATHS = -2147483648; // 0x80000000
    field public static final int CONFIG_COLOR_MODE = 16384; // 0x4000
    field public static final int CONFIG_DENSITY = 4096; // 0x1000
    field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
@@ -12053,6 +12054,7 @@ package android.content.pm {
    field public static final int CONFIG_MNC = 2; // 0x2
    field public static final int CONFIG_NAVIGATION = 64; // 0x40
    field public static final int CONFIG_ORIENTATION = 128; // 0x80
    field @FlaggedApi("android.content.res.handle_all_config_changes") public static final int CONFIG_RESOURCES_UNUSED = 134217728; // 0x8000000
    field public static final int CONFIG_SCREEN_LAYOUT = 256; // 0x100
    field public static final int CONFIG_SCREEN_SIZE = 1024; // 0x400
    field public static final int CONFIG_SMALLEST_SCREEN_SIZE = 2048; // 0x800
+8 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
import static android.content.pm.ActivityInfo.CONFIG_RESOURCES_UNUSED;
import static android.content.res.Configuration.UI_MODE_TYPE_DESK;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -6520,6 +6521,13 @@ public final class ActivityThread extends ClientTransactionHandler
            return true;
        }

        if (android.content.res.Flags.handleAllConfigChanges()) {
            if ((handledConfigChanges & CONFIG_RESOURCES_UNUSED) != 0) {
                // Report the change if activities claim they do not use resources at all.
                return true;
            }
        }

        final int diffWithBucket = SizeConfigurationBuckets.filterDiff(publicDiff, currentConfig,
                newConfig, sizeBuckets);
        // Compare to the diff which filter the change without crossing size buckets with
+29 −2
Original line number Diff line number Diff line
@@ -941,6 +941,8 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
            CONFIG_COLOR_MODE,
            CONFIG_FONT_SCALE,
            CONFIG_GRAMMATICAL_GENDER,
            CONFIG_ASSETS_PATHS,
            CONFIG_RESOURCES_UNUSED,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Config {}
@@ -1060,8 +1062,8 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
     * can itself handle asset path changes.  Set from the {@link android.R.attr#configChanges}
     * attribute. This is not a core resource configuration, but a higher-level value, so its
     * constant starts at the high bits.
     * @hide We do not want apps handling this yet, but we do need some kind of bit for diffs.
     */
    @FlaggedApi(android.content.res.Flags.FLAG_HANDLE_ALL_CONFIG_CHANGES)
    public static final int CONFIG_ASSETS_PATHS = 0x80000000;
    /**
     * Bit in {@link #configChanges} that indicates that the activity
@@ -1088,6 +1090,30 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
     */
    public static final int CONFIG_FONT_WEIGHT_ADJUSTMENT = 0x10000000;

    /**
     * <p>This is probably not the constant you want, the resources compiler supports a less
     * dangerous version of it, 'allKnown', that only suppresses all currently existing
     * configuration change restarts depending on your target SDK rather than whatever the latest
     * SDK supports, allowing the application to work with resources on future Platform versions.
     *
     * <p>Bit in {@link #configChanges} that indicates that the activity doesn't use Android
     * Resources at all and doesn't need to be restarted on any configuration changes. This bit
     * disables all restarts for configuration dimensions available in the current target SDK as
     * well as dimensions introduced in future SDKs. Use it only if the activity doesn't need
     * anything from its resources, and doesn't depend on any libraries that may provide resources
     * and need to respond to configuration changes. When set,
     * {@link Activity#onConfigurationChanged(Configuration)} will be called instead of a restart,
     * and it’s up to the implementation to ensure that no stale resource values remain loaded
     * anywhere in the code.
     *
     * <p>This overrides all other bits, and this is recommended to be used individually.
     *
     * <p>This is not a core resource configuration, but a higher-level value, so its constant
     * starts at the high bits.
     */
    @FlaggedApi(android.content.res.Flags.FLAG_HANDLE_ALL_CONFIG_CHANGES)
    public static final int CONFIG_RESOURCES_UNUSED = 0x8000000;

    /** @hide
     * Unfortunately the constants for config changes in native code are
     * different from ActivityInfo. :(  Here are the values we should use for the
@@ -1640,7 +1666,8 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
     * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION},
     * {@link #CONFIG_ORIENTATION}, {@link #CONFIG_SCREEN_LAYOUT},
     * {@link #CONFIG_DENSITY}, {@link #CONFIG_LAYOUT_DIRECTION},
     * {@link #CONFIG_COLOR_MODE}, and {link #CONFIG_GRAMMATICAL_GENDER}.
     * {@link #CONFIG_COLOR_MODE}, {@link #CONFIG_GRAMMATICAL_GENDER},
     * {@link #CONFIG_ASSETS_PATHS}, and {@link #CONFIG_RESOURCES_UNUSED}.
     * Set from the {@link android.R.attr#configChanges} attribute.
     */
    public int configChanges;
+10 −0
Original line number Diff line number Diff line
@@ -56,3 +56,13 @@ flag {
    # This flag is read in ResourcesImpl at boot time.
    is_fixed_read_only: true
}

flag {
    name: "handle_all_config_changes"
    is_exported: true
    namespace: "resource_manager"
    description: "Feature flag for allowing activities to handle all kinds of configuration changes"
    bug: "180625460"
    # This flag is read at boot time.
    is_fixed_read_only: true
}
+7 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.inputmethodservice;

import static android.content.pm.ActivityInfo.CONFIG_RESOURCES_UNUSED;

import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -88,12 +90,16 @@ public final class ImsConfigurationTracker {
        if (!mInitialized) {
            return;
        }
        // Don't restart InputMethodService that claims it does not use resources at all.
        boolean neverReset = android.content.res.Flags.handleAllConfigChanges()
                && (mHandledConfigChanges & CONFIG_RESOURCES_UNUSED) != 0;

        final int diff = mLastKnownConfig != null
                ? mLastKnownConfig.diffPublicOnly(newConfig) : CONFIG_CHANGED;
        // If the new config is the same as the config this Service is already running with,
        // then don't bother calling resetStateForNewConfiguration.
        final int unhandledDiff = (diff & ~mHandledConfigChanges);
        if (unhandledDiff != 0) {
        if (unhandledDiff != 0 && !neverReset) {
            resetStateForNewConfigurationRunner.run();
        }
        if (diff != 0) {
Loading