diff options
7 files changed, 178 insertions, 111 deletions
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 5d864df..33262b3 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -48,6 +48,9 @@ interface INotificationManager void setPackagePriority(String pkg, int uid, int priority); int getPackagePriority(String pkg, int uid); + void setPackagePeekable(String pkg, int uid, boolean peekable); + boolean getPackagePeekable(String pkg, int uid); + void setPackageVisibilityOverride(String pkg, int uid, int visibility); int getPackageVisibilityOverride(String pkg, int uid); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 55d6ac8..320d9f4 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1840,6 +1840,26 @@ public class Notification implements Parcelable } /** + * {@hide} + */ + public static String priorityToString(@Priority int pri) { + switch (pri) { + case PRIORITY_MIN: + return "MIN"; + case PRIORITY_LOW: + return "LOW"; + case PRIORITY_DEFAULT: + return "DEFAULT"; + case PRIORITY_HIGH: + return "HIGH"; + case PRIORITY_MAX: + return "MAX"; + default: + return "UNKNOWN(" + String.valueOf(pri) + ")"; + } + } + + /** * @hide */ public boolean isValid() { diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java index 1335706..22cdd58 100644 --- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java @@ -18,6 +18,7 @@ package com.android.server.notification; import android.app.Notification; import android.content.Context; +import android.util.Log; import android.util.Slog; /** @@ -25,8 +26,8 @@ import android.util.Slog; * notifications and marks them to get a temporary ranking bump. */ public class NotificationIntrusivenessExtractor implements NotificationSignalExtractor { - private static final String TAG = "NotificationNoiseExtractor"; - private static final boolean DBG = false; + private static final String TAG = "IntrusivenessExtractor"; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); /** Length of time (in milliseconds) that an intrusive or noisy notification will stay at the top of the ranking order, before it falls back to its natural position. */ @@ -48,7 +49,7 @@ public class NotificationIntrusivenessExtractor implements NotificationSignalExt (notification.defaults & Notification.DEFAULT_SOUND) != 0 || notification.sound != null || notification.fullScreenIntent != null) { - record.setRecentlyIntusive(true); + record.setRecentlyIntrusive(true); } return new RankingReconsideration(record.getKey(), HANG_TIME_MS) { @@ -59,7 +60,7 @@ public class NotificationIntrusivenessExtractor implements NotificationSignalExt @Override public void applyChangesLocked(NotificationRecord record) { - record.setRecentlyIntusive(false); + record.setRecentlyIntrusive(false); } }; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 0c71d5f..c330046 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1216,6 +1216,19 @@ public class NotificationManagerService extends SystemService { } @Override + public void setPackagePeekable(String pkg, int uid, boolean peekable) { + checkCallerIsSystem(); + + mRankingHelper.setPackagePeekable(pkg, uid, peekable); + } + + @Override + public boolean getPackagePeekable(String pkg, int uid) { + checkCallerIsSystem(); + return mRankingHelper.getPackagePeekable(pkg, uid); + } + + @Override public void setPackageVisibilityOverride(String pkg, int uid, int visibility) { checkCallerIsSystem(); mRankingHelper.setPackageVisibilityOverride(pkg, uid, visibility); @@ -1845,6 +1858,14 @@ public class NotificationManagerService extends SystemService { notification.priority = Notification.PRIORITY_HIGH; } } + // force no heads up per package config + if (!mRankingHelper.getPackagePeekable(pkg, callingUid)) { + if (notification.extras == null) { + notification.extras = new Bundle(); + } + notification.extras.putInt(Notification.EXTRA_AS_HEADS_UP, + Notification.HEADS_UP_NEVER); + } // 1. initial score: buckets of 10, around the app [-20..20] final int score = notification.priority * NOTIFICATION_PRIORITY_MULTIPLIER; diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index ea6f2db..39fd9ab 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -209,7 +209,7 @@ public final class NotificationRecord { return mContactAffinity; } - public void setRecentlyIntusive(boolean recentlyIntrusive) { + public void setRecentlyIntrusive(boolean recentlyIntrusive) { mRecentlyIntrusive = recentlyIntrusive; } diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index aea137b..803db10 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -20,6 +20,10 @@ public interface RankingConfig { void setPackagePriority(String packageName, int uid, int priority); + boolean getPackagePeekable(String packageName, int uid); + + void setPackagePeekable(String packageName, int uid, boolean peekable); + int getPackageVisibilityOverride(String packageName, int uid); void setPackageVisibilityOverride(String packageName, int uid, int visibility); diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 518e223..88055ba 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -23,9 +23,8 @@ import android.os.UserHandle; import android.service.notification.NotificationListenerService; import android.text.TextUtils; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.Slog; -import android.util.SparseIntArray; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -34,12 +33,10 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; -import java.util.Set; import java.util.concurrent.TimeUnit; public class RankingHelper implements RankingConfig { private static final String TAG = "RankingHelper"; - private static final boolean DEBUG = false; private static final int XML_VERSION = 1; @@ -50,16 +47,20 @@ public class RankingHelper implements RankingConfig { private static final String ATT_NAME = "name"; private static final String ATT_UID = "uid"; private static final String ATT_PRIORITY = "priority"; + private static final String ATT_PEEKABLE = "peekable"; private static final String ATT_VISIBILITY = "visibility"; + private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT; + private static final boolean DEFAULT_PEEKABLE = true; + private static final int DEFAULT_VISIBILITY = + NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE; + private final NotificationSignalExtractor[] mSignalExtractors; private final NotificationComparator mPreliminaryComparator = new NotificationComparator(); private final GlobalSortKeyComparator mFinalComparator = new GlobalSortKeyComparator(); - // Package name to uid, to priority. Would be better as Table<String, Int, Int> - private final ArrayMap<String, SparseIntArray> mPackagePriorities; - private final ArrayMap<String, SparseIntArray> mPackageVisibilities; - private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp; + private final ArrayMap<String, Record> mRecords = new ArrayMap<>(); // pkg|uid => Record + private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp = new ArrayMap<>(); private final Context mContext; private final Handler mRankingHandler; @@ -67,8 +68,6 @@ public class RankingHelper implements RankingConfig { public RankingHelper(Context context, Handler rankingHandler, String[] extractorNames) { mContext = context; mRankingHandler = rankingHandler; - mPackagePriorities = new ArrayMap<String, SparseIntArray>(); - mPackageVisibilities = new ArrayMap<String, SparseIntArray>(); final int N = extractorNames.length; mSignalExtractors = new NotificationSignalExtractor[N]; @@ -88,9 +87,9 @@ public class RankingHelper implements RankingConfig { Slog.w(TAG, "Problem accessing extractor " + extractorNames[i] + ".", e); } } - mProxyByGroupTmp = new ArrayMap<String, NotificationRecord>(); } + @SuppressWarnings("unchecked") public <T extends NotificationSignalExtractor> T findExtractor(Class<T> extractorClass) { final int N = mSignalExtractors.length; for (int i = 0; i < N; i++) { @@ -125,8 +124,7 @@ public class RankingHelper implements RankingConfig { if (type != XmlPullParser.START_TAG) return; String tag = parser.getName(); if (!TAG_RANKING.equals(tag)) return; - mPackagePriorities.clear(); - final int version = safeInt(parser, ATT_VERSION, XML_VERSION); + mRecords.clear(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { tag = parser.getName(); if (type == XmlPullParser.END_TAG && TAG_RANKING.equals(tag)) { @@ -135,27 +133,20 @@ public class RankingHelper implements RankingConfig { if (type == XmlPullParser.START_TAG) { if (TAG_PACKAGE.equals(tag)) { int uid = safeInt(parser, ATT_UID, UserHandle.USER_ALL); - int priority = safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT); - int vis = safeInt(parser, ATT_VISIBILITY, - NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE); + int priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY); + boolean peekable = safeBool(parser, ATT_PEEKABLE, DEFAULT_PEEKABLE); + int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); String name = parser.getAttributeValue(null, ATT_NAME); if (!TextUtils.isEmpty(name)) { - if (priority != Notification.PRIORITY_DEFAULT) { - SparseIntArray priorityByUid = mPackagePriorities.get(name); - if (priorityByUid == null) { - priorityByUid = new SparseIntArray(); - mPackagePriorities.put(name, priorityByUid); - } - priorityByUid.put(uid, priority); + if (priority != DEFAULT_PRIORITY) { + getOrCreateRecord(name, uid).priority = priority; + } + if (peekable != DEFAULT_PEEKABLE) { + getOrCreateRecord(name, uid).peekable = peekable; } - if (vis != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) { - SparseIntArray visibilityByUid = mPackageVisibilities.get(name); - if (visibilityByUid == null) { - visibilityByUid = new SparseIntArray(); - mPackageVisibilities.put(name, visibilityByUid); - } - visibilityByUid.put(uid, vis); + if (vis != DEFAULT_VISIBILITY) { + getOrCreateRecord(name, uid).visibility = vis; } } } @@ -164,49 +155,53 @@ public class RankingHelper implements RankingConfig { throw new IllegalStateException("Failed to reach END_DOCUMENT"); } + private static String recordKey(String pkg, int uid) { + return pkg + "|" + uid; + } + + private Record getOrCreateRecord(String pkg, int uid) { + final String key = recordKey(pkg, uid); + Record r = mRecords.get(key); + if (r == null) { + r = new Record(); + r.pkg = pkg; + r.uid = uid; + mRecords.put(key, r); + } + return r; + } + + private void removeDefaultRecords() { + final int N = mRecords.size(); + for (int i = N - 1; i >= 0; i--) { + final Record r = mRecords.valueAt(i); + if (r.priority == DEFAULT_PRIORITY && r.peekable == DEFAULT_PEEKABLE + && r.visibility == DEFAULT_VISIBILITY) { + mRecords.remove(i); + } + } + } + public void writeXml(XmlSerializer out) throws IOException { out.startTag(null, TAG_RANKING); out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION)); - final Set<String> packageNames = new ArraySet<>(mPackagePriorities.size() - + mPackageVisibilities.size()); - packageNames.addAll(mPackagePriorities.keySet()); - packageNames.addAll(mPackageVisibilities.keySet()); - final Set<Integer> packageUids = new ArraySet<>(); - for (String packageName : packageNames) { - packageUids.clear(); - SparseIntArray priorityByUid = mPackagePriorities.get(packageName); - SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName); - if (priorityByUid != null) { - final int M = priorityByUid.size(); - for (int j = 0; j < M; j++) { - packageUids.add(priorityByUid.keyAt(j)); - } + final int N = mRecords.size(); + for (int i = 0; i < N; i++) { + final Record r = mRecords.valueAt(i); + out.startTag(null, TAG_PACKAGE); + out.attribute(null, ATT_NAME, r.pkg); + if (r.priority != DEFAULT_PRIORITY) { + out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority)); } - if (visibilityByUid != null) { - final int M = visibilityByUid.size(); - for (int j = 0; j < M; j++) { - packageUids.add(visibilityByUid.keyAt(j)); - } + if (r.peekable != DEFAULT_PEEKABLE) { + out.attribute(null, ATT_PEEKABLE, Boolean.toString(r.peekable)); } - for (Integer uid : packageUids) { - out.startTag(null, TAG_PACKAGE); - out.attribute(null, ATT_NAME, packageName); - if (priorityByUid != null) { - final int priority = priorityByUid.get(uid); - if (priority != Notification.PRIORITY_DEFAULT) { - out.attribute(null, ATT_PRIORITY, Integer.toString(priority)); - } - } - if (visibilityByUid != null) { - final int visibility = visibilityByUid.get(uid); - if (visibility != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) { - out.attribute(null, ATT_VISIBILITY, Integer.toString(visibility)); - } - } - out.attribute(null, ATT_UID, Integer.toString(uid)); - out.endTag(null, TAG_PACKAGE); + if (r.visibility != DEFAULT_VISIBILITY) { + out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); } + out.attribute(null, ATT_UID, Integer.toString(r.uid)); + out.endTag(null, TAG_PACKAGE); } out.endTag(null, TAG_RANKING); } @@ -295,14 +290,20 @@ public class RankingHelper implements RankingConfig { } } + private static boolean safeBool(XmlPullParser parser, String att, boolean defValue) { + final String val = parser.getAttributeValue(null, att); + return tryParseBool(val, defValue); + } + + private static boolean tryParseBool(String value, boolean defValue) { + if (TextUtils.isEmpty(value)) return defValue; + return Boolean.valueOf(value); + } + @Override public int getPackagePriority(String packageName, int uid) { - int priority = Notification.PRIORITY_DEFAULT; - SparseIntArray priorityByUid = mPackagePriorities.get(packageName); - if (priorityByUid != null) { - priority = priorityByUid.get(uid, Notification.PRIORITY_DEFAULT); - } - return priority; + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.priority : DEFAULT_PRIORITY; } @Override @@ -310,24 +311,31 @@ public class RankingHelper implements RankingConfig { if (priority == getPackagePriority(packageName, uid)) { return; } - SparseIntArray priorityByUid = mPackagePriorities.get(packageName); - if (priorityByUid == null) { - priorityByUid = new SparseIntArray(); - mPackagePriorities.put(packageName, priorityByUid); + getOrCreateRecord(packageName, uid).priority = priority; + removeDefaultRecords(); + updateConfig(); + } + + @Override + public boolean getPackagePeekable(String packageName, int uid) { + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.peekable : DEFAULT_PEEKABLE; + } + + @Override + public void setPackagePeekable(String packageName, int uid, boolean peekable) { + if (peekable == getPackagePeekable(packageName, uid)) { + return; } - priorityByUid.put(uid, priority); + getOrCreateRecord(packageName, uid).peekable = peekable; + removeDefaultRecords(); updateConfig(); } @Override public int getPackageVisibilityOverride(String packageName, int uid) { - int visibility = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE; - SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName); - if (visibilityByUid != null) { - visibility = visibilityByUid.get(uid, - NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE); - } - return visibility; + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.visibility : DEFAULT_VISIBILITY; } @Override @@ -335,12 +343,8 @@ public class RankingHelper implements RankingConfig { if (visibility == getPackageVisibilityOverride(packageName, uid)) { return; } - SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName); - if (visibilityByUid == null) { - visibilityByUid = new SparseIntArray(); - mPackageVisibilities.put(packageName, visibilityByUid); - } - visibilityByUid.put(uid, visibility); + getOrCreateRecord(packageName, uid).visibility = visibility; + removeDefaultRecords(); updateConfig(); } @@ -356,28 +360,42 @@ public class RankingHelper implements RankingConfig { pw.println(mSignalExtractors[i]); } } - final int N = mPackagePriorities.size(); if (filter == null) { pw.print(prefix); - pw.println("package priorities:"); + pw.println("per-package config:"); } + final int N = mRecords.size(); for (int i = 0; i < N; i++) { - String name = mPackagePriorities.keyAt(i); - if (filter == null || filter.matches(name)) { - SparseIntArray priorityByUid = mPackagePriorities.get(name); - final int M = priorityByUid.size(); - for (int j = 0; j < M; j++) { - int uid = priorityByUid.keyAt(j); - int priority = priorityByUid.get(uid); - pw.print(prefix); - pw.print(" "); - pw.print(name); - pw.print(" ("); - pw.print(uid); - pw.print(") has priority: "); - pw.println(priority); + final Record r = mRecords.valueAt(i); + if (filter == null || filter.matches(r.pkg)) { + pw.print(prefix); + pw.print(" "); + pw.print(r.pkg); + pw.print(" ("); + pw.print(r.uid); + pw.print(')'); + if (r.priority != DEFAULT_PRIORITY) { + pw.print(" priority="); + pw.print(Notification.priorityToString(r.priority)); + } + if (r.peekable != DEFAULT_PEEKABLE) { + pw.print(" peekable="); + pw.print(r.peekable); + } + if (r.visibility != DEFAULT_VISIBILITY) { + pw.print(" visibility="); + pw.print(Notification.visibilityToString(r.visibility)); } + pw.println(); } } } + + private static class Record { + String pkg; + int uid; + int priority = DEFAULT_PRIORITY; + boolean peekable = DEFAULT_PEEKABLE; + int visibility = DEFAULT_VISIBILITY; + } } |