Loading services/core/java/com/android/server/notification/NotificationManagerService.java +39 −90 Original line number Diff line number Diff line Loading @@ -160,6 +160,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; Loading Loading @@ -276,9 +277,6 @@ public class NotificationManagerService extends SystemService { // Persistent storage for notification policy private AtomicFile mPolicyFile; // Temporary holder for <blocked-packages> config coming from old policy files. private HashSet<String> mBlockedPackages = new HashSet<String>(); private static final int DB_VERSION = 1; private static final String TAG_NOTIFICATION_POLICY = "notification-policy"; Loading Loading @@ -354,27 +352,7 @@ public class NotificationManagerService extends SystemService { final XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, StandardCharsets.UTF_8.name()); int type; String tag; int version = DB_VERSION; while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (type == START_TAG) { if (TAG_NOTIFICATION_POLICY.equals(tag)) { version = Integer.parseInt( parser.getAttributeValue(null, ATTR_VERSION)); } else if (TAG_BLOCKED_PKGS.equals(tag)) { while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (TAG_PACKAGE.equals(tag)) { mBlockedPackages.add( parser.getAttributeValue(null, ATTR_NAME)); } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) { break; } } } } while (parser.next() != END_DOCUMENT) { mZenModeHelper.readXml(parser, forRestore); mRankingHelper.readXml(parser, forRestore); } Loading @@ -383,7 +361,6 @@ public class NotificationManagerService extends SystemService { private void loadPolicyFile() { if (DBG) Slog.d(TAG, "loadPolicyFile"); synchronized(mPolicyFile) { mBlockedPackages.clear(); FileInputStream infile = null; try { Loading Loading @@ -941,7 +918,7 @@ public class NotificationManagerService extends SystemService { final File systemDir = new File(Environment.getDataDirectory(), "system"); mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml")); importOldBlockDb(); syncBlockDb(); // This is a MangedServices object that keeps track of the listeners. mListeners = new NotificationListeners(); Loading Loading @@ -1041,22 +1018,43 @@ public class NotificationManagerService extends SystemService { } /** * Read the old XML-based app block database and import those blockages into the AppOps system. * Make sure the XML config and the the AppOps system agree about blocks. */ private void importOldBlockDb() { private void syncBlockDb() { loadPolicyFile(); PackageManager pm = getContext().getPackageManager(); for (String pkg : mBlockedPackages) { PackageInfo info = null; // sync bans from ranker into app opps Map<Integer, String> packageBans = mRankingHelper.getPackageBans(); for(Entry<Integer, String> ban : packageBans.entrySet()) { final int uid = ban.getKey(); final String packageName = ban.getValue(); setNotificationsEnabledForPackageImpl(packageName, uid, false); } // sync bans from app opps into ranker packageBans.clear(); for (UserInfo user : UserManager.get(getContext()).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); final PackageManager packageManager = getContext().getPackageManager(); List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId); final int packageCount = packages.size(); for (int p = 0; p < packageCount; p++) { final String packageName = packages.get(p).packageName; try { info = pm.getPackageInfo(pkg, 0); setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false); final int uid = packageManager.getPackageUidAsUser(packageName, userId); if (!checkNotificationOp(packageName, uid)) { packageBans.put(uid, packageName); } } catch (NameNotFoundException e) { // forget you } } mBlockedPackages.clear(); } for (Entry<Integer, String> ban : packageBans.entrySet()) { mRankingHelper.setImportance(ban.getValue(), ban.getKey(), IMPORTANCE_NONE); } savePolicyFile(); } @Override Loading Loading @@ -1261,6 +1259,8 @@ public class NotificationManagerService extends SystemService { checkCallerIsSystem(); setNotificationsEnabledForPackageImpl(pkg, uid, enabled); mRankingHelper.setEnabled(pkg, uid, enabled); savePolicyFile(); } /** Loading Loading @@ -2034,21 +2034,8 @@ public class NotificationManagerService extends SystemService { JSONObject dump = new JSONObject(); try { dump.put("service", "Notification Manager"); JSONArray bans = new JSONArray(); try { ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter); for (Integer userId : packageBans.keySet()) { for (String packageName : packageBans.get(userId)) { JSONObject ban = new JSONObject(); ban.put("userId", userId); ban.put("packageName", packageName); bans.put(ban); } } } catch (NameNotFoundException e) { // pass } dump.put("bans", bans); dump.put("bans", mRankingHelper.dumpBansJson(filter)); dump.put("ranking", mRankingHelper.dumpJson(filter)); dump.put("stats", mUsageStats.dumpJson(filter)); } catch (JSONException e) { e.printStackTrace(); Loading Loading @@ -2175,45 +2162,7 @@ public class NotificationManagerService extends SystemService { r.dump(pw, " ", getContext(), filter.redact); } } try { pw.println("\n Banned Packages:"); ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter); for (Integer userId : packageBans.keySet()) { for (String packageName : packageBans.get(userId)) { pw.println(" " + userId + ": " + packageName); } } } catch (NameNotFoundException e) { // pass } } } private ArrayMap<Integer, ArrayList<String>> getPackageBans(DumpFilter filter) throws NameNotFoundException { ArrayMap<Integer, ArrayList<String>> packageBans = new ArrayMap<>(); ArrayList<String> packageNames = new ArrayList<>(); for (UserInfo user : UserManager.get(getContext()).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); final PackageManager packageManager = getContext().getPackageManager(); List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId); final int packageCount = packages.size(); for (int p = 0; p < packageCount; p++) { final String packageName = packages.get(p).packageName; if (filter == null || filter.matches(packageName)) { final int uid = packageManager.getPackageUidAsUser(packageName, userId); if (!checkNotificationOp(packageName, uid)) { packageNames.add(packageName); } } } if (!packageNames.isEmpty()) { packageBans.put(userId, packageNames); packageNames = new ArrayList<>(); } } return packageBans; } /** Loading services/core/java/com/android/server/notification/RankingHelper.java +97 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; import com.android.server.notification.NotificationManagerService.DumpFilter; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -33,6 +38,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; public class RankingHelper implements RankingConfig { private static final String TAG = "RankingHelper"; Loading Loading @@ -358,6 +365,14 @@ public class RankingHelper implements RankingConfig { updateConfig(); } public void setEnabled(String packageName, int uid, boolean enabled) { boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE; if (wasEnabled == enabled) { return; } setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE); } public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { if (filter == null) { final int N = mSignalExtractors.length; Loading Loading @@ -398,17 +413,97 @@ public class RankingHelper implements RankingConfig { } if (r.priority != DEFAULT_PRIORITY) { pw.print(" priority="); pw.print(Ranking.importanceToString(r.priority)); pw.print(Notification.priorityToString(r.priority)); } if (r.visibility != DEFAULT_VISIBILITY) { pw.print(" visibility="); pw.print(Ranking.importanceToString(r.visibility)); pw.print(Notification.visibilityToString(r.visibility)); } pw.println(); } } } public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) { JSONObject ranking = new JSONObject(); JSONArray records = new JSONArray(); try { ranking.put("noUid", mRestoredWithoutUids.size()); } catch (JSONException e) { // pass } final int N = mRecords.size(); for (int i = 0; i < N; i++) { final Record r = mRecords.valueAt(i); if (filter == null || filter.matches(r.pkg)) { JSONObject record = new JSONObject(); try { record.put("userId", UserHandle.getUserId(r.uid)); record.put("packageName", r.pkg); if (r.importance != DEFAULT_IMPORTANCE) { record.put("importance", Ranking.importanceToString(r.importance)); } if (r.priority != DEFAULT_PRIORITY) { record.put("priority", Notification.priorityToString(r.priority)); } if (r.visibility != DEFAULT_VISIBILITY) { record.put("visibility", Notification.visibilityToString(r.visibility)); } } catch (JSONException e) { // pass } records.put(record); } } try { ranking.put("records", records); } catch (JSONException e) { // pass } return ranking; } /** * Dump only the ban information as structured JSON for the stats collector. * * This is intentionally redundant with {#link dumpJson} because the old * scraper will expect this format. * * @param filter * @return */ public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) { JSONArray bans = new JSONArray(); Map<Integer, String> packageBans = getPackageBans(); for(Entry<Integer, String> ban : packageBans.entrySet()) { final int userId = UserHandle.getUserId(ban.getKey()); final String packageName = ban.getValue(); if (filter == null || filter.matches(packageName)) { JSONObject banJson = new JSONObject(); try { banJson.put("userId", userId); banJson.put("packageName", packageName); } catch (JSONException e) { e.printStackTrace(); } bans.put(banJson); } } return bans; } public Map<Integer, String> getPackageBans() { final int N = mRecords.size(); ArrayMap<Integer, String> packageBans = new ArrayMap<>(N); for (int i = 0; i < N; i++) { final Record r = mRecords.valueAt(i); if (r.importance == Ranking.IMPORTANCE_NONE) { packageBans.put(r.uid, r.pkg); } } return packageBans; } public void onPackagesChanged(boolean queryReplace, String[] pkgList) { if (queryReplace || pkgList == null || pkgList.length == 0 || mRestoredWithoutUids.isEmpty()) { Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +39 −90 Original line number Diff line number Diff line Loading @@ -160,6 +160,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; Loading Loading @@ -276,9 +277,6 @@ public class NotificationManagerService extends SystemService { // Persistent storage for notification policy private AtomicFile mPolicyFile; // Temporary holder for <blocked-packages> config coming from old policy files. private HashSet<String> mBlockedPackages = new HashSet<String>(); private static final int DB_VERSION = 1; private static final String TAG_NOTIFICATION_POLICY = "notification-policy"; Loading Loading @@ -354,27 +352,7 @@ public class NotificationManagerService extends SystemService { final XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, StandardCharsets.UTF_8.name()); int type; String tag; int version = DB_VERSION; while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (type == START_TAG) { if (TAG_NOTIFICATION_POLICY.equals(tag)) { version = Integer.parseInt( parser.getAttributeValue(null, ATTR_VERSION)); } else if (TAG_BLOCKED_PKGS.equals(tag)) { while ((type = parser.next()) != END_DOCUMENT) { tag = parser.getName(); if (TAG_PACKAGE.equals(tag)) { mBlockedPackages.add( parser.getAttributeValue(null, ATTR_NAME)); } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) { break; } } } } while (parser.next() != END_DOCUMENT) { mZenModeHelper.readXml(parser, forRestore); mRankingHelper.readXml(parser, forRestore); } Loading @@ -383,7 +361,6 @@ public class NotificationManagerService extends SystemService { private void loadPolicyFile() { if (DBG) Slog.d(TAG, "loadPolicyFile"); synchronized(mPolicyFile) { mBlockedPackages.clear(); FileInputStream infile = null; try { Loading Loading @@ -941,7 +918,7 @@ public class NotificationManagerService extends SystemService { final File systemDir = new File(Environment.getDataDirectory(), "system"); mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml")); importOldBlockDb(); syncBlockDb(); // This is a MangedServices object that keeps track of the listeners. mListeners = new NotificationListeners(); Loading Loading @@ -1041,22 +1018,43 @@ public class NotificationManagerService extends SystemService { } /** * Read the old XML-based app block database and import those blockages into the AppOps system. * Make sure the XML config and the the AppOps system agree about blocks. */ private void importOldBlockDb() { private void syncBlockDb() { loadPolicyFile(); PackageManager pm = getContext().getPackageManager(); for (String pkg : mBlockedPackages) { PackageInfo info = null; // sync bans from ranker into app opps Map<Integer, String> packageBans = mRankingHelper.getPackageBans(); for(Entry<Integer, String> ban : packageBans.entrySet()) { final int uid = ban.getKey(); final String packageName = ban.getValue(); setNotificationsEnabledForPackageImpl(packageName, uid, false); } // sync bans from app opps into ranker packageBans.clear(); for (UserInfo user : UserManager.get(getContext()).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); final PackageManager packageManager = getContext().getPackageManager(); List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId); final int packageCount = packages.size(); for (int p = 0; p < packageCount; p++) { final String packageName = packages.get(p).packageName; try { info = pm.getPackageInfo(pkg, 0); setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false); final int uid = packageManager.getPackageUidAsUser(packageName, userId); if (!checkNotificationOp(packageName, uid)) { packageBans.put(uid, packageName); } } catch (NameNotFoundException e) { // forget you } } mBlockedPackages.clear(); } for (Entry<Integer, String> ban : packageBans.entrySet()) { mRankingHelper.setImportance(ban.getValue(), ban.getKey(), IMPORTANCE_NONE); } savePolicyFile(); } @Override Loading Loading @@ -1261,6 +1259,8 @@ public class NotificationManagerService extends SystemService { checkCallerIsSystem(); setNotificationsEnabledForPackageImpl(pkg, uid, enabled); mRankingHelper.setEnabled(pkg, uid, enabled); savePolicyFile(); } /** Loading Loading @@ -2034,21 +2034,8 @@ public class NotificationManagerService extends SystemService { JSONObject dump = new JSONObject(); try { dump.put("service", "Notification Manager"); JSONArray bans = new JSONArray(); try { ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter); for (Integer userId : packageBans.keySet()) { for (String packageName : packageBans.get(userId)) { JSONObject ban = new JSONObject(); ban.put("userId", userId); ban.put("packageName", packageName); bans.put(ban); } } } catch (NameNotFoundException e) { // pass } dump.put("bans", bans); dump.put("bans", mRankingHelper.dumpBansJson(filter)); dump.put("ranking", mRankingHelper.dumpJson(filter)); dump.put("stats", mUsageStats.dumpJson(filter)); } catch (JSONException e) { e.printStackTrace(); Loading Loading @@ -2175,45 +2162,7 @@ public class NotificationManagerService extends SystemService { r.dump(pw, " ", getContext(), filter.redact); } } try { pw.println("\n Banned Packages:"); ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter); for (Integer userId : packageBans.keySet()) { for (String packageName : packageBans.get(userId)) { pw.println(" " + userId + ": " + packageName); } } } catch (NameNotFoundException e) { // pass } } } private ArrayMap<Integer, ArrayList<String>> getPackageBans(DumpFilter filter) throws NameNotFoundException { ArrayMap<Integer, ArrayList<String>> packageBans = new ArrayMap<>(); ArrayList<String> packageNames = new ArrayList<>(); for (UserInfo user : UserManager.get(getContext()).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); final PackageManager packageManager = getContext().getPackageManager(); List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId); final int packageCount = packages.size(); for (int p = 0; p < packageCount; p++) { final String packageName = packages.get(p).packageName; if (filter == null || filter.matches(packageName)) { final int uid = packageManager.getPackageUidAsUser(packageName, userId); if (!checkNotificationOp(packageName, uid)) { packageNames.add(packageName); } } } if (!packageNames.isEmpty()) { packageBans.put(userId, packageNames); packageNames = new ArrayList<>(); } } return packageBans; } /** Loading
services/core/java/com/android/server/notification/RankingHelper.java +97 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; import com.android.server.notification.NotificationManagerService.DumpFilter; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; Loading @@ -33,6 +38,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; public class RankingHelper implements RankingConfig { private static final String TAG = "RankingHelper"; Loading Loading @@ -358,6 +365,14 @@ public class RankingHelper implements RankingConfig { updateConfig(); } public void setEnabled(String packageName, int uid, boolean enabled) { boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE; if (wasEnabled == enabled) { return; } setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE); } public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { if (filter == null) { final int N = mSignalExtractors.length; Loading Loading @@ -398,17 +413,97 @@ public class RankingHelper implements RankingConfig { } if (r.priority != DEFAULT_PRIORITY) { pw.print(" priority="); pw.print(Ranking.importanceToString(r.priority)); pw.print(Notification.priorityToString(r.priority)); } if (r.visibility != DEFAULT_VISIBILITY) { pw.print(" visibility="); pw.print(Ranking.importanceToString(r.visibility)); pw.print(Notification.visibilityToString(r.visibility)); } pw.println(); } } } public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) { JSONObject ranking = new JSONObject(); JSONArray records = new JSONArray(); try { ranking.put("noUid", mRestoredWithoutUids.size()); } catch (JSONException e) { // pass } final int N = mRecords.size(); for (int i = 0; i < N; i++) { final Record r = mRecords.valueAt(i); if (filter == null || filter.matches(r.pkg)) { JSONObject record = new JSONObject(); try { record.put("userId", UserHandle.getUserId(r.uid)); record.put("packageName", r.pkg); if (r.importance != DEFAULT_IMPORTANCE) { record.put("importance", Ranking.importanceToString(r.importance)); } if (r.priority != DEFAULT_PRIORITY) { record.put("priority", Notification.priorityToString(r.priority)); } if (r.visibility != DEFAULT_VISIBILITY) { record.put("visibility", Notification.visibilityToString(r.visibility)); } } catch (JSONException e) { // pass } records.put(record); } } try { ranking.put("records", records); } catch (JSONException e) { // pass } return ranking; } /** * Dump only the ban information as structured JSON for the stats collector. * * This is intentionally redundant with {#link dumpJson} because the old * scraper will expect this format. * * @param filter * @return */ public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) { JSONArray bans = new JSONArray(); Map<Integer, String> packageBans = getPackageBans(); for(Entry<Integer, String> ban : packageBans.entrySet()) { final int userId = UserHandle.getUserId(ban.getKey()); final String packageName = ban.getValue(); if (filter == null || filter.matches(packageName)) { JSONObject banJson = new JSONObject(); try { banJson.put("userId", userId); banJson.put("packageName", packageName); } catch (JSONException e) { e.printStackTrace(); } bans.put(banJson); } } return bans; } public Map<Integer, String> getPackageBans() { final int N = mRecords.size(); ArrayMap<Integer, String> packageBans = new ArrayMap<>(N); for (int i = 0; i < N; i++) { final Record r = mRecords.valueAt(i); if (r.importance == Ranking.IMPORTANCE_NONE) { packageBans.put(r.uid, r.pkg); } } return packageBans; } public void onPackagesChanged(boolean queryReplace, String[] pkgList) { if (queryReplace || pkgList == null || pkgList.length == 0 || mRestoredWithoutUids.isEmpty()) { Loading