Loading core/java/android/app/INotificationManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.net.Uri; import android.os.Bundle; import android.service.notification.Condition; import android.service.notification.IConditionListener; import android.service.notification.IConditionProvider; Loading Loading @@ -66,6 +67,7 @@ interface INotificationManager void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim); ComponentName getEffectsSuppressor(); boolean matchesCallFilter(in Bundle extras); ZenModeConfig getZenModeConfig(); boolean setZenModeConfig(in ZenModeConfig config); Loading core/java/android/app/NotificationManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.SdkConstant; import android.app.Notification.Builder; import android.content.ComponentName; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; Loading Loading @@ -251,5 +252,17 @@ public class NotificationManager } } /** * @hide */ public boolean matchesCallFilter(Bundle extras) { INotificationManager service = getService(); try { return service.matchesCallFilter(extras); } catch (RemoteException e) { return false; } } private Context mContext; } services/core/java/com/android/server/notification/NotificationManagerService.java +9 −1 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.media.AudioManager; import android.media.IRingtonePlayer; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; Loading Loading @@ -1438,7 +1439,7 @@ public class NotificationManagerService extends SystemService { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { pw.println("Permission Denial: can't dump NotificationManager from from pid=" pw.println("Permission Denial: can't dump NotificationManager from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); return; Loading @@ -1452,6 +1453,13 @@ public class NotificationManagerService extends SystemService { enforceSystemOrSystemUI("INotificationManager.getEffectsSuppressor"); return mEffectsSuppressor; } @Override public boolean matchesCallFilter(Bundle extras) { enforceSystemOrSystemUI("INotificationManager.matchesCallFilter"); return mZenModeHelper.matchesCallFilter(extras, mRankingHelper.findExtractor(ValidateNotificationPeople.class)); } }; private String[] getActiveNotificationKeys(INotificationListener token) { Loading services/core/java/com/android/server/notification/RankingHelper.java +11 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,17 @@ public class RankingHelper implements RankingConfig { mProxyByGroupTmp = new ArrayMap<String, NotificationRecord>(); } public <T extends NotificationSignalExtractor> T findExtractor(Class<T> extractorClass) { final int N = mSignalExtractors.length; for (int i = 0; i < N; i++) { final NotificationSignalExtractor extractor = mSignalExtractors[i]; if (extractorClass.equals(extractor.getClass())) { return (T) extractor; } } return null; } public void extractSignals(NotificationRecord r) { final int N = mSignalExtractors.length; for (int i = 0; i < N; i++) { Loading services/core/java/com/android/server/notification/ValidateNotificationPeople.java +77 −41 Original line number Diff line number Diff line Loading @@ -71,8 +71,17 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { private LruCache<String, LookupResult> mPeopleCache; private RankingReconsideration validatePeople(final NotificationRecord record) { final String key = record.getKey(); final Bundle extras = record.getNotification().extras; final float[] affinityOut = new float[1]; final RankingReconsideration rr = validatePeople(key, extras, affinityOut); record.setContactAffinity(affinityOut[0]); return rr; } private PeopleRankingReconsideration validatePeople(String key, Bundle extras, float[] affinityOut) { float affinity = NONE; Bundle extras = record.getNotification().extras; if (extras == null) { return null; } Loading @@ -82,7 +91,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { return null; } if (INFO) Slog.i(TAG, "Validating: " + record.sbn.getKey()); if (INFO) Slog.i(TAG, "Validating: " + key); final LinkedList<String> pendingLookups = new LinkedList<String>(); for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) { final String handle = people[personIdx]; Loading @@ -102,51 +111,15 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { } // record the best available data, so far: record.setContactAffinity(affinity); affinityOut[0] = affinity; if (pendingLookups.isEmpty()) { if (INFO) Slog.i(TAG, "final affinity: " + affinity); return null; } if (DEBUG) Slog.d(TAG, "Pending: future work scheduled for: " + record.sbn.getKey()); return new RankingReconsideration(record.getKey()) { float mContactAffinity = NONE; @Override public void work() { if (INFO) Slog.i(TAG, "Executing: validation for: " + record.getKey()); for (final String handle: pendingLookups) { LookupResult lookupResult = null; final Uri uri = Uri.parse(handle); if ("tel".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle); lookupResult = resolvePhoneContact(uri.getSchemeSpecificPart()); } else if ("mailto".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle); lookupResult = resolveEmailContact(uri.getSchemeSpecificPart()); } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle); lookupResult = searchContacts(uri); } else { lookupResult = new LookupResult(); // invalid person for the cache Slog.w(TAG, "unsupported URI " + handle); } if (lookupResult != null) { synchronized (mPeopleCache) { mPeopleCache.put(handle, lookupResult); } mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity()); } } } @Override public void applyChangesLocked(NotificationRecord operand) { float affinityBound = operand.getContactAffinity(); operand.setContactAffinity(Math.max(mContactAffinity, affinityBound)); if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity()); } }; if (DEBUG) Slog.d(TAG, "Pending: future work scheduled for: " + key); return new PeopleRankingReconsideration(key, pendingLookups); } // VisibleForTesting Loading Loading @@ -269,6 +242,19 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { // ignore: config has no relevant information yet. } public float getContactAffinity(Bundle extras) { if (extras == null) return NONE; final String key = Long.toString(System.nanoTime()); final float[] affinityOut = new float[1]; final PeopleRankingReconsideration prr = validatePeople(key, extras, affinityOut); float affinity = affinityOut[0]; if (prr != null) { prr.work(); affinity = Math.max(prr.getContactAffinity(), affinity); } return affinity; } private static class LookupResult { private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr public static final int INVALID_ID = -1; Loading Loading @@ -328,5 +314,55 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { return this; } } private class PeopleRankingReconsideration extends RankingReconsideration { private final LinkedList<String> mPendingLookups; private float mContactAffinity = NONE; private PeopleRankingReconsideration(String key, LinkedList<String> pendingLookups) { super(key); mPendingLookups = pendingLookups; } @Override public void work() { if (INFO) Slog.i(TAG, "Executing: validation for: " + mKey); for (final String handle: mPendingLookups) { LookupResult lookupResult = null; final Uri uri = Uri.parse(handle); if ("tel".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle); lookupResult = resolvePhoneContact(uri.getSchemeSpecificPart()); } else if ("mailto".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle); lookupResult = resolveEmailContact(uri.getSchemeSpecificPart()); } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle); lookupResult = searchContacts(uri); } else { lookupResult = new LookupResult(); // invalid person for the cache Slog.w(TAG, "unsupported URI " + handle); } if (lookupResult != null) { synchronized (mPeopleCache) { mPeopleCache.put(handle, lookupResult); } mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity()); } } } @Override public void applyChangesLocked(NotificationRecord operand) { float affinityBound = operand.getContactAffinity(); operand.setContactAffinity(Math.max(mContactAffinity, affinityBound)); if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity()); } public float getContactAffinity() { return mContactAffinity; } } } Loading
core/java/android/app/INotificationManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.net.Uri; import android.os.Bundle; import android.service.notification.Condition; import android.service.notification.IConditionListener; import android.service.notification.IConditionProvider; Loading Loading @@ -66,6 +67,7 @@ interface INotificationManager void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim); ComponentName getEffectsSuppressor(); boolean matchesCallFilter(in Bundle extras); ZenModeConfig getZenModeConfig(); boolean setZenModeConfig(in ZenModeConfig config); Loading
core/java/android/app/NotificationManager.java +13 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.SdkConstant; import android.app.Notification.Builder; import android.content.ComponentName; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; Loading Loading @@ -251,5 +252,17 @@ public class NotificationManager } } /** * @hide */ public boolean matchesCallFilter(Bundle extras) { INotificationManager service = getService(); try { return service.matchesCallFilter(extras); } catch (RemoteException e) { return false; } } private Context mContext; }
services/core/java/com/android/server/notification/NotificationManagerService.java +9 −1 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.media.AudioManager; import android.media.IRingtonePlayer; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; Loading Loading @@ -1438,7 +1439,7 @@ public class NotificationManagerService extends SystemService { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { pw.println("Permission Denial: can't dump NotificationManager from from pid=" pw.println("Permission Denial: can't dump NotificationManager from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); return; Loading @@ -1452,6 +1453,13 @@ public class NotificationManagerService extends SystemService { enforceSystemOrSystemUI("INotificationManager.getEffectsSuppressor"); return mEffectsSuppressor; } @Override public boolean matchesCallFilter(Bundle extras) { enforceSystemOrSystemUI("INotificationManager.matchesCallFilter"); return mZenModeHelper.matchesCallFilter(extras, mRankingHelper.findExtractor(ValidateNotificationPeople.class)); } }; private String[] getActiveNotificationKeys(INotificationListener token) { Loading
services/core/java/com/android/server/notification/RankingHelper.java +11 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,17 @@ public class RankingHelper implements RankingConfig { mProxyByGroupTmp = new ArrayMap<String, NotificationRecord>(); } public <T extends NotificationSignalExtractor> T findExtractor(Class<T> extractorClass) { final int N = mSignalExtractors.length; for (int i = 0; i < N; i++) { final NotificationSignalExtractor extractor = mSignalExtractors[i]; if (extractorClass.equals(extractor.getClass())) { return (T) extractor; } } return null; } public void extractSignals(NotificationRecord r) { final int N = mSignalExtractors.length; for (int i = 0; i < N; i++) { Loading
services/core/java/com/android/server/notification/ValidateNotificationPeople.java +77 −41 Original line number Diff line number Diff line Loading @@ -71,8 +71,17 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { private LruCache<String, LookupResult> mPeopleCache; private RankingReconsideration validatePeople(final NotificationRecord record) { final String key = record.getKey(); final Bundle extras = record.getNotification().extras; final float[] affinityOut = new float[1]; final RankingReconsideration rr = validatePeople(key, extras, affinityOut); record.setContactAffinity(affinityOut[0]); return rr; } private PeopleRankingReconsideration validatePeople(String key, Bundle extras, float[] affinityOut) { float affinity = NONE; Bundle extras = record.getNotification().extras; if (extras == null) { return null; } Loading @@ -82,7 +91,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { return null; } if (INFO) Slog.i(TAG, "Validating: " + record.sbn.getKey()); if (INFO) Slog.i(TAG, "Validating: " + key); final LinkedList<String> pendingLookups = new LinkedList<String>(); for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) { final String handle = people[personIdx]; Loading @@ -102,51 +111,15 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { } // record the best available data, so far: record.setContactAffinity(affinity); affinityOut[0] = affinity; if (pendingLookups.isEmpty()) { if (INFO) Slog.i(TAG, "final affinity: " + affinity); return null; } if (DEBUG) Slog.d(TAG, "Pending: future work scheduled for: " + record.sbn.getKey()); return new RankingReconsideration(record.getKey()) { float mContactAffinity = NONE; @Override public void work() { if (INFO) Slog.i(TAG, "Executing: validation for: " + record.getKey()); for (final String handle: pendingLookups) { LookupResult lookupResult = null; final Uri uri = Uri.parse(handle); if ("tel".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle); lookupResult = resolvePhoneContact(uri.getSchemeSpecificPart()); } else if ("mailto".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle); lookupResult = resolveEmailContact(uri.getSchemeSpecificPart()); } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle); lookupResult = searchContacts(uri); } else { lookupResult = new LookupResult(); // invalid person for the cache Slog.w(TAG, "unsupported URI " + handle); } if (lookupResult != null) { synchronized (mPeopleCache) { mPeopleCache.put(handle, lookupResult); } mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity()); } } } @Override public void applyChangesLocked(NotificationRecord operand) { float affinityBound = operand.getContactAffinity(); operand.setContactAffinity(Math.max(mContactAffinity, affinityBound)); if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity()); } }; if (DEBUG) Slog.d(TAG, "Pending: future work scheduled for: " + key); return new PeopleRankingReconsideration(key, pendingLookups); } // VisibleForTesting Loading Loading @@ -269,6 +242,19 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { // ignore: config has no relevant information yet. } public float getContactAffinity(Bundle extras) { if (extras == null) return NONE; final String key = Long.toString(System.nanoTime()); final float[] affinityOut = new float[1]; final PeopleRankingReconsideration prr = validatePeople(key, extras, affinityOut); float affinity = affinityOut[0]; if (prr != null) { prr.work(); affinity = Math.max(prr.getContactAffinity(), affinity); } return affinity; } private static class LookupResult { private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr public static final int INVALID_ID = -1; Loading Loading @@ -328,5 +314,55 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { return this; } } private class PeopleRankingReconsideration extends RankingReconsideration { private final LinkedList<String> mPendingLookups; private float mContactAffinity = NONE; private PeopleRankingReconsideration(String key, LinkedList<String> pendingLookups) { super(key); mPendingLookups = pendingLookups; } @Override public void work() { if (INFO) Slog.i(TAG, "Executing: validation for: " + mKey); for (final String handle: mPendingLookups) { LookupResult lookupResult = null; final Uri uri = Uri.parse(handle); if ("tel".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle); lookupResult = resolvePhoneContact(uri.getSchemeSpecificPart()); } else if ("mailto".equals(uri.getScheme())) { if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle); lookupResult = resolveEmailContact(uri.getSchemeSpecificPart()); } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle); lookupResult = searchContacts(uri); } else { lookupResult = new LookupResult(); // invalid person for the cache Slog.w(TAG, "unsupported URI " + handle); } if (lookupResult != null) { synchronized (mPeopleCache) { mPeopleCache.put(handle, lookupResult); } mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity()); } } } @Override public void applyChangesLocked(NotificationRecord operand) { float affinityBound = operand.getContactAffinity(); operand.setContactAffinity(Math.max(mContactAffinity, affinityBound)); if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity()); } public float getContactAffinity() { return mContactAffinity; } } }