Loading core/java/android/view/InsetsAnimationControlImpl.java +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import static android.view.InsetsController.AnimationType; import static android.view.InsetsController.DEBUG; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_FLOATING; import static android.view.InsetsState.ISIDE_LEFT; Loading @@ -30,6 +31,7 @@ import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.Rect; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseSetArray; Loading @@ -52,6 +54,8 @@ import java.util.ArrayList; public class InsetsAnimationControlImpl implements WindowInsetsAnimationController, InsetsAnimationControlRunner { private static final String TAG = "InsetsAnimationCtrlImpl"; private final Rect mTmpFrame = new Rect(); private final WindowInsetsAnimationControlListener mListener; Loading Loading @@ -165,6 +169,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll */ public boolean applyChangeInsets(InsetsState state) { if (mCancelled) { if (DEBUG) Log.d(TAG, "applyChangeInsets canceled"); return false; } final Insets offset = Insets.subtract(mShownInsets, mPendingInsets); Loading @@ -186,9 +191,13 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll mCurrentAlpha = mPendingAlpha; mAnimation.setAlpha(mPendingAlpha); if (mFinished) { if (DEBUG) Log.d(TAG, String.format( "notifyFinished shown: %s, currentAlpha: %f, currentInsets: %s", mShownOnFinish, mCurrentAlpha, mCurrentInsets)); mController.notifyFinished(this, mShownOnFinish); releaseLeashes(); } if (DEBUG) Log.d(TAG, "Animation finished abruptly."); return mFinished; } Loading @@ -203,12 +212,15 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll @Override public void finish(boolean shown) { if (mCancelled || mFinished) { if (DEBUG) Log.d(TAG, "Animation already canceled or finished, not notifying."); return; } mShownOnFinish = shown; mFinished = true; setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */, true /* allowWhenFinished */); if (DEBUG) Log.d(TAG, "notify control request finished for types: " + mTypes); mListener.onFinished(this); } Loading @@ -225,6 +237,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll } mCancelled = true; mListener.onCancelled(mReadyDispatched ? this : null); if (DEBUG) Log.d(TAG, "notify Control request cancelled for types: " + mTypes); releaseLeashes(); } Loading core/java/android/view/InsetsAnimationThreadControlRunner.java +5 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package android.view; import static android.view.InsetsController.DEBUG; import static android.view.SyncRtSurfaceTransactionApplier.applyParams; import android.annotation.UiThread; import android.graphics.Rect; import android.os.Handler; import android.os.Trace; import android.util.Log; import android.util.SparseArray; import android.view.InsetsController.AnimationType; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; Loading @@ -37,6 +39,7 @@ import android.view.animation.Interpolator; */ public class InsetsAnimationThreadControlRunner implements InsetsAnimationControlRunner { private static final String TAG = "InsetsAnimThreadRunner"; private final InsetsAnimationControlImpl mControl; private final InsetsAnimationControlCallbacks mOuterCallbacks; private final Handler mMainThreadHandler; Loading Loading @@ -71,6 +74,7 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro @Override public void applySurfaceParams(SurfaceParams... params) { if (DEBUG) Log.d(TAG, "applySurfaceParams"); SurfaceControl.Transaction t = new SurfaceControl.Transaction(); for (int i = params.length - 1; i >= 0; i--) { SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i]; Loading @@ -82,6 +86,7 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro @Override public void releaseSurfaceControlFromRt(SurfaceControl sc) { if (DEBUG) Log.d(TAG, "releaseSurfaceControlFromRt"); // Since we don't push the SurfaceParams to the RT we can release directly sc.release(); } Loading core/java/android/view/InsetsController.java +58 −4 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.os.CancellationSignal; import android.os.Handler; import android.os.Trace; import android.util.ArraySet; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.view.InsetsSourceConsumer.ShowResult; Loading Loading @@ -152,8 +153,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation * Obtains {@link InputMethodManager} instance from host. */ InputMethodManager getInputMethodManager(); /** * @return title of the rootView, if it has one. * Note: this method is for debugging purposes only. */ @Nullable String getRootViewTitle(); } private static final String TAG = "InsetsController"; private static final int ANIMATION_DURATION_SHOW_MS = 275; private static final int ANIMATION_DURATION_HIDE_MS = 340; Loading @@ -171,6 +180,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private static final Interpolator FAST_OUT_LINEAR_IN_INTERPOLATOR = new PathInterpolator(0.4f, 0f, 1f, 1f); static final boolean DEBUG = false; static final boolean WARN = false; /** * Layout mode during insets animation: The views should be laid out as if the changing inset * types are fully shown. Before starting the animation, {@link View#onApplyWindowInsets} will Loading Loading @@ -268,6 +280,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void onReady(WindowInsetsAnimationController controller, int types) { mController = controller; if (DEBUG) Log.d(TAG, "default animation onReady types: " + types); mAnimator = ValueAnimator.ofFloat(0f, 1f); mAnimator.setDuration(mDurationMs); Loading @@ -290,6 +303,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation sEvaluator.evaluate(insetsFraction, start, end), alphaInterpolator.getInterpolation(alphaFraction), rawFraction); if (DEBUG) Log.d(TAG, "Default animation setInsetsAndAlpha fraction: " + insetsFraction); }); mAnimator.addListener(new AnimatorListenerAdapter() { Loading @@ -306,6 +321,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void onFinished(WindowInsetsAnimationController controller) { if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onFinished types:" + Type.toString(mRequestedTypes)); } @Override Loading @@ -314,6 +331,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (mAnimator != null) { mAnimator.cancel(); } if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onCancelled types:" + mRequestedTypes); } Interpolator getInterpolator() { Loading Loading @@ -348,6 +367,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation protected void onAnimationFinish() { mController.finish(mShow); if (DEBUG) Log.d(TAG, "onAnimationFinish showOnFinish: " + mShow); } /** Loading Loading @@ -420,8 +440,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final boolean useInsetsAnimationThread; } private final String TAG = "InsetsControllerImpl"; /** The local state */ private final InsetsState mState = new InsetsState(); Loading Loading @@ -494,6 +512,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation InsetsState state = new InsetsState(mState, true /* copySources */); for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { RunningAnimation runningAnimation = mRunningAnimations.get(i); if (DEBUG) Log.d(TAG, "Running animation type: " + runningAnimation.type); InsetsAnimationControlRunner runner = runningAnimation.runner; if (runner instanceof InsetsAnimationControlImpl) { InsetsAnimationControlImpl control = (InsetsAnimationControlImpl) runner; Loading @@ -516,6 +535,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacySystemUiFlags, null /* typeSideMap */); mHost.dispatchWindowInsetsAnimationProgress(insets, mUnmodifiableTmpRunningAnims); if (DEBUG) { for (WindowInsetsAnimation anim : mUnmodifiableTmpRunningAnims) { Log.d(TAG, String.format("Running animation type: %d, progress: %f", anim.getTypeMask(), anim.getInterpolatedFraction())); } } for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) { dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation()); Loading Loading @@ -553,13 +578,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (!localStateChanged && mLastDispatchedState.equals(state)) { return false; } if (DEBUG) Log.d(TAG, "onStateChanged: " + state); updateState(state); mLastDispatchedState.set(state, true /* copySources */); applyLocalVisibilityOverride(); if (localStateChanged) { if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged"); mHost.notifyInsetsChanged(); } if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */)) { if (DEBUG) Log.d(TAG, "onStateChanged, send state to WM: " + mState); updateRequestedState(); } return true; Loading Loading @@ -683,7 +711,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public void show(@InsetsType int types, boolean fromIme) { // Handle pending request ready in case there was one set. if (fromIme && mPendingImeControlRequest != null) { PendingControlRequest pendingRequest = mPendingImeControlRequest; Loading Loading @@ -711,10 +738,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation || animationType == ANIMATION_TYPE_SHOW) { // no-op: already shown or animating in (because window visibility is // applied before starting animation). if (DEBUG) Log.d(TAG, String.format( "show ignored for type: %d animType: %d requestedVisible: %s", consumer.getType(), animationType, consumer.isRequestedVisible())); continue; } typesReady |= InsetsState.toPublicType(consumer.getType()); } if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady); applyAnimation(typesReady, true /* show */, fromIme); } Loading Loading @@ -781,9 +812,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (types == 0) { // nothing to animate. listener.onCancelled(null); if (DEBUG) Log.d(TAG, "no types to animate in controlAnimationUnchecked"); return; } cancelExistingControllers(types); if (DEBUG) Log.d(TAG, "controlAnimation types: " + types); mLastStartedAnimTypes |= types; final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); Loading @@ -793,6 +826,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation fromIme, internalTypes, controls, animationType); int typesReady = typesReadyPair.first; boolean imeReady = typesReadyPair.second; if (DEBUG) Log.d(TAG, String.format( "controlAnimationUnchecked, typesReady: %s imeReady: %s", typesReady, imeReady)); if (!imeReady) { // IME isn't ready, all requested types will be animated once IME is ready abortPendingImeControlRequest(); Loading @@ -802,9 +837,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation useInsetsAnimationThread); mPendingImeControlRequest = request; mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS); if (DEBUG) Log.d(TAG, "Ime not ready. Create pending request"); if (cancellationSignal != null) { cancellationSignal.setOnCancelListener(() -> { if (mPendingImeControlRequest == request) { if (DEBUG) Log.d(TAG, "Cancellation signal abortPendingImeControlRequest"); abortPendingImeControlRequest(); } }); Loading @@ -813,6 +851,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } if (typesReady == 0) { if (DEBUG) Log.d(TAG, "No types ready. onCancelled()"); listener.onCancelled(null); return; } Loading @@ -826,6 +865,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation frame, mState, listener, typesReady, this, durationMs, interpolator, animationType); mRunningAnimations.add(new RunningAnimation(runner, animationType)); if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: " + useInsetsAnimationThread); if (cancellationSignal != null) { cancellationSignal.setOnCancelListener(runner::cancel); } Loading Loading @@ -857,8 +898,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation break; case ShowResult.IME_SHOW_DELAYED: imeReady = false; if (DEBUG) Log.d(TAG, "requestShow IME_SHOW_DELAYED"); break; case ShowResult.IME_SHOW_FAILED: if (WARN) Log.w(TAG, "requestShow IME_SHOW_FAILED. fromIme: " + fromIme); // IME cannot be shown (since it didn't have focus), proceed // with animation of other types. break; Loading @@ -873,6 +917,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation canRun = true; } if (!canRun) { if (WARN) Log.w(TAG, String.format( "collectSourceControls can't continue show for type: %s fromIme: %b", InsetsState.typeToString(consumer.getType()), fromIme)); continue; } final InsetsSourceControl control = consumer.getControl(); Loading @@ -880,7 +927,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation controls.put(consumer.getType(), new InsetsSourceControl(control)); typesReady |= toPublicType(consumer.getType()); } else if (animationType == ANIMATION_TYPE_SHOW) { if (DEBUG) Log.d(TAG, "collectSourceControls no control for show(). fromIme: " + fromIme); // We don't have a control at the moment. However, we still want to update requested // visibility state such that in case we get control, we can apply show animation. consumer.show(fromIme); Loading Loading @@ -931,6 +979,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mPendingImeControlRequest.listener.onCancelled(null); mPendingImeControlRequest = null; mHandler.removeCallbacks(mPendingControlTimeout); if (DEBUG) Log.d(TAG, "abortPendingImeControlRequest"); } } Loading @@ -938,6 +987,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) { cancelAnimation(runner, false /* invokeCallback */); if (DEBUG) Log.d(TAG, "notifyFinished. shown: " + shown); if (shown) { showDirectly(runner.getTypes()); } else { Loading @@ -964,6 +1014,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) { if (DEBUG) Log.d(TAG, String.format("cancelAnimation of types: %d, animType: %d", control.getTypes(), control.getAnimationType())); if (invokeCallback) { control.cancel(); } Loading Loading @@ -1088,6 +1140,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) { if (types == 0) { // nothing to animate. if (DEBUG) Log.d(TAG, "applyAnimation, nothing to animate"); return; } Loading Loading @@ -1142,6 +1195,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHost.dispatchWindowInsetsAnimationPrepare(animation); mHost.addOnPreDrawRunnable(() -> { if (controller.isCancelled()) { if (WARN) Log.w(TAG, "startAnimation canceled before preDraw"); return; } Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, Loading core/java/android/view/InsetsSourceConsumer.java +22 −1 Original line number Diff line number Diff line Loading @@ -19,11 +19,13 @@ package android.view; import static android.view.InsetsController.ANIMATION_TYPE_NONE; import static android.view.InsetsController.AnimationType; import static android.view.InsetsState.getDefaultVisibility; import static android.view.InsetsController.DEBUG; import static android.view.InsetsState.toPublicType; import android.annotation.IntDef; import android.annotation.Nullable; import android.graphics.Rect; import android.util.Log; import android.view.InsetsState.InternalInsetsType; import android.view.SurfaceControl.Transaction; import android.view.WindowInsets.Type.InsetsType; Loading Loading @@ -64,6 +66,7 @@ public class InsetsSourceConsumer { protected final InsetsState mState; protected final @InternalInsetsType int mType; private static final String TAG = "InsetsSourceConsumer"; private final Supplier<Transaction> mTransactionSupplier; private @Nullable InsetsSourceControl mSourceControl; private boolean mHasWindowFocus; Loading Loading @@ -103,7 +106,11 @@ public class InsetsSourceConsumer { final InsetsSourceControl lastControl = mSourceControl; mSourceControl = control; if (control != null) { if (DEBUG) Log.d(TAG, String.format("setControl -> %s on %s", InsetsState.typeToString(control.getType()), mController.getHost().getRootViewTitle())); } // We are loosing control if (mSourceControl == null) { mController.notifyControlRevoked(this); Loading @@ -118,6 +125,8 @@ public class InsetsSourceConsumer { final boolean requestedVisible = isRequestedVisibleAwaitingControl(); final boolean needAnimation = requestedVisible != mState.getSource(mType).isVisible(); if (control.getLeash() != null && (needAnimation || mIsAnimationPending)) { if (DEBUG) Log.d(TAG, String.format("Gaining control in %s, requestedVisible: %b", mController.getHost().getRootViewTitle(), requestedVisible)); if (requestedVisible) { showTypes[0] |= toPublicType(getType()); } else { Loading Loading @@ -170,11 +179,15 @@ public class InsetsSourceConsumer { @VisibleForTesting public void show(boolean fromIme) { if (DEBUG) Log.d(TAG, String.format("Call show() for type: %s fromIme: %b ", InsetsState.typeToString(mType), fromIme)); setRequestedVisible(true); } @VisibleForTesting public void hide() { if (DEBUG) Log.d(TAG, String.format("Call hide for %s on %s", InsetsState.typeToString(mType), mController.getHost().getRootViewTitle())); setRequestedVisible(false); } Loading Loading @@ -212,11 +225,16 @@ public class InsetsSourceConsumer { // If we don't have control, we are not able to change the visibility. if (!hasControl) { if (DEBUG) Log.d(TAG, "applyLocalVisibilityOverride: No control in " + mController.getHost().getRootViewTitle() + " requestedVisible " + mRequestedVisible); return false; } if (isVisible == mRequestedVisible) { return false; } if (DEBUG) Log.d(TAG, String.format("applyLocalVisibilityOverride: %s requestedVisible: %b", mController.getHost().getRootViewTitle(), mRequestedVisible)); mState.getSource(mType).setVisible(mRequestedVisible); return true; } Loading Loading @@ -271,6 +289,7 @@ public class InsetsSourceConsumer { newSource.setFrame(source.getFrame()); newSource.setVisibleFrame(source.getVisibleFrame()); mState.addSource(newSource); if (DEBUG) Log.d(TAG, "updateSource: " + newSource); } boolean notifyAnimationFinished() { Loading @@ -293,6 +312,7 @@ public class InsetsSourceConsumer { if (mRequestedVisible != requestedVisible) { mRequestedVisible = requestedVisible; mIsAnimationPending = false; if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible); } if (applyLocalVisibilityOverride()) { mController.notifyVisibilityChanged(); Loading @@ -305,6 +325,7 @@ public class InsetsSourceConsumer { } final Transaction t = mTransactionSupplier.get(); if (DEBUG) Log.d(TAG, "applyHiddenToControl: " + mRequestedVisible); if (mRequestedVisible) { t.show(mSourceControl.getLeash()); } else { Loading core/java/android/view/InsetsSourceControl.java +9 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.view.InsetsState.InternalInsetsType; import java.io.PrintWriter; import java.util.function.Consumer; /** Loading Loading @@ -101,6 +102,14 @@ public class InsetsSourceControl implements Parcelable { } } public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("InsetsSourceControl type="); pw.print(InsetsState.typeToString(mType)); pw.print(" mLeash="); pw.print(mLeash); pw.print(" mSurfacePosition="); pw.print(mSurfacePosition); pw.println(); } public static final @android.annotation.NonNull Creator<InsetsSourceControl> CREATOR = new Creator<InsetsSourceControl>() { public InsetsSourceControl createFromParcel(Parcel in) { Loading Loading
core/java/android/view/InsetsAnimationControlImpl.java +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import static android.view.InsetsController.AnimationType; import static android.view.InsetsController.DEBUG; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_FLOATING; import static android.view.InsetsState.ISIDE_LEFT; Loading @@ -30,6 +31,7 @@ import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.Rect; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseSetArray; Loading @@ -52,6 +54,8 @@ import java.util.ArrayList; public class InsetsAnimationControlImpl implements WindowInsetsAnimationController, InsetsAnimationControlRunner { private static final String TAG = "InsetsAnimationCtrlImpl"; private final Rect mTmpFrame = new Rect(); private final WindowInsetsAnimationControlListener mListener; Loading Loading @@ -165,6 +169,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll */ public boolean applyChangeInsets(InsetsState state) { if (mCancelled) { if (DEBUG) Log.d(TAG, "applyChangeInsets canceled"); return false; } final Insets offset = Insets.subtract(mShownInsets, mPendingInsets); Loading @@ -186,9 +191,13 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll mCurrentAlpha = mPendingAlpha; mAnimation.setAlpha(mPendingAlpha); if (mFinished) { if (DEBUG) Log.d(TAG, String.format( "notifyFinished shown: %s, currentAlpha: %f, currentInsets: %s", mShownOnFinish, mCurrentAlpha, mCurrentInsets)); mController.notifyFinished(this, mShownOnFinish); releaseLeashes(); } if (DEBUG) Log.d(TAG, "Animation finished abruptly."); return mFinished; } Loading @@ -203,12 +212,15 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll @Override public void finish(boolean shown) { if (mCancelled || mFinished) { if (DEBUG) Log.d(TAG, "Animation already canceled or finished, not notifying."); return; } mShownOnFinish = shown; mFinished = true; setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */, true /* allowWhenFinished */); if (DEBUG) Log.d(TAG, "notify control request finished for types: " + mTypes); mListener.onFinished(this); } Loading @@ -225,6 +237,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll } mCancelled = true; mListener.onCancelled(mReadyDispatched ? this : null); if (DEBUG) Log.d(TAG, "notify Control request cancelled for types: " + mTypes); releaseLeashes(); } Loading
core/java/android/view/InsetsAnimationThreadControlRunner.java +5 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package android.view; import static android.view.InsetsController.DEBUG; import static android.view.SyncRtSurfaceTransactionApplier.applyParams; import android.annotation.UiThread; import android.graphics.Rect; import android.os.Handler; import android.os.Trace; import android.util.Log; import android.util.SparseArray; import android.view.InsetsController.AnimationType; import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams; Loading @@ -37,6 +39,7 @@ import android.view.animation.Interpolator; */ public class InsetsAnimationThreadControlRunner implements InsetsAnimationControlRunner { private static final String TAG = "InsetsAnimThreadRunner"; private final InsetsAnimationControlImpl mControl; private final InsetsAnimationControlCallbacks mOuterCallbacks; private final Handler mMainThreadHandler; Loading Loading @@ -71,6 +74,7 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro @Override public void applySurfaceParams(SurfaceParams... params) { if (DEBUG) Log.d(TAG, "applySurfaceParams"); SurfaceControl.Transaction t = new SurfaceControl.Transaction(); for (int i = params.length - 1; i >= 0; i--) { SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i]; Loading @@ -82,6 +86,7 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro @Override public void releaseSurfaceControlFromRt(SurfaceControl sc) { if (DEBUG) Log.d(TAG, "releaseSurfaceControlFromRt"); // Since we don't push the SurfaceParams to the RT we can release directly sc.release(); } Loading
core/java/android/view/InsetsController.java +58 −4 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.os.CancellationSignal; import android.os.Handler; import android.os.Trace; import android.util.ArraySet; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.view.InsetsSourceConsumer.ShowResult; Loading Loading @@ -152,8 +153,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation * Obtains {@link InputMethodManager} instance from host. */ InputMethodManager getInputMethodManager(); /** * @return title of the rootView, if it has one. * Note: this method is for debugging purposes only. */ @Nullable String getRootViewTitle(); } private static final String TAG = "InsetsController"; private static final int ANIMATION_DURATION_SHOW_MS = 275; private static final int ANIMATION_DURATION_HIDE_MS = 340; Loading @@ -171,6 +180,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private static final Interpolator FAST_OUT_LINEAR_IN_INTERPOLATOR = new PathInterpolator(0.4f, 0f, 1f, 1f); static final boolean DEBUG = false; static final boolean WARN = false; /** * Layout mode during insets animation: The views should be laid out as if the changing inset * types are fully shown. Before starting the animation, {@link View#onApplyWindowInsets} will Loading Loading @@ -268,6 +280,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void onReady(WindowInsetsAnimationController controller, int types) { mController = controller; if (DEBUG) Log.d(TAG, "default animation onReady types: " + types); mAnimator = ValueAnimator.ofFloat(0f, 1f); mAnimator.setDuration(mDurationMs); Loading @@ -290,6 +303,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation sEvaluator.evaluate(insetsFraction, start, end), alphaInterpolator.getInterpolation(alphaFraction), rawFraction); if (DEBUG) Log.d(TAG, "Default animation setInsetsAndAlpha fraction: " + insetsFraction); }); mAnimator.addListener(new AnimatorListenerAdapter() { Loading @@ -306,6 +321,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void onFinished(WindowInsetsAnimationController controller) { if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onFinished types:" + Type.toString(mRequestedTypes)); } @Override Loading @@ -314,6 +331,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (mAnimator != null) { mAnimator.cancel(); } if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onCancelled types:" + mRequestedTypes); } Interpolator getInterpolator() { Loading Loading @@ -348,6 +367,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation protected void onAnimationFinish() { mController.finish(mShow); if (DEBUG) Log.d(TAG, "onAnimationFinish showOnFinish: " + mShow); } /** Loading Loading @@ -420,8 +440,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final boolean useInsetsAnimationThread; } private final String TAG = "InsetsControllerImpl"; /** The local state */ private final InsetsState mState = new InsetsState(); Loading Loading @@ -494,6 +512,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation InsetsState state = new InsetsState(mState, true /* copySources */); for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { RunningAnimation runningAnimation = mRunningAnimations.get(i); if (DEBUG) Log.d(TAG, "Running animation type: " + runningAnimation.type); InsetsAnimationControlRunner runner = runningAnimation.runner; if (runner instanceof InsetsAnimationControlImpl) { InsetsAnimationControlImpl control = (InsetsAnimationControlImpl) runner; Loading @@ -516,6 +535,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacySystemUiFlags, null /* typeSideMap */); mHost.dispatchWindowInsetsAnimationProgress(insets, mUnmodifiableTmpRunningAnims); if (DEBUG) { for (WindowInsetsAnimation anim : mUnmodifiableTmpRunningAnims) { Log.d(TAG, String.format("Running animation type: %d, progress: %f", anim.getTypeMask(), anim.getInterpolatedFraction())); } } for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) { dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation()); Loading Loading @@ -553,13 +578,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (!localStateChanged && mLastDispatchedState.equals(state)) { return false; } if (DEBUG) Log.d(TAG, "onStateChanged: " + state); updateState(state); mLastDispatchedState.set(state, true /* copySources */); applyLocalVisibilityOverride(); if (localStateChanged) { if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged"); mHost.notifyInsetsChanged(); } if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */)) { if (DEBUG) Log.d(TAG, "onStateChanged, send state to WM: " + mState); updateRequestedState(); } return true; Loading Loading @@ -683,7 +711,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public void show(@InsetsType int types, boolean fromIme) { // Handle pending request ready in case there was one set. if (fromIme && mPendingImeControlRequest != null) { PendingControlRequest pendingRequest = mPendingImeControlRequest; Loading Loading @@ -711,10 +738,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation || animationType == ANIMATION_TYPE_SHOW) { // no-op: already shown or animating in (because window visibility is // applied before starting animation). if (DEBUG) Log.d(TAG, String.format( "show ignored for type: %d animType: %d requestedVisible: %s", consumer.getType(), animationType, consumer.isRequestedVisible())); continue; } typesReady |= InsetsState.toPublicType(consumer.getType()); } if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady); applyAnimation(typesReady, true /* show */, fromIme); } Loading Loading @@ -781,9 +812,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (types == 0) { // nothing to animate. listener.onCancelled(null); if (DEBUG) Log.d(TAG, "no types to animate in controlAnimationUnchecked"); return; } cancelExistingControllers(types); if (DEBUG) Log.d(TAG, "controlAnimation types: " + types); mLastStartedAnimTypes |= types; final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); Loading @@ -793,6 +826,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation fromIme, internalTypes, controls, animationType); int typesReady = typesReadyPair.first; boolean imeReady = typesReadyPair.second; if (DEBUG) Log.d(TAG, String.format( "controlAnimationUnchecked, typesReady: %s imeReady: %s", typesReady, imeReady)); if (!imeReady) { // IME isn't ready, all requested types will be animated once IME is ready abortPendingImeControlRequest(); Loading @@ -802,9 +837,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation useInsetsAnimationThread); mPendingImeControlRequest = request; mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS); if (DEBUG) Log.d(TAG, "Ime not ready. Create pending request"); if (cancellationSignal != null) { cancellationSignal.setOnCancelListener(() -> { if (mPendingImeControlRequest == request) { if (DEBUG) Log.d(TAG, "Cancellation signal abortPendingImeControlRequest"); abortPendingImeControlRequest(); } }); Loading @@ -813,6 +851,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } if (typesReady == 0) { if (DEBUG) Log.d(TAG, "No types ready. onCancelled()"); listener.onCancelled(null); return; } Loading @@ -826,6 +865,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation frame, mState, listener, typesReady, this, durationMs, interpolator, animationType); mRunningAnimations.add(new RunningAnimation(runner, animationType)); if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: " + useInsetsAnimationThread); if (cancellationSignal != null) { cancellationSignal.setOnCancelListener(runner::cancel); } Loading Loading @@ -857,8 +898,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation break; case ShowResult.IME_SHOW_DELAYED: imeReady = false; if (DEBUG) Log.d(TAG, "requestShow IME_SHOW_DELAYED"); break; case ShowResult.IME_SHOW_FAILED: if (WARN) Log.w(TAG, "requestShow IME_SHOW_FAILED. fromIme: " + fromIme); // IME cannot be shown (since it didn't have focus), proceed // with animation of other types. break; Loading @@ -873,6 +917,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation canRun = true; } if (!canRun) { if (WARN) Log.w(TAG, String.format( "collectSourceControls can't continue show for type: %s fromIme: %b", InsetsState.typeToString(consumer.getType()), fromIme)); continue; } final InsetsSourceControl control = consumer.getControl(); Loading @@ -880,7 +927,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation controls.put(consumer.getType(), new InsetsSourceControl(control)); typesReady |= toPublicType(consumer.getType()); } else if (animationType == ANIMATION_TYPE_SHOW) { if (DEBUG) Log.d(TAG, "collectSourceControls no control for show(). fromIme: " + fromIme); // We don't have a control at the moment. However, we still want to update requested // visibility state such that in case we get control, we can apply show animation. consumer.show(fromIme); Loading Loading @@ -931,6 +979,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mPendingImeControlRequest.listener.onCancelled(null); mPendingImeControlRequest = null; mHandler.removeCallbacks(mPendingControlTimeout); if (DEBUG) Log.d(TAG, "abortPendingImeControlRequest"); } } Loading @@ -938,6 +987,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Override public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) { cancelAnimation(runner, false /* invokeCallback */); if (DEBUG) Log.d(TAG, "notifyFinished. shown: " + shown); if (shown) { showDirectly(runner.getTypes()); } else { Loading @@ -964,6 +1014,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) { if (DEBUG) Log.d(TAG, String.format("cancelAnimation of types: %d, animType: %d", control.getTypes(), control.getAnimationType())); if (invokeCallback) { control.cancel(); } Loading Loading @@ -1088,6 +1140,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) { if (types == 0) { // nothing to animate. if (DEBUG) Log.d(TAG, "applyAnimation, nothing to animate"); return; } Loading Loading @@ -1142,6 +1195,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mHost.dispatchWindowInsetsAnimationPrepare(animation); mHost.addOnPreDrawRunnable(() -> { if (controller.isCancelled()) { if (WARN) Log.w(TAG, "startAnimation canceled before preDraw"); return; } Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, Loading
core/java/android/view/InsetsSourceConsumer.java +22 −1 Original line number Diff line number Diff line Loading @@ -19,11 +19,13 @@ package android.view; import static android.view.InsetsController.ANIMATION_TYPE_NONE; import static android.view.InsetsController.AnimationType; import static android.view.InsetsState.getDefaultVisibility; import static android.view.InsetsController.DEBUG; import static android.view.InsetsState.toPublicType; import android.annotation.IntDef; import android.annotation.Nullable; import android.graphics.Rect; import android.util.Log; import android.view.InsetsState.InternalInsetsType; import android.view.SurfaceControl.Transaction; import android.view.WindowInsets.Type.InsetsType; Loading Loading @@ -64,6 +66,7 @@ public class InsetsSourceConsumer { protected final InsetsState mState; protected final @InternalInsetsType int mType; private static final String TAG = "InsetsSourceConsumer"; private final Supplier<Transaction> mTransactionSupplier; private @Nullable InsetsSourceControl mSourceControl; private boolean mHasWindowFocus; Loading Loading @@ -103,7 +106,11 @@ public class InsetsSourceConsumer { final InsetsSourceControl lastControl = mSourceControl; mSourceControl = control; if (control != null) { if (DEBUG) Log.d(TAG, String.format("setControl -> %s on %s", InsetsState.typeToString(control.getType()), mController.getHost().getRootViewTitle())); } // We are loosing control if (mSourceControl == null) { mController.notifyControlRevoked(this); Loading @@ -118,6 +125,8 @@ public class InsetsSourceConsumer { final boolean requestedVisible = isRequestedVisibleAwaitingControl(); final boolean needAnimation = requestedVisible != mState.getSource(mType).isVisible(); if (control.getLeash() != null && (needAnimation || mIsAnimationPending)) { if (DEBUG) Log.d(TAG, String.format("Gaining control in %s, requestedVisible: %b", mController.getHost().getRootViewTitle(), requestedVisible)); if (requestedVisible) { showTypes[0] |= toPublicType(getType()); } else { Loading Loading @@ -170,11 +179,15 @@ public class InsetsSourceConsumer { @VisibleForTesting public void show(boolean fromIme) { if (DEBUG) Log.d(TAG, String.format("Call show() for type: %s fromIme: %b ", InsetsState.typeToString(mType), fromIme)); setRequestedVisible(true); } @VisibleForTesting public void hide() { if (DEBUG) Log.d(TAG, String.format("Call hide for %s on %s", InsetsState.typeToString(mType), mController.getHost().getRootViewTitle())); setRequestedVisible(false); } Loading Loading @@ -212,11 +225,16 @@ public class InsetsSourceConsumer { // If we don't have control, we are not able to change the visibility. if (!hasControl) { if (DEBUG) Log.d(TAG, "applyLocalVisibilityOverride: No control in " + mController.getHost().getRootViewTitle() + " requestedVisible " + mRequestedVisible); return false; } if (isVisible == mRequestedVisible) { return false; } if (DEBUG) Log.d(TAG, String.format("applyLocalVisibilityOverride: %s requestedVisible: %b", mController.getHost().getRootViewTitle(), mRequestedVisible)); mState.getSource(mType).setVisible(mRequestedVisible); return true; } Loading Loading @@ -271,6 +289,7 @@ public class InsetsSourceConsumer { newSource.setFrame(source.getFrame()); newSource.setVisibleFrame(source.getVisibleFrame()); mState.addSource(newSource); if (DEBUG) Log.d(TAG, "updateSource: " + newSource); } boolean notifyAnimationFinished() { Loading @@ -293,6 +312,7 @@ public class InsetsSourceConsumer { if (mRequestedVisible != requestedVisible) { mRequestedVisible = requestedVisible; mIsAnimationPending = false; if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible); } if (applyLocalVisibilityOverride()) { mController.notifyVisibilityChanged(); Loading @@ -305,6 +325,7 @@ public class InsetsSourceConsumer { } final Transaction t = mTransactionSupplier.get(); if (DEBUG) Log.d(TAG, "applyHiddenToControl: " + mRequestedVisible); if (mRequestedVisible) { t.show(mSourceControl.getLeash()); } else { Loading
core/java/android/view/InsetsSourceControl.java +9 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.view.InsetsState.InternalInsetsType; import java.io.PrintWriter; import java.util.function.Consumer; /** Loading Loading @@ -101,6 +102,14 @@ public class InsetsSourceControl implements Parcelable { } } public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("InsetsSourceControl type="); pw.print(InsetsState.typeToString(mType)); pw.print(" mLeash="); pw.print(mLeash); pw.print(" mSurfacePosition="); pw.print(mSurfacePosition); pw.println(); } public static final @android.annotation.NonNull Creator<InsetsSourceControl> CREATOR = new Creator<InsetsSourceControl>() { public InsetsSourceControl createFromParcel(Parcel in) { Loading