summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/util/cm/SpamFilter.java58
-rw-r--r--packages/SystemUI/AndroidManifest.xml6
-rw-r--r--packages/SystemUI/res/layout/notification_guts.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java196
-rw-r--r--packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java46
-rwxr-xr-x[-rw-r--r--]packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java28
-rwxr-xr-x[-rw-r--r--]services/core/java/com/android/server/notification/NotificationManagerService.java74
7 files changed, 418 insertions, 0 deletions
diff --git a/core/java/com/android/internal/util/cm/SpamFilter.java b/core/java/com/android/internal/util/cm/SpamFilter.java
new file mode 100644
index 0000000..cc0e716
--- /dev/null
+++ b/core/java/com/android/internal/util/cm/SpamFilter.java
@@ -0,0 +1,58 @@
+package com.android.internal.util.cm;
+
+import android.app.Notification;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+public class SpamFilter {
+
+ public static final String AUTHORITY = "com.cyanogenmod.spam";
+ public static final Uri NOTIFICATION_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(AUTHORITY)
+ .build();
+
+ public static final class SpamContract {
+
+ public static final class PackageTable {
+ public static final String TABLE_NAME = "packages";
+ public static final String ID = "_id";
+ public static final String PACKAGE_NAME = "package_name";
+ }
+
+ public static final class NotificationTable {
+ public static final String TABLE_NAME = "notifications";
+ public static final String ID = "_id";
+ public static final String PACKAGE_ID = "package_id";
+ public static final String MESSAGE_TEXT = "message_text";
+ public static final String COUNT = "count";
+ public static final String LAST_BLOCKED = "last_blocked";
+ public static final String NORMALIZED_TEXT = "normalized_text";
+ }
+
+ }
+
+ public static String getNormalizedContent(String msg) {
+ return msg.toLowerCase().replaceAll("[^\\p{L}\\p{Nd}]+", "");
+ }
+
+ public static String getNotificationContent(Notification notification) {
+ Bundle extras = notification.extras;
+ String titleExtra = extras.containsKey(Notification.EXTRA_TITLE_BIG)
+ ? Notification.EXTRA_TITLE_BIG : Notification.EXTRA_TITLE;
+ CharSequence notificationTitle = extras.getCharSequence(titleExtra);
+ CharSequence notificationMessage = extras.getCharSequence(Notification.EXTRA_TEXT);
+
+ if (TextUtils.isEmpty(notificationMessage)) {
+ CharSequence[] inboxLines = extras.getCharSequenceArray(Notification.EXTRA_TEXT_LINES);
+ if (inboxLines == null || inboxLines.length == 0) {
+ notificationMessage = "";
+ } else {
+ notificationMessage = TextUtils.join("\n", inboxLines);
+ }
+ }
+ return notificationTitle + "\n" + notificationMessage;
+ }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 8375197..772067b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -411,5 +411,11 @@
<action android:name="com.android.systemui.action.CLEAR_TUNER" />
</intent-filter>
</receiver>
+
+ <provider android:name=".cm.SpamMessageProvider"
+ android:permission="android.permission.INTERACT_ACROSS_USERS_FULL"
+ android:exported="true"
+ android:authorities="com.cyanogenmod.spam" />
+
</application>
</manifest>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index d52c274..92cb601 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -87,6 +87,16 @@
/>
<ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
+ android:id="@+id/notification_inspect_filter_notification"
+ android:layout_width="52dp"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:gravity="center"
+ android:src="@drawable/ic_volume_ringer_mute"
+ android:visibility="gone"
+ />
+
+ <ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
android:id="@+id/notification_inspect_item"
android:layout_width="52dp"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java b/packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java
new file mode 100644
index 0000000..a43f263
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/SpamMessageProvider.java
@@ -0,0 +1,196 @@
+package com.android.systemui.cm;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.android.internal.util.cm.SpamFilter;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+
+public class SpamMessageProvider extends ContentProvider {
+ public static final String AUTHORITY = SpamFilter.AUTHORITY;
+
+ private static final String UPDATE_COUNT_QUERY =
+ "UPDATE " + NotificationTable.TABLE_NAME +
+ " SET " + NotificationTable.LAST_BLOCKED + "=%d," +
+ NotificationTable.COUNT + "=" + NotificationTable.COUNT + "+1 " +
+ " WHERE " + NotificationTable.ID + "='%s'";
+
+ private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ private static final int PACKAGES = 0;
+ private static final int MESSAGE = 1;
+ private static final int PACKAGE_ID = 2;
+ private static final int MESSAGE_UPDATE_COUNT = 3;
+ private static final int MESSAGE_FOR_ID = 4;
+ static {
+ sURIMatcher.addURI(AUTHORITY, "packages", PACKAGES);
+ sURIMatcher.addURI(AUTHORITY, "package/id/*", PACKAGE_ID);
+ sURIMatcher.addURI(AUTHORITY, "message", MESSAGE);
+ sURIMatcher.addURI(AUTHORITY, "message/#", MESSAGE_FOR_ID);
+ sURIMatcher.addURI(AUTHORITY, "message/inc_count/#", MESSAGE_UPDATE_COUNT);
+ }
+
+ private SpamOpenHelper mDbHelper;
+
+ @Override
+ public boolean onCreate() {
+ mDbHelper = new SpamOpenHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case PACKAGE_ID:
+ Cursor idCursor = mDbHelper.getReadableDatabase().query(PackageTable.TABLE_NAME,
+ new String[]{NotificationTable.ID}, PackageTable.PACKAGE_NAME + "=?",
+ new String[]{uri.getLastPathSegment()}, null, null, null);
+ return idCursor;
+ case PACKAGES:
+ Cursor pkgCursor = mDbHelper.getReadableDatabase().query(PackageTable.TABLE_NAME,
+ null, null, null, null, null, null);
+ return pkgCursor;
+ case MESSAGE:
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(PackageTable.TABLE_NAME + "," + NotificationTable.TABLE_NAME);
+ String pkgId = PackageTable.TABLE_NAME + "." + PackageTable.ID;
+ String notificationPkgId = NotificationTable.TABLE_NAME + "."
+ + NotificationTable.PACKAGE_ID;
+ qb.appendWhere(pkgId + "=" + notificationPkgId);
+ SQLiteDatabase db = mDbHelper.getReadableDatabase();
+ Cursor ret = qb.query(db, new String[]{NotificationTable.TABLE_NAME + ".*"},
+ selection, selectionArgs, null, null, null);
+ ret.moveToFirst();
+ return ret;
+ case MESSAGE_FOR_ID:
+ qb = new SQLiteQueryBuilder();
+ qb.setTables(NotificationTable.TABLE_NAME);
+ qb.appendWhere(NotificationTable.PACKAGE_ID + "=" + uri.getLastPathSegment());
+ db = mDbHelper.getReadableDatabase();
+ ret = qb.query(db, null, null, null, null, null, null);
+ return ret;
+ default:
+ return null;
+ }
+ }
+
+ private long getPackageId(String pkg) {
+ long rowId = -1;
+ Cursor idCursor = mDbHelper.getReadableDatabase().query(PackageTable.TABLE_NAME,
+ new String[]{NotificationTable.ID}, PackageTable.PACKAGE_NAME + "=?",
+ new String[]{pkg}, null, null, null);
+ if (idCursor != null) {
+ if (idCursor.moveToFirst()) {
+ rowId = idCursor.getLong(0);
+ }
+ idCursor.close();
+ }
+ return rowId;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ if (values == null) {
+ return null;
+ }
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case MESSAGE:
+ String msgText = values.getAsString(NotificationTable.MESSAGE_TEXT);
+ String packageName = values.getAsString(PackageTable.PACKAGE_NAME);
+ if (TextUtils.isEmpty(msgText) || TextUtils.isEmpty(packageName)) {
+ return null;
+ }
+ values.clear();
+ values.put(PackageTable.PACKAGE_NAME, packageName);
+ long packageId = getPackageId(packageName);
+ if (packageId == -1) {
+ packageId = mDbHelper.getWritableDatabase().insert(
+ PackageTable.TABLE_NAME, null, values);
+ }
+ if (packageId != -1) {
+ values.clear();
+ values.put(NotificationTable.MESSAGE_TEXT, msgText);
+ values.put(NotificationTable.NORMALIZED_TEXT,
+ SpamFilter.getNormalizedContent(msgText));
+ values.put(NotificationTable.PACKAGE_ID, packageId);
+ values.put(NotificationTable.LAST_BLOCKED, System.currentTimeMillis());
+ mDbHelper.getReadableDatabase().insert(NotificationTable.TABLE_NAME,
+ null, values);
+ notifyChange();
+ }
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ private void notifyChange() {
+ getContext().getContentResolver().notifyChange(SpamFilter.NOTIFICATION_URI, null);
+ }
+
+ private void removePackageIfNecessary(int packageId) {
+ long numEntries = DatabaseUtils.queryNumEntries(mDbHelper.getReadableDatabase(),
+ NotificationTable.TABLE_NAME, NotificationTable.PACKAGE_ID + "=?",
+ new String[]{String.valueOf(packageId)});
+ if (numEntries == 0) {
+ mDbHelper.getWritableDatabase().delete(PackageTable.TABLE_NAME, PackageTable.ID + "=?",
+ new String[]{String.valueOf(packageId)});
+ }
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case MESSAGE_FOR_ID:
+ int packageId = -1;
+ Cursor idCursor = mDbHelper.getReadableDatabase().query(NotificationTable.TABLE_NAME,
+ new String[]{NotificationTable.PACKAGE_ID}, NotificationTable.ID + "=?",
+ new String[]{uri.getLastPathSegment()}, null, null, null);
+ if (idCursor != null) {
+ if (idCursor.moveToFirst()) {
+ packageId = idCursor.getInt(0);
+ }
+ idCursor.close();
+ }
+ int result = mDbHelper.getWritableDatabase().delete(NotificationTable.TABLE_NAME,
+ NotificationTable.ID + "=?", new String[]{uri.getLastPathSegment()});
+ removePackageIfNecessary(packageId);
+ notifyChange();
+ return result;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ int match = sURIMatcher.match(uri);
+ switch (match) {
+ case MESSAGE_UPDATE_COUNT:
+ String formattedQuery = String.format(UPDATE_COUNT_QUERY,
+ System.currentTimeMillis(), uri.getLastPathSegment());
+ mDbHelper.getWritableDatabase().execSQL(formattedQuery);
+ notifyChange();
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java b/packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java
new file mode 100644
index 0000000..45dc91c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/cm/SpamOpenHelper.java
@@ -0,0 +1,46 @@
+package com.android.systemui.cm;
+
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+public class SpamOpenHelper extends SQLiteOpenHelper {
+
+ private static final String DATABASE_NAME = "spam.db";
+ private static final int VERSION = 4;
+ private static final String CREATE_PACKAGES_TABLE =
+ "create table " + PackageTable.TABLE_NAME + "(" +
+ PackageTable.ID + " INTEGER PRIMARY KEY," +
+ PackageTable.PACKAGE_NAME + " TEXT UNIQUE);";
+ private static final String CREATE_NOTIFICATIONS_TABLE =
+ "create table " + NotificationTable.TABLE_NAME + "(" +
+ NotificationTable.ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ NotificationTable.PACKAGE_ID + " INTEGER," +
+ NotificationTable.MESSAGE_TEXT + " STRING," +
+ NotificationTable.LAST_BLOCKED + " INTEGER," +
+ NotificationTable.NORMALIZED_TEXT + " STRING," +
+ NotificationTable.COUNT + " INTEGER DEFAULT 0);";
+
+ private Context mContext;
+
+ public SpamOpenHelper(Context context) {
+ super(context, DATABASE_NAME, null, VERSION);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(CREATE_PACKAGES_TABLE);
+ db.execSQL(CREATE_NOTIFICATIONS_TABLE);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ mContext.deleteDatabase(DATABASE_NAME);
+ onCreate(db);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 79174c9..f8fd25e 100644..100755
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -29,6 +29,8 @@ import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
+import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
@@ -42,6 +44,7 @@ import android.database.ContentObserver;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -87,6 +90,9 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.util.cm.SpamFilter;
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
import com.android.internal.util.NotificationColorUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -96,6 +102,7 @@ import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.recents.Recents;
+import com.android.systemui.cm.SpamMessageProvider;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -145,6 +152,12 @@ public abstract class BaseStatusBar extends SystemUI implements
private static final String BANNER_ACTION_SETUP =
"com.android.systemui.statusbar.banner_action_setup";
+ private static final Uri SPAM_MESSAGE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SpamMessageProvider.AUTHORITY)
+ .appendPath("message")
+ .build();
+
protected CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
protected H mHandler = createHandler();
@@ -920,6 +933,7 @@ public abstract class BaseStatusBar extends SystemUI implements
final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
final View appSettingsButton
= guts.findViewById(R.id.notification_inspect_app_provided_settings);
+ final View filterButton = guts.findViewById(R.id.notification_inspect_filter_notification);
if (appUid >= 0) {
final int appUidF = appUid;
settingsButton.setOnClickListener(new View.OnClickListener() {
@@ -929,6 +943,19 @@ public abstract class BaseStatusBar extends SystemUI implements
}
});
+ filterButton.setVisibility(View.VISIBLE);
+ filterButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ ContentValues values = new ContentValues();
+ String message = SpamFilter.getNotificationContent(
+ sbn.getNotification());
+ values.put(NotificationTable.MESSAGE_TEXT, message);
+ values.put(PackageTable.PACKAGE_NAME, pkg);
+ mContext.getContentResolver().insert(SPAM_MESSAGE_URI, values);
+ removeNotification(sbn.getKey(), null);
+ }
+ });
+
final Intent appSettingsQueryIntent
= new Intent(Intent.ACTION_MAIN)
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
@@ -958,6 +985,7 @@ public abstract class BaseStatusBar extends SystemUI implements
} else {
settingsButton.setVisibility(View.GONE);
appSettingsButton.setVisibility(View.GONE);
+ filterButton.setVisibility(View.GONE);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index da9e883..747fae7 100644..100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -42,7 +42,9 @@ import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
+import android.database.Cursor;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
@@ -93,6 +95,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
+import android.util.LruCache;
import android.util.Slog;
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
@@ -102,6 +105,9 @@ import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.cm.SpamFilter;
+import com.android.internal.util.cm.SpamFilter.SpamContract.NotificationTable;
+import com.android.internal.util.cm.SpamFilter.SpamContract.PackageTable;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -141,6 +147,8 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
/** {@hide} */
public class NotificationManagerService extends SystemService {
@@ -173,6 +181,8 @@ public class NotificationManagerService extends SystemService {
static final int JUNK_SCORE = -1000;
static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER;
+ private static final String IS_FILTERED_QUERY = NotificationTable.NORMALIZED_TEXT + "=? AND " +
+ PackageTable.PACKAGE_NAME + "=?";
// Notifications with scores below this will not interrupt the user, either via LED or
// sound or vibration
@@ -224,6 +234,19 @@ public class NotificationManagerService extends SystemService {
private boolean mUseAttentionLight;
boolean mSystemReady;
+ private final LruCache<Integer, FilterCacheInfo> mSpamCache;
+ private ExecutorService mSpamExecutor = Executors.newSingleThreadExecutor();
+
+ private static final Uri FILTER_MSG_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SpamFilter.AUTHORITY)
+ .appendPath("message")
+ .build();
+
+ private static final Uri UPDATE_MSG_URI = FILTER_MSG_URI.buildUpon()
+ .appendEncodedPath("inc_count")
+ .build();
+
private boolean mDisableNotificationEffects;
private int mCallState;
private String mSoundNotificationKey;
@@ -910,6 +933,7 @@ public class NotificationManagerService extends SystemService {
public NotificationManagerService(Context context) {
super(context);
+ mSpamCache = new LruCache<Integer, FilterCacheInfo>(100);
}
@Override
@@ -2239,6 +2263,11 @@ public class NotificationManagerService extends SystemService {
return;
}
+ if (isNotificationSpam(notification, pkg)) {
+ mArchive.record(r.sbn);
+ return;
+ }
+
int index = indexOfNotificationLocked(n.getKey());
if (index < 0) {
mNotificationList.add(r);
@@ -2816,6 +2845,51 @@ public class NotificationManagerService extends SystemService {
return (x < low) ? low : ((x > high) ? high : x);
}
+ private int getNotificationHash(Notification notification, String packageName) {
+ CharSequence message = SpamFilter.getNotificationContent(notification);
+ return (message + ":" + packageName).hashCode();
+ }
+
+ private static final class FilterCacheInfo {
+ String packageName;
+ int notificationId;
+ }
+
+ private boolean isNotificationSpam(Notification notification, String basePkg) {
+ Integer notificationHash = getNotificationHash(notification, basePkg);
+ boolean isSpam = false;
+ if (mSpamCache.get(notificationHash) != null) {
+ isSpam = true;
+ } else {
+ String msg = SpamFilter.getNotificationContent(notification);
+ Cursor c = getContext().getContentResolver().query(FILTER_MSG_URI, null, IS_FILTERED_QUERY,
+ new String[]{SpamFilter.getNormalizedContent(msg), basePkg}, null);
+ if (c != null) {
+ if (c.moveToFirst()) {
+ FilterCacheInfo info = new FilterCacheInfo();
+ info.packageName = basePkg;
+ int notifId = c.getInt(c.getColumnIndex(NotificationTable.ID));
+ info.notificationId = notifId;
+ mSpamCache.put(notificationHash, info);
+ isSpam = true;
+ }
+ c.close();
+ }
+ }
+ if (isSpam) {
+ final int notifId = mSpamCache.get(notificationHash).notificationId;
+ mSpamExecutor.submit(new Runnable() {
+ @Override
+ public void run() {
+ Uri updateUri = Uri.withAppendedPath(UPDATE_MSG_URI, String.valueOf(notifId));
+ getContext().getContentResolver().update(updateUri, new ContentValues(),
+ null, null);
+ }
+ });
+ }
+ return isSpam;
+ }
+
void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
AccessibilityManager manager = AccessibilityManager.getInstance(getContext());
if (!manager.isEnabled()) {