Merge "Handle upgrade and B&R compatibilty"
This commit is contained in:
committed by
Android (Google) Code Review
commit
6862d35a64
@@ -21,22 +21,27 @@ import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||
import static android.permission.PermissionManager.PERMISSION_GRANTED;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.permission.IPermissionManager;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.pm.permission.PermissionManagerServiceInternal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* NotificationManagerService helper for querying/setting the app-level notification permission
|
||||
@@ -44,7 +49,7 @@ import java.util.Map;
|
||||
public final class PermissionHelper {
|
||||
private static final String TAG = "PermissionHelper";
|
||||
|
||||
private static String NOTIFICATION_PERMISSION = Manifest.permission.POST_NOTIFICATIONS;
|
||||
private static final String NOTIFICATION_PERMISSION = Manifest.permission.POST_NOTIFICATIONS;
|
||||
|
||||
private final PermissionManagerServiceInternal mPmi;
|
||||
private final IPackageManager mPackageManager;
|
||||
@@ -77,9 +82,9 @@ public final class PermissionHelper {
|
||||
* Returns all of the apps that have requested the notification permission in a given user.
|
||||
* Must not be called with a lock held. Format: uid, packageName
|
||||
*/
|
||||
public Map<Integer, String> getAppsRequestingPermission(int userId) {
|
||||
Set<Pair<Integer, String>> getAppsRequestingPermission(int userId) {
|
||||
assertFlag();
|
||||
Map<Integer, String> requested = new HashMap<>();
|
||||
Set<Pair<Integer, String>> requested = new HashSet<>();
|
||||
List<PackageInfo> pkgs = getInstalledPackages(userId);
|
||||
for (PackageInfo pi : pkgs) {
|
||||
// when data was stored in PreferencesHelper, we only had data for apps that
|
||||
@@ -90,7 +95,7 @@ public final class PermissionHelper {
|
||||
}
|
||||
for (String perm : pi.requestedPermissions) {
|
||||
if (NOTIFICATION_PERMISSION.equals(perm)) {
|
||||
requested.put(pi.applicationInfo.uid, pi.packageName);
|
||||
requested.add(new Pair<>(pi.applicationInfo.uid, pi.packageName));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -115,9 +120,9 @@ public final class PermissionHelper {
|
||||
* Returns a list of apps that hold the notification permission. Must not be called
|
||||
* with a lock held. Format: uid, packageName.
|
||||
*/
|
||||
public Map<Integer, String> getAppsGrantedPermission(int userId) {
|
||||
Set<Pair<Integer, String>> getAppsGrantedPermission(int userId) {
|
||||
assertFlag();
|
||||
Map<Integer, String> granted = new HashMap<>();
|
||||
Set<Pair<Integer, String>> granted = new HashSet<>();
|
||||
ParceledListSlice<PackageInfo> parceledList = null;
|
||||
try {
|
||||
parceledList = mPackageManager.getPackagesHoldingPermissions(
|
||||
@@ -129,11 +134,24 @@ public final class PermissionHelper {
|
||||
return granted;
|
||||
}
|
||||
for (PackageInfo pi : parceledList.getList()) {
|
||||
granted.put(pi.applicationInfo.uid, pi.packageName);
|
||||
granted.add(new Pair<>(pi.applicationInfo.uid, pi.packageName));
|
||||
}
|
||||
return granted;
|
||||
}
|
||||
|
||||
public @NonNull
|
||||
ArrayMap<Pair<Integer, String>, Boolean> getNotificationPermissionValues(
|
||||
int userId) {
|
||||
assertFlag();
|
||||
ArrayMap<Pair<Integer, String>, Boolean> notifPermissions = new ArrayMap<>();
|
||||
Set<Pair<Integer, String>> allRequestingUids = getAppsRequestingPermission(userId);
|
||||
Set<Pair<Integer, String>> allApprovedUids = getAppsGrantedPermission(userId);
|
||||
for (Pair<Integer, String> pair : allRequestingUids) {
|
||||
notifPermissions.put(pair, allApprovedUids.contains(pair));
|
||||
}
|
||||
return notifPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants or revokes the notification permission for a given package/user. UserSet should
|
||||
* only be true if this method is being called to migrate existing user choice, because it
|
||||
@@ -159,6 +177,12 @@ public final class PermissionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void setNotificationPermission(PackagePermission pkgPerm) {
|
||||
assertFlag();
|
||||
setNotificationPermission(
|
||||
pkgPerm.packageName, pkgPerm.userId, pkgPerm.granted, pkgPerm.userSet);
|
||||
}
|
||||
|
||||
public boolean isPermissionFixed(String packageName, @UserIdInt int userId) {
|
||||
assertFlag();
|
||||
try {
|
||||
@@ -177,4 +201,42 @@ public final class PermissionHelper {
|
||||
throw new IllegalStateException("Method called without checking flag value");
|
||||
}
|
||||
}
|
||||
|
||||
public static class PackagePermission {
|
||||
public final String packageName;
|
||||
public final @UserIdInt int userId;
|
||||
public final boolean granted;
|
||||
public final boolean userSet;
|
||||
|
||||
public PackagePermission(String pkg, int userId, boolean granted, boolean userSet) {
|
||||
this.packageName = pkg;
|
||||
this.userId = userId;
|
||||
this.granted = granted;
|
||||
this.userSet = userSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PackagePermission that = (PackagePermission) o;
|
||||
return userId == that.userId && granted == that.granted && userSet == that.userSet
|
||||
&& Objects.equals(packageName, that.packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(packageName, userId, granted, userSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PackagePermission{" +
|
||||
"packageName='" + packageName + '\'' +
|
||||
", userId=" + userId +
|
||||
", granted=" + granted +
|
||||
", userSet=" + userSet +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
|
||||
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
|
||||
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
|
||||
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
|
||||
@@ -68,6 +69,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.notification.PermissionHelper.PackagePermission;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@@ -89,7 +91,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class PreferencesHelper implements RankingConfig {
|
||||
private static final String TAG = "NotificationPrefHelper";
|
||||
private static final int XML_VERSION = 2;
|
||||
private final int XML_VERSION;
|
||||
/** What version to check to do the upgrade for bubbles. */
|
||||
private static final int XML_VERSION_BUBBLES_UPGRADE = 1;
|
||||
@VisibleForTesting
|
||||
@@ -201,6 +203,12 @@ public class PreferencesHelper implements RankingConfig {
|
||||
mAppOps = appOpsManager;
|
||||
mStatsEventBuilderFactory = statsEventBuilderFactory;
|
||||
|
||||
if (mPermissionHelper.isMigrationEnabled()) {
|
||||
XML_VERSION = 3;
|
||||
} else {
|
||||
XML_VERSION = 2;
|
||||
}
|
||||
|
||||
updateBadgingEnabled();
|
||||
updateBubblesEnabled();
|
||||
updateMediaNotificationFilteringEnabled();
|
||||
@@ -217,11 +225,13 @@ public class PreferencesHelper implements RankingConfig {
|
||||
|
||||
final int xmlVersion = parser.getAttributeInt(null, ATT_VERSION, -1);
|
||||
boolean upgradeForBubbles = xmlVersion == XML_VERSION_BUBBLES_UPGRADE;
|
||||
boolean migrateToPermission = (xmlVersion < XML_VERSION);
|
||||
ArrayList<PermissionHelper.PackagePermission> pkgPerms = new ArrayList<>();
|
||||
synchronized (mPackagePreferences) {
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
|
||||
tag = parser.getName();
|
||||
if (type == XmlPullParser.END_TAG && TAG_RANKING.equals(tag)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (type == XmlPullParser.START_TAG) {
|
||||
if (TAG_STATUS_ICONS.equals(tag)) {
|
||||
@@ -252,11 +262,12 @@ public class PreferencesHelper implements RankingConfig {
|
||||
? BUBBLE_PREFERENCE_ALL
|
||||
: parser.getAttributeInt(
|
||||
null, ATT_ALLOW_BUBBLE, DEFAULT_BUBBLE_PREFERENCE);
|
||||
int appImportance = parser.getAttributeInt(
|
||||
null, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
|
||||
|
||||
PackagePreferences r = getOrCreatePackagePreferencesLocked(
|
||||
name, userId, uid,
|
||||
parser.getAttributeInt(
|
||||
null, ATT_IMPORTANCE, DEFAULT_IMPORTANCE),
|
||||
appImportance,
|
||||
parser.getAttributeInt(
|
||||
null, ATT_PRIORITY, DEFAULT_PRIORITY),
|
||||
parser.getAttributeInt(
|
||||
@@ -264,8 +275,6 @@ public class PreferencesHelper implements RankingConfig {
|
||||
parser.getAttributeBoolean(
|
||||
null, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE),
|
||||
bubblePref);
|
||||
r.importance = parser.getAttributeInt(
|
||||
null, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
|
||||
r.priority = parser.getAttributeInt(
|
||||
null, ATT_PRIORITY, DEFAULT_PRIORITY);
|
||||
r.visibility = parser.getAttributeInt(
|
||||
@@ -340,6 +349,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delegate
|
||||
if (TAG_DELEGATE.equals(tagName)) {
|
||||
int delegateId =
|
||||
@@ -367,12 +377,30 @@ public class PreferencesHelper implements RankingConfig {
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.e(TAG, "deleteDefaultChannelIfNeededLocked - Exception: " + e);
|
||||
}
|
||||
|
||||
if (migrateToPermission) {
|
||||
boolean hasChangedChannel = false;
|
||||
for (NotificationChannel channel : r.channels.values()) {
|
||||
if (channel.getUserLockedFields() != 0) {
|
||||
hasChangedChannel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PackagePermission pkgPerm = new PackagePermission(
|
||||
r.pkg, userId, appImportance != IMPORTANCE_NONE,
|
||||
hasChangedChannel || appImportance == IMPORTANCE_NONE);
|
||||
pkgPerms.add(pkgPerm);
|
||||
} else {
|
||||
r.importance = appImportance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to reach END_DOCUMENT");
|
||||
for (PackagePermission p : pkgPerms) {
|
||||
mPermissionHelper.setNotificationPermission(p);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isShortcutOk(NotificationChannel channel) {
|
||||
@@ -402,18 +430,12 @@ public class PreferencesHelper implements RankingConfig {
|
||||
|
||||
private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg,
|
||||
int uid) {
|
||||
// TODO (b/194833441): use permissionhelper instead of DEFAULT_IMPORTANCE
|
||||
return getOrCreatePackagePreferencesLocked(pkg, UserHandle.getUserId(uid), uid,
|
||||
DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE,
|
||||
DEFAULT_BUBBLE_PREFERENCE);
|
||||
}
|
||||
|
||||
private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg,
|
||||
@UserIdInt int userId, int uid) {
|
||||
return getOrCreatePackagePreferencesLocked(pkg, userId, uid,
|
||||
DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE,
|
||||
DEFAULT_BUBBLE_PREFERENCE);
|
||||
}
|
||||
|
||||
private PackagePreferences getOrCreatePackagePreferencesLocked(String pkg,
|
||||
@UserIdInt int userId, int uid, int importance, int priority, int visibility,
|
||||
boolean showBadge, int bubblePreference) {
|
||||
@@ -535,6 +557,10 @@ public class PreferencesHelper implements RankingConfig {
|
||||
out.attributeBoolean(null, ATT_HIDE_SILENT, mHideSilentStatusBarIcons);
|
||||
out.endTag(null, TAG_STATUS_ICONS);
|
||||
}
|
||||
ArrayMap<Pair<Integer, String>, Boolean> notifPermissions = new ArrayMap<>();
|
||||
if (mPermissionHelper.isMigrationEnabled() && forBackup) {
|
||||
notifPermissions = mPermissionHelper.getNotificationPermissionValues(userId);
|
||||
}
|
||||
|
||||
synchronized (mPackagePreferences) {
|
||||
final int N = mPackagePreferences.size();
|
||||
@@ -543,78 +569,81 @@ public class PreferencesHelper implements RankingConfig {
|
||||
if (forBackup && UserHandle.getUserId(r.uid) != userId) {
|
||||
continue;
|
||||
}
|
||||
final boolean hasNonDefaultSettings =
|
||||
r.importance != DEFAULT_IMPORTANCE
|
||||
|| r.priority != DEFAULT_PRIORITY
|
||||
|| r.visibility != DEFAULT_VISIBILITY
|
||||
|| r.showBadge != DEFAULT_SHOW_BADGE
|
||||
|| r.lockedAppFields != DEFAULT_LOCKED_APP_FIELDS
|
||||
|| r.channels.size() > 0
|
||||
|| r.groups.size() > 0
|
||||
|| r.delegate != null
|
||||
|| r.bubblePreference != DEFAULT_BUBBLE_PREFERENCE
|
||||
|| r.hasSentInvalidMessage
|
||||
|| r.userDemotedMsgApp
|
||||
|| r.hasSentValidMessage;
|
||||
if (hasNonDefaultSettings) {
|
||||
out.startTag(null, TAG_PACKAGE);
|
||||
out.attribute(null, ATT_NAME, r.pkg);
|
||||
out.startTag(null, TAG_PACKAGE);
|
||||
out.attribute(null, ATT_NAME, r.pkg);
|
||||
if (!notifPermissions.isEmpty()) {
|
||||
Pair<Integer, String> app = new Pair(r.uid, r.pkg);
|
||||
out.attributeInt(null, ATT_IMPORTANCE, notifPermissions.get(app)
|
||||
? IMPORTANCE_DEFAULT
|
||||
: IMPORTANCE_NONE);
|
||||
notifPermissions.remove(app);
|
||||
} else {
|
||||
if (r.importance != DEFAULT_IMPORTANCE) {
|
||||
out.attributeInt(null, ATT_IMPORTANCE, r.importance);
|
||||
}
|
||||
if (r.priority != DEFAULT_PRIORITY) {
|
||||
out.attributeInt(null, ATT_PRIORITY, r.priority);
|
||||
}
|
||||
if (r.visibility != DEFAULT_VISIBILITY) {
|
||||
out.attributeInt(null, ATT_VISIBILITY, r.visibility);
|
||||
}
|
||||
if (r.bubblePreference != DEFAULT_BUBBLE_PREFERENCE) {
|
||||
out.attributeInt(null, ATT_ALLOW_BUBBLE, r.bubblePreference);
|
||||
}
|
||||
out.attributeBoolean(null, ATT_SHOW_BADGE, r.showBadge);
|
||||
out.attributeInt(null, ATT_APP_USER_LOCKED_FIELDS,
|
||||
r.lockedAppFields);
|
||||
out.attributeBoolean(null, ATT_SENT_INVALID_MESSAGE,
|
||||
r.hasSentInvalidMessage);
|
||||
out.attributeBoolean(null, ATT_SENT_VALID_MESSAGE,
|
||||
r.hasSentValidMessage);
|
||||
out.attributeBoolean(null, ATT_USER_DEMOTED_INVALID_MSG_APP,
|
||||
r.userDemotedMsgApp);
|
||||
|
||||
if (!forBackup) {
|
||||
out.attributeInt(null, ATT_UID, r.uid);
|
||||
}
|
||||
|
||||
if (r.delegate != null) {
|
||||
out.startTag(null, TAG_DELEGATE);
|
||||
|
||||
out.attribute(null, ATT_NAME, r.delegate.mPkg);
|
||||
out.attributeInt(null, ATT_UID, r.delegate.mUid);
|
||||
if (r.delegate.mEnabled != Delegate.DEFAULT_ENABLED) {
|
||||
out.attributeBoolean(null, ATT_ENABLED, r.delegate.mEnabled);
|
||||
}
|
||||
if (r.delegate.mUserAllowed != Delegate.DEFAULT_USER_ALLOWED) {
|
||||
out.attributeBoolean(null, ATT_USER_ALLOWED, r.delegate.mUserAllowed);
|
||||
}
|
||||
out.endTag(null, TAG_DELEGATE);
|
||||
}
|
||||
|
||||
for (NotificationChannelGroup group : r.groups.values()) {
|
||||
group.writeXml(out);
|
||||
}
|
||||
|
||||
for (NotificationChannel channel : r.channels.values()) {
|
||||
if (forBackup) {
|
||||
if (!channel.isDeleted()) {
|
||||
channel.writeXmlForBackup(out, mContext);
|
||||
}
|
||||
} else {
|
||||
channel.writeXml(out);
|
||||
}
|
||||
}
|
||||
|
||||
out.endTag(null, TAG_PACKAGE);
|
||||
}
|
||||
if (r.priority != DEFAULT_PRIORITY) {
|
||||
out.attributeInt(null, ATT_PRIORITY, r.priority);
|
||||
}
|
||||
if (r.visibility != DEFAULT_VISIBILITY) {
|
||||
out.attributeInt(null, ATT_VISIBILITY, r.visibility);
|
||||
}
|
||||
if (r.bubblePreference != DEFAULT_BUBBLE_PREFERENCE) {
|
||||
out.attributeInt(null, ATT_ALLOW_BUBBLE, r.bubblePreference);
|
||||
}
|
||||
out.attributeBoolean(null, ATT_SHOW_BADGE, r.showBadge);
|
||||
out.attributeInt(null, ATT_APP_USER_LOCKED_FIELDS,
|
||||
r.lockedAppFields);
|
||||
out.attributeBoolean(null, ATT_SENT_INVALID_MESSAGE,
|
||||
r.hasSentInvalidMessage);
|
||||
out.attributeBoolean(null, ATT_SENT_VALID_MESSAGE,
|
||||
r.hasSentValidMessage);
|
||||
out.attributeBoolean(null, ATT_USER_DEMOTED_INVALID_MSG_APP,
|
||||
r.userDemotedMsgApp);
|
||||
|
||||
if (!forBackup) {
|
||||
out.attributeInt(null, ATT_UID, r.uid);
|
||||
}
|
||||
|
||||
if (r.delegate != null) {
|
||||
out.startTag(null, TAG_DELEGATE);
|
||||
|
||||
out.attribute(null, ATT_NAME, r.delegate.mPkg);
|
||||
out.attributeInt(null, ATT_UID, r.delegate.mUid);
|
||||
if (r.delegate.mEnabled != Delegate.DEFAULT_ENABLED) {
|
||||
out.attributeBoolean(null, ATT_ENABLED, r.delegate.mEnabled);
|
||||
}
|
||||
if (r.delegate.mUserAllowed != Delegate.DEFAULT_USER_ALLOWED) {
|
||||
out.attributeBoolean(null, ATT_USER_ALLOWED, r.delegate.mUserAllowed);
|
||||
}
|
||||
out.endTag(null, TAG_DELEGATE);
|
||||
}
|
||||
|
||||
for (NotificationChannelGroup group : r.groups.values()) {
|
||||
group.writeXml(out);
|
||||
}
|
||||
|
||||
for (NotificationChannel channel : r.channels.values()) {
|
||||
if (forBackup) {
|
||||
if (!channel.isDeleted()) {
|
||||
channel.writeXmlForBackup(out, mContext);
|
||||
}
|
||||
} else {
|
||||
channel.writeXml(out);
|
||||
}
|
||||
}
|
||||
|
||||
out.endTag(null, TAG_PACKAGE);
|
||||
}
|
||||
}
|
||||
// Some apps have permissions set but don't have expanded notification settings
|
||||
if (!notifPermissions.isEmpty()) {
|
||||
for (Pair<Integer, String> app : notifPermissions.keySet()) {
|
||||
out.startTag(null, TAG_PACKAGE);
|
||||
out.attribute(null, ATT_NAME, app.second);
|
||||
out.attributeInt(null, ATT_IMPORTANCE,
|
||||
notifPermissions.get(app) ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE);
|
||||
out.endTag(null, TAG_PACKAGE);
|
||||
}
|
||||
}
|
||||
out.endTag(null, TAG_RANKING);
|
||||
@@ -1904,7 +1933,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
public void dump(PrintWriter pw, String prefix,
|
||||
@NonNull NotificationManagerService.DumpFilter filter) {
|
||||
pw.print(prefix);
|
||||
pw.println("per-package config:");
|
||||
pw.println("per-package config version: " + XML_VERSION);
|
||||
|
||||
pw.println("PackagePreferences:");
|
||||
synchronized (mPackagePreferences) {
|
||||
@@ -1924,7 +1953,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
mRestoredWithoutUids);
|
||||
}
|
||||
|
||||
private static void dumpPackagePreferencesLocked(PrintWriter pw, String prefix,
|
||||
private void dumpPackagePreferencesLocked(PrintWriter pw, String prefix,
|
||||
@NonNull NotificationManagerService.DumpFilter filter,
|
||||
ArrayMap<String, PackagePreferences> packagePreferences) {
|
||||
final int N = packagePreferences.size();
|
||||
@@ -1937,7 +1966,7 @@ public class PreferencesHelper implements RankingConfig {
|
||||
pw.print(" (");
|
||||
pw.print(r.uid == UNKNOWN_UID ? "UNKNOWN_UID" : Integer.toString(r.uid));
|
||||
pw.print(')');
|
||||
if (r.importance != DEFAULT_IMPORTANCE) {
|
||||
if (!mPermissionHelper.isMigrationEnabled() && r.importance != DEFAULT_IMPORTANCE) {
|
||||
pw.print(" importance=");
|
||||
pw.print(NotificationListenerService.Ranking.importanceToString(r.importance));
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ import android.Manifest;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.permission.IPermissionManager;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
@@ -50,6 +51,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -66,6 +68,7 @@ import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -107,6 +110,9 @@ public class PermissionHelperTest extends UiServiceTestCase {
|
||||
args.add(false);
|
||||
} else if (type.getTypeName().equals("int")) {
|
||||
args.add(1);
|
||||
} else if (type.getTypeName().equals(
|
||||
"com.android.server.notification.PermissionHelper$PackagePermission")) {
|
||||
args.add(null);
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -158,15 +164,16 @@ public class PermissionHelperTest extends UiServiceTestCase {
|
||||
aiSecond.uid = 2;
|
||||
second.applicationInfo = aiSecond;
|
||||
|
||||
Map<Integer, String> expected = ImmutableMap.of(1, "first", 2, "second");
|
||||
Set<Pair<Integer, String>> expected =
|
||||
ImmutableSet.of(new Pair(1, "first"), new Pair(2, "second"));
|
||||
|
||||
ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>(
|
||||
ImmutableList.of(notThis, none, first, second));
|
||||
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS), anyInt())).thenReturn(infos);
|
||||
|
||||
Map<Integer, String> actual = mPermissionHelper.getAppsRequestingPermission(0);
|
||||
Set<Pair<Integer, String>> actual = mPermissionHelper.getAppsRequestingPermission(0);
|
||||
|
||||
assertThat(actual).containsExactlyEntriesIn(expected);
|
||||
assertThat(actual).containsExactlyElementsIn(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -202,10 +209,11 @@ public class PermissionHelperTest extends UiServiceTestCase {
|
||||
eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyInt(), eq(userId)))
|
||||
.thenReturn(infos);
|
||||
|
||||
Map<Integer, String> expected = ImmutableMap.of(1, "first", 2, "second");
|
||||
Set<Pair<Integer, String>> expected =
|
||||
ImmutableSet.of(new Pair(1, "first"), new Pair(2, "second"));
|
||||
|
||||
assertThat(mPermissionHelper.getAppsGrantedPermission(userId))
|
||||
.containsExactlyEntriesIn(expected);
|
||||
.containsExactlyElementsIn(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -268,4 +276,49 @@ public class PermissionHelperTest extends UiServiceTestCase {
|
||||
|
||||
assertThat(mPermissionHelper.isPermissionFixed("pkg", 0)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNotificationPermissionValues() throws Exception {
|
||||
int userId = 1;
|
||||
PackageInfo first = new PackageInfo();
|
||||
first.packageName = "first";
|
||||
first.requestedPermissions =
|
||||
new String[] {"something else", Manifest.permission.POST_NOTIFICATIONS};
|
||||
ApplicationInfo aiFirst = new ApplicationInfo();
|
||||
aiFirst.uid = 1;
|
||||
first.applicationInfo = aiFirst;
|
||||
|
||||
PackageInfo second = new PackageInfo();
|
||||
second.packageName = "second";
|
||||
second.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS};
|
||||
ApplicationInfo aiSecond = new ApplicationInfo();
|
||||
aiSecond.uid = 2;
|
||||
second.applicationInfo = aiSecond;
|
||||
|
||||
PackageInfo third = new PackageInfo();
|
||||
third.packageName = "third";
|
||||
third.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS};
|
||||
ApplicationInfo aiThird = new ApplicationInfo();
|
||||
aiThird.uid = 3;
|
||||
third.applicationInfo = aiThird;
|
||||
|
||||
ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>(
|
||||
ImmutableList.of(first, second));
|
||||
when(mPackageManager.getPackagesHoldingPermissions(
|
||||
eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyInt(), eq(userId)))
|
||||
.thenReturn(infos);
|
||||
ParceledListSlice<PackageInfo> requesting = new ParceledListSlice<>(
|
||||
ImmutableList.of(first, second, third));
|
||||
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS), anyInt()))
|
||||
.thenReturn(requesting);
|
||||
|
||||
Map<Pair<Integer, String>, Boolean> expected = ImmutableMap.of(new Pair(1, "first"), true,
|
||||
new Pair(2, "second"), true,
|
||||
new Pair(3, "third"), false);
|
||||
|
||||
Map<Pair<Integer, String>, Boolean> actual =
|
||||
mPermissionHelper.getNotificationPermissionValues(userId);
|
||||
|
||||
assertThat(actual).containsExactlyEntriesIn(expected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MAX;
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
import static android.media.AudioAttributes.CONTENT_TYPE_SONIFICATION;
|
||||
import static android.media.AudioAttributes.USAGE_NOTIFICATION;
|
||||
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
|
||||
|
||||
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
|
||||
@@ -102,6 +104,7 @@ import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IntArray;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.StatsEvent;
|
||||
import android.util.TypedXmlPullParser;
|
||||
import android.util.TypedXmlSerializer;
|
||||
@@ -111,6 +114,9 @@ import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.UiServiceTestCase;
|
||||
import com.android.server.notification.PermissionHelper.PackagePermission;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
@@ -581,6 +587,394 @@ public class PreferencesHelperTest extends UiServiceTestCase {
|
||||
assertTrue(foundChannel2Group);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadXml_oldXml_migrates() throws Exception {
|
||||
when(mPermissionHelper.isMigrationEnabled()).thenReturn(true);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
|
||||
mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
|
||||
|
||||
String xml = "<ranking version=\"2\">\n"
|
||||
+ "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
|
||||
+ "<channel id=\"idn\" name=\"name\" importance=\"2\" />\n"
|
||||
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "<package name=\"" + PKG_O + "\" importance=\"0\">\n"
|
||||
+ "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n"
|
||||
+ "</package>\n"
|
||||
+ "<package name=\"" + PKG_P + "\" importance=\"2\">\n"
|
||||
+ "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "</ranking>\n";
|
||||
NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW);
|
||||
idn.setSound(null, new AudioAttributes.Builder()
|
||||
.setUsage(USAGE_NOTIFICATION)
|
||||
.setContentType(CONTENT_TYPE_SONIFICATION)
|
||||
.setFlags(0)
|
||||
.build());
|
||||
idn.setShowBadge(false);
|
||||
NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW);
|
||||
ido.setShowBadge(true);
|
||||
ido.setSound(null, new AudioAttributes.Builder()
|
||||
.setUsage(USAGE_NOTIFICATION)
|
||||
.setContentType(CONTENT_TYPE_SONIFICATION)
|
||||
.setFlags(0)
|
||||
.build());
|
||||
NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH);
|
||||
idp.lockFields(2);
|
||||
idp.setSound(null, new AudioAttributes.Builder()
|
||||
.setUsage(USAGE_NOTIFICATION)
|
||||
.setContentType(CONTENT_TYPE_SONIFICATION)
|
||||
.setFlags(0)
|
||||
.build());
|
||||
|
||||
// Notifications enabled, not user set
|
||||
PackagePermission nMr1Expected = new PackagePermission(PKG_N_MR1, 0, true, false);
|
||||
// Notifications not enabled, so user set
|
||||
PackagePermission oExpected = new PackagePermission(PKG_O, 0, false, true);
|
||||
// Notifications enabled, user set b/c channel modified
|
||||
PackagePermission pExpected = new PackagePermission(PKG_P, 0, true, true);
|
||||
|
||||
loadByteArrayXml(xml.getBytes(), true, UserHandle.USER_SYSTEM);
|
||||
|
||||
assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
|
||||
|
||||
assertEquals(idn, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, idn.getId(), false));
|
||||
compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false));
|
||||
compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false));
|
||||
|
||||
verify(mPermissionHelper).setNotificationPermission(nMr1Expected);
|
||||
verify(mPermissionHelper).setNotificationPermission(oExpected);
|
||||
verify(mPermissionHelper).setNotificationPermission(pExpected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadXml_newXml_noMigration() throws Exception {
|
||||
when(mPermissionHelper.isMigrationEnabled()).thenReturn(true);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
|
||||
mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
|
||||
|
||||
String xml = "<ranking version=\"3\">\n"
|
||||
+ "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
|
||||
+ "<channel id=\"idn\" name=\"name\" importance=\"2\"/>\n"
|
||||
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "<package name=\"" + PKG_O + "\" >\n"
|
||||
+ "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n"
|
||||
+ "</package>\n"
|
||||
+ "<package name=\"" + PKG_P + "\" >\n"
|
||||
+ "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "</ranking>\n";
|
||||
NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW);
|
||||
idn.setSound(null, new AudioAttributes.Builder()
|
||||
.setUsage(USAGE_NOTIFICATION)
|
||||
.setContentType(CONTENT_TYPE_SONIFICATION)
|
||||
.setFlags(0)
|
||||
.build());
|
||||
idn.setShowBadge(false);
|
||||
NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW);
|
||||
ido.setShowBadge(true);
|
||||
ido.setSound(null, new AudioAttributes.Builder()
|
||||
.setUsage(USAGE_NOTIFICATION)
|
||||
.setContentType(CONTENT_TYPE_SONIFICATION)
|
||||
.setFlags(0)
|
||||
.build());
|
||||
NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH);
|
||||
idp.lockFields(2);
|
||||
idp.setSound(null, new AudioAttributes.Builder()
|
||||
.setUsage(USAGE_NOTIFICATION)
|
||||
.setContentType(CONTENT_TYPE_SONIFICATION)
|
||||
.setFlags(0)
|
||||
.build());
|
||||
|
||||
loadByteArrayXml(xml.getBytes(), true, UserHandle.USER_SYSTEM);
|
||||
|
||||
assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
|
||||
|
||||
assertEquals(idn, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, idn.getId(), false));
|
||||
compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false));
|
||||
compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false));
|
||||
|
||||
verify(mPermissionHelper, never()).setNotificationPermission(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChannelXmlForNonBackup_postMigration() throws Exception {
|
||||
when(mPermissionHelper.isMigrationEnabled()).thenReturn(true);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
|
||||
mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
|
||||
|
||||
ArrayMap<Pair<Integer, String>, Boolean> appPermissions = new ArrayMap<>();
|
||||
appPermissions.put(new Pair(1, "first"), true);
|
||||
appPermissions.put(new Pair(3, "third"), false);
|
||||
appPermissions.put(new Pair(UID_P, PKG_P), true);
|
||||
appPermissions.put(new Pair(UID_O, PKG_O), false);
|
||||
appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), true);
|
||||
|
||||
when(mPermissionHelper.getNotificationPermissionValues(UserHandle.USER_SYSTEM))
|
||||
.thenReturn(appPermissions);
|
||||
|
||||
NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
|
||||
NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
|
||||
NotificationChannel channel1 =
|
||||
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
|
||||
channel1.setSound(null, null);
|
||||
NotificationChannel channel2 =
|
||||
new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
|
||||
channel2.setDescription("descriptions for all");
|
||||
channel2.setSound(null, null);
|
||||
channel2.enableLights(true);
|
||||
channel2.setBypassDnd(true);
|
||||
channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
|
||||
channel2.enableVibration(false);
|
||||
channel2.setGroup(ncg.getId());
|
||||
channel2.setLightColor(Color.BLUE);
|
||||
NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH);
|
||||
channel3.enableVibration(true);
|
||||
|
||||
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
|
||||
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false);
|
||||
mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
|
||||
|
||||
mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
|
||||
mHelper.setInvalidMessageSent(PKG_P, UID_P);
|
||||
mHelper.setValidMessageSent(PKG_P, UID_P);
|
||||
mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(
|
||||
PKG_N_MR1, UID_N_MR1, false, UserHandle.USER_SYSTEM);
|
||||
String expected = "<ranking version=\"3\">\n"
|
||||
+ "<package name=\"com.example.o\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
|
||||
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\" uid=\"1111\">\n"
|
||||
+ "<channel id=\"id\" name=\"name\" importance=\"2\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "<package name=\"com.example.p\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\""
|
||||
+ " user_demote_msg_app=\"true\" uid=\"2222\" />\n"
|
||||
+ "<package name=\"com.example.n_mr1\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
|
||||
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\" uid=\"0\">\n"
|
||||
+ "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n"
|
||||
+ "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n"
|
||||
+ "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" "
|
||||
+ "orig_imp=\"4\" />\n"
|
||||
+ "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" "
|
||||
+ "importance=\"2\" priority=\"2\" visibility=\"-1\" lights=\"true\" "
|
||||
+ "light_color=\"-16776961\" show_badge=\"true\" group=\"1\" orig_imp=\"2\" />\n"
|
||||
+ "<channel id=\"id3\" name=\"NAM3\" importance=\"4\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" "
|
||||
+ "orig_imp=\"4\" />\n"
|
||||
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "</ranking>";
|
||||
assertThat(baos.toString()).contains(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChannelXmlForBackup_postMigration() throws Exception {
|
||||
when(mPermissionHelper.isMigrationEnabled()).thenReturn(true);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
|
||||
mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
|
||||
|
||||
ArrayMap<Pair<Integer, String>, Boolean> appPermissions = new ArrayMap<>();
|
||||
appPermissions.put(new Pair(1, "first"), true);
|
||||
appPermissions.put(new Pair(3, "third"), false);
|
||||
appPermissions.put(new Pair(UID_P, PKG_P), true);
|
||||
appPermissions.put(new Pair(UID_O, PKG_O), false);
|
||||
appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), true);
|
||||
|
||||
when(mPermissionHelper.getNotificationPermissionValues(UserHandle.USER_SYSTEM))
|
||||
.thenReturn(appPermissions);
|
||||
|
||||
NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
|
||||
NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
|
||||
NotificationChannel channel1 =
|
||||
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
|
||||
channel1.setSound(null, null);
|
||||
NotificationChannel channel2 =
|
||||
new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
|
||||
channel2.setDescription("descriptions for all");
|
||||
channel2.setSound(null, null);
|
||||
channel2.enableLights(true);
|
||||
channel2.setBypassDnd(true);
|
||||
channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
|
||||
channel2.enableVibration(false);
|
||||
channel2.setGroup(ncg.getId());
|
||||
channel2.setLightColor(Color.BLUE);
|
||||
NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH);
|
||||
channel3.enableVibration(true);
|
||||
|
||||
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
|
||||
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false);
|
||||
mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
|
||||
|
||||
mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
|
||||
mHelper.setInvalidMessageSent(PKG_P, UID_P);
|
||||
mHelper.setValidMessageSent(PKG_P, UID_P);
|
||||
mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(
|
||||
PKG_N_MR1, UID_N_MR1, true, UserHandle.USER_SYSTEM);
|
||||
String expected = "<ranking version=\"3\">\n"
|
||||
// Importance 0 because off in permissionhelper
|
||||
+ "<package name=\"com.example.o\" importance=\"0\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
|
||||
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n"
|
||||
+ "<channel id=\"id\" name=\"name\" importance=\"2\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n"
|
||||
+ "</package>\n"
|
||||
// Importance default because on in permission helper
|
||||
+ "<package name=\"com.example.p\" importance=\"3\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\""
|
||||
+ " user_demote_msg_app=\"true\" />\n"
|
||||
// Importance default because on in permission helper
|
||||
+ "<package name=\"com.example.n_mr1\" importance=\"3\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
|
||||
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n"
|
||||
+ "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n"
|
||||
+ "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n"
|
||||
+ "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" "
|
||||
+ "orig_imp=\"4\" />\n"
|
||||
+ "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" "
|
||||
+ "importance=\"2\" priority=\"2\" visibility=\"-1\" lights=\"true\" "
|
||||
+ "light_color=\"-16776961\" show_badge=\"true\" group=\"1\" orig_imp=\"2\" />\n"
|
||||
+ "<channel id=\"id3\" name=\"NAM3\" importance=\"4\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" "
|
||||
+ "orig_imp=\"4\" />\n"
|
||||
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
|
||||
+ "</package>\n"
|
||||
// Packages that exist solely in permissionhelper
|
||||
+ "<package name=\"first\" importance=\"3\" />\n"
|
||||
+ "<package name=\"third\" importance=\"0\" />\n"
|
||||
+ "</ranking>";
|
||||
assertThat(baos.toString()).contains(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChannelXmlForBackup_postMigration_noExternal() throws Exception {
|
||||
when(mPermissionHelper.isMigrationEnabled()).thenReturn(true);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
|
||||
mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
|
||||
|
||||
ArrayMap<Pair<Integer, String>, Boolean> appPermissions = new ArrayMap<>();
|
||||
appPermissions.put(new Pair(UID_P, PKG_P), true);
|
||||
appPermissions.put(new Pair(UID_O, PKG_O), false);
|
||||
when(mPermissionHelper.getNotificationPermissionValues(UserHandle.USER_SYSTEM))
|
||||
.thenReturn(appPermissions);
|
||||
|
||||
NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
|
||||
NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
|
||||
NotificationChannel channel1 =
|
||||
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
|
||||
channel1.setSound(null, null);
|
||||
NotificationChannel channel2 =
|
||||
new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
|
||||
channel2.setDescription("descriptions for all");
|
||||
channel2.setSound(null, null);
|
||||
channel2.enableLights(true);
|
||||
channel2.setBypassDnd(true);
|
||||
channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
|
||||
channel2.enableVibration(false);
|
||||
channel2.setGroup(ncg.getId());
|
||||
channel2.setLightColor(Color.BLUE);
|
||||
NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH);
|
||||
channel3.enableVibration(true);
|
||||
|
||||
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
|
||||
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
|
||||
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false);
|
||||
mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false);
|
||||
|
||||
mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
|
||||
mHelper.setInvalidMessageSent(PKG_P, UID_P);
|
||||
mHelper.setValidMessageSent(PKG_P, UID_P);
|
||||
mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(
|
||||
PKG_N_MR1, UID_N_MR1, true, UserHandle.USER_SYSTEM);
|
||||
String expected = "<ranking version=\"3\">\n"
|
||||
// Importance 0 because off in permissionhelper
|
||||
+ "<package name=\"com.example.o\" importance=\"0\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
|
||||
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n"
|
||||
+ "<channel id=\"id\" name=\"name\" importance=\"2\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n"
|
||||
+ "</package>\n"
|
||||
// Importance default because on in permission helper
|
||||
+ "<package name=\"com.example.p\" importance=\"3\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\""
|
||||
+ " user_demote_msg_app=\"true\" />\n"
|
||||
// Importance missing because missing from permission helper
|
||||
+ "<package name=\"com.example.n_mr1\" show_badge=\"true\" "
|
||||
+ "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" "
|
||||
+ "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n"
|
||||
+ "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n"
|
||||
+ "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n"
|
||||
+ "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" "
|
||||
+ "orig_imp=\"4\" />\n"
|
||||
+ "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" "
|
||||
+ "importance=\"2\" priority=\"2\" visibility=\"-1\" lights=\"true\" "
|
||||
+ "light_color=\"-16776961\" show_badge=\"true\" group=\"1\" orig_imp=\"2\" />\n"
|
||||
+ "<channel id=\"id3\" name=\"NAM3\" importance=\"4\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" "
|
||||
+ "orig_imp=\"4\" />\n"
|
||||
+ "<channel id=\"miscellaneous\" name=\"Uncategorized\" "
|
||||
+ "sound=\"content://settings/system/notification_sound\" usage=\"5\" "
|
||||
+ "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
|
||||
+ "</package>\n"
|
||||
+ "</ranking>";
|
||||
assertThat(baos.toString()).contains(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChannelXmlForBackup_postMigration_noLocalSettings() throws Exception {
|
||||
when(mPermissionHelper.isMigrationEnabled()).thenReturn(true);
|
||||
mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
|
||||
mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory);
|
||||
|
||||
ArrayMap<Pair<Integer, String>, Boolean> appPermissions = new ArrayMap<>();
|
||||
appPermissions.put(new Pair(1, "first"), true);
|
||||
appPermissions.put(new Pair(3, "third"), false);
|
||||
appPermissions.put(new Pair(UID_P, PKG_P), true);
|
||||
appPermissions.put(new Pair(UID_O, PKG_O), false);
|
||||
appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), true);
|
||||
|
||||
when(mPermissionHelper.getNotificationPermissionValues(UserHandle.USER_SYSTEM))
|
||||
.thenReturn(appPermissions);
|
||||
|
||||
ByteArrayOutputStream baos = writeXmlAndPurge(
|
||||
PKG_N_MR1, UID_N_MR1, true, UserHandle.USER_SYSTEM);
|
||||
String expected = "<ranking version=\"3\">\n"
|
||||
// Packages that exist solely in permissionhelper
|
||||
+ "<package name=\"" + PKG_P + "\" importance=\"3\" />\n"
|
||||
+ "<package name=\"" + PKG_O + "\" importance=\"0\" />\n"
|
||||
+ "<package name=\"" + PKG_N_MR1 + "\" importance=\"3\" />\n"
|
||||
+ "<package name=\"first\" importance=\"3\" />\n"
|
||||
+ "<package name=\"third\" importance=\"0\" />\n"
|
||||
+ "</ranking>";
|
||||
assertThat(baos.toString()).contains(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackupXml_backupCanonicalizedSoundUri() throws Exception {
|
||||
NotificationChannel channel =
|
||||
|
||||
Reference in New Issue
Block a user