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

Commit 57fccd61 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

Send broadcast to pkg installers on config change

Send a protected system broadcast to apps that hold
the INSTALL_PACKAGES permission whenever a change to
properties like locale or display density happens.

Receivers can be registered in the manifest, and a process
will be woken up to receive the broadcast.

This will happen rarely, since the configuration changes
eligible to trigger this broadcast are rare themselves.

Bug: 63918966
Test: manual

Change-Id: I817a51ea05f762e02561691825d57d643db7dc30
parent 1b6f5155
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -829,6 +829,7 @@ package android.content {
    field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
    field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
    field public static final deprecated java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
    field public static final java.lang.String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
    field public static final java.lang.String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
    field public static final java.lang.String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
    field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
+20 −0
Original line number Diff line number Diff line
@@ -2399,6 +2399,26 @@ public class Intent implements Parcelable, Cloneable {
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";

    /**
     * Broadcast Action: The current device {@link android.content.res.Configuration} has changed
     * such that the device may be eligible for the installation of additional configuration splits.
     * Configuration properties that can trigger this broadcast include locale and display density.
     *
     * <p class="note">
     * Unlike {@link #ACTION_CONFIGURATION_CHANGED}, you <em>can</em> receive this through
     * components declared in manifests. However, the receiver <em>must</em> hold the
     * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
     *
     * <p class="note">
     * This is a protected intent that can only be sent by the system.
     *
     * @hide
     */
    @SystemApi
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_SPLIT_CONFIGURATION_CHANGED =
            "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
    /**
     * Broadcast Action: The current device's locale has changed.
     *
+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@
    <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
    <protected-broadcast android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
    <protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
    <protected-broadcast android:name="android.intent.action.SPLIT_CONFIGURATION_CHANGED" />
    <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
    <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" />
    <protected-broadcast android:name="android.intent.action.BATTERY_LOW" />
+24 −3
Original line number Diff line number Diff line
@@ -21936,7 +21936,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        try {
            if (values != null) {
                changes = updateGlobalConfiguration(values, initLocale, persistent, userId,
                changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId,
                        deferResume);
            }
@@ -21954,8 +21954,16 @@ public class ActivityManagerService extends IActivityManager.Stub
        return kept;
    }
    /**
     * Returns true if this configuration change is interesting enough to send an
     * {@link Intent#ACTION_SPLIT_CONFIGURATION_CHANGED} broadcast.
     */
    private static boolean isSplitConfigurationChange(int configDiff) {
        return (configDiff & (ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_DENSITY)) != 0;
    }
    /** Update default (global) configuration and notify listeners about changes. */
    private int updateGlobalConfiguration(@NonNull Configuration values, boolean initLocale,
    private int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
            boolean persistent, int userId, boolean deferResume) {
        mTempConfig.setTo(getGlobalConfiguration());
        final int changes = mTempConfig.updateFrom(values);
@@ -22058,6 +22066,19 @@ public class ActivityManagerService extends IActivityManager.Stub
                    UserHandle.USER_ALL);
        }
        // Send a broadcast to PackageInstallers if the configuration change is interesting
        // for the purposes of installing additional splits.
        if (!initLocale && isSplitConfigurationChange(changes)) {
            intent = new Intent(Intent.ACTION_SPLIT_CONFIGURATION_CHANGED);
            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            // Typically only app stores will have this permission.
            String[] permissions = new String[] { android.Manifest.permission.INSTALL_PACKAGES };
            broadcastIntentLocked(null, null, intent, null, null, 0, null, null, permissions,
                    OP_NONE, null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
        }
        // Override configuration of the default display duplicates global config, so we need to
        // update it also. This will also notify WindowManager about changes.
        performDisplayOverrideConfigUpdate(mStackSupervisor.getConfiguration(), deferResume,
@@ -22130,7 +22151,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    // Override configuration of the default display duplicates global config, so
                    // we're calling global config update instead for default display. It will also
                    // apply the correct override config.
                    changes = updateGlobalConfiguration(values, false /* initLocale */,
                    changes = updateGlobalConfigurationLocked(values, false /* initLocale */,
                            false /* persistent */, UserHandle.USER_NULL /* userId */, deferResume);
                } else {
                    changes = performDisplayOverrideConfigUpdate(values, deferResume, displayId);