Skip to content

Commit 0a6a123

Browse files
cwrenAndroid (Google) Code Review
authored andcommitted
Merge "Pull up updateNotification to BaseStatusBar in preparation for modifying update behvior." into jb-dev
2 parents 747eeb4 + 0c8275b commit 0a6a123

File tree

4 files changed

+239
-438
lines changed

4 files changed

+239
-438
lines changed

packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import android.os.RemoteException;
3636
import android.os.ServiceManager;
3737
import android.provider.Settings;
38+
import android.text.TextUtils;
3839
import android.util.Log;
3940
import android.util.Slog;
4041
import android.view.Display;
@@ -47,6 +48,7 @@
4748
import android.view.ViewGroup.LayoutParams;
4849
import android.view.WindowManager;
4950
import android.view.WindowManagerImpl;
51+
import android.widget.ImageView;
5052
import android.widget.LinearLayout;
5153
import android.widget.RemoteViews;
5254
import android.widget.PopupMenu;
@@ -62,6 +64,7 @@
6264
import com.android.systemui.recent.RecentTasksLoader;
6365
import com.android.systemui.recent.TaskDescription;
6466
import com.android.systemui.statusbar.CommandQueue;
67+
import com.android.systemui.statusbar.policy.NotificationRowLayout;
6568
import com.android.systemui.statusbar.tablet.StatusBarPanel;
6669

6770
import com.android.systemui.R;
@@ -77,11 +80,24 @@ public abstract class BaseStatusBar extends SystemUI implements
7780
protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
7881
protected static final int MSG_OPEN_SEARCH_PANEL = 1024;
7982
protected static final int MSG_CLOSE_SEARCH_PANEL = 1025;
83+
protected static final int MSG_SHOW_INTRUDER = 1026;
84+
protected static final int MSG_HIDE_INTRUDER = 1027;
85+
86+
protected static final boolean ENABLE_INTRUDERS = false;
87+
88+
public static final int EXPANDED_LEAVE_ALONE = -10000;
89+
public static final int EXPANDED_FULL_OPEN = -10001;
8090

8191
protected CommandQueue mCommandQueue;
8292
protected IStatusBarService mBarService;
8393
protected H mHandler = createHandler();
8494

95+
// all notifications
96+
protected NotificationData mNotificationData = new NotificationData();
97+
protected NotificationRowLayout mPile;
98+
99+
protected StatusBarNotification mCurrentlyIntrudingNotification;
100+
85101
// used to notify status bar for suppressing notification LED
86102
protected boolean mPanelSlightlyVisible;
87103

@@ -634,4 +650,190 @@ protected void visibilityChanged(boolean visible) {
634650
}
635651
}
636652

653+
/**
654+
* Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
655+
* about the failure.
656+
*
657+
* WARNING: this will call back into us. Don't hold any locks.
658+
*/
659+
void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
660+
removeNotification(key);
661+
try {
662+
mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
663+
} catch (RemoteException ex) {
664+
// The end is nigh.
665+
}
666+
}
667+
668+
protected StatusBarNotification removeNotificationViews(IBinder key) {
669+
NotificationData.Entry entry = mNotificationData.remove(key);
670+
if (entry == null) {
671+
Slog.w(TAG, "removeNotification for unknown key: " + key);
672+
return null;
673+
}
674+
// Remove the expanded view.
675+
ViewGroup rowParent = (ViewGroup)entry.row.getParent();
676+
if (rowParent != null) rowParent.removeView(entry.row);
677+
updateNotificationIcons();
678+
679+
return entry.notification;
680+
}
681+
682+
protected StatusBarIconView addNotificationViews(IBinder key,
683+
StatusBarNotification notification) {
684+
if (DEBUG) {
685+
Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
686+
}
687+
// Construct the icon.
688+
final StatusBarIconView iconView = new StatusBarIconView(mContext,
689+
notification.pkg + "/0x" + Integer.toHexString(notification.id),
690+
notification.notification);
691+
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
692+
693+
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
694+
notification.notification.icon,
695+
notification.notification.iconLevel,
696+
notification.notification.number,
697+
notification.notification.tickerText);
698+
if (!iconView.set(ic)) {
699+
handleNotificationError(key, notification, "Couldn't create icon: " + ic);
700+
return null;
701+
}
702+
// Construct the expanded view.
703+
NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
704+
if (!inflateViews(entry, mPile)) {
705+
handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
706+
+ notification);
707+
return null;
708+
}
709+
710+
// Add the expanded view and icon.
711+
int pos = mNotificationData.add(entry);
712+
if (DEBUG) {
713+
Slog.d(TAG, "addNotificationViews: added at " + pos);
714+
}
715+
updateNotificationIcons();
716+
717+
return iconView;
718+
}
719+
720+
protected abstract void haltTicker();
721+
protected abstract void setAreThereNotifications();
722+
protected abstract void updateNotificationIcons();
723+
protected abstract void tick(IBinder key, StatusBarNotification n, boolean firstTime);
724+
protected abstract void updateExpandedViewPos(int expandedPosition);
725+
726+
protected boolean isTopNotification(ViewGroup parent, NotificationData.Entry entry) {
727+
return parent.indexOfChild(entry.row) == 0;
728+
}
729+
730+
public void updateNotification(IBinder key, StatusBarNotification notification) {
731+
if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
732+
733+
final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
734+
if (oldEntry == null) {
735+
Slog.w(TAG, "updateNotification for unknown key: " + key);
736+
return;
737+
}
738+
739+
final StatusBarNotification oldNotification = oldEntry.notification;
740+
741+
// XXX: modify when we do something more intelligent with the two content views
742+
final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null)
743+
? oldNotification.notification.bigContentView
744+
: oldNotification.notification.contentView;
745+
final RemoteViews contentView = (notification.notification.bigContentView != null)
746+
? notification.notification.bigContentView
747+
: notification.notification.contentView;
748+
749+
if (DEBUG) {
750+
Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
751+
+ " ongoing=" + oldNotification.isOngoing()
752+
+ " expanded=" + oldEntry.expanded
753+
+ " contentView=" + oldContentView
754+
+ " rowParent=" + oldEntry.row.getParent());
755+
Slog.d(TAG, "new notification: when=" + notification.notification.when
756+
+ " ongoing=" + oldNotification.isOngoing()
757+
+ " contentView=" + contentView);
758+
}
759+
760+
// Can we just reapply the RemoteViews in place? If when didn't change, the order
761+
// didn't change.
762+
boolean contentsUnchanged = oldEntry.expanded != null
763+
&& contentView != null && oldContentView != null
764+
&& contentView.getPackage() != null
765+
&& oldContentView.getPackage() != null
766+
&& oldContentView.getPackage().equals(contentView.getPackage())
767+
&& oldContentView.getLayoutId() == contentView.getLayoutId();
768+
ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
769+
boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
770+
&& notification.score == oldNotification.score;
771+
// score now encompasses/supersedes isOngoing()
772+
773+
boolean updateTicker = notification.notification.tickerText != null
774+
&& !TextUtils.equals(notification.notification.tickerText,
775+
oldEntry.notification.notification.tickerText);
776+
boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
777+
if (contentsUnchanged && (orderUnchanged || isTopAnyway)) {
778+
if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
779+
oldEntry.notification = notification;
780+
try {
781+
// Reapply the RemoteViews
782+
contentView.reapply(mContext, oldEntry.content);
783+
// update the contentIntent
784+
final PendingIntent contentIntent = notification.notification.contentIntent;
785+
if (contentIntent != null) {
786+
final View.OnClickListener listener = makeClicker(contentIntent,
787+
notification.pkg, notification.tag, notification.id);
788+
oldEntry.content.setOnClickListener(listener);
789+
} else {
790+
oldEntry.content.setOnClickListener(null);
791+
}
792+
// Update the icon.
793+
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
794+
notification.notification.icon, notification.notification.iconLevel,
795+
notification.notification.number,
796+
notification.notification.tickerText);
797+
if (!oldEntry.icon.set(ic)) {
798+
handleNotificationError(key, notification, "Couldn't update icon: " + ic);
799+
return;
800+
}
801+
}
802+
catch (RuntimeException e) {
803+
// It failed to add cleanly. Log, and remove the view from the panel.
804+
Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
805+
removeNotificationViews(key);
806+
addNotificationViews(key, notification);
807+
}
808+
} else {
809+
if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
810+
removeNotificationViews(key);
811+
addNotificationViews(key, notification);
812+
}
813+
814+
// Update the veto button accordingly (and as a result, whether this row is
815+
// swipe-dismissable)
816+
updateNotificationVetoButton(oldEntry.row, notification);
817+
818+
// Restart the ticker if it's still running
819+
if (updateTicker) {
820+
haltTicker();
821+
tick(key, notification, false);
822+
}
823+
824+
// Recalculate the position of the sliding windows and the titles.
825+
setAreThereNotifications();
826+
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
827+
828+
// See if we need to update the intruder.
829+
if (ENABLE_INTRUDERS && oldNotification == mCurrentlyIntrudingNotification) {
830+
if (DEBUG) Slog.d(TAG, "updating the current intruder:" + notification);
831+
// XXX: this is a hack for Alarms. The real implementation will need to *update*
832+
// the intruder.
833+
if (notification.notification.fullScreenIntent == null) { // TODO(dsandler): consistent logic with add()
834+
if (DEBUG) Slog.d(TAG, "no longer intrudes!");
835+
mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
836+
}
837+
}
838+
}
637839
}

0 commit comments

Comments
 (0)