diff options
author | Joe Onorato <joeo@android.com> | 2010-06-04 16:08:02 -0400 |
---|---|---|
committer | Joe Onorato <joeo@android.com> | 2010-06-09 09:15:25 -0700 |
commit | 005847b03b2ebe3eb1a974a8a04ad51bca6636cd (patch) | |
tree | 1664f30f2320bddcf44b0af581b492589a38fcda /packages/SystemUI | |
parent | d956ae8b813da893ab6a9357acfe287c529d6ac2 (diff) | |
download | frameworks_base-005847b03b2ebe3eb1a974a8a04ad51bca6636cd.zip frameworks_base-005847b03b2ebe3eb1a974a8a04ad51bca6636cd.tar.gz frameworks_base-005847b03b2ebe3eb1a974a8a04ad51bca6636cd.tar.bz2 |
Handle errors inflating notifications (and their icons).
On an inflation error, the StatusBarService cleans up, removes / doesn't add
the views, and calls into the StatusBarManagerService, which tells the
NotificationManagerService to remove the notification.
That then calls all the way back into the StatusBarService, but I think being
extra careful is okay. Throughout the status bar, it's all keyed off of the
IBinder key, so if the app comes in with a good notification while we're
cleaning up, we won't lose the new notification or anything like that.
Change-Id: Iea78a637495a8b67810c214b951d5ddb93becacb
Diffstat (limited to 'packages/SystemUI')
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java | 46 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java | 57 |
2 files changed, 63 insertions, 40 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java index ad59a0c..ca589cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java @@ -373,6 +373,14 @@ public class PhoneStatusBarService extends StatusBarService { oldEntry.content.setOnClickListener(new Launcher(contentIntent, notification.pkg, notification.tag, notification.id)); } + // Update the icon. + final StatusBarIcon ic = new StatusBarIcon(notification.pkg, + notification.notification.icon, notification.notification.iconLevel, + notification.notification.number); + 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. @@ -380,9 +388,6 @@ public class PhoneStatusBarService extends StatusBarService { removeNotificationViews(key); addNotificationViews(key, notification); } - // Update the icon. - oldEntry.icon.set(new StatusBarIcon(notification.pkg, notification.notification.icon, - notification.notification.iconLevel, notification.notification.number)); } else { Slog.d(TAG, "not reusing notification"); removeNotificationViews(key); @@ -451,8 +456,9 @@ public class PhoneStatusBarService extends StatusBarService { exception = e; } if (expanded == null) { - Slog.e(TAG, "couldn't inflate view for package " + notification.pkg, exception); - row.setVisibility(View.GONE); + String ident = notification.pkg + "/0x" + Integer.toHexString(notification.id); + Slog.e(TAG, "couldn't inflate view for notification " + ident); + return null; } else { content.addView(expanded); row.setDrawingCacheEnabled(true); @@ -474,14 +480,23 @@ public class PhoneStatusBarService extends StatusBarService { } // Construct the expanded view. final View[] views = makeNotificationView(notification, parent); + if (views == null) { + handleNotificationError(key, notification, "Couldn't expand RemoteViews for: " + + notification); + return; + } final View row = views[0]; final View content = views[1]; final View expanded = views[2]; // Construct the icon. - StatusBarIconView iconView = new StatusBarIconView(this, + final StatusBarIconView iconView = new StatusBarIconView(this, notification.pkg + "/0x" + Integer.toHexString(notification.id)); - iconView.set(new StatusBarIcon(notification.pkg, notification.notification.icon, - notification.notification.iconLevel, notification.notification.number)); + final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon, + notification.notification.iconLevel, notification.notification.number); + if (!iconView.set(ic)) { + handleNotificationError(key, notification, "Coulding create icon: " + ic); + return; + } // Add the expanded view. final int viewIndex = list.add(key, notification, row, content, expanded, iconView); parent.addView(row, viewIndex); @@ -967,6 +982,21 @@ public class PhoneStatusBarService extends StatusBarService { } } + /** + * 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, message); + } catch (RemoteException ex) { + // The end is nigh. + } + } + private class MyTicker extends Ticker { MyTicker(Context context, StatusBarView sb) { super(context, sb); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 5eb0d68..bc1e798 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -32,7 +32,6 @@ public class StatusBarIconView extends AnimatedImageView { private StatusBarIcon mIcon; @ViewDebug.ExportedProperty private String mSlot; - @ViewDebug.ExportedProperty private boolean mError; public StatusBarIconView(Context context, String slot) { super(context); @@ -52,39 +51,33 @@ public class StatusBarIconView extends AnimatedImageView { return a.equals(b); } - public void set(StatusBarIcon icon) { - error: { - final boolean iconEquals = !mError - && mIcon != null - && streq(mIcon.iconPackage, icon.iconPackage) - && mIcon.iconId == icon.iconId; - final boolean levelEquals = !mError - && iconEquals - && mIcon.iconLevel == icon.iconLevel; - final boolean visibilityEquals = !mError - && mIcon != null - && mIcon.visible == icon.visible; - mError = false; - if (!iconEquals) { - Drawable drawable = getIcon(icon); - if (drawable == null) { - mError = true; - Slog.w(PhoneStatusBarService.TAG, "No icon ID for slot " + mSlot); - break error; - } - setImageDrawable(drawable); - } - if (!levelEquals) { - setImageLevel(icon.iconLevel); - } - if (!visibilityEquals) { - setVisibility(icon.visible ? VISIBLE : GONE); + /** + * Returns whether the set succeeded. + */ + public boolean set(StatusBarIcon icon) { + final boolean iconEquals = mIcon != null + && streq(mIcon.iconPackage, icon.iconPackage) + && mIcon.iconId == icon.iconId; + final boolean levelEquals = iconEquals + && mIcon.iconLevel == icon.iconLevel; + final boolean visibilityEquals = mIcon != null + && mIcon.visible == icon.visible; + if (!iconEquals) { + Drawable drawable = getIcon(icon); + if (drawable == null) { + Slog.w(PhoneStatusBarService.TAG, "No icon for slot " + mSlot); + return false; } - mIcon = icon.clone(); + setImageDrawable(drawable); + } + if (!levelEquals) { + setImageLevel(icon.iconLevel); } - if (mError) { - setVisibility(GONE); + if (!visibilityEquals) { + setVisibility(icon.visible ? VISIBLE : GONE); } + mIcon = icon.clone(); + return true; } private Drawable getIcon(StatusBarIcon icon) { @@ -106,7 +99,7 @@ public class StatusBarIconView extends AnimatedImageView { try { r = context.getPackageManager().getResourcesForApplication(icon.iconPackage); } catch (PackageManager.NameNotFoundException ex) { - Slog.e(PhoneStatusBarService.TAG, "Icon package not found: "+icon.iconPackage, ex); + Slog.e(PhoneStatusBarService.TAG, "Icon package not found: " + icon.iconPackage); return null; } } else { |