Pull up updateNotification to BaseStatusBar in preparation for modifying update behvior.

Bug: 6455789
Change-Id: I09fbf4d31643813cb4dfecaa496327d9625a15af
This commit is contained in:
Chris Wren
2012-05-08 13:36:48 -04:00
parent ca81b7ddeb
commit 0c8275b392
4 changed files with 239 additions and 438 deletions

View File

@@ -34,6 +34,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
@@ -46,6 +47,7 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.PopupMenu;
@@ -61,6 +63,7 @@ import com.android.systemui.recent.RecentsPanelView;
import com.android.systemui.recent.RecentTasksLoader;
import com.android.systemui.recent.TaskDescription;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.NotificationRowLayout;
import com.android.systemui.statusbar.tablet.StatusBarPanel;
import com.android.systemui.R;
@@ -76,11 +79,24 @@ public abstract class BaseStatusBar extends SystemUI implements
protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
protected static final int MSG_OPEN_SEARCH_PANEL = 1024;
protected static final int MSG_CLOSE_SEARCH_PANEL = 1025;
protected static final int MSG_SHOW_INTRUDER = 1026;
protected static final int MSG_HIDE_INTRUDER = 1027;
protected static final boolean ENABLE_INTRUDERS = false;
public static final int EXPANDED_LEAVE_ALONE = -10000;
public static final int EXPANDED_FULL_OPEN = -10001;
protected CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
protected H mHandler = createHandler();
// all notifications
protected NotificationData mNotificationData = new NotificationData();
protected NotificationRowLayout mPile;
protected StatusBarNotification mCurrentlyIntrudingNotification;
// used to notify status bar for suppressing notification LED
protected boolean mPanelSlightlyVisible;
@@ -633,4 +649,190 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
/**
* Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
* about the failure.
*
* WARNING: this will call back into us. Don't hold any locks.
*/
void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
removeNotification(key);
try {
mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
} catch (RemoteException ex) {
// The end is nigh.
}
}
protected StatusBarNotification removeNotificationViews(IBinder key) {
NotificationData.Entry entry = mNotificationData.remove(key);
if (entry == null) {
Slog.w(TAG, "removeNotification for unknown key: " + key);
return null;
}
// Remove the expanded view.
ViewGroup rowParent = (ViewGroup)entry.row.getParent();
if (rowParent != null) rowParent.removeView(entry.row);
updateNotificationIcons();
return entry.notification;
}
protected StatusBarIconView addNotificationViews(IBinder key,
StatusBarNotification notification) {
if (DEBUG) {
Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
}
// Construct the icon.
final StatusBarIconView iconView = new StatusBarIconView(mContext,
notification.pkg + "/0x" + Integer.toHexString(notification.id),
notification.notification);
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
notification.notification.icon,
notification.notification.iconLevel,
notification.notification.number,
notification.notification.tickerText);
if (!iconView.set(ic)) {
handleNotificationError(key, notification, "Couldn't create icon: " + ic);
return null;
}
// Construct the expanded view.
NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
if (!inflateViews(entry, mPile)) {
handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
+ notification);
return null;
}
// Add the expanded view and icon.
int pos = mNotificationData.add(entry);
if (DEBUG) {
Slog.d(TAG, "addNotificationViews: added at " + pos);
}
updateNotificationIcons();
return iconView;
}
protected abstract void haltTicker();
protected abstract void setAreThereNotifications();
protected abstract void updateNotificationIcons();
protected abstract void tick(IBinder key, StatusBarNotification n, boolean firstTime);
protected abstract void updateExpandedViewPos(int expandedPosition);
protected boolean isTopNotification(ViewGroup parent, NotificationData.Entry entry) {
return parent.indexOfChild(entry.row) == 0;
}
public void updateNotification(IBinder key, StatusBarNotification notification) {
if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
if (oldEntry == null) {
Slog.w(TAG, "updateNotification for unknown key: " + key);
return;
}
final StatusBarNotification oldNotification = oldEntry.notification;
// XXX: modify when we do something more intelligent with the two content views
final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null)
? oldNotification.notification.bigContentView
: oldNotification.notification.contentView;
final RemoteViews contentView = (notification.notification.bigContentView != null)
? notification.notification.bigContentView
: notification.notification.contentView;
if (DEBUG) {
Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
+ " ongoing=" + oldNotification.isOngoing()
+ " expanded=" + oldEntry.expanded
+ " contentView=" + oldContentView
+ " rowParent=" + oldEntry.row.getParent());
Slog.d(TAG, "new notification: when=" + notification.notification.when
+ " ongoing=" + oldNotification.isOngoing()
+ " contentView=" + contentView);
}
// Can we just reapply the RemoteViews in place? If when didn't change, the order
// didn't change.
boolean contentsUnchanged = oldEntry.expanded != null
&& contentView != null && oldContentView != null
&& contentView.getPackage() != null
&& oldContentView.getPackage() != null
&& oldContentView.getPackage().equals(contentView.getPackage())
&& oldContentView.getLayoutId() == contentView.getLayoutId();
ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
&& notification.score == oldNotification.score;
// score now encompasses/supersedes isOngoing()
boolean updateTicker = notification.notification.tickerText != null
&& !TextUtils.equals(notification.notification.tickerText,
oldEntry.notification.notification.tickerText);
boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
if (contentsUnchanged && (orderUnchanged || isTopAnyway)) {
if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
oldEntry.notification = notification;
try {
// Reapply the RemoteViews
contentView.reapply(mContext, oldEntry.content);
// update the contentIntent
final PendingIntent contentIntent = notification.notification.contentIntent;
if (contentIntent != null) {
final View.OnClickListener listener = makeClicker(contentIntent,
notification.pkg, notification.tag, notification.id);
oldEntry.content.setOnClickListener(listener);
} else {
oldEntry.content.setOnClickListener(null);
}
// Update the icon.
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
notification.notification.icon, notification.notification.iconLevel,
notification.notification.number,
notification.notification.tickerText);
if (!oldEntry.icon.set(ic)) {
handleNotificationError(key, notification, "Couldn't update icon: " + ic);
return;
}
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
removeNotificationViews(key);
addNotificationViews(key, notification);
}
} else {
if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
removeNotificationViews(key);
addNotificationViews(key, notification);
}
// Update the veto button accordingly (and as a result, whether this row is
// swipe-dismissable)
updateNotificationVetoButton(oldEntry.row, notification);
// Restart the ticker if it's still running
if (updateTicker) {
haltTicker();
tick(key, notification, false);
}
// Recalculate the position of the sliding windows and the titles.
setAreThereNotifications();
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
// See if we need to update the intruder.
if (ENABLE_INTRUDERS && oldNotification == mCurrentlyIntrudingNotification) {
if (DEBUG) Slog.d(TAG, "updating the current intruder:" + notification);
// XXX: this is a hack for Alarms. The real implementation will need to *update*
// the intruder.
if (notification.notification.fullScreenIntent == null) { // TODO(dsandler): consistent logic with add()
if (DEBUG) Slog.d(TAG, "no longer intrudes!");
mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
}
}
}
}

View File

@@ -42,7 +42,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
@@ -105,16 +104,10 @@ public class PhoneStatusBar extends BaseStatusBar {
public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START";
private static final boolean ENABLE_INTRUDERS = false;
private static final boolean DIM_BEHIND_EXPANDED_PANEL = false;
static final int EXPANDED_LEAVE_ALONE = -10000;
static final int EXPANDED_FULL_OPEN = -10001;
private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
private static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
private static final int MSG_SHOW_INTRUDER = 1002;
private static final int MSG_HIDE_INTRUDER = 1003;
// 1020-1030 reserved for BaseStatusBar
// will likely move to a resource or other tunable param at some point
@@ -179,10 +172,6 @@ public class PhoneStatusBar extends BaseStatusBar {
CloseDragHandle mCloseView;
private int mCloseViewHeight;
// all notifications
NotificationData mNotificationData = new NotificationData();
NotificationRowLayout mPile;
// position
int[] mPositionTmp = new int[2];
boolean mExpanded;
@@ -518,7 +507,7 @@ public class PhoneStatusBar extends BaseStatusBar {
toggleRecentApps();
}
};
private StatusBarNotification mCurrentlyIntrudingNotification;
View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
@@ -693,7 +682,7 @@ public class PhoneStatusBar extends BaseStatusBar {
// show the ticker if there isn't an intruder too
if (mCurrentlyIntrudingNotification == null) {
tick(notification);
tick(null, notification, true);
}
}
@@ -702,117 +691,6 @@ public class PhoneStatusBar extends BaseStatusBar {
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
}
public void updateNotification(IBinder key, StatusBarNotification notification) {
if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
if (oldEntry == null) {
Slog.w(TAG, "updateNotification for unknown key: " + key);
return;
}
final StatusBarNotification oldNotification = oldEntry.notification;
// XXX: modify when we do something more intelligent with the two content views
final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null)
? oldNotification.notification.bigContentView
: oldNotification.notification.contentView;
final RemoteViews contentView = (notification.notification.bigContentView != null)
? notification.notification.bigContentView
: notification.notification.contentView;
if (DEBUG) {
Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
+ " ongoing=" + oldNotification.isOngoing()
+ " expanded=" + oldEntry.expanded
+ " contentView=" + oldContentView
+ " rowParent=" + oldEntry.row.getParent());
Slog.d(TAG, "new notification: when=" + notification.notification.when
+ " ongoing=" + oldNotification.isOngoing()
+ " contentView=" + contentView);
}
// Can we just reapply the RemoteViews in place? If when didn't change, the order
// didn't change.
boolean contentsUnchanged = oldEntry.expanded != null
&& contentView != null && oldContentView != null
&& contentView.getPackage() != null
&& oldContentView.getPackage() != null
&& oldContentView.getPackage().equals(contentView.getPackage())
&& oldContentView.getLayoutId() == contentView.getLayoutId();
ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
&& notification.score == oldNotification.score;
// score now encompasses/supersedes isOngoing()
boolean updateTicker = notification.notification.tickerText != null
&& !TextUtils.equals(notification.notification.tickerText,
oldEntry.notification.notification.tickerText);
boolean isFirstAnyway = rowParent.indexOfChild(oldEntry.row) == 0;
if (contentsUnchanged && (orderUnchanged || isFirstAnyway)) {
if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
oldEntry.notification = notification;
try {
// Reapply the RemoteViews
contentView.reapply(mContext, oldEntry.content);
// update the contentIntent
final PendingIntent contentIntent = notification.notification.contentIntent;
if (contentIntent != null) {
final View.OnClickListener listener = new NotificationClicker(contentIntent,
notification.pkg, notification.tag, notification.id);
oldEntry.content.setOnClickListener(listener);
} else {
oldEntry.content.setOnClickListener(null);
}
// Update the icon.
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
notification.notification.icon, notification.notification.iconLevel,
notification.notification.number,
notification.notification.tickerText);
if (!oldEntry.icon.set(ic)) {
handleNotificationError(key, notification, "Couldn't update icon: " + ic);
return;
}
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
removeNotificationViews(key);
addNotificationViews(key, notification);
}
} else {
if (SPEW) Slog.d(TAG, "not reusing notification");
removeNotificationViews(key);
addNotificationViews(key, notification);
}
// Update the veto button accordingly (and as a result, whether this row is
// swipe-dismissable)
updateNotificationVetoButton(oldEntry.row, notification);
// Restart the ticker if it's still running
if (updateTicker) {
mTicker.halt();
tick(notification);
}
// Recalculate the position of the sliding windows and the titles.
setAreThereNotifications();
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
// See if we need to update the intruder.
if (ENABLE_INTRUDERS && oldNotification == mCurrentlyIntrudingNotification) {
if (DEBUG) Slog.d(TAG, "updating the current intruder:" + notification);
// XXX: this is a hack for Alarms. The real implementation will need to *update*
// the intruder.
if (notification.notification.fullScreenIntent == null) { // TODO(dsandler): consistent logic with add()
if (DEBUG) Slog.d(TAG, "no longer intrudes!");
mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
}
}
}
public void removeNotification(IBinder key) {
StatusBarNotification old = removeNotificationViews(key);
if (SPEW) Slog.d(TAG, "removeNotification key=" + key + " old=" + old);
@@ -841,44 +719,6 @@ public class PhoneStatusBar extends BaseStatusBar {
updateRecentsPanel();
}
StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
if (DEBUG) {
Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
}
// Construct the icon.
final StatusBarIconView iconView = new StatusBarIconView(mContext,
notification.pkg + "/0x" + Integer.toHexString(notification.id),
notification.notification);
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
notification.notification.icon,
notification.notification.iconLevel,
notification.notification.number,
notification.notification.tickerText);
if (!iconView.set(ic)) {
handleNotificationError(key, notification, "Couldn't create icon: " + ic);
return null;
}
// Construct the expanded view.
NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
if (!inflateViews(entry, mPile)) {
handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
+ notification);
return null;
}
// Add the expanded view and icon.
int pos = mNotificationData.add(entry);
if (DEBUG) {
Slog.d(TAG, "addNotificationViews: added at " + pos);
}
updateNotificationIcons();
return iconView;
}
private void loadNotificationShade() {
int N = mNotificationData.size();
@@ -915,7 +755,8 @@ public class PhoneStatusBar extends BaseStatusBar {
updateNotificationIcons();
}
private void updateNotificationIcons() {
@Override
protected void updateNotificationIcons() {
loadNotificationShade();
final LinearLayout.LayoutParams params
@@ -956,21 +797,8 @@ public class PhoneStatusBar extends BaseStatusBar {
}
}
StatusBarNotification removeNotificationViews(IBinder key) {
NotificationData.Entry entry = mNotificationData.remove(key);
if (entry == null) {
Slog.w(TAG, "removeNotification for unknown key: " + key);
return null;
}
// Remove the expanded view.
ViewGroup rowParent = (ViewGroup)entry.row.getParent();
if (rowParent != null) rowParent.removeView(entry.row);
updateNotificationIcons();
return entry.notification;
}
private void setAreThereNotifications() {
@Override
protected void setAreThereNotifications() {
final boolean any = mNotificationData.size() > 0;
final boolean clearable = any && mNotificationData.hasClearableItems();
@@ -1754,7 +1582,8 @@ public class PhoneStatusBar extends BaseStatusBar {
}
}
private void tick(StatusBarNotification n) {
@Override
protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
// no ticking in lights-out mode
if (!areLightsOn()) return;
@@ -1770,21 +1599,6 @@ public class PhoneStatusBar extends BaseStatusBar {
}
}
/**
* Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
* about the failure.
*
* WARNING: this will call back into us. Don't hold any locks.
*/
void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
removeNotification(key);
try {
mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
} catch (RemoteException ex) {
// The end is nigh.
}
}
private class MyTicker extends Ticker {
MyTicker(Context context, View sb) {
super(context, sb);
@@ -1961,7 +1775,8 @@ public class PhoneStatusBar extends BaseStatusBar {
return mDisplayMetrics.heightPixels - mNotificationPanelMarginBottomPx;
}
void updateExpandedViewPos(int expandedPosition) {
@Override
protected void updateExpandedViewPos(int expandedPosition) {
if (SPEW) {
Slog.d(TAG, "updateExpandedViewPos before expandedPosition=" + expandedPosition
//+ " mTrackingParams.y=" + ((mTrackingParams == null) ? "?" : mTrackingParams.y)
@@ -2288,5 +2103,10 @@ public class PhoneStatusBar extends BaseStatusBar {
vibrate();
}
};
@Override
protected void haltTicker() {
mTicker.halt();
}
}

View File

@@ -31,6 +31,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.policy.FixedSizeDrawable;
public class PhoneStatusBarView extends FrameLayout {
@@ -95,7 +96,7 @@ public class PhoneStatusBarView extends FrameLayout {
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mService.updateExpandedViewPos(PhoneStatusBar.EXPANDED_LEAVE_ALONE);
mService.updateExpandedViewPos(BaseStatusBar.EXPANDED_LEAVE_ALONE);
}
@Override

View File

@@ -109,7 +109,6 @@ public class TabletStatusBar extends BaseStatusBar implements
private static final boolean FAKE_SPACE_BAR = true;
// Notification "peeking" (flyover preview of individual notifications)
final static boolean NOTIFICATION_PEEK_ENABLED = false;
final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms
final static int NOTIFICATION_PEEK_FADE_DELAY = 3000; // ms
@@ -127,9 +126,6 @@ public class TabletStatusBar extends BaseStatusBar implements
IWindowManager mWindowManager;
// tracking all current notifications
private NotificationData mNotificationData = new NotificationData();
TabletStatusBarView mStatusBarView;
View mNotificationArea;
View mNotificationTrigger;
@@ -160,8 +156,6 @@ public class TabletStatusBar extends BaseStatusBar implements
int mNotificationPeekTapDuration;
int mNotificationFlingVelocity;
NotificationRowLayout mPile;
BatteryController mBatteryController;
BluetoothController mBluetoothController;
LocationController mLocationController;
@@ -290,47 +284,6 @@ public class TabletStatusBar extends BaseStatusBar implements
WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
// Notification preview window
if (NOTIFICATION_PEEK_ENABLED) {
mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context,
R.layout.system_bar_notification_peek, null);
mNotificationPeekWindow.setBar(this);
mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
mNotificationPeekWindow.setVisibility(View.GONE);
mNotificationPeekWindow.setOnTouchListener(
new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PEEK, mNotificationPeekWindow));
mNotificationPeekScrubRight = new LayoutTransition();
mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING,
ObjectAnimator.ofInt(null, "left", -512, 0));
mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING,
ObjectAnimator.ofInt(null, "left", -512, 0));
mNotificationPeekScrubRight.setDuration(500);
mNotificationPeekScrubLeft = new LayoutTransition();
mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING,
ObjectAnimator.ofInt(null, "left", 512, 0));
mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING,
ObjectAnimator.ofInt(null, "left", 512, 0));
mNotificationPeekScrubLeft.setDuration(500);
// XXX: setIgnoreChildren?
lp = new WindowManager.LayoutParams(
512, // ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
lp.y = res.getDimensionPixelOffset(R.dimen.peek_window_y_offset);
lp.setTitle("NotificationPeekWindow");
lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
}
// Recents Panel
mRecentTasksLoader = new RecentTasksLoader(context);
updateRecentsPanel();
@@ -494,24 +447,16 @@ public class TabletStatusBar extends BaseStatusBar implements
// the whole right-hand side of the bar
mNotificationArea = sb.findViewById(R.id.notificationArea);
if (!NOTIFICATION_PEEK_ENABLED) {
mNotificationArea.setOnTouchListener(new NotificationTriggerTouchListener());
}
mNotificationArea.setOnTouchListener(new NotificationTriggerTouchListener());
// the button to open the notification area
mNotificationTrigger = sb.findViewById(R.id.notificationTrigger);
if (NOTIFICATION_PEEK_ENABLED) {
mNotificationTrigger.setOnTouchListener(new NotificationTriggerTouchListener());
}
// the more notifications icon
mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
// where the icons go
mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
if (NOTIFICATION_PEEK_ENABLED) {
mIconLayout.setOnTouchListener(new NotificationIconTouchListener());
}
ViewConfiguration vc = ViewConfiguration.get(context);
mNotificationPeekTapDuration = vc.getTapTimeout();
@@ -829,9 +774,6 @@ public class TabletStatusBar extends BaseStatusBar implements
case MSG_OPEN_NOTIFICATION_PANEL:
if (DEBUG) Slog.d(TAG, "opening notifications panel");
if (!mNotificationPanel.isShowing()) {
if (NOTIFICATION_PEEK_ENABLED) {
mNotificationPeekWindow.setVisibility(View.GONE);
}
mNotificationPanel.show(true, true);
mNotificationArea.setVisibility(View.INVISIBLE);
mTicker.halt();
@@ -918,106 +860,6 @@ public class TabletStatusBar extends BaseStatusBar implements
setAreThereNotifications();
}
public void updateNotification(IBinder key, StatusBarNotification notification) {
if (DEBUG) Slog.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
if (oldEntry == null) {
Slog.w(TAG, "updateNotification for unknown key: " + key);
return;
}
final StatusBarNotification oldNotification = oldEntry.notification;
// XXX: modify when we do something more intelligent with the two content views
final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null)
? oldNotification.notification.bigContentView
: oldNotification.notification.contentView;
final RemoteViews contentView = (notification.notification.bigContentView != null)
? notification.notification.bigContentView
: notification.notification.contentView;
if (DEBUG) {
Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
+ " ongoing=" + oldNotification.isOngoing()
+ " expanded=" + oldEntry.expanded
+ " contentView=" + oldContentView
+ " rowParent=" + oldEntry.row.getParent());
Slog.d(TAG, "new notification: when=" + notification.notification.when
+ " ongoing=" + oldNotification.isOngoing()
+ " contentView=" + contentView);
}
// Can we just reapply the RemoteViews in place? If when didn't change, the order
// didn't change.
boolean contentsUnchanged = oldEntry.expanded != null
&& contentView != null && oldContentView != null
&& contentView.getPackage() != null
&& oldContentView.getPackage() != null
&& oldContentView.getPackage().equals(contentView.getPackage())
&& oldContentView.getLayoutId() == contentView.getLayoutId();
ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
&& notification.score == oldNotification.score;
// score now encompasses/supersedes isOngoing()
boolean updateTicker = notification.notification.tickerText != null
&& !TextUtils.equals(notification.notification.tickerText,
oldEntry.notification.notification.tickerText);
boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
oldEntry.notification = notification;
try {
// Reapply the RemoteViews
contentView.reapply(mContext, oldEntry.content);
// update the contentIntent
final PendingIntent contentIntent = notification.notification.contentIntent;
if (contentIntent != null) {
final View.OnClickListener listener = makeClicker(contentIntent,
notification.pkg, notification.tag, notification.id);
oldEntry.content.setOnClickListener(listener);
} else {
oldEntry.content.setOnClickListener(null);
}
// Update the icon.
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
notification.notification.icon, notification.notification.iconLevel,
notification.notification.number,
notification.notification.tickerText);
if (!oldEntry.icon.set(ic)) {
handleNotificationError(key, notification, "Couldn't update icon: " + ic);
return;
}
if (NOTIFICATION_PEEK_ENABLED && key == mNotificationPeekKey) {
// must update the peek window
Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
peekMsg.arg1 = mNotificationPeekIndex;
mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
mHandler.sendMessage(peekMsg);
}
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
removeNotificationViews(key);
addNotificationViews(key, notification);
}
} else {
if (DEBUG) Slog.d(TAG, "not reusing notification for key: " + key);
removeNotificationViews(key);
addNotificationViews(key, notification);
}
// Restart the ticker if it's still running
if (updateTicker) {
mTicker.halt();
tick(key, notification, false);
}
setAreThereNotifications();
}
public void removeNotification(IBinder key) {
if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ")");
removeNotificationViews(key);
@@ -1107,7 +949,8 @@ public class TabletStatusBar extends BaseStatusBar implements
return n.tickerView != null || !TextUtils.isEmpty(n.tickerText);
}
private void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
@Override
protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
// Don't show the ticker when the windowshade is open.
if (mNotificationPanel.isShowing()) {
return;
@@ -1136,11 +979,6 @@ public class TabletStatusBar extends BaseStatusBar implements
}
public void animateExpand() {
if (NOTIFICATION_PEEK_ENABLED) {
mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
}
mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
}
@@ -1160,10 +998,6 @@ public class TabletStatusBar extends BaseStatusBar implements
mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
mHandler.removeMessages(MSG_CLOSE_COMPAT_MODE_PANEL);
mHandler.sendEmptyMessage(MSG_CLOSE_COMPAT_MODE_PANEL);
if (NOTIFICATION_PEEK_ENABLED) {
mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
}
}
@Override // CommandQueue
@@ -1352,24 +1186,13 @@ public class TabletStatusBar extends BaseStatusBar implements
}
}
private void setAreThereNotifications() {
@Override
protected void setAreThereNotifications() {
if (mNotificationPanel != null) {
mNotificationPanel.setClearable(mNotificationData.hasClearableItems());
}
}
/**
* Cancel this notification and tell the status bar service about the failure. Hold no locks.
*/
void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
removeNotification(key);
try {
mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
} catch (RemoteException ex) {
// The end is nigh.
}
}
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) {
if (v == mRecentButton) {
@@ -1407,28 +1230,6 @@ public class TabletStatusBar extends BaseStatusBar implements
mHandler.sendEmptyMessage(msg);
}
StatusBarNotification removeNotificationViews(IBinder key) {
NotificationData.Entry entry = mNotificationData.remove(key);
if (entry == null) {
Slog.w(TAG, "removeNotification for unknown key: " + key);
return null;
}
// Remove the expanded view.
ViewGroup rowParent = (ViewGroup)entry.row.getParent();
if (rowParent != null) rowParent.removeView(entry.row);
if (NOTIFICATION_PEEK_ENABLED && key == mNotificationPeekKey) {
// must close the peek as well, since it's gone
mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PEEK);
}
// Remove the icon.
// ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
// if (iconParent != null) iconParent.removeView(entry.icon);
updateNotificationIcons();
return entry.notification;
}
private class NotificationTriggerTouchListener implements View.OnTouchListener {
VelocityTracker mVT;
float mInitialTouchX, mInitialTouchY;
@@ -1621,50 +1422,14 @@ public class TabletStatusBar extends BaseStatusBar implements
}
}
StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
if (DEBUG) {
Slog.d(TAG, "addNotificationViews(key=" + key + ", notification=" + notification);
}
// Construct the icon.
final StatusBarIconView iconView = new StatusBarIconView(mContext,
notification.pkg + "/0x" + Integer.toHexString(notification.id),
notification.notification);
iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
notification.notification.icon,
notification.notification.iconLevel,
notification.notification.number,
notification.notification.tickerText);
if (!iconView.set(ic)) {
handleNotificationError(key, notification, "Couldn't attach StatusBarIcon: " + ic);
return null;
}
// Construct the expanded view.
NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
if (!inflateViews(entry, mPile)) {
handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
+ notification);
return null;
}
// Add the icon.
int pos = mNotificationData.add(entry);
if (DEBUG) {
Slog.d(TAG, "addNotificationViews: added at " + pos);
}
updateNotificationIcons();
return iconView;
}
private void reloadAllNotificationIcons() {
if (mIconLayout == null) return;
mIconLayout.removeAllViews();
updateNotificationIcons();
}
private void updateNotificationIcons() {
@Override
protected void updateNotificationIcons() {
// XXX: need to implement a new limited linear layout class
// to avoid removing & readding everything
@@ -1837,6 +1602,19 @@ public class TabletStatusBar extends BaseStatusBar implements
mNetworkController.dump(fd, pw, args);
}
@Override
protected boolean isTopNotification(ViewGroup parent, NotificationData.Entry entry) {
return parent.indexOfChild(entry.row) == parent.getChildCount()-1;
}
@Override
protected void haltTicker() {
mTicker.halt();
}
@Override
protected void updateExpandedViewPos(int expandedPosition) {
}
}