Loading core/java/android/app/INotificationManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -34,5 +34,8 @@ interface INotificationManager void cancelToast(String pkg, ITransientNotification callback); void enqueueNotificationWithTag(String pkg, String tag, int id, in Notification notification, inout int[] idReceived); void cancelNotificationWithTag(String pkg, String tag, int id); void setNotificationsEnabledForPackage(String pkg, boolean enabled); boolean areNotificationsEnabledForPackage(String pkg); } packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +0 −29 Original line number Diff line number Diff line Loading @@ -218,11 +218,6 @@ public class PhoneStatusBar extends BaseStatusBar { private int mNavigationIconHints = 0; // TODO(dsandler): codify this stuff in NotificationManager's header somewhere private int mDisplayMinScore = Notification.PRIORITY_LOW * 10; private int mIntruderMinScore = Notification.PRIORITY_HIGH * 10; private int mIntruderInImmersiveMinScore = Notification.PRIORITY_HIGH * 10 + 5; private class ExpandedDialog extends Dialog { ExpandedDialog(Context context) { super(context, com.android.internal.R.style.Theme_Translucent_NoTitleBar); Loading Loading @@ -2132,30 +2127,6 @@ public class PhoneStatusBar extends BaseStatusBar { vib.vibrate(250); } public int getScoreThreshold() { return mDisplayMinScore; } public void setScoreThreshold(int score) { // XXX HAX if (mDisplayMinScore != score) { this.mDisplayMinScore = score; applyScoreThreshold(); } } private void applyScoreThreshold() { int N = mNotificationData.size(); for (int i=0; i<N; i++) { NotificationData.Entry entry = mNotificationData.get(i); int vis = (entry.notification.score < mDisplayMinScore) ? View.GONE : View.VISIBLE; entry.row.setVisibility(vis); entry.icon.setVisibility(vis); } } Runnable mStartTracing = new Runnable() { public void run() { vibrate(); Loading services/java/com/android/server/NotificationManagerService.java +215 −16 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.server; import com.android.internal.os.AtomicFile; import com.android.internal.statusbar.StatusBarNotification; import com.android.internal.util.FastXmlSerializer; import android.app.ActivityManagerNative; import android.app.IActivityManager; Loading @@ -37,9 +39,10 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.database.ContentObserver; import android.media.AudioManager; import android.net.NetworkPolicy; import android.net.NetworkTemplate; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; Loading @@ -53,14 +56,36 @@ import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.Xml; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import static android.net.NetworkPolicyManager.POLICY_NONE; import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute; import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute; import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; /** {@hide} */ public class NotificationManagerService extends INotificationManager.Stub Loading @@ -81,6 +106,13 @@ public class NotificationManagerService extends INotificationManager.Stub private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION; private static final boolean SCORE_ONGOING_HIGHER = false; private static final int JUNK_SCORE = -1000; private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; private static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER; private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true; private static final boolean ENABLE_BLOCKED_TOASTS = true; final Context mContext; final IActivityManager mAm; final IBinder mForegroundToken = new Binder(); Loading Loading @@ -115,6 +147,144 @@ public class NotificationManagerService extends INotificationManager.Stub private ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>(); private NotificationRecord mLedNotification; // Notification control database. For now just contains disabled packages. private AtomicFile mPolicyFile; private HashSet<String> mBlockedPackages = new HashSet<String>(); private static final int DB_VERSION = 1; private static final String TAG_BODY = "notification-policy"; private static final String ATTR_VERSION = "version"; private static final String TAG_BLOCKED_PKGS = "blocked-packages"; private static final String TAG_PACKAGE = "package"; private static final String ATTR_NAME = "name"; private void loadBlockDb() { synchronized(mBlockedPackages) { if (mPolicyFile == null) { File dir = new File("/data/system"); mPolicyFile = new AtomicFile(new File(dir, "notification_policy.xml")); mBlockedPackages.clear(); FileInputStream infile = null; try { infile = mPolicyFile.openRead(); final XmlPullParser parser = Xml.newPullParser(); parser.setInput(infile, null); int type; String tag; int version = DB_VERSION; while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (type == START_TAG) { if (TAG_BODY.equals(tag)) { version = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION)); } else if (TAG_BLOCKED_PKGS.equals(tag)) { while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (TAG_PACKAGE.equals(tag)) { mBlockedPackages.add(parser.getAttributeValue(null, ATTR_NAME)); } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) { break; } } } } } } catch (FileNotFoundException e) { // No data yet } catch (IOException e) { Log.wtf(TAG, "Unable to read blocked notifications database", e); } catch (NumberFormatException e) { Log.wtf(TAG, "Unable to parse blocked notifications database", e); } catch (XmlPullParserException e) { Log.wtf(TAG, "Unable to parse blocked notifications database", e); } finally { IoUtils.closeQuietly(infile); } } } } private void writeBlockDb() { synchronized(mBlockedPackages) { FileOutputStream outfile = null; try { outfile = mPolicyFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); out.setOutput(outfile, "utf-8"); out.startDocument(null, true); out.startTag(null, TAG_BODY); { out.attribute(null, ATTR_VERSION, String.valueOf(DB_VERSION)); out.startTag(null, TAG_BLOCKED_PKGS); { // write all known network policies for (String pkg : mBlockedPackages) { out.startTag(null, TAG_PACKAGE); { out.attribute(null, ATTR_NAME, pkg); } out.endTag(null, TAG_PACKAGE); } } out.endTag(null, TAG_BLOCKED_PKGS); } out.endTag(null, TAG_BODY); out.endDocument(); mPolicyFile.finishWrite(outfile); } catch (IOException e) { if (outfile != null) { mPolicyFile.failWrite(outfile); } } } } public boolean areNotificationsEnabledForPackage(String pkg) { checkCallerIsSystem(); return areNotificationsEnabledForPackageInt(pkg); } // Unchecked. Not exposed via Binder, but can be called in the course of enqueue*(). private boolean areNotificationsEnabledForPackageInt(String pkg) { final boolean enabled = !mBlockedPackages.contains(pkg); if (DBG) { Slog.v(TAG, "notifications are " + (enabled?"en":"dis") + "abled for " + pkg); } return enabled; } public void setNotificationsEnabledForPackage(String pkg, boolean enabled) { checkCallerIsSystem(); if (DBG) { Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg); } if (enabled) { mBlockedPackages.remove(pkg); } else { mBlockedPackages.add(pkg); // Now, cancel any outstanding notifications that are part of a just-disabled app if (ENABLE_BLOCKED_NOTIFICATIONS) { synchronized (mNotificationList) { final int N = mNotificationList.size(); for (int i=0; i<N; i++) { final NotificationRecord r = mNotificationList.get(i); if (r.pkg.equals(pkg)) { cancelNotificationLocked(r, false); } } } } // Don't bother canceling toasts, they'll go away soon enough. } writeBlockDb(); } private static String idDebugString(Context baseContext, String packageName, int id) { Context c = null; Loading Loading @@ -405,6 +575,8 @@ public class NotificationManagerService extends INotificationManager.Stub mToastQueue = new ArrayList<ToastRecord>(); mHandler = new WorkerHandler(); loadBlockDb(); mStatusBar = statusBar; statusBar.setNotificationCallbacks(mNotificationCallbacks); Loading Loading @@ -465,6 +637,13 @@ public class NotificationManagerService extends INotificationManager.Stub return ; } final boolean isSystemToast = ("android".equals(pkg)); if (ENABLE_BLOCKED_TOASTS && !isSystemToast && !areNotificationsEnabledForPackageInt(pkg)) { Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request."); return; } synchronized (mToastQueue) { int callingPid = Binder.getCallingPid(); long callingId = Binder.clearCallingIdentity(); Loading @@ -479,7 +658,7 @@ public class NotificationManagerService extends INotificationManager.Stub } else { // Limit the number of toasts that any given package except the android // package can enqueue. Prevents DOS attacks and deals with leaks. if (!"android".equals(pkg)) { if (!isSystemToast) { int count = 0; final int N = mToastQueue.size(); for (int i=0; i<N; i++) { Loading Loading @@ -675,11 +854,15 @@ public class NotificationManagerService extends INotificationManager.Stub public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid, String tag, int id, Notification notification, int[] idOut) { checkIncomingCall(pkg); if (DBG) { Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); } checkCallerIsSystemOrSameApp(pkg); final boolean isSystemNotification = ("android".equals(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)) { if (!isSystemNotification) { synchronized (mNotificationList) { int count = 0; final int N = mNotificationList.size(); Loading Loading @@ -728,17 +911,25 @@ public class NotificationManagerService extends INotificationManager.Stub } // 1. initial score: buckets of 10, around the app int score = notification.priority * 10; //[-20..20] int score = notification.priority * NOTIFICATION_PRIORITY_MULTIPLIER; //[-20..20] // 2. Consult oracles (external heuristics) // TODO(dsandler): oracles // 2. Consult external heuristics (TBD) // 3. Apply local heuristics & overrides // 3. Apply local rules // blocked apps // TODO(dsandler): add block db if (pkg.startsWith("com.test.spammer.")) { score = -1000; if (ENABLE_BLOCKED_NOTIFICATIONS && !isSystemNotification && !areNotificationsEnabledForPackageInt(pkg)) { score = JUNK_SCORE; Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request."); } if (DBG) { Slog.v(TAG, "Assigned score=" + score + " to " + notification); } if (score < SCORE_DISPLAY_THRESHOLD) { // Notification will be blocked because the score is too low. return; } synchronized (mNotificationList) { Loading Loading @@ -1030,7 +1221,7 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelNotificationWithTag(String pkg, String tag, int id) { checkIncomingCall(pkg); checkCallerIsSystemOrSameApp(pkg); // Don't allow client applications to cancel foreground service notis. cancelNotification(pkg, tag, id, 0, Binder.getCallingUid() == Process.SYSTEM_UID Loading @@ -1038,14 +1229,22 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelAllNotifications(String pkg) { checkIncomingCall(pkg); checkCallerIsSystemOrSameApp(pkg); // Calling from user space, don't allow the canceling of actively // running foreground services. cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true); } void checkIncomingCall(String pkg) { void checkCallerIsSystem() { int uid = Binder.getCallingUid(); if (uid == Process.SYSTEM_UID || uid == 0) { return; } throw new SecurityException("Disallowed call for uid " + uid); } void checkCallerIsSystemOrSameApp(String pkg) { int uid = Binder.getCallingUid(); if (uid == Process.SYSTEM_UID || uid == 0) { return; Loading Loading
core/java/android/app/INotificationManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -34,5 +34,8 @@ interface INotificationManager void cancelToast(String pkg, ITransientNotification callback); void enqueueNotificationWithTag(String pkg, String tag, int id, in Notification notification, inout int[] idReceived); void cancelNotificationWithTag(String pkg, String tag, int id); void setNotificationsEnabledForPackage(String pkg, boolean enabled); boolean areNotificationsEnabledForPackage(String pkg); }
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +0 −29 Original line number Diff line number Diff line Loading @@ -218,11 +218,6 @@ public class PhoneStatusBar extends BaseStatusBar { private int mNavigationIconHints = 0; // TODO(dsandler): codify this stuff in NotificationManager's header somewhere private int mDisplayMinScore = Notification.PRIORITY_LOW * 10; private int mIntruderMinScore = Notification.PRIORITY_HIGH * 10; private int mIntruderInImmersiveMinScore = Notification.PRIORITY_HIGH * 10 + 5; private class ExpandedDialog extends Dialog { ExpandedDialog(Context context) { super(context, com.android.internal.R.style.Theme_Translucent_NoTitleBar); Loading Loading @@ -2132,30 +2127,6 @@ public class PhoneStatusBar extends BaseStatusBar { vib.vibrate(250); } public int getScoreThreshold() { return mDisplayMinScore; } public void setScoreThreshold(int score) { // XXX HAX if (mDisplayMinScore != score) { this.mDisplayMinScore = score; applyScoreThreshold(); } } private void applyScoreThreshold() { int N = mNotificationData.size(); for (int i=0; i<N; i++) { NotificationData.Entry entry = mNotificationData.get(i); int vis = (entry.notification.score < mDisplayMinScore) ? View.GONE : View.VISIBLE; entry.row.setVisibility(vis); entry.icon.setVisibility(vis); } } Runnable mStartTracing = new Runnable() { public void run() { vibrate(); Loading
services/java/com/android/server/NotificationManagerService.java +215 −16 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.server; import com.android.internal.os.AtomicFile; import com.android.internal.statusbar.StatusBarNotification; import com.android.internal.util.FastXmlSerializer; import android.app.ActivityManagerNative; import android.app.IActivityManager; Loading @@ -37,9 +39,10 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.database.ContentObserver; import android.media.AudioManager; import android.net.NetworkPolicy; import android.net.NetworkTemplate; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; Loading @@ -53,14 +56,36 @@ import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.Xml; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import libcore.io.IoUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import static android.net.NetworkPolicyManager.POLICY_NONE; import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute; import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute; import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; /** {@hide} */ public class NotificationManagerService extends INotificationManager.Stub Loading @@ -81,6 +106,13 @@ public class NotificationManagerService extends INotificationManager.Stub private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION; private static final boolean SCORE_ONGOING_HIGHER = false; private static final int JUNK_SCORE = -1000; private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; private static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER; private static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true; private static final boolean ENABLE_BLOCKED_TOASTS = true; final Context mContext; final IActivityManager mAm; final IBinder mForegroundToken = new Binder(); Loading Loading @@ -115,6 +147,144 @@ public class NotificationManagerService extends INotificationManager.Stub private ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>(); private NotificationRecord mLedNotification; // Notification control database. For now just contains disabled packages. private AtomicFile mPolicyFile; private HashSet<String> mBlockedPackages = new HashSet<String>(); private static final int DB_VERSION = 1; private static final String TAG_BODY = "notification-policy"; private static final String ATTR_VERSION = "version"; private static final String TAG_BLOCKED_PKGS = "blocked-packages"; private static final String TAG_PACKAGE = "package"; private static final String ATTR_NAME = "name"; private void loadBlockDb() { synchronized(mBlockedPackages) { if (mPolicyFile == null) { File dir = new File("/data/system"); mPolicyFile = new AtomicFile(new File(dir, "notification_policy.xml")); mBlockedPackages.clear(); FileInputStream infile = null; try { infile = mPolicyFile.openRead(); final XmlPullParser parser = Xml.newPullParser(); parser.setInput(infile, null); int type; String tag; int version = DB_VERSION; while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (type == START_TAG) { if (TAG_BODY.equals(tag)) { version = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION)); } else if (TAG_BLOCKED_PKGS.equals(tag)) { while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (TAG_PACKAGE.equals(tag)) { mBlockedPackages.add(parser.getAttributeValue(null, ATTR_NAME)); } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) { break; } } } } } } catch (FileNotFoundException e) { // No data yet } catch (IOException e) { Log.wtf(TAG, "Unable to read blocked notifications database", e); } catch (NumberFormatException e) { Log.wtf(TAG, "Unable to parse blocked notifications database", e); } catch (XmlPullParserException e) { Log.wtf(TAG, "Unable to parse blocked notifications database", e); } finally { IoUtils.closeQuietly(infile); } } } } private void writeBlockDb() { synchronized(mBlockedPackages) { FileOutputStream outfile = null; try { outfile = mPolicyFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); out.setOutput(outfile, "utf-8"); out.startDocument(null, true); out.startTag(null, TAG_BODY); { out.attribute(null, ATTR_VERSION, String.valueOf(DB_VERSION)); out.startTag(null, TAG_BLOCKED_PKGS); { // write all known network policies for (String pkg : mBlockedPackages) { out.startTag(null, TAG_PACKAGE); { out.attribute(null, ATTR_NAME, pkg); } out.endTag(null, TAG_PACKAGE); } } out.endTag(null, TAG_BLOCKED_PKGS); } out.endTag(null, TAG_BODY); out.endDocument(); mPolicyFile.finishWrite(outfile); } catch (IOException e) { if (outfile != null) { mPolicyFile.failWrite(outfile); } } } } public boolean areNotificationsEnabledForPackage(String pkg) { checkCallerIsSystem(); return areNotificationsEnabledForPackageInt(pkg); } // Unchecked. Not exposed via Binder, but can be called in the course of enqueue*(). private boolean areNotificationsEnabledForPackageInt(String pkg) { final boolean enabled = !mBlockedPackages.contains(pkg); if (DBG) { Slog.v(TAG, "notifications are " + (enabled?"en":"dis") + "abled for " + pkg); } return enabled; } public void setNotificationsEnabledForPackage(String pkg, boolean enabled) { checkCallerIsSystem(); if (DBG) { Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg); } if (enabled) { mBlockedPackages.remove(pkg); } else { mBlockedPackages.add(pkg); // Now, cancel any outstanding notifications that are part of a just-disabled app if (ENABLE_BLOCKED_NOTIFICATIONS) { synchronized (mNotificationList) { final int N = mNotificationList.size(); for (int i=0; i<N; i++) { final NotificationRecord r = mNotificationList.get(i); if (r.pkg.equals(pkg)) { cancelNotificationLocked(r, false); } } } } // Don't bother canceling toasts, they'll go away soon enough. } writeBlockDb(); } private static String idDebugString(Context baseContext, String packageName, int id) { Context c = null; Loading Loading @@ -405,6 +575,8 @@ public class NotificationManagerService extends INotificationManager.Stub mToastQueue = new ArrayList<ToastRecord>(); mHandler = new WorkerHandler(); loadBlockDb(); mStatusBar = statusBar; statusBar.setNotificationCallbacks(mNotificationCallbacks); Loading Loading @@ -465,6 +637,13 @@ public class NotificationManagerService extends INotificationManager.Stub return ; } final boolean isSystemToast = ("android".equals(pkg)); if (ENABLE_BLOCKED_TOASTS && !isSystemToast && !areNotificationsEnabledForPackageInt(pkg)) { Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request."); return; } synchronized (mToastQueue) { int callingPid = Binder.getCallingPid(); long callingId = Binder.clearCallingIdentity(); Loading @@ -479,7 +658,7 @@ public class NotificationManagerService extends INotificationManager.Stub } else { // Limit the number of toasts that any given package except the android // package can enqueue. Prevents DOS attacks and deals with leaks. if (!"android".equals(pkg)) { if (!isSystemToast) { int count = 0; final int N = mToastQueue.size(); for (int i=0; i<N; i++) { Loading Loading @@ -675,11 +854,15 @@ public class NotificationManagerService extends INotificationManager.Stub public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid, String tag, int id, Notification notification, int[] idOut) { checkIncomingCall(pkg); if (DBG) { Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification); } checkCallerIsSystemOrSameApp(pkg); final boolean isSystemNotification = ("android".equals(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)) { if (!isSystemNotification) { synchronized (mNotificationList) { int count = 0; final int N = mNotificationList.size(); Loading Loading @@ -728,17 +911,25 @@ public class NotificationManagerService extends INotificationManager.Stub } // 1. initial score: buckets of 10, around the app int score = notification.priority * 10; //[-20..20] int score = notification.priority * NOTIFICATION_PRIORITY_MULTIPLIER; //[-20..20] // 2. Consult oracles (external heuristics) // TODO(dsandler): oracles // 2. Consult external heuristics (TBD) // 3. Apply local heuristics & overrides // 3. Apply local rules // blocked apps // TODO(dsandler): add block db if (pkg.startsWith("com.test.spammer.")) { score = -1000; if (ENABLE_BLOCKED_NOTIFICATIONS && !isSystemNotification && !areNotificationsEnabledForPackageInt(pkg)) { score = JUNK_SCORE; Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request."); } if (DBG) { Slog.v(TAG, "Assigned score=" + score + " to " + notification); } if (score < SCORE_DISPLAY_THRESHOLD) { // Notification will be blocked because the score is too low. return; } synchronized (mNotificationList) { Loading Loading @@ -1030,7 +1221,7 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelNotificationWithTag(String pkg, String tag, int id) { checkIncomingCall(pkg); checkCallerIsSystemOrSameApp(pkg); // Don't allow client applications to cancel foreground service notis. cancelNotification(pkg, tag, id, 0, Binder.getCallingUid() == Process.SYSTEM_UID Loading @@ -1038,14 +1229,22 @@ public class NotificationManagerService extends INotificationManager.Stub } public void cancelAllNotifications(String pkg) { checkIncomingCall(pkg); checkCallerIsSystemOrSameApp(pkg); // Calling from user space, don't allow the canceling of actively // running foreground services. cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true); } void checkIncomingCall(String pkg) { void checkCallerIsSystem() { int uid = Binder.getCallingUid(); if (uid == Process.SYSTEM_UID || uid == 0) { return; } throw new SecurityException("Disallowed call for uid " + uid); } void checkCallerIsSystemOrSameApp(String pkg) { int uid = Binder.getCallingUid(); if (uid == Process.SYSTEM_UID || uid == 0) { return; Loading