diff options
author | John Spurlock <jspurlock@google.com> | 2014-08-29 22:17:09 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-08-29 22:17:10 +0000 |
commit | bd6937841983230bd65dc08548367caa7d409238 (patch) | |
tree | c7021170d466d862701a19a29bafc132789205cc | |
parent | 0de79f16f3bfe060d25d481d52155d69233864e4 (diff) | |
parent | 2b122f4c2e691f0319e4f9ea5873989792bb56a6 (diff) | |
download | frameworks_base-bd6937841983230bd65dc08548367caa7d409238.zip frameworks_base-bd6937841983230bd65dc08548367caa7d409238.tar.gz frameworks_base-bd6937841983230bd65dc08548367caa7d409238.tar.bz2 |
Merge "Add a hidden system method to check call filter." into lmp-dev
6 files changed, 130 insertions, 46 deletions
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index fb28c5d..dbd180f 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -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; @@ -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); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index fc047de..7dc1ad6 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -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; @@ -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; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 4101232..d0f4054 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -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; @@ -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; @@ -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) { diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 01188af..435177b 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -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++) { diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java index bdc364c..aa47858 100644 --- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java +++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java @@ -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; } @@ -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]; @@ -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 @@ -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; @@ -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; + } + } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 7a5336b..fd35ede 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -34,6 +34,7 @@ import android.database.ContentObserver; import android.media.AudioAttributes; import android.media.AudioManager; import android.net.Uri; +import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings.Global; @@ -189,7 +190,7 @@ public class ZenModeHelper { } private boolean shouldInterceptAudience(NotificationRecord record) { - if (!audienceMatches(record)) { + if (!audienceMatches(record.getContactAffinity())) { ZenLog.traceIntercepted(record, "!audienceMatches"); return true; } @@ -372,14 +373,27 @@ public class ZenModeHelper { return record.isCategory(Notification.CATEGORY_MESSAGE) || isDefaultMessagingApp(record); } - private boolean audienceMatches(NotificationRecord record) { + public boolean matchesCallFilter(Bundle extras, ValidateNotificationPeople validator) { + final int zen = mZenMode; + if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) return false; // nothing gets through + if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { + if (!mConfig.allowCalls) return false; // no calls get through + if (validator != null) { + final float contactAffinity = validator.getContactAffinity(extras); + return audienceMatches(contactAffinity); + } + } + return true; + } + + private boolean audienceMatches(float contactAffinity) { switch (mConfig.allowFrom) { case ZenModeConfig.SOURCE_ANYONE: return true; case ZenModeConfig.SOURCE_CONTACT: - return record.getContactAffinity() >= ValidateNotificationPeople.VALID_CONTACT; + return contactAffinity >= ValidateNotificationPeople.VALID_CONTACT; case ZenModeConfig.SOURCE_STAR: - return record.getContactAffinity() >= ValidateNotificationPeople.STARRED_CONTACT; + return contactAffinity >= ValidateNotificationPeople.STARRED_CONTACT; default: Slog.w(TAG, "Encountered unknown source: " + mConfig.allowFrom); return true; |