Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +9 −2 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe private final BubbleTaskStackListener mTaskStackListener; private BubbleStateChangeListener mStateChangeListener; private BubbleExpandListener mExpandListener; @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; private BubbleData mBubbleData; private BubbleStackView mStackView; Loading Loading @@ -179,6 +180,11 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe @Inject public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data) { this(context, statusBarWindowController, data, null /* synchronizer */); } public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer) { mContext = context; mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); Loading Loading @@ -206,6 +212,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe } mBubbleData = data; mSurfaceSynchronizer = synchronizer; } /** Loading Loading @@ -297,7 +304,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe mStackView.updateBubble(notif, updatePosition); } else { if (mStackView == null) { mStackView = new BubbleStackView(mContext, mBubbleData); mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer); ViewGroup sbv = mStatusBarWindowController.getStatusBarView(); // XXX: Bug when you expand the shade on top of expanded bubble, there is no scrim // between bubble and the shade Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +66 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.bubbles; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.annotation.NonNull; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; Loading @@ -32,6 +33,7 @@ import android.os.Bundle; import android.service.notification.StatusBarNotification; import android.util.Log; import android.util.StatsLog; import android.view.Choreographer; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; Loading Loading @@ -67,6 +69,43 @@ public class BubbleStackView extends FrameLayout { private static final String TAG = "BubbleStackView"; private static final boolean DEBUG = false; /** * Interface to synchronize {@link View} state and the screen. * * {@hide} */ interface SurfaceSynchronizer { /** * Wait until requested change on a {@link View} is reflected on the screen. * * @param callback callback to run after the change is reflected on the screen. */ void syncSurfaceAndRun(Runnable callback); } private static final SurfaceSynchronizer DEFAULT_SURFACE_SYNCHRONIZER = new SurfaceSynchronizer() { @Override public void syncSurfaceAndRun(Runnable callback) { Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() { // Just wait 2 frames. There is no guarantee, but this is usually enough time that // the requested change is reflected on the screen. // TODO: Once SurfaceFlinger provide APIs to sync the state of {@code View} and // surfaces, rewrite this logic with them. private int mFrameWait = 2; @Override public void doFrame(long frameTimeNanos) { if (--mFrameWait > 0) { Choreographer.getInstance().postFrameCallback(this); } else { callback.run(); } } }); } }; private Point mDisplaySize; private final SpringAnimation mExpandedViewXAnim; Loading @@ -79,7 +118,6 @@ public class BubbleStackView extends FrameLayout { private FrameLayout mExpandedViewContainer; private int mBubbleSize; private int mBubblePadding; private int mExpandedAnimateXDistance; Loading Loading @@ -129,7 +167,11 @@ public class BubbleStackView extends FrameLayout { } }; public BubbleStackView(Context context, BubbleData data) { @NonNull private final SurfaceSynchronizer mSurfaceSynchronizer; public BubbleStackView(Context context, BubbleData data, @Nullable SurfaceSynchronizer synchronizer) { super(context); mBubbleData = data; Loading Loading @@ -160,6 +202,7 @@ public class BubbleStackView extends FrameLayout { mStackAnimationController = new StackAnimationController(); mExpandedAnimationController = new ExpandedAnimationController(mDisplaySize); mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER; mBubbleContainer = new PhysicsAnimationLayout(context); mBubbleContainer.setMaxRenderedChildren( Loading Loading @@ -314,18 +357,29 @@ public class BubbleStackView extends FrameLayout { // If we weren't previously expanded we should animate open. animateExpansion(true /* expand */); logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); mExpandedBubble.entry.setShowInShadeWhenBubble(false); notifyExpansionChanged(mExpandedBubble.entry, true /* expanded */); } else { // Otherwise just update the views // TODO: probably animate / page to expanded one // Make the container of the expanded view transparent before removing the expanded view // from it. Otherwise a punch hole created by {@link android.view.SurfaceView} in the // expanded view becomes visible on the screen. See b/126856255 mExpandedViewContainer.setAlpha(0.0f); mSurfaceSynchronizer.syncSurfaceAndRun(new Runnable() { @Override public void run() { updateExpandedBubble(); updatePointerPosition(); requestUpdate(); logBubbleEvent(prevBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); } logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); mExpandedBubble.entry.setShowInShadeWhenBubble(false); notifyExpansionChanged(mExpandedBubble.entry, true /* expanded */); } }); } } /** * Sets the entry that should be expanded and expands if needed. Loading Loading @@ -769,6 +823,7 @@ public class BubbleStackView extends FrameLayout { mExpandedViewContainer.addView(mExpandedBubble.expandedView); mExpandedBubble.expandedView.populateExpandedView(); mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE); mExpandedViewContainer.setAlpha(1.0f); } } Loading packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -329,10 +329,10 @@ public class BubbleControllerTest extends SysuiTestCase { } static class TestableBubbleController extends BubbleController { // Let's assume surfaces can be synchronized immediately. TestableBubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data) { super(context, statusBarWindowController, data); super(context, statusBarWindowController, data, Runnable::run); } @Override Loading Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +9 −2 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe private final BubbleTaskStackListener mTaskStackListener; private BubbleStateChangeListener mStateChangeListener; private BubbleExpandListener mExpandListener; @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; private BubbleData mBubbleData; private BubbleStackView mStackView; Loading Loading @@ -179,6 +180,11 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe @Inject public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data) { this(context, statusBarWindowController, data, null /* synchronizer */); } public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer) { mContext = context; mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); Loading Loading @@ -206,6 +212,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe } mBubbleData = data; mSurfaceSynchronizer = synchronizer; } /** Loading Loading @@ -297,7 +304,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe mStackView.updateBubble(notif, updatePosition); } else { if (mStackView == null) { mStackView = new BubbleStackView(mContext, mBubbleData); mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer); ViewGroup sbv = mStatusBarWindowController.getStatusBarView(); // XXX: Bug when you expand the shade on top of expanded bubble, there is no scrim // between bubble and the shade Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +66 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.bubbles; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.annotation.NonNull; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; Loading @@ -32,6 +33,7 @@ import android.os.Bundle; import android.service.notification.StatusBarNotification; import android.util.Log; import android.util.StatsLog; import android.view.Choreographer; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; Loading Loading @@ -67,6 +69,43 @@ public class BubbleStackView extends FrameLayout { private static final String TAG = "BubbleStackView"; private static final boolean DEBUG = false; /** * Interface to synchronize {@link View} state and the screen. * * {@hide} */ interface SurfaceSynchronizer { /** * Wait until requested change on a {@link View} is reflected on the screen. * * @param callback callback to run after the change is reflected on the screen. */ void syncSurfaceAndRun(Runnable callback); } private static final SurfaceSynchronizer DEFAULT_SURFACE_SYNCHRONIZER = new SurfaceSynchronizer() { @Override public void syncSurfaceAndRun(Runnable callback) { Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() { // Just wait 2 frames. There is no guarantee, but this is usually enough time that // the requested change is reflected on the screen. // TODO: Once SurfaceFlinger provide APIs to sync the state of {@code View} and // surfaces, rewrite this logic with them. private int mFrameWait = 2; @Override public void doFrame(long frameTimeNanos) { if (--mFrameWait > 0) { Choreographer.getInstance().postFrameCallback(this); } else { callback.run(); } } }); } }; private Point mDisplaySize; private final SpringAnimation mExpandedViewXAnim; Loading @@ -79,7 +118,6 @@ public class BubbleStackView extends FrameLayout { private FrameLayout mExpandedViewContainer; private int mBubbleSize; private int mBubblePadding; private int mExpandedAnimateXDistance; Loading Loading @@ -129,7 +167,11 @@ public class BubbleStackView extends FrameLayout { } }; public BubbleStackView(Context context, BubbleData data) { @NonNull private final SurfaceSynchronizer mSurfaceSynchronizer; public BubbleStackView(Context context, BubbleData data, @Nullable SurfaceSynchronizer synchronizer) { super(context); mBubbleData = data; Loading Loading @@ -160,6 +202,7 @@ public class BubbleStackView extends FrameLayout { mStackAnimationController = new StackAnimationController(); mExpandedAnimationController = new ExpandedAnimationController(mDisplaySize); mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER; mBubbleContainer = new PhysicsAnimationLayout(context); mBubbleContainer.setMaxRenderedChildren( Loading Loading @@ -314,18 +357,29 @@ public class BubbleStackView extends FrameLayout { // If we weren't previously expanded we should animate open. animateExpansion(true /* expand */); logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); mExpandedBubble.entry.setShowInShadeWhenBubble(false); notifyExpansionChanged(mExpandedBubble.entry, true /* expanded */); } else { // Otherwise just update the views // TODO: probably animate / page to expanded one // Make the container of the expanded view transparent before removing the expanded view // from it. Otherwise a punch hole created by {@link android.view.SurfaceView} in the // expanded view becomes visible on the screen. See b/126856255 mExpandedViewContainer.setAlpha(0.0f); mSurfaceSynchronizer.syncSurfaceAndRun(new Runnable() { @Override public void run() { updateExpandedBubble(); updatePointerPosition(); requestUpdate(); logBubbleEvent(prevBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); } logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); mExpandedBubble.entry.setShowInShadeWhenBubble(false); notifyExpansionChanged(mExpandedBubble.entry, true /* expanded */); } }); } } /** * Sets the entry that should be expanded and expands if needed. Loading Loading @@ -769,6 +823,7 @@ public class BubbleStackView extends FrameLayout { mExpandedViewContainer.addView(mExpandedBubble.expandedView); mExpandedBubble.expandedView.populateExpandedView(); mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE); mExpandedViewContainer.setAlpha(1.0f); } } Loading
packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -329,10 +329,10 @@ public class BubbleControllerTest extends SysuiTestCase { } static class TestableBubbleController extends BubbleController { // Let's assume surfaces can be synchronized immediately. TestableBubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data) { super(context, statusBarWindowController, data); super(context, statusBarWindowController, data, Runnable::run); } @Override Loading