Loading data/etc/services.core.protolog.json +18 −12 Original line number Diff line number Diff line Loading @@ -529,6 +529,12 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/ActivityStarter.java" }, "-1582845629": { "message": "Starting animation on %s", "level": "VERBOSE", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, "-1575977269": { "message": "Skipping %s: mismatch root %s", "level": "DEBUG", Loading Loading @@ -925,6 +931,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, "-1243510456": { "message": "Dim animation requested: %s", "level": "VERBOSE", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, "-1237827119": { "message": "Schedule remove starting %s startingWindow=%s animate=%b Callers=%s", "level": "VERBOSE", Loading Loading @@ -1171,6 +1183,12 @@ "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "-1028213464": { "message": "%s skipping animation and directly setting alpha=%f, blur=%d", "level": "DEBUG", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, "-1022146708": { "message": "Skipping %s: mismatch activity type", "level": "DEBUG", Loading Loading @@ -1795,12 +1813,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-504637678": { "message": "Starting animation on dim layer %s, requested by %s, alpha: %f -> %f, blur: %d -> %d", "level": "VERBOSE", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/SmoothDimmer.java" }, "-503656156": { "message": "Update process config of %s to new config %s", "level": "VERBOSE", Loading Loading @@ -4027,12 +4039,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "1620751818": { "message": "Dim %s skipping animation and directly setting alpha=%f, blur=%d", "level": "DEBUG", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/SmoothDimmer.java" }, "1621562070": { "message": " startWCT=%s", "level": "VERBOSE", Loading services/core/java/com/android/server/wm/Dimmer.java +2 −2 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ public abstract class Dimmer { /** * Mark all dims as pending completion on the next call to {@link #updateDims} * * Called before iterating on mHost's children, first step of dimming. * This is intended for us by the host container, to be called at the beginning of * {@link WindowContainer#prepareSurfaces}. After calling this, the container should * chain {@link WindowContainer#prepareSurfaces} down to it's children to give them Loading @@ -100,8 +101,7 @@ public abstract class Dimmer { /** * Call after invoking {@link WindowContainer#prepareSurfaces} on children as * described in {@link #resetDimStates}. The dim bounds returned by {@link #resetDimStates} * should be set before calling this method. * described in {@link #resetDimStates}. * * @param t A transaction in which to update the dims. * @return true if any Dims were updated. Loading services/core/java/com/android/server/wm/DimmerAnimationHelper.java 0 → 100644 +334 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DIMMER; import static com.android.server.wm.AlphaAnimationSpecProto.DURATION_MS; import static com.android.server.wm.AlphaAnimationSpecProto.FROM; import static com.android.server.wm.AlphaAnimationSpecProto.TO; import static com.android.server.wm.AnimationSpecProto.ALPHA; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl; import com.android.internal.protolog.common.ProtoLog; import java.io.PrintWriter; /** * Contains the information relative to the changes to apply to the dim layer */ public class DimmerAnimationHelper { private static final String TAG = TAG_WITH_CLASS_NAME ? "DimmerAnimationHelper" : TAG_WM; private static final int DEFAULT_DIM_ANIM_DURATION_MS = 200; /** * Contains the requested changes */ static class Change { private float mAlpha = -1f; private int mBlurRadius = -1; private WindowContainer mDimmingContainer = null; private int mRelativeLayer = -1; private static final float EPSILON = 0.0001f; Change() {} Change(Change other) { mAlpha = other.mAlpha; mBlurRadius = other.mBlurRadius; mDimmingContainer = other.mDimmingContainer; mRelativeLayer = other.mRelativeLayer; } // Same alpha and blur boolean hasSameVisualProperties(Change other) { return Math.abs(mAlpha - other.mAlpha) < EPSILON && mBlurRadius == other.mBlurRadius; } boolean hasSameDimmingContainer(Change other) { return mDimmingContainer != null && mDimmingContainer == other.mDimmingContainer; } void inheritPropertiesFromAnimation(AnimationSpec anim) { mAlpha = anim.mCurrentAlpha; mBlurRadius = anim.mCurrentBlur; } @Override public String toString() { return "Dim state: alpha=" + mAlpha + ", blur=" + mBlurRadius + ", container=" + mDimmingContainer + ", relativePosition=" + mRelativeLayer; } } private Change mCurrentProperties = new Change(); private Change mRequestedProperties = new Change(); private AnimationSpec mAlphaAnimationSpec; private final AnimationAdapterFactory mAnimationAdapterFactory; private AnimationAdapter mLocalAnimationAdapter; DimmerAnimationHelper(AnimationAdapterFactory animationFactory) { mAnimationAdapterFactory = animationFactory; } void setExitParameters() { setRequestedRelativeParent(mRequestedProperties.mDimmingContainer, -1 /* relativeLayer */); setRequestedAppearance(0f /* alpha */, 0 /* blur */); } // Sets a requested change without applying it immediately void setRequestedRelativeParent(WindowContainer relativeParent, int relativeLayer) { mRequestedProperties.mDimmingContainer = relativeParent; mRequestedProperties.mRelativeLayer = relativeLayer; } // Sets a requested change without applying it immediately void setRequestedAppearance(float alpha, int blurRadius) { mRequestedProperties.mAlpha = alpha; mRequestedProperties.mBlurRadius = blurRadius; } /** * Commit the last changes we received. Called after * {@link Change#setExitParameters()}, * {@link Change#setRequestedRelativeParent(WindowContainer, int)}, or * {@link Change#setRequestedAppearance(float, int)} */ void applyChanges(SurfaceControl.Transaction t, SmoothDimmer.DimState dim) { if (mRequestedProperties.mDimmingContainer == null) { Log.e(TAG, this + " does not have a dimming container. Have you forgotten to " + "call adjustRelativeLayer?"); return; } if (mRequestedProperties.mDimmingContainer.mSurfaceControl == null) { Log.w(TAG, "container " + mRequestedProperties.mDimmingContainer + "does not have a surface"); dim.remove(t); return; } dim.ensureVisible(t); relativeReparent(dim.mDimSurface, mRequestedProperties.mDimmingContainer.getSurfaceControl(), mRequestedProperties.mRelativeLayer, t); if (!mCurrentProperties.hasSameVisualProperties(mRequestedProperties)) { stopCurrentAnimation(dim.mDimSurface); if (dim.mSkipAnimation // If the container doesn't change but requests a dim change, then it is // directly providing us the animated values || (mRequestedProperties.hasSameDimmingContainer(mCurrentProperties) && dim.isDimming())) { ProtoLog.d(WM_DEBUG_DIMMER, "%s skipping animation and directly setting alpha=%f, blur=%d", dim, mRequestedProperties.mAlpha, mRequestedProperties.mBlurRadius); setAlphaBlur(dim.mDimSurface, mRequestedProperties.mAlpha, mRequestedProperties.mBlurRadius, t); dim.mSkipAnimation = false; } else { startAnimation(t, dim); } } else if (!dim.isDimming()) { // We are not dimming, so we tried the exit animation but the alpha is already 0, // therefore, let's just remove this surface dim.remove(t); } mCurrentProperties = new Change(mRequestedProperties); } private void startAnimation( SurfaceControl.Transaction t, SmoothDimmer.DimState dim) { ProtoLog.v(WM_DEBUG_DIMMER, "Starting animation on %s", dim); mAlphaAnimationSpec = getRequestedAnimationSpec(); mLocalAnimationAdapter = mAnimationAdapterFactory.get(mAlphaAnimationSpec, dim.mHostContainer.mWmService.mSurfaceAnimationRunner); float targetAlpha = mRequestedProperties.mAlpha; int targetBlur = mRequestedProperties.mBlurRadius; mLocalAnimationAdapter.startAnimation(dim.mDimSurface, t, ANIMATION_TYPE_DIMMER, /* finishCallback */ (type, animator) -> { setAlphaBlur(dim.mDimSurface, targetAlpha, targetBlur, t); if (targetAlpha == 0f && !dim.isDimming()) { dim.remove(t); } mLocalAnimationAdapter = null; mAlphaAnimationSpec = null; }); } private boolean isAnimating() { return mAlphaAnimationSpec != null; } void stopCurrentAnimation(SurfaceControl surface) { if (mLocalAnimationAdapter != null && isAnimating()) { // Save the current animation progress and cancel the animation mCurrentProperties.inheritPropertiesFromAnimation(mAlphaAnimationSpec); mLocalAnimationAdapter.onAnimationCancelled(surface); mLocalAnimationAdapter = null; mAlphaAnimationSpec = null; } } private AnimationSpec getRequestedAnimationSpec() { final float startAlpha = Math.max(mCurrentProperties.mAlpha, 0f); final int startBlur = Math.max(mCurrentProperties.mBlurRadius, 0); long duration = (long) (getDimDuration(mRequestedProperties.mDimmingContainer) * Math.abs(mRequestedProperties.mAlpha - startAlpha)); final AnimationSpec spec = new AnimationSpec( new AnimationSpec.AnimationExtremes<>(startAlpha, mRequestedProperties.mAlpha), new AnimationSpec.AnimationExtremes<>(startBlur, mRequestedProperties.mBlurRadius), duration ); ProtoLog.v(WM_DEBUG_DIMMER, "Dim animation requested: %s", spec); return spec; } /** * Change the relative parent of this dim layer */ void relativeReparent(SurfaceControl dimLayer, SurfaceControl relativeParent, int relativePosition, SurfaceControl.Transaction t) { try { t.setRelativeLayer(dimLayer, relativeParent, relativePosition); } catch (NullPointerException e) { Log.w(TAG, "Tried to change parent of dim " + dimLayer + " after remove", e); } } void setAlphaBlur(SurfaceControl sc, float alpha, int blur, SurfaceControl.Transaction t) { try { t.setAlpha(sc, alpha); t.setBackgroundBlurRadius(sc, blur); } catch (NullPointerException e) { Log.w(TAG , "Tried to change look of dim " + sc + " after remove", e); } } private long getDimDuration(WindowContainer container) { // Use the same duration as the animation on the WindowContainer AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation(); final float durationScale = container.mWmService.getTransitionAnimationScaleLocked(); return animationAdapter == null ? (long) (DEFAULT_DIM_ANIM_DURATION_MS * durationScale) : animationAdapter.getDurationHint(); } /** * Collects the animation specifics */ static class AnimationSpec implements LocalAnimationAdapter.AnimationSpec { private static final String TAG = TAG_WITH_CLASS_NAME ? "DimmerAnimationSpec" : TAG_WM; static class AnimationExtremes<T> { final T mStartValue; final T mFinishValue; AnimationExtremes(T fromValue, T toValue) { mStartValue = fromValue; mFinishValue = toValue; } @Override public String toString() { return "[" + mStartValue + "->" + mFinishValue + "]"; } } private final long mDuration; private final AnimationSpec.AnimationExtremes<Float> mAlpha; private final AnimationSpec.AnimationExtremes<Integer> mBlur; float mCurrentAlpha = 0; int mCurrentBlur = 0; boolean mStarted = false; AnimationSpec(AnimationSpec.AnimationExtremes<Float> alpha, AnimationSpec.AnimationExtremes<Integer> blur, long duration) { mAlpha = alpha; mBlur = blur; mDuration = duration; } @Override public long getDuration() { return mDuration; } @Override public void apply(SurfaceControl.Transaction t, SurfaceControl sc, long currentPlayTime) { if (!mStarted) { // The first frame would end up in the sync transaction, and since this could be // applied after the animation transaction, we avoid putting visible changes here. // The initial state of the animation matches the current state of the dim anyway. mStarted = true; return; } final float fraction = getFraction(currentPlayTime); mCurrentAlpha = fraction * (mAlpha.mFinishValue - mAlpha.mStartValue) + mAlpha.mStartValue; mCurrentBlur = (int) fraction * (mBlur.mFinishValue - mBlur.mStartValue) + mBlur.mStartValue; if (sc.isValid()) { t.setAlpha(sc, mCurrentAlpha); t.setBackgroundBlurRadius(sc, mCurrentBlur); } else { Log.w(TAG, "Dimmer#AnimationSpec tried to access " + sc + " after release"); } } @Override public String toString() { return "Animation spec: alpha=" + mAlpha + ", blur=" + mBlur; } @Override public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("from_alpha="); pw.print(mAlpha.mStartValue); pw.print(" to_alpha="); pw.print(mAlpha.mFinishValue); pw.print(prefix); pw.print("from_blur="); pw.print(mBlur.mStartValue); pw.print(" to_blur="); pw.print(mBlur.mFinishValue); pw.print(" duration="); pw.println(mDuration); } @Override public void dumpDebugInner(ProtoOutputStream proto) { final long token = proto.start(ALPHA); proto.write(FROM, mAlpha.mStartValue); proto.write(TO, mAlpha.mFinishValue); proto.write(DURATION_MS, mDuration); proto.end(token); } } static class AnimationAdapterFactory { public AnimationAdapter get(LocalAnimationAdapter.AnimationSpec alphaAnimationSpec, SurfaceAnimationRunner runner) { return new LocalAnimationAdapter(alphaAnimationSpec, runner); } } } services/core/java/com/android/server/wm/SmoothDimmer.java +119 −304 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/wmtests/src/com/android/server/wm/DimmerTests.java +2 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,8 @@ public class DimmerTests extends WindowTestsBase { } } static class MockAnimationAdapterFactory extends SmoothDimmer.AnimationAdapterFactory { static class MockAnimationAdapterFactory extends DimmerAnimationHelper.AnimationAdapterFactory { @Override public AnimationAdapter get(LocalAnimationAdapter.AnimationSpec alphaAnimationSpec, SurfaceAnimationRunner runner) { return sTestAnimation; Loading Loading
data/etc/services.core.protolog.json +18 −12 Original line number Diff line number Diff line Loading @@ -529,6 +529,12 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/ActivityStarter.java" }, "-1582845629": { "message": "Starting animation on %s", "level": "VERBOSE", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, "-1575977269": { "message": "Skipping %s: mismatch root %s", "level": "DEBUG", Loading Loading @@ -925,6 +931,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, "-1243510456": { "message": "Dim animation requested: %s", "level": "VERBOSE", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, "-1237827119": { "message": "Schedule remove starting %s startingWindow=%s animate=%b Callers=%s", "level": "VERBOSE", Loading Loading @@ -1171,6 +1183,12 @@ "group": "WM_DEBUG_BACK_PREVIEW", "at": "com\/android\/server\/wm\/BackNavigationController.java" }, "-1028213464": { "message": "%s skipping animation and directly setting alpha=%f, blur=%d", "level": "DEBUG", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/DimmerAnimationHelper.java" }, "-1022146708": { "message": "Skipping %s: mismatch activity type", "level": "DEBUG", Loading Loading @@ -1795,12 +1813,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-504637678": { "message": "Starting animation on dim layer %s, requested by %s, alpha: %f -> %f, blur: %d -> %d", "level": "VERBOSE", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/SmoothDimmer.java" }, "-503656156": { "message": "Update process config of %s to new config %s", "level": "VERBOSE", Loading Loading @@ -4027,12 +4039,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "1620751818": { "message": "Dim %s skipping animation and directly setting alpha=%f, blur=%d", "level": "DEBUG", "group": "WM_DEBUG_DIMMER", "at": "com\/android\/server\/wm\/SmoothDimmer.java" }, "1621562070": { "message": " startWCT=%s", "level": "VERBOSE", Loading
services/core/java/com/android/server/wm/Dimmer.java +2 −2 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ public abstract class Dimmer { /** * Mark all dims as pending completion on the next call to {@link #updateDims} * * Called before iterating on mHost's children, first step of dimming. * This is intended for us by the host container, to be called at the beginning of * {@link WindowContainer#prepareSurfaces}. After calling this, the container should * chain {@link WindowContainer#prepareSurfaces} down to it's children to give them Loading @@ -100,8 +101,7 @@ public abstract class Dimmer { /** * Call after invoking {@link WindowContainer#prepareSurfaces} on children as * described in {@link #resetDimStates}. The dim bounds returned by {@link #resetDimStates} * should be set before calling this method. * described in {@link #resetDimStates}. * * @param t A transaction in which to update the dims. * @return true if any Dims were updated. Loading
services/core/java/com/android/server/wm/DimmerAnimationHelper.java 0 → 100644 +334 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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 static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DIMMER; import static com.android.server.wm.AlphaAnimationSpecProto.DURATION_MS; import static com.android.server.wm.AlphaAnimationSpecProto.FROM; import static com.android.server.wm.AlphaAnimationSpecProto.TO; import static com.android.server.wm.AnimationSpecProto.ALPHA; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl; import com.android.internal.protolog.common.ProtoLog; import java.io.PrintWriter; /** * Contains the information relative to the changes to apply to the dim layer */ public class DimmerAnimationHelper { private static final String TAG = TAG_WITH_CLASS_NAME ? "DimmerAnimationHelper" : TAG_WM; private static final int DEFAULT_DIM_ANIM_DURATION_MS = 200; /** * Contains the requested changes */ static class Change { private float mAlpha = -1f; private int mBlurRadius = -1; private WindowContainer mDimmingContainer = null; private int mRelativeLayer = -1; private static final float EPSILON = 0.0001f; Change() {} Change(Change other) { mAlpha = other.mAlpha; mBlurRadius = other.mBlurRadius; mDimmingContainer = other.mDimmingContainer; mRelativeLayer = other.mRelativeLayer; } // Same alpha and blur boolean hasSameVisualProperties(Change other) { return Math.abs(mAlpha - other.mAlpha) < EPSILON && mBlurRadius == other.mBlurRadius; } boolean hasSameDimmingContainer(Change other) { return mDimmingContainer != null && mDimmingContainer == other.mDimmingContainer; } void inheritPropertiesFromAnimation(AnimationSpec anim) { mAlpha = anim.mCurrentAlpha; mBlurRadius = anim.mCurrentBlur; } @Override public String toString() { return "Dim state: alpha=" + mAlpha + ", blur=" + mBlurRadius + ", container=" + mDimmingContainer + ", relativePosition=" + mRelativeLayer; } } private Change mCurrentProperties = new Change(); private Change mRequestedProperties = new Change(); private AnimationSpec mAlphaAnimationSpec; private final AnimationAdapterFactory mAnimationAdapterFactory; private AnimationAdapter mLocalAnimationAdapter; DimmerAnimationHelper(AnimationAdapterFactory animationFactory) { mAnimationAdapterFactory = animationFactory; } void setExitParameters() { setRequestedRelativeParent(mRequestedProperties.mDimmingContainer, -1 /* relativeLayer */); setRequestedAppearance(0f /* alpha */, 0 /* blur */); } // Sets a requested change without applying it immediately void setRequestedRelativeParent(WindowContainer relativeParent, int relativeLayer) { mRequestedProperties.mDimmingContainer = relativeParent; mRequestedProperties.mRelativeLayer = relativeLayer; } // Sets a requested change without applying it immediately void setRequestedAppearance(float alpha, int blurRadius) { mRequestedProperties.mAlpha = alpha; mRequestedProperties.mBlurRadius = blurRadius; } /** * Commit the last changes we received. Called after * {@link Change#setExitParameters()}, * {@link Change#setRequestedRelativeParent(WindowContainer, int)}, or * {@link Change#setRequestedAppearance(float, int)} */ void applyChanges(SurfaceControl.Transaction t, SmoothDimmer.DimState dim) { if (mRequestedProperties.mDimmingContainer == null) { Log.e(TAG, this + " does not have a dimming container. Have you forgotten to " + "call adjustRelativeLayer?"); return; } if (mRequestedProperties.mDimmingContainer.mSurfaceControl == null) { Log.w(TAG, "container " + mRequestedProperties.mDimmingContainer + "does not have a surface"); dim.remove(t); return; } dim.ensureVisible(t); relativeReparent(dim.mDimSurface, mRequestedProperties.mDimmingContainer.getSurfaceControl(), mRequestedProperties.mRelativeLayer, t); if (!mCurrentProperties.hasSameVisualProperties(mRequestedProperties)) { stopCurrentAnimation(dim.mDimSurface); if (dim.mSkipAnimation // If the container doesn't change but requests a dim change, then it is // directly providing us the animated values || (mRequestedProperties.hasSameDimmingContainer(mCurrentProperties) && dim.isDimming())) { ProtoLog.d(WM_DEBUG_DIMMER, "%s skipping animation and directly setting alpha=%f, blur=%d", dim, mRequestedProperties.mAlpha, mRequestedProperties.mBlurRadius); setAlphaBlur(dim.mDimSurface, mRequestedProperties.mAlpha, mRequestedProperties.mBlurRadius, t); dim.mSkipAnimation = false; } else { startAnimation(t, dim); } } else if (!dim.isDimming()) { // We are not dimming, so we tried the exit animation but the alpha is already 0, // therefore, let's just remove this surface dim.remove(t); } mCurrentProperties = new Change(mRequestedProperties); } private void startAnimation( SurfaceControl.Transaction t, SmoothDimmer.DimState dim) { ProtoLog.v(WM_DEBUG_DIMMER, "Starting animation on %s", dim); mAlphaAnimationSpec = getRequestedAnimationSpec(); mLocalAnimationAdapter = mAnimationAdapterFactory.get(mAlphaAnimationSpec, dim.mHostContainer.mWmService.mSurfaceAnimationRunner); float targetAlpha = mRequestedProperties.mAlpha; int targetBlur = mRequestedProperties.mBlurRadius; mLocalAnimationAdapter.startAnimation(dim.mDimSurface, t, ANIMATION_TYPE_DIMMER, /* finishCallback */ (type, animator) -> { setAlphaBlur(dim.mDimSurface, targetAlpha, targetBlur, t); if (targetAlpha == 0f && !dim.isDimming()) { dim.remove(t); } mLocalAnimationAdapter = null; mAlphaAnimationSpec = null; }); } private boolean isAnimating() { return mAlphaAnimationSpec != null; } void stopCurrentAnimation(SurfaceControl surface) { if (mLocalAnimationAdapter != null && isAnimating()) { // Save the current animation progress and cancel the animation mCurrentProperties.inheritPropertiesFromAnimation(mAlphaAnimationSpec); mLocalAnimationAdapter.onAnimationCancelled(surface); mLocalAnimationAdapter = null; mAlphaAnimationSpec = null; } } private AnimationSpec getRequestedAnimationSpec() { final float startAlpha = Math.max(mCurrentProperties.mAlpha, 0f); final int startBlur = Math.max(mCurrentProperties.mBlurRadius, 0); long duration = (long) (getDimDuration(mRequestedProperties.mDimmingContainer) * Math.abs(mRequestedProperties.mAlpha - startAlpha)); final AnimationSpec spec = new AnimationSpec( new AnimationSpec.AnimationExtremes<>(startAlpha, mRequestedProperties.mAlpha), new AnimationSpec.AnimationExtremes<>(startBlur, mRequestedProperties.mBlurRadius), duration ); ProtoLog.v(WM_DEBUG_DIMMER, "Dim animation requested: %s", spec); return spec; } /** * Change the relative parent of this dim layer */ void relativeReparent(SurfaceControl dimLayer, SurfaceControl relativeParent, int relativePosition, SurfaceControl.Transaction t) { try { t.setRelativeLayer(dimLayer, relativeParent, relativePosition); } catch (NullPointerException e) { Log.w(TAG, "Tried to change parent of dim " + dimLayer + " after remove", e); } } void setAlphaBlur(SurfaceControl sc, float alpha, int blur, SurfaceControl.Transaction t) { try { t.setAlpha(sc, alpha); t.setBackgroundBlurRadius(sc, blur); } catch (NullPointerException e) { Log.w(TAG , "Tried to change look of dim " + sc + " after remove", e); } } private long getDimDuration(WindowContainer container) { // Use the same duration as the animation on the WindowContainer AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation(); final float durationScale = container.mWmService.getTransitionAnimationScaleLocked(); return animationAdapter == null ? (long) (DEFAULT_DIM_ANIM_DURATION_MS * durationScale) : animationAdapter.getDurationHint(); } /** * Collects the animation specifics */ static class AnimationSpec implements LocalAnimationAdapter.AnimationSpec { private static final String TAG = TAG_WITH_CLASS_NAME ? "DimmerAnimationSpec" : TAG_WM; static class AnimationExtremes<T> { final T mStartValue; final T mFinishValue; AnimationExtremes(T fromValue, T toValue) { mStartValue = fromValue; mFinishValue = toValue; } @Override public String toString() { return "[" + mStartValue + "->" + mFinishValue + "]"; } } private final long mDuration; private final AnimationSpec.AnimationExtremes<Float> mAlpha; private final AnimationSpec.AnimationExtremes<Integer> mBlur; float mCurrentAlpha = 0; int mCurrentBlur = 0; boolean mStarted = false; AnimationSpec(AnimationSpec.AnimationExtremes<Float> alpha, AnimationSpec.AnimationExtremes<Integer> blur, long duration) { mAlpha = alpha; mBlur = blur; mDuration = duration; } @Override public long getDuration() { return mDuration; } @Override public void apply(SurfaceControl.Transaction t, SurfaceControl sc, long currentPlayTime) { if (!mStarted) { // The first frame would end up in the sync transaction, and since this could be // applied after the animation transaction, we avoid putting visible changes here. // The initial state of the animation matches the current state of the dim anyway. mStarted = true; return; } final float fraction = getFraction(currentPlayTime); mCurrentAlpha = fraction * (mAlpha.mFinishValue - mAlpha.mStartValue) + mAlpha.mStartValue; mCurrentBlur = (int) fraction * (mBlur.mFinishValue - mBlur.mStartValue) + mBlur.mStartValue; if (sc.isValid()) { t.setAlpha(sc, mCurrentAlpha); t.setBackgroundBlurRadius(sc, mCurrentBlur); } else { Log.w(TAG, "Dimmer#AnimationSpec tried to access " + sc + " after release"); } } @Override public String toString() { return "Animation spec: alpha=" + mAlpha + ", blur=" + mBlur; } @Override public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("from_alpha="); pw.print(mAlpha.mStartValue); pw.print(" to_alpha="); pw.print(mAlpha.mFinishValue); pw.print(prefix); pw.print("from_blur="); pw.print(mBlur.mStartValue); pw.print(" to_blur="); pw.print(mBlur.mFinishValue); pw.print(" duration="); pw.println(mDuration); } @Override public void dumpDebugInner(ProtoOutputStream proto) { final long token = proto.start(ALPHA); proto.write(FROM, mAlpha.mStartValue); proto.write(TO, mAlpha.mFinishValue); proto.write(DURATION_MS, mDuration); proto.end(token); } } static class AnimationAdapterFactory { public AnimationAdapter get(LocalAnimationAdapter.AnimationSpec alphaAnimationSpec, SurfaceAnimationRunner runner) { return new LocalAnimationAdapter(alphaAnimationSpec, runner); } } }
services/core/java/com/android/server/wm/SmoothDimmer.java +119 −304 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/wmtests/src/com/android/server/wm/DimmerTests.java +2 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,8 @@ public class DimmerTests extends WindowTestsBase { } } static class MockAnimationAdapterFactory extends SmoothDimmer.AnimationAdapterFactory { static class MockAnimationAdapterFactory extends DimmerAnimationHelper.AnimationAdapterFactory { @Override public AnimationAdapter get(LocalAnimationAdapter.AnimationSpec alphaAnimationSpec, SurfaceAnimationRunner runner) { return sTestAnimation; Loading