don't call other services in dump

Currently the ranker config file is synced to app opps.
Also sync App Opps to the config file.
Then use that data to inform the dump, instead of polling.

Bug: 25424580
Change-Id: I6089532aa8618a31bfc3a36bee630c04c3ef3798
This commit is contained in:
Chris Wren
2016-03-15 12:48:55 -04:00
parent 3e9717bf38
commit acf424a37a
2 changed files with 136 additions and 92 deletions

View File

@@ -158,6 +158,7 @@ import java.util.ArrayList;
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;
@@ -274,9 +275,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";
@@ -352,27 +350,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);
}
@@ -381,7 +359,6 @@ public class NotificationManagerService extends SystemService {
private void loadPolicyFile() {
if (DBG) Slog.d(TAG, "loadPolicyFile");
synchronized(mPolicyFile) {
mBlockedPackages.clear();
FileInputStream infile = null;
try {
@@ -935,7 +912,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();
@@ -1045,22 +1022,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;
try {
info = pm.getPackageInfo(pkg, 0);
setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false);
} catch (NameNotFoundException e) {
// forget you
// 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 {
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
@@ -1265,6 +1263,8 @@ public class NotificationManagerService extends SystemService {
checkCallerIsSystem();
setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
mRankingHelper.setEnabled(pkg, uid, enabled);
savePolicyFile();
}
/**
@@ -2027,21 +2027,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();
@@ -2168,47 +2155,9 @@ 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;
}
/**
* The private API only accessible to the system process.
*/

View File

@@ -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;
@@ -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";
@@ -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;
@@ -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()) {