Loading core/java/android/app/ActivityThread.java +23 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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)) { Loading core/java/android/app/ConfigurationController.java +19 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading core/java/android/app/servertransaction/ClientTransactionItem.java +1 −0 Original line number Diff line number Diff line Loading @@ -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}. Loading core/java/android/app/servertransaction/ClientTransactionListenerController.java +95 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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() { Loading Loading @@ -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); } } core/java/android/app/servertransaction/TransactionExecutor.java +0 −57 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); } Loading Loading @@ -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 Loading
core/java/android/app/ActivityThread.java +23 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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)) { Loading
core/java/android/app/ConfigurationController.java +19 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading
core/java/android/app/servertransaction/ClientTransactionItem.java +1 −0 Original line number Diff line number Diff line Loading @@ -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}. Loading
core/java/android/app/servertransaction/ClientTransactionListenerController.java +95 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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() { Loading Loading @@ -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); } }
core/java/android/app/servertransaction/TransactionExecutor.java +0 −57 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); } Loading Loading @@ -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