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

Commit e03a3175 authored by Chris Li's avatar Chris Li
Browse files

Avoid redundant post message from WindowStateInsetsControlChangeItem

Bug: 339380439
Test: refactor, pass existing tests
Flag: com.android.window.flags.insets_control_changed_item
Change-Id: I7beaca1b2ee7fb3f72c4419dc8dc87e38709be5f
parent 85ae83ec
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -69,7 +69,12 @@ public class WindowStateInsetsControlChangeItem extends WindowStateTransactionIt
        }
        instance.setWindow(window);
        instance.mInsetsState = new InsetsState(insetsState, true /* copySources */);
        instance.mActiveControls = new InsetsSourceControl.Array(activeControls);
        instance.mActiveControls = new InsetsSourceControl.Array(
                activeControls, true /* copyControls */);
        // This source control is an extra copy if the client is not local. By setting
        // PARCELABLE_WRITE_RETURN_VALUE, the leash will be released at the end of
        // SurfaceControl.writeToParcel.
        instance.mActiveControls.setParcelableFlags(PARCELABLE_WRITE_RETURN_VALUE);

        return instance;
    }
+37 −5
Original line number Diff line number Diff line
@@ -269,22 +269,54 @@ public class InsetsSourceControl implements Parcelable {
        public Array() {
        }

        public Array(@NonNull Array other) {
            mControls = other.mControls;
        /**
         * @param copyControls whether or not to make a copy of the each {@link InsetsSourceControl}
         */
        public Array(@NonNull Array other, boolean copyControls) {
            setTo(other, copyControls);
        }

        public Array(Parcel in) {
        public Array(@NonNull Parcel in) {
            readFromParcel(in);
        }

        public void set(@Nullable InsetsSourceControl[] controls) {
        /** Updates the current Array to the given Array. */
        public void setTo(@NonNull Array other, boolean copyControls) {
            set(other.mControls, copyControls);
        }

        /** Updates the current controls to the given controls. */
        public void set(@Nullable InsetsSourceControl[] controls, boolean copyControls) {
            if (controls == null || !copyControls) {
                mControls = controls;
                return;
            }
            // Make a copy of the array.
            mControls = new InsetsSourceControl[controls.length];
            for (int i = mControls.length - 1; i >= 0; i--) {
                if (controls[i] != null) {
                    mControls[i] = new InsetsSourceControl(controls[i]);
                }
            }
        }

        /** Gets the controls. */
        public @Nullable InsetsSourceControl[] get() {
            return mControls;
        }

        /** Sets the given flags to all controls. */
        public void setParcelableFlags(int parcelableFlags) {
            if (mControls == null) {
                return;
            }
            for (InsetsSourceControl control : mControls) {
                if (control != null) {
                    control.setParcelableFlags(parcelableFlags);
                }
            }
        }

        @Override
        public int describeContents() {
            return 0;
+62 −42
Original line number Diff line number Diff line
@@ -2276,6 +2276,33 @@ public final class ViewRootImpl implements ViewParent,
        requestLayout();
    }
    /** Handles messages {@link #MSG_INSETS_CONTROL_CHANGED}. */
    private void handleInsetsControlChanged(@NonNull InsetsState insetsState,
            @NonNull InsetsSourceControl.Array activeControls) {
        final InsetsSourceControl[] controls = activeControls.get();
        if (mTranslator != null) {
            mTranslator.translateInsetsStateInScreenToAppWindow(insetsState);
            mTranslator.translateSourceControlsInScreenToAppWindow(controls);
        }
        // Deliver state change before control change, such that:
        // a) When gaining control, controller can compare with server state to evaluate
        // whether it needs to run animation.
        // b) When loosing control, controller can restore server state by taking last
        // dispatched state as truth.
        mInsetsController.onStateChanged(insetsState);
        if (mAdded) {
            mInsetsController.onControlsChanged(controls);
        } else if (controls != null) {
            for (InsetsSourceControl control : controls) {
                if (control != null) {
                    control.release(SurfaceControl::release);
                }
            }
        }
    }
    private final DisplayListener mDisplayListener = new DisplayListener() {
        @Override
        public void onDisplayChanged(int displayId) {
@@ -6591,24 +6618,11 @@ public final class ViewRootImpl implements ViewParent,
                    break;
                }
                case MSG_INSETS_CONTROL_CHANGED: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    // Deliver state change before control change, such that:
                    // a) When gaining control, controller can compare with server state to evaluate
                    // whether it needs to run animation.
                    // b) When loosing control, controller can restore server state by taking last
                    // dispatched state as truth.
                    mInsetsController.onStateChanged((InsetsState) args.arg1);
                    InsetsSourceControl[] controls = (InsetsSourceControl[]) args.arg2;
                    if (mAdded) {
                        mInsetsController.onControlsChanged(controls);
                    } else if (controls != null) {
                        for (InsetsSourceControl control : controls) {
                            if (control != null) {
                                control.release(SurfaceControl::release);
                            }
                        }
                    }
                    final SomeArgs args = (SomeArgs) msg.obj;
                    final InsetsState insetsState = (InsetsState) args.arg1;
                    final InsetsSourceControl.Array activeControls =
                            (InsetsSourceControl.Array) args.arg2;
                    handleInsetsControlChanged(insetsState, activeControls);
                    args.recycle();
                    break;
                }
@@ -9828,25 +9842,9 @@ public final class ViewRootImpl implements ViewParent,
        mHandler.sendMessage(msg);
    }
    private void dispatchInsetsControlChanged(InsetsState insetsState,
            InsetsSourceControl[] activeControls) {
        if (Binder.getCallingPid() == android.os.Process.myPid()) {
            insetsState = new InsetsState(insetsState, true /* copySource */);
            if (activeControls != null) {
                for (int i = activeControls.length - 1; i >= 0; i--) {
                    activeControls[i] = new InsetsSourceControl(activeControls[i]);
                }
            }
        }
        if (mTranslator != null) {
            mTranslator.translateInsetsStateInScreenToAppWindow(insetsState);
            mTranslator.translateSourceControlsInScreenToAppWindow(activeControls);
        }
        if (insetsState != null && insetsState.isSourceOrDefaultVisible(ID_IME, Type.ime())) {
            ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchInsetsControlChanged",
                    getInsetsController().getHost().getInputMethodManager(), null /* icProto */);
        }
        SomeArgs args = SomeArgs.obtain();
    private void dispatchInsetsControlChanged(@NonNull InsetsState insetsState,
            @NonNull InsetsSourceControl.Array activeControls) {
        final SomeArgs args = SomeArgs.obtain();
        args.arg1 = insetsState;
        args.arg2 = activeControls;
        mHandler.obtainMessage(MSG_INSETS_CONTROL_CHANGED, args).sendToTarget();
@@ -11289,9 +11287,9 @@ public final class ViewRootImpl implements ViewParent,
                return;
            }
            // The the parameters from WindowStateResizeItem are already copied.
            final boolean needCopy =
            final boolean needsCopy =
                    !isFromResizeItem && (Binder.getCallingPid() == Process.myPid());
            if (needCopy) {
            if (needsCopy) {
                insetsState = new InsetsState(insetsState, true /* copySource */);
                frames = new ClientWindowFrames(frames);
                mergedConfiguration = new MergedConfiguration(mergedConfiguration);
@@ -11307,10 +11305,32 @@ public final class ViewRootImpl implements ViewParent,
            final boolean isFromInsetsControlChangeItem = mIsFromTransactionItem;
            mIsFromTransactionItem = false;
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.dispatchInsetsControlChanged(insetsState, activeControls.get());
            if (viewAncestor == null) {
                return;
            }
            if (insetsState.isSourceOrDefaultVisible(ID_IME, Type.ime())) {
                ImeTracing.getInstance().triggerClientDump(
                        "ViewRootImpl#dispatchInsetsControlChanged",
                        viewAncestor.getInsetsController().getHost().getInputMethodManager(),
                        null /* icProto */);
            }
            // TODO(b/339380439): no need to post if the call is from InsetsControlChangeItem
            // If the UI thread is the same as the current thread that is dispatching
            // WindowStateInsetsControlChangeItem, then it can run directly.
            if (isFromInsetsControlChangeItem && viewAncestor.mHandler.getLooper()
                    == ActivityThread.currentActivityThread().getLooper()) {
                viewAncestor.handleInsetsControlChanged(insetsState, activeControls);
                return;
            }
            // The parameters from WindowStateInsetsControlChangeItem are already copied.
            final boolean needsCopy =
                    !isFromInsetsControlChangeItem && (Binder.getCallingPid() == Process.myPid());
            if (needsCopy) {
                insetsState = new InsetsState(insetsState, true /* copySource */);
                activeControls = new InsetsSourceControl.Array(
                        activeControls, true /* copyControls */);
            }
            viewAncestor.dispatchInsetsControlChanged(insetsState, activeControls);
        }
        @Override
+10 −19
Original line number Diff line number Diff line
@@ -1525,7 +1525,7 @@ public class WindowManagerService extends IWindowManager.Stub
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
            float[] outSizeCompatScale) {
        outActiveControls.set(null);
        outActiveControls.set(null, false /* copyControls */);
        int[] appOp = new int[1];
        final boolean isRoundedCornerOverlay = (attrs.privateFlags
                & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
@@ -2317,7 +2317,7 @@ public class WindowManagerService extends IWindowManager.Stub
            InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,
            Bundle outBundle, WindowRelayoutResult outRelayoutResult) {
        if (outActiveControls != null) {
            outActiveControls.set(null);
            outActiveControls.set(null, false /* copyControls */);
        }
        int result = 0;
        boolean configChanged = false;
@@ -2745,23 +2745,14 @@ public class WindowManagerService extends IWindowManager.Stub
    private void getInsetsSourceControls(WindowState win, InsetsSourceControl.Array outArray) {
        final InsetsSourceControl[] controls =
                win.getDisplayContent().getInsetsStateController().getControlsForDispatch(win);
        if (controls != null) {
            final int length = controls.length;
            final InsetsSourceControl[] outControls = new InsetsSourceControl[length];
            for (int i = 0; i < length; i++) {
        // We will leave the critical section before returning the leash to the client,
        // so we need to copy the leash to prevent others release the one that we are
        // about to return.
                if (controls[i] != null) {
        outArray.set(controls, true /* copyControls */);
        // This source control is an extra copy if the client is not local. By setting
        // PARCELABLE_WRITE_RETURN_VALUE, the leash will be released at the end of
        // SurfaceControl.writeToParcel.
                    outControls[i] = new InsetsSourceControl(controls[i]);
                    outControls[i].setParcelableFlags(PARCELABLE_WRITE_RETURN_VALUE);
                }
            }
            outArray.set(outControls);
        }
        outArray.setParcelableFlags(PARCELABLE_WRITE_RETURN_VALUE);
    }

    private void tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator) {
+2 −1
Original line number Diff line number Diff line
@@ -3820,7 +3820,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        final InsetsStateController stateController =
                getDisplayContent().getInsetsStateController();
        final InsetsState insetsState = getCompatInsetsState();
        mLastReportedActiveControls.set(stateController.getControlsForDispatch(this));
        mLastReportedActiveControls.set(stateController.getControlsForDispatch(this),
                false /* copyControls */);
        if (Flags.insetsControlChangedItem()) {
            getProcess().scheduleClientTransactionItem(WindowStateInsetsControlChangeItem.obtain(
                    mClient, insetsState, mLastReportedActiveControls));