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

Commit 500a38fc authored by Tarandeep Singh's avatar Tarandeep Singh Committed by Taran Singh
Browse files

Postpone IME show animation till IME is drawn in WM.

With this change, we postpone IME show animation until IME layout is fully
drawn in WM.
Earlier, we were showing IME right after InputMethodService called
Window.show(), which didn't guarantee that layout draw was completed.

Fix: 139487540
Bug: 111084606
Test: Manually verified as follows:
     1: Kill IME process or restart system to make sure IME window isn't
     created.
     2. Tap on edit field to make sure IME shows-up first time.
Change-Id: I35f3fdca43e6bae598a08237ba724962d575cb80
parent 07795adc
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -3569,10 +3569,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            if (!calledWithValidTokenLocked(token)) {
                return;
            }
            if (!setVisible) {
                // Client hides the IME directly.
                if (mCurClient != null && mCurClient.client != null) {
                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
                            MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, mCurClient));
                }
            } else {
                // Send to window manager to show IME after IME layout finishes.
                mWindowManagerInternal.showImePostLayout(mLastImeTargetWindow);
            }
        }
    }

+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import android.view.InsetsSource;
import android.view.WindowInsets;

/**
 * Controller for IME inset source on the server. It's called provider as it provides the
 * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
 */
class ImeInsetsSourceProvider extends InsetsSourceProvider {

    private WindowState mCurImeTarget;
    private Runnable mShowImeRunner;
    private boolean mIsImeLayoutDrawn;

    ImeInsetsSourceProvider(InsetsSource source,
            InsetsStateController stateController, DisplayContent displayContent) {
        super(source, stateController, displayContent);
    }

    /**
     * Called when a layout pass has occurred.
     */
    void onPostLayout() {
        super.onPostLayout();

        if (mCurImeTarget != null
                && mCurImeTarget == mDisplayContent.mInputMethodTarget
                && mWin != null
                && mWin.isDrawnLw()
                && !mWin.mGivenInsetsPending) {
            mIsImeLayoutDrawn = true;
        }
    }

    /**
     * Called when Insets have been dispatched to client.
     */
    void onPostInsetsDispatched() {
        if (mIsImeLayoutDrawn && mShowImeRunner != null) {
            // Show IME if InputMethodService requested to be shown and it's layout has finished.
            mShowImeRunner.run();
            mIsImeLayoutDrawn = false;
            mShowImeRunner = null;
        }
    }

    /**
     * Called from {@link WindowManagerInternal#showImePostLayout} when {@link InputMethodService}
     * requests to show IME on {@param imeTarget}.
     * @param imeTarget imeTarget on which IME is displayed.
     */
    void scheduleShowImePostLayout(WindowState imeTarget) {
        mCurImeTarget = imeTarget;
        mShowImeRunner = () -> {
            // Target should still be the same.
            if (mCurImeTarget == mDisplayContent.mInputMethodTarget) {
                mDisplayContent.mInputMethodTarget.showInsets(
                        WindowInsets.Type.ime(), true /* fromIme */);
            }
            mCurImeTarget = null;
        };
    }

}
+4 −3
Original line number Diff line number Diff line
@@ -47,9 +47,11 @@ import java.io.PrintWriter;
 */
class InsetsSourceProvider {

    protected final DisplayContent mDisplayContent;
    protected final @NonNull InsetsSource mSource;
    protected WindowState mWin;

    private final Rect mTmpRect = new Rect();
    private final @NonNull InsetsSource mSource;
    private final DisplayContent mDisplayContent;
    private final InsetsStateController mStateController;
    private final InsetsSourceControl mFakeControl;
    private @Nullable InsetsSourceControl mControl;
@@ -57,7 +59,6 @@ class InsetsSourceProvider {
    private @Nullable InsetsControlTarget mFakeControlTarget;

    private @Nullable ControlAdapter mAdapter;
    private WindowState mWin;
    private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;

    /** The visibility override from the current controlling window. */
+13 −2
Original line number Diff line number Diff line
@@ -108,9 +108,19 @@ class InsetsStateController {
     * @return The provider of a specific type.
     */
    InsetsSourceProvider getSourceProvider(@InternalInsetType int type) {
        if (type == TYPE_IME) {
            return mProviders.computeIfAbsent(type,
                    key -> new ImeInsetsSourceProvider(
                            mState.getSource(key), this, mDisplayContent));
        } else {
            return mProviders.computeIfAbsent(type,
                    key -> new InsetsSourceProvider(mState.getSource(key), this, mDisplayContent));
        }
    }

    ImeInsetsSourceProvider getImeSourceProvider() {
        return (ImeInsetsSourceProvider) getSourceProvider(TYPE_IME);
    }

    /**
     * Called when a layout pass has occurred.
@@ -124,6 +134,7 @@ class InsetsStateController {
            mLastState.set(mState, true /* copySources */);
            notifyInsetsChanged();
        }
        getImeSourceProvider().onPostInsetsDispatched();
    }

    void onInsetsModified(WindowState windowState, InsetsState state) {
+7 −0
Original line number Diff line number Diff line
@@ -501,6 +501,13 @@ public abstract class WindowManagerInternal {
     */
    public abstract boolean shouldShowIme(int displayId);

    /**
     * Show IME on imeTargetWindow once IME has finished layout.
     *
     * @param imeTargetWindowToken token of the (IME target) window on which IME should be shown.
     */
    public abstract void showImePostLayout(IBinder imeTargetWindowToken);

    /**
     * Tell window manager about a package that should not be running with high refresh rate
     * setting until removeNonHighRefreshRatePackage is called for the same package.
Loading