summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/NotificationManagerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/NotificationManagerService.java')
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java151
1 files changed, 87 insertions, 64 deletions
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 73d17ea..63325dd 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -16,9 +16,8 @@
package com.android.server;
-import com.android.server.status.IconData;
-import com.android.server.status.NotificationData;
-import com.android.server.status.StatusBarService;
+import com.android.internal.statusbar.StatusBarNotification;
+import com.android.server.StatusBarManagerService;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
@@ -39,9 +38,11 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.hardware.Usb;
import android.media.AudioManager;
import android.net.Uri;
import android.os.BatteryManager;
+import android.os.Bundle;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -66,11 +67,14 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-class NotificationManagerService extends INotificationManager.Stub
+/** {@hide} */
+public class NotificationManagerService extends INotificationManager.Stub
{
private static final String TAG = "NotificationService";
private static final boolean DBG = false;
+ private static final int MAX_PACKAGE_NOTIFICATIONS = 50;
+
// message codes
private static final int MESSAGE_TIMEOUT = 2;
@@ -86,7 +90,7 @@ class NotificationManagerService extends INotificationManager.Stub
final IBinder mForegroundToken = new Binder();
private WorkerHandler mHandler;
- private StatusBarService mStatusBarService;
+ private StatusBarManagerService mStatusBar;
private LightsService mLightsService;
private LightsService.Light mBatteryLight;
private LightsService.Light mNotificationLight;
@@ -110,8 +114,6 @@ class NotificationManagerService extends INotificationManager.Stub
private boolean mNotificationPulseEnabled;
// for adb connected notifications
- private boolean mUsbConnected;
- private boolean mAdbEnabled = false;
private boolean mAdbNotificationShown = false;
private Notification mAdbNotification;
@@ -163,16 +165,21 @@ class NotificationManagerService extends INotificationManager.Stub
final String pkg;
final String tag;
final int id;
+ final int uid;
+ final int initialPid;
ITransientNotification callback;
int duration;
final Notification notification;
IBinder statusBarKey;
- NotificationRecord(String pkg, String tag, int id, Notification notification)
+ NotificationRecord(String pkg, String tag, int id, int uid, int initialPid,
+ Notification notification)
{
this.pkg = pkg;
this.tag = tag;
this.id = id;
+ this.uid = uid;
+ this.initialPid = initialPid;
this.notification = notification;
}
@@ -238,8 +245,8 @@ class NotificationManagerService extends INotificationManager.Stub
}
}
- private StatusBarService.NotificationCallbacks mNotificationCallbacks
- = new StatusBarService.NotificationCallbacks() {
+ private StatusBarManagerService.NotificationCallbacks mNotificationCallbacks
+ = new StatusBarManagerService.NotificationCallbacks() {
public void onSetDisabled(int status) {
synchronized (mNotificationList) {
@@ -302,6 +309,21 @@ class NotificationManagerService extends INotificationManager.Stub
updateLightsLocked();
}
}
+
+ public void onNotificationError(String pkg, String tag, int id,
+ int uid, int initialPid, String message) {
+ Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
+ + "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")");
+ cancelNotification(pkg, tag, id, 0, 0);
+ long ident = Binder.clearCallingIdentity();
+ try {
+ ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg,
+ "Bad notification posted from package " + pkg
+ + ": " + message);
+ } catch (RemoteException e) {
+ }
+ Binder.restoreCallingIdentity(ident);
+ }
};
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -326,12 +348,14 @@ class NotificationManagerService extends INotificationManager.Stub
mBatteryFull = batteryFull;
updateLights();
}
- } else if (action.equals(Intent.ACTION_UMS_CONNECTED)) {
- mUsbConnected = true;
- updateAdbNotification();
- } else if (action.equals(Intent.ACTION_UMS_DISCONNECTED)) {
- mUsbConnected = false;
- updateAdbNotification();
+ } else if (action.equals(Usb.ACTION_USB_STATE)) {
+ Bundle extras = intent.getExtras();
+ boolean usbConnected = extras.getBoolean(Usb.USB_CONNECTED);
+ boolean adbEnabled = (Usb.USB_FUNCTION_ENABLED.equals(
+ extras.getString(Usb.USB_FUNCTION_ADB)));
+ updateAdbNotification(usbConnected && adbEnabled);
+ } else if (action.equals(Usb.ACTION_USB_DISCONNECTED)) {
+ updateAdbNotification(false);
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)
|| (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
@@ -377,8 +401,6 @@ class NotificationManagerService extends INotificationManager.Stub
void observe() {
ContentResolver resolver = mContext.getContentResolver();
- resolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.ADB_ENABLED), false, this);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.NOTIFICATION_LIGHT_PULSE), false, this);
update();
@@ -390,12 +412,6 @@ class NotificationManagerService extends INotificationManager.Stub
public void update() {
ContentResolver resolver = mContext.getContentResolver();
- boolean adbEnabled = Settings.Secure.getInt(resolver,
- Settings.Secure.ADB_ENABLED, 0) != 0;
- if (mAdbEnabled != adbEnabled) {
- mAdbEnabled = adbEnabled;
- updateAdbNotification();
- }
boolean pulseEnabled = Settings.System.getInt(resolver,
Settings.System.NOTIFICATION_LIGHT_PULSE, 0) != 0;
if (mNotificationPulseEnabled != pulseEnabled) {
@@ -405,7 +421,7 @@ class NotificationManagerService extends INotificationManager.Stub
}
}
- NotificationManagerService(Context context, StatusBarService statusBar,
+ NotificationManagerService(Context context, StatusBarManagerService statusBar,
LightsService lights)
{
super();
@@ -417,7 +433,7 @@ class NotificationManagerService extends INotificationManager.Stub
mToastQueue = new ArrayList<ToastRecord>();
mHandler = new WorkerHandler();
- mStatusBarService = statusBar;
+ mStatusBar = statusBar;
statusBar.setNotificationCallbacks(mNotificationCallbacks);
mBatteryLight = lights.getLight(LightsService.LIGHT_ID_BATTERY);
@@ -444,8 +460,7 @@ class NotificationManagerService extends INotificationManager.Stub
// register for battery changed notifications
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(Intent.ACTION_UMS_CONNECTED);
- filter.addAction(Intent.ACTION_UMS_DISCONNECTED);
+ filter.addAction(Usb.ACTION_USB_STATE);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
@@ -653,11 +668,43 @@ class NotificationManagerService extends INotificationManager.Stub
enqueueNotificationWithTag(pkg, null /* tag */, id, notification, idOut);
}
- public void enqueueNotificationWithTag(String pkg, String tag, int id,
- Notification notification, int[] idOut)
+ public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,
+ int[] idOut)
+ {
+ enqueueNotificationInternal(pkg, Binder.getCallingUid(), Binder.getCallingPid(),
+ tag, id, notification, idOut);
+ }
+
+ // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
+ // uid/pid of another application)
+ public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
+ String tag, int id, Notification notification, int[] idOut)
{
+ Slog.d(TAG, "enqueueNotificationWithTag: calling uid=" + callingUid
+ + ", pid=" + callingPid);
+
checkIncomingCall(pkg);
+ // Limit the number of notifications that any given package except the android
+ // package can enqueue. Prevents DOS attacks and deals with leaks.
+ if (!"android".equals(pkg)) {
+ synchronized (mNotificationList) {
+ int count = 0;
+ final int N = mNotificationList.size();
+ for (int i=0; i<N; i++) {
+ final NotificationRecord r = mNotificationList.get(i);
+ if (r.pkg.equals(pkg)) {
+ count++;
+ if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+ Slog.e(TAG, "Package has already posted " + count
+ + " notifications. Not showing more. package=" + pkg);
+ return;
+ }
+ }
+ }
+ }
+ }
+
// This conditional is a dirty hack to limit the logging done on
// behalf of the download manager without affecting other apps.
if (!pkg.equals("com.android.providers.downloads")
@@ -681,7 +728,8 @@ class NotificationManagerService extends INotificationManager.Stub
}
synchronized (mNotificationList) {
- NotificationRecord r = new NotificationRecord(pkg, tag, id, notification);
+ NotificationRecord r = new NotificationRecord(pkg, tag, id,
+ callingUid, callingPid, notification);
NotificationRecord old = null;
int index = indexOfNotificationLocked(pkg, tag, id);
@@ -705,36 +753,13 @@ class NotificationManagerService extends INotificationManager.Stub
}
if (notification.icon != 0) {
- IconData icon = IconData.makeIcon(null, pkg, notification.icon,
- notification.iconLevel,
- notification.number);
- CharSequence truncatedTicker = notification.tickerText;
-
- // TODO: make this restriction do something smarter like never fill
- // more than two screens. "Why would anyone need more than 80 characters." :-/
- final int maxTickerLen = 80;
- if (truncatedTicker != null && truncatedTicker.length() > maxTickerLen) {
- truncatedTicker = truncatedTicker.subSequence(0, maxTickerLen);
- }
-
- NotificationData n = new NotificationData();
- n.pkg = pkg;
- n.tag = tag;
- n.id = id;
- n.when = notification.when;
- n.tickerText = truncatedTicker;
- n.ongoingEvent = (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
- if (!n.ongoingEvent && (notification.flags & Notification.FLAG_NO_CLEAR) == 0) {
- n.clearable = true;
- }
- n.contentView = notification.contentView;
- n.contentIntent = notification.contentIntent;
- n.deleteIntent = notification.deleteIntent;
+ StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
+ r.uid, r.initialPid, notification);
if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey;
long identity = Binder.clearCallingIdentity();
try {
- mStatusBarService.updateIcon(r.statusBarKey, icon, n);
+ mStatusBar.updateNotification(r.statusBarKey, n);
}
finally {
Binder.restoreCallingIdentity(identity);
@@ -742,21 +767,19 @@ class NotificationManagerService extends INotificationManager.Stub
} else {
long identity = Binder.clearCallingIdentity();
try {
- r.statusBarKey = mStatusBarService.addIcon(icon, n);
+ r.statusBarKey = mStatusBar.addNotification(n);
mAttentionLight.pulse();
}
finally {
Binder.restoreCallingIdentity(identity);
}
}
-
sendAccessibilityEvent(notification, pkg);
-
} else {
if (old != null && old.statusBarKey != null) {
long identity = Binder.clearCallingIdentity();
try {
- mStatusBarService.removeIcon(old.statusBarKey);
+ mStatusBar.removeNotification(old.statusBarKey);
}
finally {
Binder.restoreCallingIdentity(identity);
@@ -864,7 +887,7 @@ class NotificationManagerService extends INotificationManager.Stub
if (r.notification.icon != 0) {
long identity = Binder.clearCallingIdentity();
try {
- mStatusBarService.removeIcon(r.statusBarKey);
+ mStatusBar.removeNotification(r.statusBarKey);
}
finally {
Binder.restoreCallingIdentity(identity);
@@ -1118,8 +1141,8 @@ class NotificationManagerService extends INotificationManager.Stub
// This is here instead of StatusBarPolicy because it is an important
// security feature that we don't want people customizing the platform
// to accidentally lose.
- private void updateAdbNotification() {
- if (mAdbEnabled && mUsbConnected) {
+ private void updateAdbNotification(boolean adbEnabled) {
+ if (adbEnabled) {
if ("0".equals(SystemProperties.get("persist.adb.notify"))) {
return;
}