Loading packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +31 −5 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ package com.android.systemui.bubbles; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.UserHandle; import android.view.LayoutInflater; Loading @@ -37,6 +40,7 @@ class Bubble { private final String mKey; private final String mGroupId; private String mAppName; private final BubbleExpandedView.OnBubbleBlockedListener mListener; private boolean mInflated; Loading @@ -45,6 +49,7 @@ class Bubble { BubbleExpandedView expandedView; private long mLastUpdated; private long mLastAccessed; private PackageManager mPm; public static String groupId(NotificationEntry entry) { UserHandle user = entry.notification.getUser(); Loading @@ -53,16 +58,33 @@ class Bubble { /** Used in tests when no UI is required. */ @VisibleForTesting(visibility = PRIVATE) Bubble(NotificationEntry e) { this (e, null); Bubble(Context context, NotificationEntry e) { this (context, e, null); } Bubble(NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) { Bubble(Context context, NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) { entry = e; mKey = e.key; mLastUpdated = e.notification.getPostTime(); mGroupId = groupId(e); mListener = listener; mPm = context.getPackageManager(); ApplicationInfo info; try { info = mPm.getApplicationInfo( entry.notification.getPackageName(), PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE); if (info != null) { mAppName = String.valueOf(mPm.getApplicationLabel(info)); } } catch (PackageManager.NameNotFoundException unused) { mAppName = entry.notification.getPackageName(); } } public String getKey() { Loading @@ -77,6 +99,10 @@ class Bubble { return entry.notification.getPackageName(); } public String getAppName() { return mAppName; } boolean isInflated() { return mInflated; } Loading @@ -97,9 +123,9 @@ class Bubble { expandedView = (BubbleExpandedView) inflater.inflate( R.layout.bubble_expanded_view, stackView, false /* attachToRoot */); expandedView.setEntry(entry, stackView); expandedView.setEntry(entry, stackView, mAppName); expandedView.setOnBlockedListener(mListener); mInflated = true; } Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +16 −18 Original line number Diff line number Diff line Loading @@ -193,7 +193,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (shouldCollapse) { collapseStack(); } updateVisibility(); updateStack(); } } Loading Loading @@ -534,10 +534,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } // Runs on state change. @Override public void apply() { mNotificationEntryManager.updateNotifications(); updateVisibility(); updateStack(); if (DEBUG) { Log.d(TAG, "[BubbleData]"); Loading @@ -554,34 +555,31 @@ public class BubbleController implements ConfigurationController.ConfigurationLi }; /** * Lets any listeners know if bubble state has changed. * Updates the visibility of the bubbles based on current state. * Does not un-bubble, just hides or un-hides. Notifies any * {@link BubbleStateChangeListener}s of visibility changes. * Updates stack description for TalkBack focus. */ private void updateBubblesShowing() { public void updateStack() { if (mStackView == null) { return; } if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) { // Bubbles only appear in unlocked shade mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE); } else if (mStackView != null) { mStackView.setVisibility(INVISIBLE); } // Let listeners know if bubble state changed. boolean hadBubbles = mStatusBarWindowController.getBubblesShowing(); boolean hasBubblesShowing = hasBubbles() && mStackView.getVisibility() == VISIBLE; mStatusBarWindowController.setBubblesShowing(hasBubblesShowing); if (mStateChangeListener != null && hadBubbles != hasBubblesShowing) { mStateChangeListener.onHasBubblesChanged(hasBubblesShowing); } } /** * Updates the visibility of the bubbles based on current state. * Does not un-bubble, just hides or un-hides. Will notify any * {@link BubbleStateChangeListener}s if visibility changes. */ public void updateVisibility() { if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) { // Bubbles only appear in unlocked shade mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE); } else if (mStackView != null) { mStackView.setVisibility(INVISIBLE); } updateBubblesShowing(); mStackView.updateContentDescription(); } /** Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +1 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ public class BubbleData { Bubble bubble = getBubbleWithKey(entry.key); if (bubble == null) { // Create a new bubble bubble = new Bubble(entry, this::onBubbleBlocked); bubble = new Bubble(mContext, entry, this::onBubbleBlocked); doAdd(bubble); trim(); } else { Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +3 −4 Original line number Diff line number Diff line Loading @@ -244,9 +244,10 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList /** * Sets the notification entry used to populate this view. */ public void setEntry(NotificationEntry entry, BubbleStackView stackView) { public void setEntry(NotificationEntry entry, BubbleStackView stackView, String appName) { mStackView = stackView; mEntry = entry; mAppName = appName; ApplicationInfo info; try { Loading @@ -257,12 +258,10 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE); if (info != null) { mAppName = String.valueOf(mPm.getApplicationLabel(info)); mAppIcon = mPm.getApplicationIcon(info); } } catch (PackageManager.NameNotFoundException e) { // Ahh... just use package name mAppName = entry.notification.getPackageName(); // Do nothing. } if (mAppIcon == null) { mAppIcon = mPm.getDefaultActivityIcon(); Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +38 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.app.Notification; import android.content.Context; import android.content.res.Resources; import android.graphics.ColorMatrix; Loading Loading @@ -553,6 +554,43 @@ public class BubbleStackView extends FrameLayout { return false; } /** * Update content description for a11y TalkBack. */ public void updateContentDescription() { if (mBubbleData.getBubbles().isEmpty()) { return; } Bubble topBubble = mBubbleData.getBubbles().get(0); String appName = topBubble.getAppName(); Notification notification = topBubble.entry.notification.getNotification(); CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE); String titleStr = getResources().getString(R.string.stream_notification); if (titleCharSeq != null) { titleStr = titleCharSeq.toString(); } int moreCount = mBubbleContainer.getChildCount() - 1; // Example: Title from app name. String singleDescription = getResources().getString( R.string.bubble_content_description_single, titleStr, appName); // Example: Title from app name and 4 more. String stackDescription = getResources().getString( R.string.bubble_content_description_stack, titleStr, appName, moreCount); if (mIsExpanded) { // TODO(b/129522932) - update content description for each bubble in expanded view. } else { // Collapsed stack. if (moreCount > 0) { mBubbleContainer.setContentDescription(stackDescription); } else { mBubbleContainer.setContentDescription(singleDescription); } } } private void updateSystemGestureExcludeRects() { // Exclude the region occupied by the first BubbleView in the stack Rect excludeZone = mSystemGestureExclusionRects.get(0); Loading Loading
packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +31 −5 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ package com.android.systemui.bubbles; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.UserHandle; import android.view.LayoutInflater; Loading @@ -37,6 +40,7 @@ class Bubble { private final String mKey; private final String mGroupId; private String mAppName; private final BubbleExpandedView.OnBubbleBlockedListener mListener; private boolean mInflated; Loading @@ -45,6 +49,7 @@ class Bubble { BubbleExpandedView expandedView; private long mLastUpdated; private long mLastAccessed; private PackageManager mPm; public static String groupId(NotificationEntry entry) { UserHandle user = entry.notification.getUser(); Loading @@ -53,16 +58,33 @@ class Bubble { /** Used in tests when no UI is required. */ @VisibleForTesting(visibility = PRIVATE) Bubble(NotificationEntry e) { this (e, null); Bubble(Context context, NotificationEntry e) { this (context, e, null); } Bubble(NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) { Bubble(Context context, NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) { entry = e; mKey = e.key; mLastUpdated = e.notification.getPostTime(); mGroupId = groupId(e); mListener = listener; mPm = context.getPackageManager(); ApplicationInfo info; try { info = mPm.getApplicationInfo( entry.notification.getPackageName(), PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE); if (info != null) { mAppName = String.valueOf(mPm.getApplicationLabel(info)); } } catch (PackageManager.NameNotFoundException unused) { mAppName = entry.notification.getPackageName(); } } public String getKey() { Loading @@ -77,6 +99,10 @@ class Bubble { return entry.notification.getPackageName(); } public String getAppName() { return mAppName; } boolean isInflated() { return mInflated; } Loading @@ -97,9 +123,9 @@ class Bubble { expandedView = (BubbleExpandedView) inflater.inflate( R.layout.bubble_expanded_view, stackView, false /* attachToRoot */); expandedView.setEntry(entry, stackView); expandedView.setEntry(entry, stackView, mAppName); expandedView.setOnBlockedListener(mListener); mInflated = true; } Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +16 −18 Original line number Diff line number Diff line Loading @@ -193,7 +193,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (shouldCollapse) { collapseStack(); } updateVisibility(); updateStack(); } } Loading Loading @@ -534,10 +534,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } // Runs on state change. @Override public void apply() { mNotificationEntryManager.updateNotifications(); updateVisibility(); updateStack(); if (DEBUG) { Log.d(TAG, "[BubbleData]"); Loading @@ -554,34 +555,31 @@ public class BubbleController implements ConfigurationController.ConfigurationLi }; /** * Lets any listeners know if bubble state has changed. * Updates the visibility of the bubbles based on current state. * Does not un-bubble, just hides or un-hides. Notifies any * {@link BubbleStateChangeListener}s of visibility changes. * Updates stack description for TalkBack focus. */ private void updateBubblesShowing() { public void updateStack() { if (mStackView == null) { return; } if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) { // Bubbles only appear in unlocked shade mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE); } else if (mStackView != null) { mStackView.setVisibility(INVISIBLE); } // Let listeners know if bubble state changed. boolean hadBubbles = mStatusBarWindowController.getBubblesShowing(); boolean hasBubblesShowing = hasBubbles() && mStackView.getVisibility() == VISIBLE; mStatusBarWindowController.setBubblesShowing(hasBubblesShowing); if (mStateChangeListener != null && hadBubbles != hasBubblesShowing) { mStateChangeListener.onHasBubblesChanged(hasBubblesShowing); } } /** * Updates the visibility of the bubbles based on current state. * Does not un-bubble, just hides or un-hides. Will notify any * {@link BubbleStateChangeListener}s if visibility changes. */ public void updateVisibility() { if (mStatusBarStateListener.getCurrentState() == SHADE && hasBubbles()) { // Bubbles only appear in unlocked shade mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE); } else if (mStackView != null) { mStackView.setVisibility(INVISIBLE); } updateBubblesShowing(); mStackView.updateContentDescription(); } /** Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +1 −1 Original line number Diff line number Diff line Loading @@ -178,7 +178,7 @@ public class BubbleData { Bubble bubble = getBubbleWithKey(entry.key); if (bubble == null) { // Create a new bubble bubble = new Bubble(entry, this::onBubbleBlocked); bubble = new Bubble(mContext, entry, this::onBubbleBlocked); doAdd(bubble); trim(); } else { Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +3 −4 Original line number Diff line number Diff line Loading @@ -244,9 +244,10 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList /** * Sets the notification entry used to populate this view. */ public void setEntry(NotificationEntry entry, BubbleStackView stackView) { public void setEntry(NotificationEntry entry, BubbleStackView stackView, String appName) { mStackView = stackView; mEntry = entry; mAppName = appName; ApplicationInfo info; try { Loading @@ -257,12 +258,10 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE); if (info != null) { mAppName = String.valueOf(mPm.getApplicationLabel(info)); mAppIcon = mPm.getApplicationIcon(info); } } catch (PackageManager.NameNotFoundException e) { // Ahh... just use package name mAppName = entry.notification.getPackageName(); // Do nothing. } if (mAppIcon == null) { mAppIcon = mPm.getDefaultActivityIcon(); Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +38 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.app.Notification; import android.content.Context; import android.content.res.Resources; import android.graphics.ColorMatrix; Loading Loading @@ -553,6 +554,43 @@ public class BubbleStackView extends FrameLayout { return false; } /** * Update content description for a11y TalkBack. */ public void updateContentDescription() { if (mBubbleData.getBubbles().isEmpty()) { return; } Bubble topBubble = mBubbleData.getBubbles().get(0); String appName = topBubble.getAppName(); Notification notification = topBubble.entry.notification.getNotification(); CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE); String titleStr = getResources().getString(R.string.stream_notification); if (titleCharSeq != null) { titleStr = titleCharSeq.toString(); } int moreCount = mBubbleContainer.getChildCount() - 1; // Example: Title from app name. String singleDescription = getResources().getString( R.string.bubble_content_description_single, titleStr, appName); // Example: Title from app name and 4 more. String stackDescription = getResources().getString( R.string.bubble_content_description_stack, titleStr, appName, moreCount); if (mIsExpanded) { // TODO(b/129522932) - update content description for each bubble in expanded view. } else { // Collapsed stack. if (moreCount > 0) { mBubbleContainer.setContentDescription(stackDescription); } else { mBubbleContainer.setContentDescription(singleDescription); } } } private void updateSystemGestureExcludeRects() { // Exclude the region occupied by the first BubbleView in the stack Rect excludeZone = mSystemGestureExclusionRects.get(0); Loading