am 84a39cb0: Merge "Add a hidden system method to check call filter." into lmp-dev
* commit '84a39cb09e300386d6875c1f555c969089814fd8': Add a hidden system method to check call filter.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user