Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.systemui.wm; |
| 18 | |
| 19 | import android.animation.Animator; |
| 20 | import android.animation.AnimatorListenerAdapter; |
| 21 | import android.animation.ValueAnimator; |
Yunfan Chen | c02a5ac | 2020-06-16 01:52:41 +0000 | [diff] [blame] | 22 | import android.content.Context; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 23 | import android.content.res.Configuration; |
Tiger Huang | 227c665 | 2020-03-19 22:28:43 +0800 | [diff] [blame] | 24 | import android.graphics.Point; |
Tony Huang | d1cb440 | 2020-04-27 11:36:00 +0800 | [diff] [blame] | 25 | import android.graphics.Rect; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 26 | import android.os.Handler; |
| 27 | import android.os.RemoteException; |
Yunfan Chen | c02a5ac | 2020-06-16 01:52:41 +0000 | [diff] [blame] | 28 | import android.os.ServiceManager; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 29 | import android.util.Slog; |
| 30 | import android.util.SparseArray; |
| 31 | import android.view.IDisplayWindowInsetsController; |
| 32 | import android.view.InsetsSource; |
| 33 | import android.view.InsetsSourceControl; |
| 34 | import android.view.InsetsState; |
| 35 | import android.view.Surface; |
| 36 | import android.view.SurfaceControl; |
| 37 | import android.view.WindowInsets; |
| 38 | import android.view.animation.Interpolator; |
| 39 | import android.view.animation.PathInterpolator; |
| 40 | |
Yunfan Chen | c02a5ac | 2020-06-16 01:52:41 +0000 | [diff] [blame] | 41 | import com.android.internal.view.IInputMethodManager; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 42 | import com.android.systemui.TransactionPool; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 43 | import com.android.systemui.dagger.qualifiers.Main; |
| 44 | |
| 45 | import java.util.ArrayList; |
| 46 | |
| 47 | import javax.inject.Inject; |
| 48 | import javax.inject.Singleton; |
| 49 | |
| 50 | /** |
| 51 | * Manages IME control at the display-level. This occurs when IME comes up in multi-window mode. |
| 52 | */ |
| 53 | @Singleton |
Winson Chung | 95c9fca | 2020-01-22 09:48:40 -0800 | [diff] [blame] | 54 | public class DisplayImeController implements DisplayController.OnDisplaysChangedListener { |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 55 | private static final String TAG = "DisplayImeController"; |
| 56 | |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 57 | private static final boolean DEBUG = false; |
| 58 | |
Evan Rosky | 437a879 | 2020-06-19 18:17:34 -0700 | [diff] [blame] | 59 | // NOTE: All these constants came from InsetsController. |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 60 | public static final int ANIMATION_DURATION_SHOW_MS = 275; |
| 61 | public static final int ANIMATION_DURATION_HIDE_MS = 340; |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 62 | public static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 63 | private static final int DIRECTION_NONE = 0; |
| 64 | private static final int DIRECTION_SHOW = 1; |
| 65 | private static final int DIRECTION_HIDE = 2; |
Evan Rosky | 437a879 | 2020-06-19 18:17:34 -0700 | [diff] [blame] | 66 | private static final int FLOATING_IME_BOTTOM_INSET = -80; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 67 | |
| 68 | SystemWindows mSystemWindows; |
| 69 | final Handler mHandler; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 70 | final TransactionPool mTransactionPool; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 71 | |
| 72 | final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>(); |
| 73 | |
| 74 | final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>(); |
| 75 | |
| 76 | @Inject |
Winson Chung | 95c9fca | 2020-01-22 09:48:40 -0800 | [diff] [blame] | 77 | public DisplayImeController(SystemWindows syswin, DisplayController displayController, |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 78 | @Main Handler mainHandler, TransactionPool transactionPool) { |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 79 | mHandler = mainHandler; |
| 80 | mSystemWindows = syswin; |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 81 | mTransactionPool = transactionPool; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 82 | displayController.addDisplayWindowListener(this); |
| 83 | } |
| 84 | |
| 85 | @Override |
| 86 | public void onDisplayAdded(int displayId) { |
| 87 | // Add's a system-ui window-manager specifically for ime. This type is special because |
| 88 | // WM will defer IME inset handling to it in multi-window scenarious. |
| 89 | PerDisplay pd = new PerDisplay(displayId, |
| 90 | mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation()); |
| 91 | try { |
| 92 | mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, pd); |
| 93 | } catch (RemoteException e) { |
| 94 | Slog.w(TAG, "Unable to set insets controller on display " + displayId); |
| 95 | } |
| 96 | mImePerDisplay.put(displayId, pd); |
| 97 | } |
| 98 | |
| 99 | @Override |
| 100 | public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { |
| 101 | PerDisplay pd = mImePerDisplay.get(displayId); |
| 102 | if (pd == null) { |
| 103 | return; |
| 104 | } |
| 105 | if (mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation() |
| 106 | != pd.mRotation && isImeShowing(displayId)) { |
Tiger Huang | 227c665 | 2020-03-19 22:28:43 +0800 | [diff] [blame] | 107 | pd.startAnimation(true, false /* forceRestart */); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 108 | } |
| 109 | } |
| 110 | |
| 111 | @Override |
| 112 | public void onDisplayRemoved(int displayId) { |
| 113 | try { |
| 114 | mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, null); |
| 115 | } catch (RemoteException e) { |
| 116 | Slog.w(TAG, "Unable to remove insets controller on display " + displayId); |
| 117 | } |
| 118 | mImePerDisplay.remove(displayId); |
| 119 | } |
| 120 | |
| 121 | private boolean isImeShowing(int displayId) { |
| 122 | PerDisplay pd = mImePerDisplay.get(displayId); |
| 123 | if (pd == null) { |
| 124 | return false; |
| 125 | } |
| 126 | final InsetsSource imeSource = pd.mInsetsState.getSource(InsetsState.ITYPE_IME); |
| 127 | return imeSource != null && pd.mImeSourceControl != null && imeSource.isVisible(); |
| 128 | } |
| 129 | |
| 130 | private void dispatchPositionChanged(int displayId, int imeTop, |
| 131 | SurfaceControl.Transaction t) { |
| 132 | synchronized (mPositionProcessors) { |
| 133 | for (ImePositionProcessor pp : mPositionProcessors) { |
| 134 | pp.onImePositionChanged(displayId, imeTop, t); |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 139 | private void dispatchStartPositioning(int displayId, int hiddenTop, int shownTop, |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 140 | boolean show, SurfaceControl.Transaction t) { |
| 141 | synchronized (mPositionProcessors) { |
| 142 | for (ImePositionProcessor pp : mPositionProcessors) { |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 143 | pp.onImeStartPositioning(displayId, hiddenTop, shownTop, show, t); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 144 | } |
| 145 | } |
| 146 | } |
| 147 | |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 148 | private void dispatchEndPositioning(int displayId, boolean cancel, |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 149 | SurfaceControl.Transaction t) { |
| 150 | synchronized (mPositionProcessors) { |
| 151 | for (ImePositionProcessor pp : mPositionProcessors) { |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 152 | pp.onImeEndPositioning(displayId, cancel, t); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 153 | } |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | /** |
| 158 | * Adds an {@link ImePositionProcessor} to be called during ime position updates. |
| 159 | */ |
| 160 | public void addPositionProcessor(ImePositionProcessor processor) { |
| 161 | synchronized (mPositionProcessors) { |
| 162 | if (mPositionProcessors.contains(processor)) { |
| 163 | return; |
| 164 | } |
| 165 | mPositionProcessors.add(processor); |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * Removes an {@link ImePositionProcessor} to be called during ime position updates. |
| 171 | */ |
| 172 | public void removePositionProcessor(ImePositionProcessor processor) { |
| 173 | synchronized (mPositionProcessors) { |
| 174 | mPositionProcessors.remove(processor); |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | class PerDisplay extends IDisplayWindowInsetsController.Stub { |
| 179 | final int mDisplayId; |
| 180 | final InsetsState mInsetsState = new InsetsState(); |
| 181 | InsetsSourceControl mImeSourceControl = null; |
| 182 | int mAnimationDirection = DIRECTION_NONE; |
| 183 | ValueAnimator mAnimation = null; |
| 184 | int mRotation = Surface.ROTATION_0; |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 185 | boolean mImeShowing = false; |
Evan Rosky | af3d637 | 2020-05-14 19:01:11 -0700 | [diff] [blame] | 186 | final Rect mImeFrame = new Rect(); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 187 | |
| 188 | PerDisplay(int displayId, int initialRotation) { |
| 189 | mDisplayId = displayId; |
| 190 | mRotation = initialRotation; |
| 191 | } |
| 192 | |
| 193 | @Override |
| 194 | public void insetsChanged(InsetsState insetsState) { |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 195 | mHandler.post(() -> { |
| 196 | if (mInsetsState.equals(insetsState)) { |
| 197 | return; |
| 198 | } |
Tony Huang | d1cb440 | 2020-04-27 11:36:00 +0800 | [diff] [blame] | 199 | |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 200 | final InsetsSource newSource = insetsState.getSource(InsetsState.ITYPE_IME); |
| 201 | final Rect newFrame = newSource.getFrame(); |
| 202 | final Rect oldFrame = mInsetsState.getSource(InsetsState.ITYPE_IME).getFrame(); |
Tony Huang | d1cb440 | 2020-04-27 11:36:00 +0800 | [diff] [blame] | 203 | |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 204 | mInsetsState.set(insetsState, true /* copySources */); |
| 205 | if (mImeShowing && !newFrame.equals(oldFrame) && newSource.isVisible()) { |
| 206 | if (DEBUG) Slog.d(TAG, "insetsChanged when IME showing, restart animation"); |
| 207 | startAnimation(mImeShowing, true /* forceRestart */); |
| 208 | } |
| 209 | }); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 210 | } |
| 211 | |
| 212 | @Override |
| 213 | public void insetsControlChanged(InsetsState insetsState, |
| 214 | InsetsSourceControl[] activeControls) { |
| 215 | insetsChanged(insetsState); |
| 216 | if (activeControls != null) { |
| 217 | for (InsetsSourceControl activeControl : activeControls) { |
| 218 | if (activeControl == null) { |
| 219 | continue; |
| 220 | } |
| 221 | if (activeControl.getType() == InsetsState.ITYPE_IME) { |
Tiger Huang | 227c665 | 2020-03-19 22:28:43 +0800 | [diff] [blame] | 222 | mHandler.post(() -> { |
| 223 | final Point lastSurfacePosition = mImeSourceControl != null |
| 224 | ? mImeSourceControl.getSurfacePosition() : null; |
| 225 | mImeSourceControl = activeControl; |
| 226 | if (!activeControl.getSurfacePosition().equals(lastSurfacePosition) |
| 227 | && mAnimation != null) { |
| 228 | startAnimation(mImeShowing, true /* forceRestart */); |
| 229 | } |
| 230 | }); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 231 | } |
| 232 | } |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | @Override |
| 237 | public void showInsets(int types, boolean fromIme) { |
| 238 | if ((types & WindowInsets.Type.ime()) == 0) { |
| 239 | return; |
| 240 | } |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 241 | if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 242 | mHandler.post(() -> startAnimation(true /* show */, false /* forceRestart */)); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 243 | } |
| 244 | |
| 245 | @Override |
| 246 | public void hideInsets(int types, boolean fromIme) { |
| 247 | if ((types & WindowInsets.Type.ime()) == 0) { |
| 248 | return; |
| 249 | } |
Evan Rosky | fdc71c4 | 2020-03-13 18:23:08 -0700 | [diff] [blame] | 250 | if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 251 | mHandler.post(() -> startAnimation(false /* show */, false /* forceRestart */)); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | /** |
| 255 | * Sends the local visibility state back to window manager. Needed for legacy adjustForIme. |
| 256 | */ |
| 257 | private void setVisibleDirectly(boolean visible) { |
| 258 | mInsetsState.getSource(InsetsState.ITYPE_IME).setVisible(visible); |
| 259 | try { |
| 260 | mSystemWindows.mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState); |
| 261 | } catch (RemoteException e) { |
| 262 | } |
| 263 | } |
| 264 | |
Evan Rosky | af3d637 | 2020-05-14 19:01:11 -0700 | [diff] [blame] | 265 | private int imeTop(float surfaceOffset) { |
| 266 | return mImeFrame.top + (int) surfaceOffset; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 267 | } |
| 268 | |
Tiger Huang | 227c665 | 2020-03-19 22:28:43 +0800 | [diff] [blame] | 269 | private void startAnimation(final boolean show, final boolean forceRestart) { |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 270 | final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME); |
| 271 | if (imeSource == null || mImeSourceControl == null) { |
| 272 | return; |
| 273 | } |
Evan Rosky | af3d637 | 2020-05-14 19:01:11 -0700 | [diff] [blame] | 274 | // Set frame, but only if the new frame isn't empty -- this maintains continuity |
| 275 | final Rect newFrame = imeSource.getFrame(); |
Evan Rosky | 437a879 | 2020-06-19 18:17:34 -0700 | [diff] [blame] | 276 | mImeFrame.set(newFrame); |
| 277 | final boolean isFloating = newFrame.height() == 0; |
| 278 | if (isFloating) { |
| 279 | // This is likely a "floating" or "expanded" IME, so to get animations, just |
| 280 | // pretend the ime has some size just below the screen. |
Evan Rosky | af3d637 | 2020-05-14 19:01:11 -0700 | [diff] [blame] | 281 | mImeFrame.set(newFrame); |
Evan Rosky | 437a879 | 2020-06-19 18:17:34 -0700 | [diff] [blame] | 282 | final int floatingInset = (int) ( |
| 283 | mSystemWindows.mDisplayController.getDisplayLayout(mDisplayId).density() |
| 284 | * FLOATING_IME_BOTTOM_INSET); |
| 285 | mImeFrame.bottom -= floatingInset; |
Evan Rosky | af3d637 | 2020-05-14 19:01:11 -0700 | [diff] [blame] | 286 | } |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 287 | if (DEBUG) { |
| 288 | Slog.d(TAG, "Run startAnim show:" + show + " was:" |
| 289 | + (mAnimationDirection == DIRECTION_SHOW ? "SHOW" |
| 290 | : (mAnimationDirection == DIRECTION_HIDE ? "HIDE" : "NONE"))); |
| 291 | } |
| 292 | if (!forceRestart && (mAnimationDirection == DIRECTION_SHOW && show) |
| 293 | || (mAnimationDirection == DIRECTION_HIDE && !show)) { |
| 294 | return; |
| 295 | } |
| 296 | boolean seek = false; |
| 297 | float seekValue = 0; |
| 298 | if (mAnimation != null) { |
| 299 | if (mAnimation.isRunning()) { |
| 300 | seekValue = (float) mAnimation.getAnimatedValue(); |
Tiger Huang | ef8f9a2 | 2020-04-08 00:57:38 +0800 | [diff] [blame] | 301 | seek = true; |
| 302 | } |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 303 | mAnimation.cancel(); |
| 304 | } |
| 305 | final float defaultY = mImeSourceControl.getSurfacePosition().y; |
| 306 | final float x = mImeSourceControl.getSurfacePosition().x; |
| 307 | final float hiddenY = defaultY + mImeFrame.height(); |
| 308 | final float shownY = defaultY; |
| 309 | final float startY = show ? hiddenY : shownY; |
| 310 | final float endY = show ? shownY : hiddenY; |
| 311 | if (mAnimationDirection == DIRECTION_NONE && mImeShowing && show) { |
| 312 | // IME is already showing, so set seek to end |
| 313 | seekValue = shownY; |
| 314 | seek = true; |
| 315 | } |
| 316 | mAnimationDirection = show ? DIRECTION_SHOW : DIRECTION_HIDE; |
| 317 | mImeShowing = show; |
| 318 | mAnimation = ValueAnimator.ofFloat(startY, endY); |
| 319 | mAnimation.setDuration( |
| 320 | show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS); |
| 321 | if (seek) { |
| 322 | mAnimation.setCurrentFraction((seekValue - startY) / (endY - startY)); |
| 323 | } |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 324 | |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 325 | mAnimation.addUpdateListener(animation -> { |
| 326 | SurfaceControl.Transaction t = mTransactionPool.acquire(); |
| 327 | float value = (float) animation.getAnimatedValue(); |
| 328 | t.setPosition(mImeSourceControl.getLeash(), x, value); |
Evan Rosky | 437a879 | 2020-06-19 18:17:34 -0700 | [diff] [blame] | 329 | final float alpha = isFloating ? (value - hiddenY) / (shownY - hiddenY) : 1.f; |
| 330 | t.setAlpha(mImeSourceControl.getLeash(), alpha); |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 331 | dispatchPositionChanged(mDisplayId, imeTop(value), t); |
| 332 | t.apply(); |
| 333 | mTransactionPool.release(t); |
| 334 | }); |
| 335 | mAnimation.setInterpolator(INTERPOLATOR); |
| 336 | mAnimation.addListener(new AnimatorListenerAdapter() { |
| 337 | private boolean mCancelled = false; |
| 338 | @Override |
| 339 | public void onAnimationStart(Animator animation) { |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 340 | SurfaceControl.Transaction t = mTransactionPool.acquire(); |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 341 | t.setPosition(mImeSourceControl.getLeash(), x, startY); |
Evan Rosky | 437a879 | 2020-06-19 18:17:34 -0700 | [diff] [blame] | 342 | final float alpha = isFloating ? (startY - hiddenY) / (shownY - hiddenY) : 1.f; |
| 343 | t.setAlpha(mImeSourceControl.getLeash(), alpha); |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 344 | if (DEBUG) { |
| 345 | Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:" |
| 346 | + imeTop(hiddenY) + "->" + imeTop(shownY) |
| 347 | + " showing:" + (mAnimationDirection == DIRECTION_SHOW)); |
| 348 | } |
| 349 | dispatchStartPositioning(mDisplayId, imeTop(hiddenY), |
| 350 | imeTop(shownY), mAnimationDirection == DIRECTION_SHOW, |
| 351 | t); |
| 352 | if (mAnimationDirection == DIRECTION_SHOW) { |
| 353 | t.show(mImeSourceControl.getLeash()); |
| 354 | } |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 355 | t.apply(); |
Evan Rosky | af9f27c | 2020-02-18 18:58:35 +0000 | [diff] [blame] | 356 | mTransactionPool.release(t); |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 357 | } |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 358 | @Override |
| 359 | public void onAnimationCancel(Animator animation) { |
| 360 | mCancelled = true; |
| 361 | } |
| 362 | @Override |
| 363 | public void onAnimationEnd(Animator animation) { |
| 364 | if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled); |
| 365 | SurfaceControl.Transaction t = mTransactionPool.acquire(); |
| 366 | if (!mCancelled) { |
| 367 | t.setPosition(mImeSourceControl.getLeash(), x, endY); |
Evan Rosky | 437a879 | 2020-06-19 18:17:34 -0700 | [diff] [blame] | 368 | t.setAlpha(mImeSourceControl.getLeash(), 1.f); |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 369 | } |
| 370 | dispatchEndPositioning(mDisplayId, mCancelled, t); |
| 371 | if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) { |
| 372 | t.hide(mImeSourceControl.getLeash()); |
Yunfan Chen | c02a5ac | 2020-06-16 01:52:41 +0000 | [diff] [blame] | 373 | final IInputMethodManager imms = getImms(); |
| 374 | if (imms != null) { |
| 375 | try { |
| 376 | // Remove the IME surface to make the insets invisible for |
| 377 | // non-client controlled insets. |
| 378 | imms.removeImeSurface(); |
| 379 | } catch (RemoteException e) { |
| 380 | Slog.e(TAG, "Failed to remove IME surface.", e); |
| 381 | } |
| 382 | } |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 383 | } |
| 384 | t.apply(); |
| 385 | mTransactionPool.release(t); |
| 386 | |
| 387 | mAnimationDirection = DIRECTION_NONE; |
| 388 | mAnimation = null; |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 389 | } |
| 390 | }); |
Evan Rosky | 653a725 | 2020-05-28 17:12:26 -0700 | [diff] [blame] | 391 | if (!show) { |
| 392 | // When going away, queue up insets change first, otherwise any bounds changes |
| 393 | // can have a "flicker" of ime-provided insets. |
| 394 | setVisibleDirectly(false /* visible */); |
| 395 | } |
| 396 | mAnimation.start(); |
| 397 | if (show) { |
| 398 | // When showing away, queue up insets change last, otherwise any bounds changes |
| 399 | // can have a "flicker" of ime-provided insets. |
| 400 | setVisibleDirectly(true /* visible */); |
| 401 | } |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 402 | } |
| 403 | } |
| 404 | |
| 405 | /** |
| 406 | * Allows other things to synchronize with the ime position |
| 407 | */ |
| 408 | public interface ImePositionProcessor { |
| 409 | /** |
| 410 | * Called when the IME position is starting to animate. |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 411 | * |
| 412 | * @param hiddenTop The y position of the top of the IME surface when it is hidden. |
Yunfan Chen | c02a5ac | 2020-06-16 01:52:41 +0000 | [diff] [blame] | 413 | * @param shownTop The y position of the top of the IME surface when it is shown. |
| 414 | * @param showing {@code true} when we are animating from hidden to shown, {@code false} |
| 415 | * when animating from shown to hidden. |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 416 | */ |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 417 | default void onImeStartPositioning(int displayId, int hiddenTop, int shownTop, |
Winson Chung | 95c9fca | 2020-01-22 09:48:40 -0800 | [diff] [blame] | 418 | boolean showing, SurfaceControl.Transaction t) {} |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 419 | |
| 420 | /** |
| 421 | * Called when the ime position changed. This is expected to be a synchronous call on the |
| 422 | * animation thread. Operations can be added to the transaction to be applied in sync. |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 423 | * |
| 424 | * @param imeTop The current y position of the top of the IME surface. |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 425 | */ |
Winson Chung | 95c9fca | 2020-01-22 09:48:40 -0800 | [diff] [blame] | 426 | default void onImePositionChanged(int displayId, int imeTop, |
| 427 | SurfaceControl.Transaction t) {} |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 428 | |
| 429 | /** |
| 430 | * Called when the IME position is done animating. |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 431 | * |
| 432 | * @param cancel {@code true} if this was cancelled. This implies another start is coming. |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 433 | */ |
Evan Rosky | 9572920 | 2020-02-21 10:16:08 -0800 | [diff] [blame] | 434 | default void onImeEndPositioning(int displayId, boolean cancel, |
Winson Chung | 95c9fca | 2020-01-22 09:48:40 -0800 | [diff] [blame] | 435 | SurfaceControl.Transaction t) {} |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 436 | } |
Yunfan Chen | c02a5ac | 2020-06-16 01:52:41 +0000 | [diff] [blame] | 437 | |
| 438 | public IInputMethodManager getImms() { |
| 439 | return IInputMethodManager.Stub.asInterface( |
| 440 | ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); |
| 441 | } |
Evan Rosky | 8d782e0 | 2019-10-14 15:43:53 -0700 | [diff] [blame] | 442 | } |