Merge "IME to systemui"

This commit is contained in:
Evan Rosky
2020-01-08 22:28:40 +00:00
committed by Android (Google) Code Review
9 changed files with 550 additions and 10 deletions

View File

@@ -0,0 +1,48 @@
/**
* 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 android.view;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
/**
* Singular controller of insets to use when there isn't another obvious controller available.
* Specifically, this will take over insets control in multi-window.
* @hide
*/
oneway interface IDisplayWindowInsetsController {
/**
* @see IWindow#insetsChanged
*/
void insetsChanged(in InsetsState insetsState);
/**
* @see IWindow#insetsControlChanged
*/
void insetsControlChanged(in InsetsState insetsState, in InsetsSourceControl[] activeControls);
/**
* @see IWindow#showInsets
*/
void showInsets(int types, boolean fromIme);
/**
* @see IWindow#hideInsets
*/
void hideInsets(int types, boolean fromIme);
}

View File

@@ -35,6 +35,7 @@ import android.os.ParcelFileDescriptor;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IDockedStackListener;
import android.view.IDisplayWindowInsetsController;
import android.view.IDisplayWindowListener;
import android.view.IDisplayFoldListener;
import android.view.IDisplayWindowRotationController;
@@ -49,6 +50,7 @@ import android.view.IWindowSession;
import android.view.IWindowSessionCallback;
import android.view.KeyEvent;
import android.view.InputEvent;
import android.view.InsetsState;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.InputChannel;
@@ -711,4 +713,16 @@ interface IWindowManager
* @return true if the display was successfully mirrored.
*/
boolean mirrorDisplay(int displayId, out SurfaceControl outSurfaceControl);
/**
* When in multi-window mode, the provided displayWindowInsetsController will control insets
* animations.
*/
void setDisplayWindowInsetsController(
int displayId, in IDisplayWindowInsetsController displayWindowInsetsController);
/**
* Called when a remote process modifies insets on a display window container.
*/
void modifyDisplayWindowInsets(int displayId, in InsetsState state);
}

View File

@@ -121,6 +121,7 @@ import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.util.leak.LeakReporter;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.wm.DisplayImeController;
import com.android.systemui.wm.DisplayWindowController;
import com.android.systemui.wm.SystemWindows;
@@ -321,6 +322,7 @@ public class Dependency {
@Inject Lazy<StatusBar> mStatusBar;
@Inject Lazy<DisplayWindowController> mDisplayWindowController;
@Inject Lazy<SystemWindows> mSystemWindows;
@Inject Lazy<DisplayImeController> mDisplayImeController;
@Inject
public Dependency() {
@@ -509,6 +511,7 @@ public class Dependency {
mProviders.put(StatusBar.class, mStatusBar::get);
mProviders.put(DisplayWindowController.class, mDisplayWindowController::get);
mProviders.put(SystemWindows.class, mSystemWindows::get);
mProviders.put(DisplayImeController.class, mDisplayImeController::get);
// TODO(b/118592525): to support multi-display , we start to add something which is
// per-display, while others may be global. I think it's time to add

View File

@@ -0,0 +1,333 @@
/*
* 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.systemui.wm;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
import android.view.IDisplayWindowInsetsController;
import android.view.InsetsSource;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowInsets;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import com.android.systemui.dagger.qualifiers.Main;
import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Manages IME control at the display-level. This occurs when IME comes up in multi-window mode.
*/
@Singleton
public class DisplayImeController implements DisplayWindowController.DisplayWindowListener {
private static final String TAG = "DisplayImeController";
static final int ANIMATION_DURATION_SHOW_MS = 275;
static final int ANIMATION_DURATION_HIDE_MS = 340;
static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
private static final int DIRECTION_NONE = 0;
private static final int DIRECTION_SHOW = 1;
private static final int DIRECTION_HIDE = 2;
SystemWindows mSystemWindows;
final Handler mHandler;
final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>();
@Inject
DisplayImeController(SystemWindows syswin, DisplayWindowController displayController,
@Main Handler mainHandler) {
mHandler = mainHandler;
mSystemWindows = syswin;
displayController.addDisplayWindowListener(this);
}
@Override
public void onDisplayAdded(int displayId) {
// Add's a system-ui window-manager specifically for ime. This type is special because
// WM will defer IME inset handling to it in multi-window scenarious.
PerDisplay pd = new PerDisplay(displayId,
mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation());
try {
mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, pd);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to set insets controller on display " + displayId);
}
mImePerDisplay.put(displayId, pd);
}
@Override
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
PerDisplay pd = mImePerDisplay.get(displayId);
if (pd == null) {
return;
}
if (mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation()
!= pd.mRotation && isImeShowing(displayId)) {
pd.startAnimation(true);
}
}
@Override
public void onDisplayRemoved(int displayId) {
try {
mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, null);
} catch (RemoteException e) {
Slog.w(TAG, "Unable to remove insets controller on display " + displayId);
}
mImePerDisplay.remove(displayId);
}
private boolean isImeShowing(int displayId) {
PerDisplay pd = mImePerDisplay.get(displayId);
if (pd == null) {
return false;
}
final InsetsSource imeSource = pd.mInsetsState.getSource(InsetsState.ITYPE_IME);
return imeSource != null && pd.mImeSourceControl != null && imeSource.isVisible();
}
private void dispatchPositionChanged(int displayId, int imeTop,
SurfaceControl.Transaction t) {
synchronized (mPositionProcessors) {
for (ImePositionProcessor pp : mPositionProcessors) {
pp.onImePositionChanged(displayId, imeTop, t);
}
}
}
private void dispatchStartPositioning(int displayId, int imeTop, int finalImeTop,
boolean show, SurfaceControl.Transaction t) {
synchronized (mPositionProcessors) {
for (ImePositionProcessor pp : mPositionProcessors) {
pp.onImeStartPositioning(displayId, imeTop, finalImeTop, show, t);
}
}
}
private void dispatchEndPositioning(int displayId, int imeTop, boolean show,
SurfaceControl.Transaction t) {
synchronized (mPositionProcessors) {
for (ImePositionProcessor pp : mPositionProcessors) {
pp.onImeEndPositioning(displayId, imeTop, show, t);
}
}
}
/**
* Adds an {@link ImePositionProcessor} to be called during ime position updates.
*/
public void addPositionProcessor(ImePositionProcessor processor) {
synchronized (mPositionProcessors) {
if (mPositionProcessors.contains(processor)) {
return;
}
mPositionProcessors.add(processor);
}
}
/**
* Removes an {@link ImePositionProcessor} to be called during ime position updates.
*/
public void removePositionProcessor(ImePositionProcessor processor) {
synchronized (mPositionProcessors) {
mPositionProcessors.remove(processor);
}
}
class PerDisplay extends IDisplayWindowInsetsController.Stub {
final int mDisplayId;
final InsetsState mInsetsState = new InsetsState();
InsetsSourceControl mImeSourceControl = null;
int mAnimationDirection = DIRECTION_NONE;
ValueAnimator mAnimation = null;
int mRotation = Surface.ROTATION_0;
PerDisplay(int displayId, int initialRotation) {
mDisplayId = displayId;
mRotation = initialRotation;
}
@Override
public void insetsChanged(InsetsState insetsState) {
if (mInsetsState.equals(insetsState)) {
return;
}
mInsetsState.set(insetsState, true /* copySources */);
}
@Override
public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) {
insetsChanged(insetsState);
if (activeControls != null) {
for (InsetsSourceControl activeControl : activeControls) {
if (activeControl == null) {
continue;
}
if (activeControl.getType() == InsetsState.ITYPE_IME) {
mImeSourceControl = activeControl;
}
}
}
}
@Override
public void showInsets(int types, boolean fromIme) {
if ((types & WindowInsets.Type.ime()) == 0) {
return;
}
startAnimation(true /* show */);
}
@Override
public void hideInsets(int types, boolean fromIme) {
if ((types & WindowInsets.Type.ime()) == 0) {
return;
}
startAnimation(false /* show */);
}
/**
* Sends the local visibility state back to window manager. Needed for legacy adjustForIme.
*/
private void setVisibleDirectly(boolean visible) {
mInsetsState.getSource(InsetsState.ITYPE_IME).setVisible(visible);
try {
mSystemWindows.mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState);
} catch (RemoteException e) {
}
}
private int imeTop(InsetsSource imeSource, float surfaceOffset) {
return imeSource.getFrame().top + (int) surfaceOffset;
}
private void startAnimation(final boolean show) {
final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME);
if (imeSource == null || mImeSourceControl == null) {
return;
}
if ((mAnimationDirection == DIRECTION_SHOW && show)
|| (mAnimationDirection == DIRECTION_HIDE && !show)) {
return;
}
if (mAnimationDirection != DIRECTION_NONE) {
mAnimation.end();
mAnimationDirection = DIRECTION_NONE;
}
mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE;
mHandler.post(() -> {
final float defaultY = mImeSourceControl.getSurfacePosition().y;
final float x = mImeSourceControl.getSurfacePosition().x;
final float startY = show ? defaultY + imeSource.getFrame().height() : defaultY;
final float endY = show ? defaultY : defaultY + imeSource.getFrame().height();
mAnimation = ValueAnimator.ofFloat(startY, endY);
mAnimation.setDuration(
show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS);
mAnimation.addUpdateListener(animation -> {
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
float value = (float) animation.getAnimatedValue();
t.setPosition(mImeSourceControl.getLeash(), x, value);
dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t);
t.apply();
t.close();
});
mAnimation.setInterpolator(INTERPOLATOR);
mAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
t.setPosition(mImeSourceControl.getLeash(), x, startY);
dispatchStartPositioning(mDisplayId, imeTop(imeSource, startY),
imeTop(imeSource, endY), mAnimationDirection == DIRECTION_SHOW,
t);
if (mAnimationDirection == DIRECTION_SHOW) {
t.show(mImeSourceControl.getLeash());
}
t.apply();
t.close();
}
@Override
public void onAnimationEnd(Animator animation) {
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
t.setPosition(mImeSourceControl.getLeash(), x, endY);
dispatchEndPositioning(mDisplayId, imeTop(imeSource, endY),
mAnimationDirection == DIRECTION_SHOW, t);
if (mAnimationDirection == DIRECTION_HIDE) {
t.hide(mImeSourceControl.getLeash());
}
t.apply();
t.close();
mAnimationDirection = DIRECTION_NONE;
mAnimation = null;
}
});
if (!show) {
// When going away, queue up insets change first, otherwise any bounds changes
// can have a "flicker" of ime-provided insets.
setVisibleDirectly(false /* visible */);
}
mAnimation.start();
if (show) {
// When showing away, queue up insets change last, otherwise any bounds changes
// can have a "flicker" of ime-provided insets.
setVisibleDirectly(true /* visible */);
}
});
}
}
/**
* Allows other things to synchronize with the ime position
*/
public interface ImePositionProcessor {
/**
* Called when the IME position is starting to animate.
*/
void onImeStartPositioning(int displayId, int imeTop, int finalImeTop, boolean showing,
SurfaceControl.Transaction t);
/**
* Called when the ime position changed. This is expected to be a synchronous call on the
* animation thread. Operations can be added to the transaction to be applied in sync.
*/
void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t);
/**
* Called when the IME position is done animating.
*/
void onImeEndPositioning(int displayId, int imeTop, boolean showing,
SurfaceControl.Transaction t);
}
}

View File

@@ -205,6 +205,7 @@ import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IDisplayWindowInsetsController;
import android.view.ISystemGestureExclusionListener;
import android.view.IWindow;
import android.view.InputChannel;
@@ -218,6 +219,7 @@ import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
@@ -570,6 +572,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
WindowState mInputMethodTarget;
InsetsControlTarget mInputMethodControlTarget;
/** If true hold off on modifying the animation layer of mInputMethodTarget */
boolean mInputMethodTargetWaitingAnim;
@@ -598,6 +602,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private final float mWindowCornerRadius;
private final SparseArray<ShellRoot> mShellRoots = new SparseArray<>();
RemoteInsetsControlTarget mRemoteInsetsControlTarget = null;
private final IBinder.DeathRecipient mRemoteInsetsDeath =
() -> {
synchronized (mWmService.mGlobalLock) {
mRemoteInsetsControlTarget = null;
}
};
private RootWindowContainer mRootWindowContainer;
@@ -1156,6 +1167,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mShellRoots.remove(windowType);
}
void setRemoteInsetsController(IDisplayWindowInsetsController controller) {
if (mRemoteInsetsControlTarget != null) {
mRemoteInsetsControlTarget.mRemoteInsetsController.asBinder().unlinkToDeath(
mRemoteInsetsDeath, 0);
mRemoteInsetsControlTarget = null;
}
if (controller != null) {
try {
controller.asBinder().linkToDeath(mRemoteInsetsDeath, 0);
mRemoteInsetsControlTarget = new RemoteInsetsControlTarget(controller);
} catch (RemoteException e) {
return;
}
}
}
/** Changes the display the input window token is housed on to this one. */
void reParentWindowToken(WindowToken token) {
final DisplayContent prevDc = token.getDisplayContent();
@@ -3383,6 +3410,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
boolean isImeAttachedToApp() {
return (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord != null
&& mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
// An activity with override bounds should be letterboxed inside its parent bounds,
// so it doesn't fill the screen.
&& mInputMethodTarget.mActivityRecord.matchParentBounds());
}
private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
return;
@@ -3391,7 +3426,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mInputMethodTarget = target;
mInputMethodTargetWaitingAnim = targetWaitingAnim;
assignWindowLayers(false /* setLayoutNeeded */);
mInsetsStateController.onImeTargetChanged(target);
mInputMethodControlTarget = computeImeControlTarget();
mInsetsStateController.onImeTargetChanged(mInputMethodControlTarget);
updateImeParent();
}
@@ -3416,11 +3452,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Attach it to app if the target is part of an app and such app is covering the entire
// screen. If it's not covering the entire screen the IME might extend beyond the apps
// bounds.
if (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord != null
&& mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
// An activity with override bounds should be letterboxed inside its parent bounds,
// so it doesn't fill the screen.
&& mInputMethodTarget.mActivityRecord.matchParentBounds()) {
if (isImeAttachedToApp()) {
return mInputMethodTarget.mActivityRecord.getSurfaceControl();
}
@@ -3428,6 +3460,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return mWindowContainers.getSurfaceControl();
}
/**
* Computes which control-target the IME should be attached to.
*/
@VisibleForTesting
InsetsControlTarget computeImeControlTarget() {
if (!isImeAttachedToApp() && mRemoteInsetsControlTarget != null) {
return mRemoteInsetsControlTarget;
}
// Otherwise, we just use the ime target
return mInputMethodTarget;
}
void setLayoutNeeded() {
if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
mLayoutNeeded = true;
@@ -6688,4 +6733,50 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
Context getDisplayUiContext() {
return mDisplayPolicy.getSystemUiContext();
}
class RemoteInsetsControlTarget implements InsetsControlTarget {
private final IDisplayWindowInsetsController mRemoteInsetsController;
RemoteInsetsControlTarget(IDisplayWindowInsetsController controller) {
mRemoteInsetsController = controller;
}
void notifyInsetsChanged() {
try {
mRemoteInsetsController.insetsChanged(
getInsetsStateController().getRawInsetsState());
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver inset state change", e);
}
}
@Override
public void notifyInsetsControlChanged() {
final InsetsStateController stateController = getInsetsStateController();
try {
mRemoteInsetsController.insetsControlChanged(stateController.getRawInsetsState(),
stateController.getControlsForDispatch(this));
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver inset state change", e);
}
}
@Override
public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
try {
mRemoteInsetsController.showInsets(types, fromIme);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver showInsets", e);
}
}
@Override
public void hideInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
try {
mRemoteInsetsController.hideInsets(types, fromIme);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver showInsets", e);
}
}
}
}

View File

@@ -69,7 +69,7 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
mShowImeRunner = () -> {
// Target should still be the same.
if (isImeTargetFromDisplayContentAndImeSame()) {
mDisplayContent.mInputMethodTarget.showInsets(
mDisplayContent.mInputMethodControlTarget.showInsets(
WindowInsets.Type.ime(), true /* fromIme */);
}
abortShowImePostLayout();

View File

@@ -210,7 +210,7 @@ class InsetsSourceProvider {
new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top));
}
boolean onInsetsModified(WindowState caller, InsetsSource modifiedSource) {
boolean onInsetsModified(InsetsControlTarget caller, InsetsSource modifiedSource) {
if (mControlTarget != caller || modifiedSource.isVisible() == mClientVisible) {
return false;
}

View File

@@ -91,6 +91,10 @@ class InsetsStateController {
return state;
}
InsetsState getRawInsetsState() {
return mState;
}
@Nullable InsetsSourceControl[] getControlsForDispatch(InsetsControlTarget target) {
ArrayList<Integer> controlled = mControlTargetTypeMap.get(target);
if (controlled == null) {
@@ -144,7 +148,7 @@ class InsetsStateController {
getImeSourceProvider().onPostInsetsDispatched();
}
void onInsetsModified(WindowState windowState, InsetsState state) {
void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
boolean changed = false;
for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
final InsetsSource source = state.sourceAt(i);
@@ -296,6 +300,9 @@ class InsetsStateController {
void notifyInsetsChanged() {
mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
if (mDisplayContent.mRemoteInsetsControlTarget != null) {
mDisplayContent.mRemoteInsetsControlTarget.notifyInsetsChanged();
}
}
void dump(String prefix, PrintWriter pw) {

View File

@@ -205,6 +205,7 @@ import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IDisplayFoldListener;
import android.view.IDisplayWindowInsetsController;
import android.view.IDisplayWindowListener;
import android.view.IDisplayWindowRotationController;
import android.view.IDockedStackListener;
@@ -3726,6 +3727,48 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
@Override
public void setDisplayWindowInsetsController(
int displayId, IDisplayWindowInsetsController insetsController) {
if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc == null) {
return;
}
dc.setRemoteInsetsController(insetsController);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
@Override
public void modifyDisplayWindowInsets(int displayId, InsetsState state) {
if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc == null || dc.mRemoteInsetsControlTarget == null) {
return;
}
dc.getInsetsStateController().onInsetsModified(
dc.mRemoteInsetsControlTarget, state);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
@Override
public int watchRotation(IRotationWatcher watcher, int displayId) {
final DisplayContent displayContent;
@@ -7314,7 +7357,8 @@ public class WindowManagerService extends IWindowManager.Stub
// If there was a pending IME show(), reset it as IME has been
// requested to be hidden.
dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
dc.mInputMethodTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
dc.mInputMethodControlTarget.hideInsets(WindowInsets.Type.ime(),
true /* fromIme */);
}
}
}