Merge "Postpone IME show animation till IME is drawn in WM."
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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. */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user