Loading packages/SystemUI/src/com/android/systemui/Dependency.java +3 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.appops.AppOpsController; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.Bubbles; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; Loading Loading @@ -288,7 +288,7 @@ public class Dependency { @Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil; @Inject Lazy<SmartReplyController> mSmartReplyController; @Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler; @Inject Lazy<BubbleController> mBubbleController; @Inject Lazy<Bubbles> mBubbles; @Inject Lazy<NotificationEntryManager> mNotificationEntryManager; @Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager; @Inject Lazy<AutoHideController> mAutoHideController; Loading Loading @@ -483,7 +483,7 @@ public class Dependency { mProviders.put(SmartReplyController.class, mSmartReplyController::get); mProviders.put(RemoteInputQuickSettingsDisabler.class, mRemoteInputQuickSettingsDisabler::get); mProviders.put(BubbleController.class, mBubbleController::get); mProviders.put(Bubbles.class, mBubbles::get); mProviders.put(NotificationEntryManager.class, mNotificationEntryManager::get); mProviders.put(ForegroundServiceNotificationListener.class, mForegroundServiceNotificationListener::get); Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +24 −75 Original line number Diff line number Diff line Loading @@ -129,7 +129,8 @@ import java.util.Objects; * * The controller manages addition, removal, and visible state of bubbles on screen. */ public class BubbleController implements ConfigurationController.ConfigurationListener, Dumpable { public class BubbleController implements Bubbles, ConfigurationController.ConfigurationListener, Dumpable { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; Loading Loading @@ -520,6 +521,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi /** * See {@link NotifCallback}. */ @Override public void addNotifCallback(NotifCallback callback) { mCallbacks.add(callback); } Loading Loading @@ -701,6 +703,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * since we want the scrim's appearance and behavior to be identical to that of the notification * shade scrim. */ @Override public ScrimView getScrimForBubble() { return mBubbleScrim; } Loading @@ -709,6 +712,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * Called when the status bar has become visible or invisible (either permanently or * temporarily). */ @Override public void onStatusBarVisibilityChanged(boolean visible) { if (mStackView != null) { // Hide the stack temporarily if the status bar has been made invisible, and the stack Loading @@ -726,14 +730,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mInflateSynchronously = inflateSynchronously; } void setOverflowListener(BubbleData.Listener listener) { @Override public void setOverflowListener(BubbleData.Listener listener) { mOverflowListener = listener; } /** * @return Bubbles for updating overflow. */ List<Bubble> getOverflowBubbles() { @Override public List<Bubble> getOverflowBubbles() { return mBubbleData.getOverflowBubbles(); } Loading Loading @@ -956,13 +962,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } boolean inLandscape() { return mOrientation == Configuration.ORIENTATION_LANDSCAPE; } /** * Set a listener to be notified of bubble expand events. */ @Override public void setExpandListener(BubbleExpandListener listener) { mExpandListener = ((isExpanding, key) -> { if (listener != null) { Loading @@ -988,29 +991,17 @@ public class BubbleController implements ConfigurationController.ConfigurationLi return mBubbleData.hasBubbles(); } /** * Whether the stack of bubbles is expanded or not. */ @Override public boolean isStackExpanded() { return mBubbleData.isExpanded(); } /** * Tell the stack of bubbles to collapse. */ @Override public void collapseStack() { mBubbleData.setExpanded(false /* expanded */); } /** * True if either: * (1) There is a bubble associated with the provided key and if its notification is hidden * from the shade. * (2) There is a group summary associated with the provided key that is hidden from the shade * because it has been dismissed but still has child bubbles active. * * False otherwise. */ @Override public boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry) { String key = entry.getKey(); boolean isSuppressedBubble = (mBubbleData.hasAnyBubbleWithKey(key) Loading @@ -1022,19 +1013,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi return (isSummary && isSuppressedSummary) || isSuppressedBubble; } /** * True if: * (1) The current notification entry same as selected bubble notification entry and the * stack is currently expanded. * * False otherwise. */ @Override public boolean isBubbleExpanded(NotificationEntry entry) { return isStackExpanded() && mBubbleData != null && mBubbleData.getSelectedBubble() != null && mBubbleData.getSelectedBubble().getKey().equals(entry.getKey()) ? true : false; } void promoteBubbleFromOverflow(Bubble bubble) { @Override public void promoteBubbleFromOverflow(Bubble bubble) { mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK); bubble.setInflateSynchronously(mInflateSynchronously); bubble.setShouldAutoExpand(true); Loading @@ -1042,12 +1028,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi setIsBubble(bubble, true /* isBubble */); } /** * Request the stack expand if needed, then select the specified Bubble as current. * If no bubble exists for this entry, one is created. * * @param entry the notification for the bubble to be selected */ @Override public void expandStackAndSelectBubble(NotificationEntry entry) { if (mStatusBarStateListener.getCurrentState() == SHADE) { mNotifEntryToExpandOnShadeUnlock = null; Loading Loading @@ -1075,12 +1056,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } /** * When a notification is marked Priority, expand the stack if needed, * then (maybe create and) select the given bubble. * * @param entry the notification for the bubble to show */ @Override public void onUserChangedImportance(NotificationEntry entry) { try { int flags = Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; Loading @@ -1095,10 +1071,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } /** * Directs a back gesture at the bubble stack. When opened, the current expanded bubble * is forwarded a back key down/up pair. */ @Override public void performBackPressIfNeeded() { if (mStackView != null) { mStackView.performBackPressIfNeeded(); Loading Loading @@ -1162,15 +1135,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mContext, mStackView, mBubbleIconFactory, false /* skipInflation */); } /** * Called when a user has indicated that an active notification should be shown as a bubble. * <p> * This method will collapse the shade, create the bubble without a flyout or dot, and suppress * the notification from appearing in the shade. * * @param entry the notification to change bubble state for. * @param shouldBubble whether the notification should show as a bubble or not. */ @Override public void onUserChangedBubble(@NonNull final NotificationEntry entry, boolean shouldBubble) { NotificationChannel channel = entry.getChannel(); final String appPkg = entry.getSbn().getPackageName(); Loading Loading @@ -1209,13 +1174,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } /** * Removes the bubble with the given key. * <p> * Must be called from the main thread. */ @MainThread void removeBubble(String key, int reason) { @Override public void removeBubble(String key, int reason) { if (mBubbleData.hasAnyBubbleWithKey(key)) { mBubbleData.dismissBubbleWithKey(key, reason); } Loading Loading @@ -1457,16 +1418,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } }; /** * We intercept notification entries (including group summaries) dismissed by the user when * there is an active bubble associated with it. We do this so that developers can still * cancel it (and hence the bubbles associated with it). However, these intercepted * notifications should then be hidden from the shade since the user has cancelled them, so we * {@link Bubble#setSuppressNotification}. For the case of suppressed summaries, we also add * {@link BubbleData#addSummaryToSuppress}. * * @return true if we want to intercept the dismissal of the entry, else false. */ @Override public boolean handleDismissalInterception(NotificationEntry entry) { if (entry == null) { return false; Loading Loading @@ -1589,10 +1541,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mStackView.updateContentDescription(); } /** * The display id of the expanded view, if the stack is expanded and not occluded by the * status bar, otherwise returns {@link Display#INVALID_DISPLAY}. */ @Override public int getExpandedDisplayId(Context context) { if (mStackView == null) { return INVALID_DISPLAY; Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +4 −4 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ public class BubbleExpandedView extends LinearLayout { private boolean mIsOverflow; private BubbleController mBubbleController = Dependency.get(BubbleController.class); private Bubbles mBubbles = Dependency.get(Bubbles.class); private WindowManager mWindowManager; private ActivityManager mActivityManager; Loading Loading @@ -168,7 +168,7 @@ public class BubbleExpandedView extends LinearLayout { + "bubble=" + getBubbleKey()); } if (mActivityView == null) { mBubbleController.removeBubble(getBubbleKey(), mBubbles.removeBubble(getBubbleKey(), BubbleController.DISMISS_INVALID_INTENT); return; } Loading @@ -194,7 +194,7 @@ public class BubbleExpandedView extends LinearLayout { // the bubble again so we'll just remove it. Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey() + ", " + e.getMessage() + "; removing bubble"); mBubbleController.removeBubble(getBubbleKey(), mBubbles.removeBubble(getBubbleKey(), BubbleController.DISMISS_INVALID_INTENT); } }); Loading Loading @@ -242,7 +242,7 @@ public class BubbleExpandedView extends LinearLayout { } if (mBubble != null) { // Must post because this is called from a binder thread. post(() -> mBubbleController.removeBubble(mBubble.getKey(), post(() -> mBubbles.removeBubble(mBubble.getKey(), BubbleController.DISMISS_TASK_FINISHED)); } } Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java +9 −9 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ public class BubbleOverflowActivity extends Activity { private TextView mEmptyStateTitle; private TextView mEmptyStateSubtitle; private ImageView mEmptyStateImage; private BubbleController mBubbleController; private Bubbles mBubbles; private BubbleOverflowAdapter mAdapter; private RecyclerView mRecyclerView; private List<Bubble> mOverflowBubbles = new ArrayList<>(); Loading @@ -71,7 +71,8 @@ public class BubbleOverflowActivity extends Activity { } @Override public boolean canScrollVertically() { if (mBubbleController.inLandscape()) { if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { return super.canScrollVertically(); } return false; Loading @@ -93,8 +94,8 @@ public class BubbleOverflowActivity extends Activity { } @Inject public BubbleOverflowActivity(BubbleController controller) { mBubbleController = controller; public BubbleOverflowActivity(Bubbles bubbles) { mBubbles = bubbles; } @Override Loading Loading @@ -131,15 +132,15 @@ public class BubbleOverflowActivity extends Activity { final int viewHeight = recyclerViewHeight / rows; mAdapter = new BubbleOverflowAdapter(getApplicationContext(), mOverflowBubbles, mBubbleController::promoteBubbleFromOverflow, viewWidth, viewHeight); mBubbles::promoteBubbleFromOverflow, viewWidth, viewHeight); mRecyclerView.setAdapter(mAdapter); mOverflowBubbles.clear(); mOverflowBubbles.addAll(mBubbleController.getOverflowBubbles()); mOverflowBubbles.addAll(mBubbles.getOverflowBubbles()); mAdapter.notifyDataSetChanged(); updateEmptyStateVisibility(); mBubbleController.setOverflowListener(mDataListener); mBubbles.setOverflowListener(mDataListener); updateTheme(); } Loading Loading @@ -209,8 +210,7 @@ public class BubbleOverflowActivity extends Activity { if (DEBUG_OVERFLOW) { Log.d(TAG, BubbleDebugConfig.formatBubblesString( mBubbleController.getOverflowBubbles(), null)); mBubbles.getOverflowBubbles(), null)); } } }; Loading packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bubbles; import android.annotation.NonNull; import android.content.Context; import android.view.Display; import androidx.annotation.MainThread; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.phone.ScrimController; import java.util.List; /** * Interface to engage bubbles feature. */ public interface Bubbles { /** * @return {@code true} if there is a bubble associated with the provided key and if its * notification is hidden from the shade or there is a group summary associated with the * provided key that is hidden from the shade because it has been dismissed but still has child * bubbles active. */ boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry); /** * @return {@code true} if the current notification entry same as selected bubble * notification entry and the stack is currently expanded. */ boolean isBubbleExpanded(NotificationEntry entry); /** @return {@code true} if stack of bubbles is expanded or not. */ boolean isStackExpanded(); /** * @return the {@link ScrimView} drawn behind the bubble stack. This is managed by * {@link ScrimController} since we want the scrim's appearance and behavior to be identical to * that of the notification shade scrim. */ ScrimView getScrimForBubble(); /** * @return the display id of the expanded view, if the stack is expanded and not occluded by the * status bar, otherwise returns {@link Display#INVALID_DISPLAY}. */ int getExpandedDisplayId(Context context); /** @return Bubbles for updating overflow. */ List<Bubble> getOverflowBubbles(); /** Tell the stack of bubbles to collapse. */ void collapseStack(); /** * Request the stack expand if needed, then select the specified Bubble as current. * If no bubble exists for this entry, one is created. * * @param entry the notification for the bubble to be selected */ void expandStackAndSelectBubble(NotificationEntry entry); /** * Directs a back gesture at the bubble stack. When opened, the current expanded bubble * is forwarded a back key down/up pair. */ void performBackPressIfNeeded(); /** Promote the provided bubbles when overflow view. */ void promoteBubbleFromOverflow(Bubble bubble); /** * We intercept notification entries (including group summaries) dismissed by the user when * there is an active bubble associated with it. We do this so that developers can still * cancel it (and hence the bubbles associated with it). However, these intercepted * notifications should then be hidden from the shade since the user has cancelled them, so we * {@link Bubble#setSuppressNotification}. For the case of suppressed summaries, we also add * {@link BubbleData#addSummaryToSuppress}. * * @return true if we want to intercept the dismissal of the entry, else false. */ boolean handleDismissalInterception(NotificationEntry entry); /** * Removes the bubble with the given key. * <p> * Must be called from the main thread. */ @MainThread void removeBubble(String key, int reason); /** * When a notification is marked Priority, expand the stack if needed, * then (maybe create and) select the given bubble. * * @param entry the notification for the bubble to show */ void onUserChangedImportance(NotificationEntry entry); /** * Called when the status bar has become visible or invisible (either permanently or * temporarily). */ void onStatusBarVisibilityChanged(boolean visible); /** * Called when a user has indicated that an active notification should be shown as a bubble. * <p> * This method will collapse the shade, create the bubble without a flyout or dot, and suppress * the notification from appearing in the shade. * * @param entry the notification to change bubble state for. * @param shouldBubble whether the notification should show as a bubble or not. */ void onUserChangedBubble(@NonNull NotificationEntry entry, boolean shouldBubble); /** See {@link BubbleController.NotifCallback}. */ void addNotifCallback(BubbleController.NotifCallback callback); /** Set a listener to be notified of bubble expand events. */ void setExpandListener(BubbleController.BubbleExpandListener listener); /** Set a listener to be notified of when overflow view update. */ void setOverflowListener(BubbleData.Listener listener); } Loading
packages/SystemUI/src/com/android/systemui/Dependency.java +3 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.appops.AppOpsController; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.Bubbles; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; Loading Loading @@ -288,7 +288,7 @@ public class Dependency { @Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil; @Inject Lazy<SmartReplyController> mSmartReplyController; @Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler; @Inject Lazy<BubbleController> mBubbleController; @Inject Lazy<Bubbles> mBubbles; @Inject Lazy<NotificationEntryManager> mNotificationEntryManager; @Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager; @Inject Lazy<AutoHideController> mAutoHideController; Loading Loading @@ -483,7 +483,7 @@ public class Dependency { mProviders.put(SmartReplyController.class, mSmartReplyController::get); mProviders.put(RemoteInputQuickSettingsDisabler.class, mRemoteInputQuickSettingsDisabler::get); mProviders.put(BubbleController.class, mBubbleController::get); mProviders.put(Bubbles.class, mBubbles::get); mProviders.put(NotificationEntryManager.class, mNotificationEntryManager::get); mProviders.put(ForegroundServiceNotificationListener.class, mForegroundServiceNotificationListener::get); Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +24 −75 Original line number Diff line number Diff line Loading @@ -129,7 +129,8 @@ import java.util.Objects; * * The controller manages addition, removal, and visible state of bubbles on screen. */ public class BubbleController implements ConfigurationController.ConfigurationListener, Dumpable { public class BubbleController implements Bubbles, ConfigurationController.ConfigurationListener, Dumpable { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; Loading Loading @@ -520,6 +521,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi /** * See {@link NotifCallback}. */ @Override public void addNotifCallback(NotifCallback callback) { mCallbacks.add(callback); } Loading Loading @@ -701,6 +703,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * since we want the scrim's appearance and behavior to be identical to that of the notification * shade scrim. */ @Override public ScrimView getScrimForBubble() { return mBubbleScrim; } Loading @@ -709,6 +712,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * Called when the status bar has become visible or invisible (either permanently or * temporarily). */ @Override public void onStatusBarVisibilityChanged(boolean visible) { if (mStackView != null) { // Hide the stack temporarily if the status bar has been made invisible, and the stack Loading @@ -726,14 +730,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mInflateSynchronously = inflateSynchronously; } void setOverflowListener(BubbleData.Listener listener) { @Override public void setOverflowListener(BubbleData.Listener listener) { mOverflowListener = listener; } /** * @return Bubbles for updating overflow. */ List<Bubble> getOverflowBubbles() { @Override public List<Bubble> getOverflowBubbles() { return mBubbleData.getOverflowBubbles(); } Loading Loading @@ -956,13 +962,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } boolean inLandscape() { return mOrientation == Configuration.ORIENTATION_LANDSCAPE; } /** * Set a listener to be notified of bubble expand events. */ @Override public void setExpandListener(BubbleExpandListener listener) { mExpandListener = ((isExpanding, key) -> { if (listener != null) { Loading @@ -988,29 +991,17 @@ public class BubbleController implements ConfigurationController.ConfigurationLi return mBubbleData.hasBubbles(); } /** * Whether the stack of bubbles is expanded or not. */ @Override public boolean isStackExpanded() { return mBubbleData.isExpanded(); } /** * Tell the stack of bubbles to collapse. */ @Override public void collapseStack() { mBubbleData.setExpanded(false /* expanded */); } /** * True if either: * (1) There is a bubble associated with the provided key and if its notification is hidden * from the shade. * (2) There is a group summary associated with the provided key that is hidden from the shade * because it has been dismissed but still has child bubbles active. * * False otherwise. */ @Override public boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry) { String key = entry.getKey(); boolean isSuppressedBubble = (mBubbleData.hasAnyBubbleWithKey(key) Loading @@ -1022,19 +1013,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi return (isSummary && isSuppressedSummary) || isSuppressedBubble; } /** * True if: * (1) The current notification entry same as selected bubble notification entry and the * stack is currently expanded. * * False otherwise. */ @Override public boolean isBubbleExpanded(NotificationEntry entry) { return isStackExpanded() && mBubbleData != null && mBubbleData.getSelectedBubble() != null && mBubbleData.getSelectedBubble().getKey().equals(entry.getKey()) ? true : false; } void promoteBubbleFromOverflow(Bubble bubble) { @Override public void promoteBubbleFromOverflow(Bubble bubble) { mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK); bubble.setInflateSynchronously(mInflateSynchronously); bubble.setShouldAutoExpand(true); Loading @@ -1042,12 +1028,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi setIsBubble(bubble, true /* isBubble */); } /** * Request the stack expand if needed, then select the specified Bubble as current. * If no bubble exists for this entry, one is created. * * @param entry the notification for the bubble to be selected */ @Override public void expandStackAndSelectBubble(NotificationEntry entry) { if (mStatusBarStateListener.getCurrentState() == SHADE) { mNotifEntryToExpandOnShadeUnlock = null; Loading Loading @@ -1075,12 +1056,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } /** * When a notification is marked Priority, expand the stack if needed, * then (maybe create and) select the given bubble. * * @param entry the notification for the bubble to show */ @Override public void onUserChangedImportance(NotificationEntry entry) { try { int flags = Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION; Loading @@ -1095,10 +1071,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } /** * Directs a back gesture at the bubble stack. When opened, the current expanded bubble * is forwarded a back key down/up pair. */ @Override public void performBackPressIfNeeded() { if (mStackView != null) { mStackView.performBackPressIfNeeded(); Loading Loading @@ -1162,15 +1135,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mContext, mStackView, mBubbleIconFactory, false /* skipInflation */); } /** * Called when a user has indicated that an active notification should be shown as a bubble. * <p> * This method will collapse the shade, create the bubble without a flyout or dot, and suppress * the notification from appearing in the shade. * * @param entry the notification to change bubble state for. * @param shouldBubble whether the notification should show as a bubble or not. */ @Override public void onUserChangedBubble(@NonNull final NotificationEntry entry, boolean shouldBubble) { NotificationChannel channel = entry.getChannel(); final String appPkg = entry.getSbn().getPackageName(); Loading Loading @@ -1209,13 +1174,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } /** * Removes the bubble with the given key. * <p> * Must be called from the main thread. */ @MainThread void removeBubble(String key, int reason) { @Override public void removeBubble(String key, int reason) { if (mBubbleData.hasAnyBubbleWithKey(key)) { mBubbleData.dismissBubbleWithKey(key, reason); } Loading Loading @@ -1457,16 +1418,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } }; /** * We intercept notification entries (including group summaries) dismissed by the user when * there is an active bubble associated with it. We do this so that developers can still * cancel it (and hence the bubbles associated with it). However, these intercepted * notifications should then be hidden from the shade since the user has cancelled them, so we * {@link Bubble#setSuppressNotification}. For the case of suppressed summaries, we also add * {@link BubbleData#addSummaryToSuppress}. * * @return true if we want to intercept the dismissal of the entry, else false. */ @Override public boolean handleDismissalInterception(NotificationEntry entry) { if (entry == null) { return false; Loading Loading @@ -1589,10 +1541,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mStackView.updateContentDescription(); } /** * The display id of the expanded view, if the stack is expanded and not occluded by the * status bar, otherwise returns {@link Display#INVALID_DISPLAY}. */ @Override public int getExpandedDisplayId(Context context) { if (mStackView == null) { return INVALID_DISPLAY; Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +4 −4 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ public class BubbleExpandedView extends LinearLayout { private boolean mIsOverflow; private BubbleController mBubbleController = Dependency.get(BubbleController.class); private Bubbles mBubbles = Dependency.get(Bubbles.class); private WindowManager mWindowManager; private ActivityManager mActivityManager; Loading Loading @@ -168,7 +168,7 @@ public class BubbleExpandedView extends LinearLayout { + "bubble=" + getBubbleKey()); } if (mActivityView == null) { mBubbleController.removeBubble(getBubbleKey(), mBubbles.removeBubble(getBubbleKey(), BubbleController.DISMISS_INVALID_INTENT); return; } Loading @@ -194,7 +194,7 @@ public class BubbleExpandedView extends LinearLayout { // the bubble again so we'll just remove it. Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey() + ", " + e.getMessage() + "; removing bubble"); mBubbleController.removeBubble(getBubbleKey(), mBubbles.removeBubble(getBubbleKey(), BubbleController.DISMISS_INVALID_INTENT); } }); Loading Loading @@ -242,7 +242,7 @@ public class BubbleExpandedView extends LinearLayout { } if (mBubble != null) { // Must post because this is called from a binder thread. post(() -> mBubbleController.removeBubble(mBubble.getKey(), post(() -> mBubbles.removeBubble(mBubble.getKey(), BubbleController.DISMISS_TASK_FINISHED)); } } Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java +9 −9 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ public class BubbleOverflowActivity extends Activity { private TextView mEmptyStateTitle; private TextView mEmptyStateSubtitle; private ImageView mEmptyStateImage; private BubbleController mBubbleController; private Bubbles mBubbles; private BubbleOverflowAdapter mAdapter; private RecyclerView mRecyclerView; private List<Bubble> mOverflowBubbles = new ArrayList<>(); Loading @@ -71,7 +71,8 @@ public class BubbleOverflowActivity extends Activity { } @Override public boolean canScrollVertically() { if (mBubbleController.inLandscape()) { if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { return super.canScrollVertically(); } return false; Loading @@ -93,8 +94,8 @@ public class BubbleOverflowActivity extends Activity { } @Inject public BubbleOverflowActivity(BubbleController controller) { mBubbleController = controller; public BubbleOverflowActivity(Bubbles bubbles) { mBubbles = bubbles; } @Override Loading Loading @@ -131,15 +132,15 @@ public class BubbleOverflowActivity extends Activity { final int viewHeight = recyclerViewHeight / rows; mAdapter = new BubbleOverflowAdapter(getApplicationContext(), mOverflowBubbles, mBubbleController::promoteBubbleFromOverflow, viewWidth, viewHeight); mBubbles::promoteBubbleFromOverflow, viewWidth, viewHeight); mRecyclerView.setAdapter(mAdapter); mOverflowBubbles.clear(); mOverflowBubbles.addAll(mBubbleController.getOverflowBubbles()); mOverflowBubbles.addAll(mBubbles.getOverflowBubbles()); mAdapter.notifyDataSetChanged(); updateEmptyStateVisibility(); mBubbleController.setOverflowListener(mDataListener); mBubbles.setOverflowListener(mDataListener); updateTheme(); } Loading Loading @@ -209,8 +210,7 @@ public class BubbleOverflowActivity extends Activity { if (DEBUG_OVERFLOW) { Log.d(TAG, BubbleDebugConfig.formatBubblesString( mBubbleController.getOverflowBubbles(), null)); mBubbles.getOverflowBubbles(), null)); } } }; Loading
packages/SystemUI/src/com/android/systemui/bubbles/Bubbles.java 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bubbles; import android.annotation.NonNull; import android.content.Context; import android.view.Display; import androidx.annotation.MainThread; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.phone.ScrimController; import java.util.List; /** * Interface to engage bubbles feature. */ public interface Bubbles { /** * @return {@code true} if there is a bubble associated with the provided key and if its * notification is hidden from the shade or there is a group summary associated with the * provided key that is hidden from the shade because it has been dismissed but still has child * bubbles active. */ boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry); /** * @return {@code true} if the current notification entry same as selected bubble * notification entry and the stack is currently expanded. */ boolean isBubbleExpanded(NotificationEntry entry); /** @return {@code true} if stack of bubbles is expanded or not. */ boolean isStackExpanded(); /** * @return the {@link ScrimView} drawn behind the bubble stack. This is managed by * {@link ScrimController} since we want the scrim's appearance and behavior to be identical to * that of the notification shade scrim. */ ScrimView getScrimForBubble(); /** * @return the display id of the expanded view, if the stack is expanded and not occluded by the * status bar, otherwise returns {@link Display#INVALID_DISPLAY}. */ int getExpandedDisplayId(Context context); /** @return Bubbles for updating overflow. */ List<Bubble> getOverflowBubbles(); /** Tell the stack of bubbles to collapse. */ void collapseStack(); /** * Request the stack expand if needed, then select the specified Bubble as current. * If no bubble exists for this entry, one is created. * * @param entry the notification for the bubble to be selected */ void expandStackAndSelectBubble(NotificationEntry entry); /** * Directs a back gesture at the bubble stack. When opened, the current expanded bubble * is forwarded a back key down/up pair. */ void performBackPressIfNeeded(); /** Promote the provided bubbles when overflow view. */ void promoteBubbleFromOverflow(Bubble bubble); /** * We intercept notification entries (including group summaries) dismissed by the user when * there is an active bubble associated with it. We do this so that developers can still * cancel it (and hence the bubbles associated with it). However, these intercepted * notifications should then be hidden from the shade since the user has cancelled them, so we * {@link Bubble#setSuppressNotification}. For the case of suppressed summaries, we also add * {@link BubbleData#addSummaryToSuppress}. * * @return true if we want to intercept the dismissal of the entry, else false. */ boolean handleDismissalInterception(NotificationEntry entry); /** * Removes the bubble with the given key. * <p> * Must be called from the main thread. */ @MainThread void removeBubble(String key, int reason); /** * When a notification is marked Priority, expand the stack if needed, * then (maybe create and) select the given bubble. * * @param entry the notification for the bubble to show */ void onUserChangedImportance(NotificationEntry entry); /** * Called when the status bar has become visible or invisible (either permanently or * temporarily). */ void onStatusBarVisibilityChanged(boolean visible); /** * Called when a user has indicated that an active notification should be shown as a bubble. * <p> * This method will collapse the shade, create the bubble without a flyout or dot, and suppress * the notification from appearing in the shade. * * @param entry the notification to change bubble state for. * @param shouldBubble whether the notification should show as a bubble or not. */ void onUserChangedBubble(@NonNull NotificationEntry entry, boolean shouldBubble); /** See {@link BubbleController.NotifCallback}. */ void addNotifCallback(BubbleController.NotifCallback callback); /** Set a listener to be notified of bubble expand events. */ void setExpandListener(BubbleController.BubbleExpandListener listener); /** Set a listener to be notified of when overflow view update. */ void setOverflowListener(BubbleData.Listener listener); }