diff options
| author | 2019-05-16 12:43:17 -0700 | |
|---|---|---|
| committer | 2019-05-16 12:43:17 -0700 | |
| commit | 26b9cd8a5f7d46c56c612f6bc8166f9e63298eca (patch) | |
| tree | 74dba494b49228a357b0e9d582306cd28acaf677 | |
| parent | 0ce74605e72b511f30a7d0ce4f2502f0f47b956b (diff) | |
| parent | 5b1a00e832a84a84a8431d5f3729a603d6baed71 (diff) | |
Merge "Talkback for focus on collapsed bubble stack" into qt-dev am: 4360543283 am: 169ab54a87
am: 5b1a00e832
Change-Id: If4b605eb6f1b914fffb4dc5feb5a1e1667d572f7
6 files changed, 97 insertions, 36 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java index 8aad0f8bd831..f60e95e32600 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java @@ -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; @@ -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; @@ -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(); @@ -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() { @@ -77,6 +99,10 @@ class Bubble { return entry.notification.getPackageName(); } + public String getAppName() { + return mAppName; + } + boolean isInflated() { return mInflated; } @@ -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; } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 48edf67a3ed4..aed117bb7871 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -193,7 +193,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (shouldCollapse) { collapseStack(); } - updateVisibility(); + updateStack(); } } @@ -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]"); @@ -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(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 9156e06fe54e..1858244d13bc 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -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 { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index 39867c3a0bdb..fa137a1f6207 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -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 { @@ -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(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 4fef157183c2..4ad3a332ebe6 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -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; @@ -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); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java index 33b2e6e59470..364a0f7ed2e9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java @@ -103,13 +103,13 @@ public class BubbleDataTest extends SysuiTestCase { mEntryB3 = createBubbleEntry(1, "b3", "package.b"); mEntryC1 = createBubbleEntry(1, "c1", "package.c"); - mBubbleA1 = new Bubble(mEntryA1); - mBubbleA2 = new Bubble(mEntryA2); - mBubbleA3 = new Bubble(mEntryA3); - mBubbleB1 = new Bubble(mEntryB1); - mBubbleB2 = new Bubble(mEntryB2); - mBubbleB3 = new Bubble(mEntryB3); - mBubbleC1 = new Bubble(mEntryC1); + mBubbleA1 = new Bubble(mContext, mEntryA1); + mBubbleA2 = new Bubble(mContext, mEntryA2); + mBubbleA3 = new Bubble(mContext, mEntryA3); + mBubbleB1 = new Bubble(mContext, mEntryB1); + mBubbleB2 = new Bubble(mContext, mEntryB2); + mBubbleB3 = new Bubble(mContext, mEntryB3); + mBubbleC1 = new Bubble(mContext, mEntryC1); mBubbleData = new BubbleData(getContext()); @@ -803,4 +803,4 @@ public class BubbleDataTest extends SysuiTestCase { private static <T> List<T> listOf(T... a) { return ImmutableList.copyOf(a); } -} +}
\ No newline at end of file |