diff options
author | Christoph Studer <chstuder@google.com> | 2014-07-25 17:50:30 +0200 |
---|---|---|
committer | Christoph Studer <chstuder@google.com> | 2014-07-30 21:43:17 +0200 |
commit | c8db24bc32034accf1eb614c8d68bb80b41ae73f (patch) | |
tree | 169263034e6bb7a71586b93e1766bdb04d8dda3e /packages | |
parent | 4579fd2d0c23f92546633e472439f9207acb3ae0 (diff) | |
download | frameworks_base-c8db24bc32034accf1eb614c8d68bb80b41ae73f.zip frameworks_base-c8db24bc32034accf1eb614c8d68bb80b41ae73f.tar.gz frameworks_base-c8db24bc32034accf1eb614c8d68bb80b41ae73f.tar.bz2 |
SysUI: Display group children when no summary is present
Also move common notification filtering into NotificationData
such that clients won't have to do it themselves anymore.
Probably also fixes a couple of multi-user issues.
Bug: 16302692
Bug: 16224431
Change-Id: Ic3c11cd1a224044486f5544e068ca5297d30c521
Diffstat (limited to 'packages')
4 files changed, 216 insertions, 194 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index f8cdd40..8eca0ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -36,7 +36,6 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.database.ContentObserver; import android.graphics.Rect; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; @@ -96,7 +95,8 @@ import static com.android.keyguard.KeyguardHostView.OnDismissAction; public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener, - RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger { + RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger, + NotificationData.Environment { public static final String TAG = "StatusBar"; public static final boolean DEBUG = false; public static final boolean MULTIUSER_DEBUG = false; @@ -132,7 +132,7 @@ public abstract class BaseStatusBar extends SystemUI implements protected H mHandler = createHandler(); // all notifications - protected NotificationData mNotificationData = new NotificationData(); + protected NotificationData mNotificationData; protected NotificationStackScrollLayout mStackScroller; // for heads up notifications @@ -201,6 +201,7 @@ public abstract class BaseStatusBar extends SystemUI implements protected NotificationOverflowContainer mKeyguardIconOverflowContainer; protected DismissView mDismissView; + @Override // NotificationData.Environment public boolean isDeviceProvisioned() { return mDeviceProvisioned; } @@ -304,10 +305,6 @@ public abstract class BaseStatusBar extends SystemUI implements @Override public void run() { for (StatusBarNotification sbn : notifications) { - if (shouldFilterOut(sbn.getNotification())) { - if (DEBUG) Log.d(TAG, "Ignoring notification: " + sbn); - continue; - } addNotification(sbn, currentRanking); } } @@ -322,20 +319,8 @@ public abstract class BaseStatusBar extends SystemUI implements @Override public void run() { Notification n = sbn.getNotification(); - boolean isUpdate = mNotificationData.findByKey(sbn.getKey()) != null + boolean isUpdate = mNotificationData.get(sbn.getKey()) != null || isHeadsUp(sbn.getKey()); - if (shouldFilterOut(n)) { - if (DEBUG) Log.d(TAG, "Ignoring notification: " + sbn); - // If this is an update, i.e. the notification existed - // before but wasn't filtered out, remove the old - // instance. Otherwise just update the ranking. - if (isUpdate) { - removeNotification(sbn.getKey(), rankingMap); - } else { - updateNotificationRanking(rankingMap); - } - return; - } if (isUpdate) { updateNotification(sbn, rankingMap); } else { @@ -368,11 +353,6 @@ public abstract class BaseStatusBar extends SystemUI implements }); } - private boolean shouldFilterOut(Notification n) { - // Don't accept group children. - return n.getGroup() != null - && (n.flags & Notification.FLAG_GROUP_SUMMARY) == 0; - } }; private void updateCurrentProfilesCache() { @@ -391,6 +371,8 @@ public abstract class BaseStatusBar extends SystemUI implements mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); mDisplay = mWindowManager.getDefaultDisplay(); + mNotificationData = new NotificationData(this); + mDreamManager = IDreamManager.Stub.asInterface( ServiceManager.checkService(DreamService.DREAM_SERVICE)); mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); @@ -499,7 +481,8 @@ public abstract class BaseStatusBar extends SystemUI implements return mHeadsUpNotificationView != null && mHeadsUpNotificationView.isShowing(key); } - public boolean notificationIsForCurrentProfiles(StatusBarNotification n) { + @Override // NotificationData.Environment + public boolean isNotificationForCurrentProfiles(StatusBarNotification n) { final int thisUserId = mCurrentUserId; final int notificationUserId = n.getUserId(); if (DEBUG && MULTIUSER_DEBUG) { @@ -881,6 +864,16 @@ public abstract class BaseStatusBar extends SystemUI implements return mUsersAllowingPrivateNotifications.get(userHandle); } + /** + * Returns true if we're on a secure lockscreen and the user wants to hide "sensitive" + * notification data. If so, private notifications should show their (possibly + * auto-generated) publicVersion, and secret notifications should be totally invisible. + */ + @Override // NotificationData.Environment + public boolean shouldHideSensitiveContents(int userid) { + return isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(userid); + } + public void onNotificationClear(StatusBarNotification notification) { try { mBarService.onNotificationClear( @@ -1381,11 +1374,14 @@ public abstract class BaseStatusBar extends SystemUI implements protected void updateRowStates() { int maxKeyguardNotifications = getMaxKeyguardNotifications(); mKeyguardIconOverflowContainer.getIconsView().removeAllViews(); - final int N = mNotificationData.size(); + + ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); + final int N = activeNotifications.size(); + int visibleNotifications = 0; boolean onKeyguard = mState == StatusBarState.KEYGUARD; for (int i = 0; i < N; i++) { - NotificationData.Entry entry = mNotificationData.get(i); + NotificationData.Entry entry = activeNotifications.get(i); if (onKeyguard) { entry.row.setExpansionDisabled(true); } else { @@ -1461,7 +1457,7 @@ public abstract class BaseStatusBar extends SystemUI implements if (wasHeadsUp) { oldEntry = mHeadsUpNotificationView.getEntry(); } else { - oldEntry = mNotificationData.findByKey(key); + oldEntry = mNotificationData.get(key); } if (oldEntry == null) { return; @@ -1620,6 +1616,7 @@ public abstract class BaseStatusBar extends SystemUI implements notification.getNotification().tickerText); oldEntry.icon.set(ic); inflateViews(oldEntry, mStackScroller, wasHeadsUp); + mNotificationData.updateRanking(ranking); updateNotifications(); } } @@ -1630,7 +1627,7 @@ public abstract class BaseStatusBar extends SystemUI implements updateNotificationVetoButton(oldEntry.row, notification); // Is this for you? - boolean isForCurrentUser = notificationIsForCurrentProfiles(notification); + boolean isForCurrentUser = isNotificationForCurrentProfiles(notification); if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you"); // Restart the ticker if it's still running @@ -1725,14 +1722,6 @@ public abstract class BaseStatusBar extends SystemUI implements return interrupt; } - // Q: What kinds of notifications should show during setup? - // A: Almost none! Only things coming from the system (package is "android") that also - // have special "kind" tags marking them as relevant for setup (see below). - protected boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) { - return "android".equals(sbn.getPackageName()) - && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP); - } - public boolean inKeyguardRestrictedInputMode() { return KeyguardTouchDelegate.getInstance(mContext).isInputRestricted(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index a1ab7ec..7581cc9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -20,18 +20,22 @@ import android.app.Notification; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; +import android.util.ArrayMap; +import android.util.ArraySet; import android.view.View; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; /** * The list of currently displaying notifications. - * - * TODO: Rename to NotificationList. */ public class NotificationData { + + private final Environment mEnvironment; + public static final class Entry { public String key; public StatusBarNotification notification; @@ -44,7 +48,6 @@ public class NotificationData { public boolean autoRedacted; // whether the redacted notification was generated by us public boolean legacy; // whether the notification has a legacy, dark background - public Entry() {} public Entry(StatusBarNotification n, StatusBarIconView ic) { this.key = n.getKey(); this.notification = n; @@ -58,12 +61,6 @@ public class NotificationData { return expandedBig; } public View getPublicContentView() { return expandedPublic; } - /** - * Set the flag indicating that this is being touched by the user. - */ - public void setUserLocked(boolean userLocked) { - row.setUserLocked(userLocked); - } public void setInterruption() { interruption = true; @@ -90,7 +87,9 @@ public class NotificationData { } } - private final ArrayList<Entry> mEntries = new ArrayList<Entry>(); + private final ArrayMap<String, Entry> mEntries = new ArrayMap<>(); + private final ArrayList<Entry> mSortedAndFiltered = new ArrayList<>(); + private RankingMap mRankingMap; private final Ranking mTmpRanking = new Ranking(); private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() { @@ -118,36 +117,37 @@ public class NotificationData { } }; - public int size() { - return mEntries.size(); + public NotificationData(Environment environment) { + mEnvironment = environment; } - public Entry get(int i) { - return mEntries.get(i); + /** + * Returns the sorted list of active notifications (depending on {@link Environment} + * + * <p> + * This call doesn't update the list of active notifications. Call {@link #filterAndSort()} + * when the environment changes. + * <p> + * Don't hold on to or modify the returned list. + */ + public ArrayList<Entry> getActiveNotifications() { + return mSortedAndFiltered; } - public Entry findByKey(String key) { - for (Entry e : mEntries) { - if (e.key.equals(key)) { - return e; - } - } - return null; + public Entry get(String key) { + return mEntries.get(key); } public void add(Entry entry, RankingMap ranking) { - mEntries.add(entry); + mEntries.put(entry.notification.getKey(), entry); updateRankingAndSort(ranking); } public Entry remove(String key, RankingMap ranking) { - Entry e = findByKey(key); - if (e == null) { - return null; - } - mEntries.remove(e); + Entry removed = mEntries.remove(key); + if (removed == null) return null; updateRankingAndSort(ranking); - return e; + return removed; } public void updateRanking(RankingMap ranking) { @@ -155,45 +155,79 @@ public class NotificationData { } public boolean isAmbient(String key) { - // TODO: Remove when switching to NotificationListener. - if (mRankingMap == null) { - for (Entry entry : mEntries) { - if (key.equals(entry.key)) { - return entry.notification.getNotification().priority == - Notification.PRIORITY_MIN; - } - } - } else { - mRankingMap.getRanking(key, mTmpRanking); - return mTmpRanking.isAmbient(); - } - return false; + mRankingMap.getRanking(key, mTmpRanking); + return mTmpRanking.isAmbient(); } private void updateRankingAndSort(RankingMap ranking) { if (ranking != null) { mRankingMap = ranking; } - Collections.sort(mEntries, mRankingComparator); + filterAndSort(); } - /** - * Return whether there are any visible items (i.e. items without an error). - */ - public boolean hasVisibleItems() { - for (Entry e : mEntries) { - if (e.expanded != null) { // the view successfully inflated - return true; + // TODO: This should not be public. Instead the Environment should notify this class when + // anything changed, and this class should call back the UI so it updates itself. + public void filterAndSort() { + mSortedAndFiltered.clear(); + + ArraySet<String> groupsWithSummaries = null; + final int N = mEntries.size(); + for (int i = 0; i < N; i++) { + Entry entry = mEntries.valueAt(i); + StatusBarNotification sbn = entry.notification; + + if (shouldFilterOut(sbn)) { + continue; + } + + if (sbn.getNotification().isGroupSummary()) { + if (groupsWithSummaries == null) { + groupsWithSummaries = new ArraySet<>(); + } + groupsWithSummaries.add(sbn.getGroupKey()); + } + mSortedAndFiltered.add(entry); + } + + // Second pass: Filter out group children with summary. + if (groupsWithSummaries != null) { + final int M = mSortedAndFiltered.size(); + for (int i = M - 1; i >= 0; i--) { + Entry ent = mSortedAndFiltered.get(i); + StatusBarNotification sbn = ent.notification; + if (sbn.getNotification().isGroupChild() && + groupsWithSummaries.contains(sbn.getGroupKey())) { + mSortedAndFiltered.remove(i); + } } } + + Collections.sort(mSortedAndFiltered, mRankingComparator); + } + + private boolean shouldFilterOut(StatusBarNotification sbn) { + if (!(mEnvironment.isDeviceProvisioned() || + showNotificationEvenIfUnprovisioned(sbn))) { + return true; + } + + if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) { + return true; + } + + if (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET && + mEnvironment.shouldHideSensitiveContents(sbn.getUserId())) { + return true; + } return false; } /** - * Return whether there are any clearable items (that aren't errors). + * Return whether there are any clearable notifications (that aren't errors). */ - public boolean hasClearableItems() { - for (Entry e : mEntries) { + public boolean hasActiveClearableNotifications() { + for (Entry e : mSortedAndFiltered) { if (e.expanded != null) { // the view successfully inflated if (e.notification.isClearable()) { return true; @@ -202,4 +236,54 @@ public class NotificationData { } return false; } + + // Q: What kinds of notifications should show during setup? + // A: Almost none! Only things coming from the system (package is "android") that also + // have special "kind" tags marking them as relevant for setup (see below). + public static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) { + return "android".equals(sbn.getPackageName()) + && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP); + } + + public void dump(PrintWriter pw, String indent) { + int N = mSortedAndFiltered.size(); + pw.print(indent); + pw.println("active notifications: " + N); + for (int i = 0; i < N; i++) { + NotificationData.Entry e = mSortedAndFiltered.get(i); + dumpEntry(pw, indent, i, e); + } + + int M = mEntries.size(); + pw.print(indent); + pw.println("inactive notifications: " + M); + for (int i = 0; i < M; i++) { + Entry entry = mEntries.valueAt(i); + if (!mSortedAndFiltered.contains(entry)) { + dumpEntry(pw, indent, i, entry); + } + } + } + + private void dumpEntry(PrintWriter pw, String indent, int i, Entry e) { + pw.print(indent); + pw.println(" [" + i + "] key=" + e.key + " icon=" + e.icon); + StatusBarNotification n = e.notification; + pw.print(indent); + pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" + n + .getScore()); + pw.print(indent); + pw.println(" notification=" + n.getNotification()); + pw.print(indent); + pw.println(" tickerText=\"" + n.getNotification().tickerText + "\""); + } + + /** + * Provides access to keyguard state and user settings dependent data. + */ + public interface Environment { + public boolean shouldHideSensitiveContents(int userId); + public boolean isDeviceProvisioned(); + public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 6644a6c..cccfb7b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1346,7 +1346,7 @@ public class NotificationPanelView extends PanelView implements float factor = 1f; if (mNotificationStackScroller.getNotGoneChildCount() > 0) { factor = 0.6f; - } else if (!mStatusBar.hasNotifications()) { + } else if (!mStatusBar.hasActiveNotifications()) { factor = 0.4f; } mEmptyDragAmount = amount * factor; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 044f69c..20a4092 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -453,8 +453,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private Runnable mLaunchTransitionEndRunnable; private boolean mLaunchTransitionFadingAway; - private boolean mHasNotifications; - private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD | ViewState.LOCATION_TOP_STACK_PEEKING | ViewState.LOCATION_MAIN_AREA @@ -498,9 +496,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // notifications. // 3. Report newly visible and no-longer visible notifications. // 4. Keep currently visible notifications for next report. - int N = mNotificationData.size(); + ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); + int N = activeNotifications.size(); for (int i = 0; i < N; i++) { - Entry entry = mNotificationData.get(i); + Entry entry = activeNotifications.get(i); String key = entry.notification.getKey(); boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key); boolean currentlyVisible = @@ -1314,7 +1313,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Recalculate the position of the sliding windows and the titles. updateExpandedViewPos(EXPANDED_LEAVE_ALONE); - if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 + if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications() && !mNotificationPanel.isTracking()) { if (mState == StatusBarState.SHADE) { animateCollapsePanels(); @@ -1342,27 +1341,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private void updateNotificationShade() { if (mStackScroller == null) return; - int N = mNotificationData.size(); - - ArrayList<View> toShow = new ArrayList<View>(); - - final boolean provisioned = isDeviceProvisioned(); - // If the device hasn't been through Setup, we only show system notifications + ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); + ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size()); + final int N = activeNotifications.size(); for (int i=0; i<N; i++) { - Entry ent = mNotificationData.get(i); - if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue; - - if (!notificationIsForCurrentProfiles(ent.notification)) continue; + Entry ent = activeNotifications.get(i); + int vis = ent.notification.getNotification().visibility; + // Display public version of the notification if we need to redact. final boolean hideSensitive = shouldHideSensitiveContents(ent.notification.getUserId()); - final int vis = ent.notification.getNotification().visibility; - - // when isLockscreenPublicMode() we suppress VISIBILITY_SECRET notifications - if (vis == Notification.VISIBILITY_SECRET && hideSensitive) { - continue; - } - - // when isLockscreenPublicMode() we show the public form of VISIBILITY_PRIVATE notifications boolean showingPublic = vis == Notification.VISIBILITY_PRIVATE && hideSensitive; ent.row.setShowingPublic(showingPublic); if (ent.autoRedacted && ent.legacy) { @@ -1419,40 +1406,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, updateSpeedbump(); updateClearAll(); - mNotificationPanel.setQsExpansionEnabled(provisioned && mUserSetup); + mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() && mUserSetup); mShadeUpdates.check(); } private void updateClearAll() { - boolean showDismissView = false; - if (mState != StatusBarState.KEYGUARD) { - for (int i = 0; i < mNotificationData.size(); i++) { - Entry entry = mNotificationData.get(i); - if (entry.row.getParent() == null) { - // This view isn't even added, so the stack scroller doesn't - // know about it. Ignore completely. - continue; - } - if (entry.row.getVisibility() != View.GONE && entry.expanded != null - && entry.notification.isClearable()) { - showDismissView = true; - break; - } - } - } + boolean showDismissView = + mState != StatusBarState.KEYGUARD && + mNotificationData.hasActiveClearableNotifications(); mStackScroller.updateDismissView(showDismissView); } private void updateSpeedbump() { int speedbumpIndex = -1; int currentIndex = 0; - for (int i = 0; i < mNotificationData.size(); i++) { - Entry entry = mNotificationData.get(i); - if (entry.row.getParent() == null) { - // This view isn't even added, so the stack scroller doesn't - // know about it. Ignore completely. - continue; - } + ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); + final int N = activeNotifications.size(); + for (int i = 0; i < N; i++) { + Entry entry = activeNotifications.get(i); if (entry.row.getVisibility() != View.GONE && mNotificationData.isAmbient(entry.key)) { speedbumpIndex = currentIndex; @@ -1468,47 +1439,35 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // TODO: Move this into updateNotificationIcons()? if (mNotificationIcons == null) return; + mNotificationData.filterAndSort(); + updateNotificationShade(); updateNotificationIcons(); } - /** - * Returns true if we're on a secure lockscreen and the user wants to hide "sensitive" - * notification data. If so, private notifications should show their (possibly - * auto-generated) publicVersion, and secret notifications should be totally invisible. - */ - private boolean shouldHideSensitiveContents(int userid) { - return isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(userid); - } - private void updateNotificationIcons() { final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight); - int N = mNotificationData.size(); - - if (DEBUG) { - Log.d(TAG, "refreshing icons: " + N + " notifications, mNotificationIcons=" + - mNotificationIcons); - } + ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); + final int N = activeNotifications.size(); + ArrayList<StatusBarIconView> toShow = new ArrayList<>(N); - ArrayList<View> toShow = new ArrayList<View>(); - - final boolean provisioned = isDeviceProvisioned(); - // If the device hasn't been through Setup, we only show system notifications - for (int i=0; i<N; i++) { - Entry ent = mNotificationData.get(i); - if (!((provisioned && ent.notification.getScore() >= HIDE_ICONS_BELOW_SCORE) - || showNotificationEvenIfUnprovisioned(ent.notification))) continue; - if (!notificationIsForCurrentProfiles(ent.notification)) continue; - if (ent.notification.getNotification().visibility == Notification.VISIBILITY_SECRET - && shouldHideSensitiveContents(ent.notification.getUserId())) { - // in "public" mode (atop a secure keyguard), secret notifs are totally hidden + // Filter out notifications with low scores. + for (int i = 0; i < N; i++) { + Entry ent = activeNotifications.get(i); + if (ent.notification.getScore() < HIDE_ICONS_BELOW_SCORE && + !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) { continue; } toShow.add(ent.icon); } + if (DEBUG) { + Log.d(TAG, "refreshing icons: " + toShow.size() + + " notifications, mNotificationIcons=" + mNotificationIcons); + } + ArrayList<View> toRemove = new ArrayList<View>(); for (int i=0; i<mNotificationIcons.getChildCount(); i++) { View child = mNotificationIcons.getChildAt(i); @@ -1584,17 +1543,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override protected void setAreThereNotifications() { - final boolean any = mNotificationData.size() > 0; - - final boolean clearable = any && mNotificationData.hasClearableItems(); if (SPEW) { - Log.d(TAG, "setAreThereNotifications: N=" + mNotificationData.size() - + " any=" + any + " clearable=" + clearable); + final boolean clearable = hasActiveNotifications() && + mNotificationData.hasActiveClearableNotifications(); + Log.d(TAG, "setAreThereNotifications: N=" + + mNotificationData.getActiveNotifications().size() + " any=" + + hasActiveNotifications() + " clearable=" + clearable); } final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out); - final boolean showDot = (any&&!areLightsOn()); + final boolean showDot = hasActiveNotifications() && !areLightsOn(); if (showDot != (nlo.getAlpha() == 1.0f)) { if (showDot) { nlo.setAlpha(0f); @@ -1616,20 +1575,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, findAndUpdateMediaNotifications(); updateCarrierLabelVisibility(false); - - // TODO: Multiuser handling! - mHasNotifications = any; } public void findAndUpdateMediaNotifications() { boolean metaDataChanged = false; synchronized (mNotificationData) { - final int N = mNotificationData.size(); + ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); + final int N = activeNotifications.size(); Entry mediaNotification = null; MediaController controller = null; - for (int i=0; i<N; i++) { - final Entry entry = mNotificationData.get(i); + for (int i = 0; i < N; i++) { + final Entry entry = activeNotifications.get(i); if (isMediaNotification(entry)) { final MediaSession.Token token = entry.notification.getNotification().extras .getParcelable(Notification.EXTRA_MEDIA_SESSION); @@ -1667,7 +1624,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, final String pkg = aController.getPackageName(); for (int i = 0; i < N; i++) { - final Entry entry = mNotificationData.get(i); + final Entry entry = activeNotifications.get(i); if (entry.notification.getPackageName().equals(pkg)) { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: found controller matching " @@ -2602,7 +2559,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (!isDeviceProvisioned()) return; // not for you - if (!notificationIsForCurrentProfiles(n)) return; + if (!isNotificationForCurrentProfiles(n)) return; // Show the ticker if one is requested. Also don't do this // until status bar window is attached to the window manager, @@ -2753,16 +2710,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (DUMPTRUCK) { synchronized (mNotificationData) { - int N = mNotificationData.size(); - pw.println(" notification icons: " + N); - for (int i=0; i<N; i++) { - NotificationData.Entry e = mNotificationData.get(i); - pw.println(" [" + i + "] key=" + e.key + " icon=" + e.icon); - StatusBarNotification n = e.notification; - pw.println(" pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" + n.getScore()); - pw.println(" notification=" + n.getNotification()); - pw.println(" tickerText=\"" + n.getNotification().tickerText + "\""); - } + mNotificationData.dump(pw, " "); } int N = mStatusIcons.getChildCount(); @@ -3610,7 +3558,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public boolean onDraggedDown(View startingChild) { - if (mHasNotifications) { + if (hasActiveNotifications()) { // We have notifications, go to locked shade. goToLockedShade(startingChild); @@ -3752,8 +3700,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, notifyUiVisibilityChanged(mSystemUiVisibility); } - public boolean hasNotifications() { - return mHasNotifications; + public boolean hasActiveNotifications() { + return !mNotificationData.getActiveNotifications().isEmpty(); } private final class ShadeUpdates { @@ -3762,8 +3710,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void check() { mNewVisibleNotifications.clear(); - for (int i = 0; i < mNotificationData.size(); i++) { - final Entry entry = mNotificationData.get(i); + ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); + for (int i = 0; i < activeNotifications.size(); i++) { + final Entry entry = activeNotifications.get(i); final boolean visible = entry.row != null && entry.row.getVisibility() == View.VISIBLE; if (visible) { |