Merge "Postpone IME show animation till IME is drawn in WM."

This commit is contained in:
Taran Singh
2019-10-08 08:33:35 +00:00
committed by Android (Google) Code Review
6 changed files with 137 additions and 8 deletions

View File

@@ -3569,9 +3569,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (!calledWithValidTokenLocked(token)) {
return;
}
if (mCurClient != null && mCurClient.client != null) {
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, mCurClient));
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);
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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;
};
}
}

View File

@@ -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. */

View File

@@ -108,8 +108,18 @@ class InsetsStateController {
* @return The provider of a specific type.
*/
InsetsSourceProvider getSourceProvider(@InternalInsetType int type) {
return mProviders.computeIfAbsent(type,
key -> new InsetsSourceProvider(mState.getSource(key), this, mDisplayContent));
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);
}
/**
@@ -124,6 +134,7 @@ class InsetsStateController {
mLastState.set(mState, true /* copySources */);
notifyInsetsChanged();
}
getImeSourceProvider().onPostInsetsDispatched();
}
void onInsetsModified(WindowState windowState, InsetsState state) {

View File

@@ -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.

View File

@@ -7302,6 +7302,29 @@ public class WindowManagerService extends IWindowManager.Stub
return false;
}
@Override
public void showImePostLayout(IBinder imeTargetWindowToken) {
synchronized (mGlobalLock) {
final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
if (imeTarget == null) {
return;
}
final DisplayContent displayContent = imeTarget.getDisplayContent();
if (displayContent == null) {
Slog.w(TAG_WM, "Attempted to show IME on an IME target that does not exist: "
+ imeTarget.getName());
return;
}
if (displayContent.isUntrustedVirtualDisplay()) {
throw new SecurityException("Attempted to show IME on an untrusted "
+ "virtual display: " + displayContent.getDisplayId());
}
displayContent.getInsetsStateController().getImeSourceProvider()
.scheduleShowImePostLayout(imeTarget);
}
}
@Override
public boolean isUidAllowedOnDisplay(int displayId, int uid) {
if (displayId == Display.DEFAULT_DISPLAY) {