Pull up updateNotification to BaseStatusBar in preparation for modifying update behvior.
Bug: 6455789 Change-Id: I09fbf4d31643813cb4dfecaa496327d9625a15af
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user