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

Commit 13c14aab authored by Chris Li's avatar Chris Li Committed by Android (Google) Code Review
Browse files

Merge "Ensure onDisplayChanged is always triggered" into main

parents 6372e29a b8871190
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -2608,7 +2608,14 @@ public final class ActivityThread extends ClientTransactionHandler
                    break;
                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    final ClientTransactionListenerController controller =
                            ClientTransactionListenerController.getInstance();
                    controller.onClientTransactionStarted();
                    try {
                        mTransactionExecutor.execute(transaction);
                    } finally {
                        controller.onClientTransactionFinished();
                    }
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side
                        // instead of ClientLifecycleManager to avoid being cleared before this
@@ -6747,6 +6754,21 @@ public final class ActivityThread extends ClientTransactionHandler
    void handleActivityConfigurationChanged(@NonNull ActivityClientRecord r,
            @NonNull Configuration overrideConfig, int displayId,
            @NonNull ActivityWindowInfo activityWindowInfo, boolean alwaysReportChange) {
        final ClientTransactionListenerController controller =
                ClientTransactionListenerController.getInstance();
        final Context contextToUpdate = r.activity;
        controller.onContextConfigurationPreChanged(contextToUpdate);
        try {
            handleActivityConfigurationChangedInner(r, overrideConfig, displayId,
                    activityWindowInfo, alwaysReportChange);
        } finally {
            controller.onContextConfigurationPostChanged(contextToUpdate);
        }
    }

    private void handleActivityConfigurationChangedInner(@NonNull ActivityClientRecord r,
            @NonNull Configuration overrideConfig, int displayId,
            @NonNull ActivityWindowInfo activityWindowInfo, boolean alwaysReportChange) {
        synchronized (mPendingOverrideConfigs) {
            final Configuration pendingOverrideConfig = mPendingOverrideConfigs.get(r.token);
            if (overrideConfig.isOtherSeqNewer(pendingOverrideConfig)) {
+19 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.servertransaction.ClientTransactionListenerController;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.CompatibilityInfo;
@@ -145,6 +146,24 @@ class ConfigurationController {
     */
    void handleConfigurationChanged(@Nullable Configuration config,
            @Nullable CompatibilityInfo compat) {
        final ClientTransactionListenerController controller =
                ClientTransactionListenerController.getInstance();
        final Context contextToUpdate = ActivityThread.currentApplication();
        controller.onContextConfigurationPreChanged(contextToUpdate);
        try {
            handleConfigurationChangedInner(config, compat);
        } finally {
            controller.onContextConfigurationPostChanged(contextToUpdate);
        }
    }

    /**
     * Update the configuration to latest.
     * @param config The new configuration.
     * @param compat The new compatibility information.
     */
    private void handleConfigurationChangedInner(@Nullable Configuration config,
            @Nullable CompatibilityInfo compat) {
        int configDiff;
        boolean equivalent;

+1 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ public abstract class ClientTransactionItem implements BaseClientRequest, Parcel
        return true;
    }

    // TODO(b/260873529): cleanup
    /**
     * If this {@link ClientTransactionItem} is updating configuration, returns the {@link Context}
     * it is updating; otherwise, returns {@code null}.
+95 −7
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.app.servertransaction;

import static android.app.WindowConfiguration.areConfigurationsEqualForDisplay;

import static com.android.window.flags.Flags.activityWindowInfoFlag;
import static com.android.window.flags.Flags.bundleClientTransactionFlag;

@@ -24,8 +26,11 @@ import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityThread;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.display.DisplayManagerGlobal;
import android.os.IBinder;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.window.ActivityWindowInfo;

@@ -51,6 +56,15 @@ public class ClientTransactionListenerController {
    private final ArraySet<BiConsumer<IBinder, ActivityWindowInfo>>
            mActivityWindowInfoChangedListeners = new ArraySet<>();

    /**
     * Keeps track of the Context whose Configuration will get updated, mapping to the config before
     * the change.
     */
    private final ArrayMap<Context, Configuration> mContextToPreChangedConfigMap = new ArrayMap<>();

    /** Whether there is an {@link ClientTransaction} being executed. */
    private boolean mIsClientTransactionExecuting;

    /** Gets the singleton controller. */
    @NonNull
    public static ClientTransactionListenerController getInstance() {
@@ -126,18 +140,92 @@ public class ClientTransactionListenerController {
        }
    }

    /**
     * Called when receives a {@link ClientTransaction} that is updating display-related
     * window configuration.
     */
    public void onDisplayChanged(int displayId) {
        if (!bundleClientTransactionFlag()) {
    /** Called when starts executing a remote {@link ClientTransaction}. */
    public void onClientTransactionStarted() {
        mIsClientTransactionExecuting = true;
    }

    /** Called when finishes executing a remote {@link ClientTransaction}. */
    public void onClientTransactionFinished() {
        notifyDisplayManagerIfNeeded();
        mIsClientTransactionExecuting = false;
    }

    /** Called before updating the Configuration of the given {@code context}. */
    public void onContextConfigurationPreChanged(@NonNull Context context) {
        if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
            // Not enable for system server.
            return;
        }
        if (mContextToPreChangedConfigMap.containsKey(context)) {
            // There is an earlier change that hasn't been reported yet.
            return;
        }
        if (ActivityThread.isSystem()) {
        mContextToPreChangedConfigMap.put(context,
                new Configuration(context.getResources().getConfiguration()));
    }

    /** Called after updating the Configuration of the given {@code context}. */
    public void onContextConfigurationPostChanged(@NonNull Context context) {
        if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
            // Not enable for system server.
            return;
        }
        if (mIsClientTransactionExecuting) {
            // Wait until #onClientTransactionFinished to prevent it from triggering the same
            // #onDisplayChanged multiple times within the same ClientTransaction.
            return;
        }
        final Configuration preChangedConfig = mContextToPreChangedConfigMap.remove(context);
        if (preChangedConfig != null && shouldReportDisplayChange(context, preChangedConfig)) {
            onDisplayChanged(context.getDisplayId());
        }
    }

    /**
     * When {@link Configuration} is changed, we want to trigger display change callback as well,
     * because Display reads some fields from {@link Configuration}.
     */
    private void notifyDisplayManagerIfNeeded() {
        if (mContextToPreChangedConfigMap.isEmpty()) {
            return;
        }
        // Whether the configuration change should trigger DisplayListener#onDisplayChanged.
        try {
            // Calculate display ids that have config changed.
            final ArraySet<Integer> configUpdatedDisplayIds = new ArraySet<>();
            final int contextCount = mContextToPreChangedConfigMap.size();
            for (int i = 0; i < contextCount; i++) {
                final Context context = mContextToPreChangedConfigMap.keyAt(i);
                final Configuration preChangedConfig = mContextToPreChangedConfigMap.valueAt(i);
                if (shouldReportDisplayChange(context, preChangedConfig)) {
                    configUpdatedDisplayIds.add(context.getDisplayId());
                }
            }

            // Dispatch the display changed callbacks.
            final int displayCount = configUpdatedDisplayIds.size();
            for (int i = 0; i < displayCount; i++) {
                final int displayId = configUpdatedDisplayIds.valueAt(i);
                onDisplayChanged(displayId);
            }
        } finally {
            mContextToPreChangedConfigMap.clear();
        }
    }

    private boolean shouldReportDisplayChange(@NonNull Context context,
            @NonNull Configuration preChangedConfig) {
        final Configuration postChangedConfig = context.getResources().getConfiguration();
        return !areConfigurationsEqualForDisplay(postChangedConfig, preChangedConfig);
    }

    /**
     * Called when receives a {@link Configuration} changed event that is updating display-related
     * window configuration.
     */
    @VisibleForTesting
    public void onDisplayChanged(int displayId) {
        mDisplayManager.handleDisplayChangeFromWindowManager(displayId);
    }
}
+0 −57
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.app.servertransaction;

import static android.app.WindowConfiguration.areConfigurationsEqualForDisplay;
import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
@@ -32,17 +31,12 @@ import static android.app.servertransaction.TransactionExecutorHelper.shouldExcl
import static android.app.servertransaction.TransactionExecutorHelper.tId;
import static android.app.servertransaction.TransactionExecutorHelper.transactionToString;

import static com.android.window.flags.Flags.bundleClientTransactionFlag;

import android.annotation.NonNull;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.content.Context;
import android.content.res.Configuration;
import android.os.IBinder;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Slog;

@@ -63,12 +57,6 @@ public class TransactionExecutor {
    private final PendingTransactionActions mPendingActions = new PendingTransactionActions();
    private final TransactionExecutorHelper mHelper = new TransactionExecutorHelper();

    /**
     * Keeps track of the Context whose Configuration got updated within a transaction, mapping to
     * the config before the transaction.
     */
    private final ArrayMap<Context, Configuration> mContextToPreChangedConfigMap = new ArrayMap<>();

    /** Initialize an instance with transaction handler, that will execute all requested actions. */
    public TransactionExecutor(@NonNull ClientTransactionHandler clientTransactionHandler) {
        mTransactionHandler = clientTransactionHandler;
@@ -104,37 +92,6 @@ public class TransactionExecutor {
            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        }

        if (!mContextToPreChangedConfigMap.isEmpty()) {
            // Whether this transaction should trigger DisplayListener#onDisplayChanged.
            try {
                // Calculate display ids that have config changed.
                final ArraySet<Integer> configUpdatedDisplayIds = new ArraySet<>();
                final int contextCount = mContextToPreChangedConfigMap.size();
                for (int i = 0; i < contextCount; i++) {
                    final Context context = mContextToPreChangedConfigMap.keyAt(i);
                    final Configuration preTransactionConfig =
                            mContextToPreChangedConfigMap.valueAt(i);
                    final Configuration postTransactionConfig = context.getResources()
                            .getConfiguration();
                    if (!areConfigurationsEqualForDisplay(
                            postTransactionConfig, preTransactionConfig)) {
                        configUpdatedDisplayIds.add(context.getDisplayId());
                    }
                }

                // Dispatch the display changed callbacks.
                final ClientTransactionListenerController controller =
                        ClientTransactionListenerController.getInstance();
                final int displayCount = configUpdatedDisplayIds.size();
                for (int i = 0; i < displayCount; i++) {
                    final int displayId = configUpdatedDisplayIds.valueAt(i);
                    controller.onDisplayChanged(displayId);
                }
            } finally {
                mContextToPreChangedConfigMap.clear();
            }
        }

        mPendingActions.clear();
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
    }
@@ -214,20 +171,6 @@ public class TransactionExecutor {
            }
        }

        final boolean shouldTrackConfigUpdatedContext =
                // No configuration change for local transaction.
                !mTransactionHandler.isExecutingLocalTransaction()
                        && bundleClientTransactionFlag();
        final Context configUpdatedContext = shouldTrackConfigUpdatedContext
                ? item.getContextToUpdate(mTransactionHandler)
                : null;
        if (configUpdatedContext != null
                && !mContextToPreChangedConfigMap.containsKey(configUpdatedContext)) {
            // Keep track of the first pre-executed config of each changed Context.
            mContextToPreChangedConfigMap.put(configUpdatedContext,
                    new Configuration(configUpdatedContext.getResources().getConfiguration()));
        }

        item.execute(mTransactionHandler, mPendingActions);

        item.postExecute(mTransactionHandler, mPendingActions);
Loading