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

Commit edf1b37a authored by Charles Chen's avatar Charles Chen
Browse files

Fix testRegisterComponentCallbacksOnWindowContext flaky

This flakiness is due to race of config updates when WindowContext attaches to
DisplyArea.
This CL fixed it by:
1. Don't dispatch config updates to the client side when registering to
   DA. We have reported the value by the return value of
   #attachWindowContextToDisplayArea.
2. Use Handler#runWithScissors when attahing DA or DC. It can prevent
   WindowContext reports stale config values and also guarantee the order of
   onConfigurationChanged call.

Bug: 190019118
fixes: 228911504
Test: atest RegisterComponentCallbacksTest --iterations
Test: atest WindowContextTest WindowContextTests
Test: atest WindowMetricsWindowContextTests

Change-Id: I496d00bbfdc20b9bbf433d5d8ec65bf1f46d3dd3
parent 99b30edb
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -165,10 +165,11 @@ public abstract class WindowProviderService extends Service implements WindowPro
        }
    }

    // Suppress the lint because ths is overridden from Context.
    @SuppressLint("OnNameExpected")
    @Override
    // Suppress the lint because ths is overridden from Context.
    public @Nullable Object getSystemService(@NonNull String name) {
    @Nullable
    public Object getSystemService(@NonNull String name) {
        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        }
+4 −4
Original line number Diff line number Diff line
@@ -91,7 +91,6 @@ public class WindowTokenClient extends IWindowToken.Stub {
            throw new IllegalStateException("Context is already attached.");
        }
        mContextRef = new WeakReference<>(context);
        mConfiguration.setTo(context.getResources().getConfiguration());
        mShouldDumpConfigForIme = Build.IS_DEBUGGABLE
                && context instanceof AbstractInputMethodService;
    }
@@ -112,7 +111,8 @@ public class WindowTokenClient extends IWindowToken.Stub {
            if (configuration == null) {
                return false;
            }
            onConfigurationChanged(configuration, displayId, false /* shouldReportConfigChange */);
            mHandler.runWithScissors(() -> onConfigurationChanged(configuration, displayId,
                    false /* shouldReportConfigChange */), 0 /* timeout */);
            mAttachToWindowContainer = true;
            return true;
        } catch (RemoteException e) {
@@ -137,8 +137,8 @@ public class WindowTokenClient extends IWindowToken.Stub {
            if (configuration == null) {
                return false;
            }
            mHandler.post(() -> onConfigurationChanged(configuration, displayId,
                    false /* shouldReportConfigChange */));
            mHandler.runWithScissors(() -> onConfigurationChanged(configuration, displayId,
                    false /* shouldReportConfigChange */), 0 /* timeout */);
            mAttachToWindowContainer = true;
            return true;
        } catch (RemoteException e) {
+9 −2
Original line number Diff line number Diff line
@@ -637,13 +637,20 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
    }

    void registerConfigurationChangeListener(ConfigurationContainerListener listener) {
        registerConfigurationChangeListener(listener, true /* shouldDispatchConfig */);
    }

    void registerConfigurationChangeListener(ConfigurationContainerListener listener,
            boolean shouldDispatchConfig) {
        if (mChangeListeners.contains(listener)) {
            return;
        }
        mChangeListeners.add(listener);
        if (shouldDispatchConfig) {
            listener.onRequestedOverrideConfigurationChanged(mResolvedOverrideConfiguration);
            listener.onMergedOverrideConfigurationChanged(mMergedOverrideConfiguration);
        }
    }

    void unregisterConfigurationChangeListener(ConfigurationContainerListener listener) {
        mChangeListeners.remove(listener);
+9 −2
Original line number Diff line number Diff line
@@ -3747,14 +3747,21 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
    }

    void registerWindowContainerListener(WindowContainerListener listener) {
        registerWindowContainerListener(listener, true /* shouldPropConfig */);
    }

    void registerWindowContainerListener(WindowContainerListener listener,
            boolean shouldDispatchConfig) {
        if (mListeners.contains(listener)) {
            return;
        }
        mListeners.add(listener);
        // Also register to ConfigurationChangeListener to receive configuration changes.
        registerConfigurationChangeListener(listener);
        registerConfigurationChangeListener(listener, shouldDispatchConfig);
        if (shouldDispatchConfig) {
            listener.onDisplayChanged(getDisplayContent());
        }
    }

    void unregisterWindowContainerListener(WindowContainerListener listener) {
        mListeners.remove(listener);
+20 −3
Original line number Diff line number Diff line
@@ -68,6 +68,16 @@ class WindowContextListenerController {
    @VisibleForTesting
    final ArrayMap<IBinder, WindowContextListenerImpl> mListeners = new ArrayMap<>();

    /**
     * @see #registerWindowContainerListener(IBinder, WindowContainer, int, int, Bundle, boolean)
     */
    void registerWindowContainerListener(@NonNull IBinder clientToken,
            @NonNull WindowContainer<?> container, int ownerUid, @WindowType int type,
            @Nullable Bundle options) {
        registerWindowContainerListener(clientToken, container, ownerUid, type, options,
                true /* shouDispatchConfigWhenRegistering */);
    }

    /**
     * Registers the listener to a {@code container} which is associated with
     * a {@code clientToken}, which is a {@link android.window.WindowContext} representation. If the
@@ -80,15 +90,18 @@ class WindowContextListenerController {
     * @param ownerUid the caller UID
     * @param type the window type
     * @param options a bundle used to pass window-related options.
     * @param shouDispatchConfigWhenRegistering {@code true} to indicate the current
     *                {@code container}'s config will dispatch to the client side when
     *                registering the {@link WindowContextListenerImpl}
     */
    void registerWindowContainerListener(@NonNull IBinder clientToken,
            @NonNull WindowContainer<?> container, int ownerUid, @WindowType int type,
            @Nullable Bundle options) {
            @Nullable Bundle options, boolean shouDispatchConfigWhenRegistering) {
        WindowContextListenerImpl listener = mListeners.get(clientToken);
        if (listener == null) {
            listener = new WindowContextListenerImpl(clientToken, container, ownerUid, type,
                    options);
            listener.register();
            listener.register(shouDispatchConfigWhenRegistering);
        } else {
            listener.updateContainer(container);
        }
@@ -228,12 +241,16 @@ class WindowContextListenerController {
        }

        private void register() {
            register(true /* shouldDispatchConfig */);
        }

        private void register(boolean shouldDispatchConfig) {
            final IBinder token = mClientToken.asBinder();
            if (mDeathRecipient == null) {
                throw new IllegalStateException("Invalid client token: " + token);
            }
            mListeners.putIfAbsent(token, this);
            mContainer.registerWindowContainerListener(this);
            mContainer.registerWindowContainerListener(this, shouldDispatchConfig);
        }

        private void unregister() {
Loading