Merge "Fix blockable system notifications" into tm-dev

This commit is contained in:
Julia Reynolds
2022-05-12 11:55:40 +00:00
committed by Android (Google) Code Review
8 changed files with 215 additions and 100 deletions

View File

@@ -320,7 +320,6 @@ package android.app {
method public void setDemoted(boolean);
method public void setFgServiceShown(boolean);
method public void setImportanceLockedByCriticalDeviceFunction(boolean);
method public void setImportanceLockedByOEM(boolean);
method public void setImportantConversation(boolean);
method public void setOriginalImportance(int);
}

View File

@@ -77,6 +77,7 @@ interface INotificationManager
boolean areNotificationsEnabledForPackage(String pkg, int uid);
boolean areNotificationsEnabled(String pkg);
int getPackageImportance(String pkg);
boolean isImportanceLocked(String pkg, int uid);
List<String> getAllowedAssistantAdjustments(String pkg);
void allowAssistantAdjustment(String adjustmentType);

View File

@@ -253,7 +253,6 @@ public final class NotificationChannel implements Parcelable {
// If this is a blockable system notification channel.
private boolean mBlockableSystem = false;
private int mAllowBubbles = DEFAULT_ALLOW_BUBBLE;
private boolean mImportanceLockedByOEM;
private boolean mImportanceLockedDefaultApp;
private String mParentId = null;
private String mConversationId = null;
@@ -322,13 +321,13 @@ public final class NotificationChannel implements Parcelable {
mLightColor = in.readInt();
mBlockableSystem = in.readBoolean();
mAllowBubbles = in.readInt();
mImportanceLockedByOEM = in.readBoolean();
mOriginalImportance = in.readInt();
mParentId = in.readString();
mConversationId = in.readString();
mDemoted = in.readBoolean();
mImportantConvo = in.readBoolean();
mDeletedTime = in.readLong();
mImportanceLockedDefaultApp = in.readBoolean();
}
@Override
@@ -382,13 +381,13 @@ public final class NotificationChannel implements Parcelable {
dest.writeInt(mLightColor);
dest.writeBoolean(mBlockableSystem);
dest.writeInt(mAllowBubbles);
dest.writeBoolean(mImportanceLockedByOEM);
dest.writeInt(mOriginalImportance);
dest.writeString(mParentId);
dest.writeString(mConversationId);
dest.writeBoolean(mDemoted);
dest.writeBoolean(mImportantConvo);
dest.writeLong(mDeletedTime);
dest.writeBoolean(mImportanceLockedDefaultApp);
}
/**
@@ -847,14 +846,6 @@ public final class NotificationChannel implements Parcelable {
return mBlockableSystem;
}
/**
* @hide
*/
@TestApi
public void setImportanceLockedByOEM(boolean locked) {
mImportanceLockedByOEM = locked;
}
/**
* @hide
*/
@@ -1107,8 +1098,8 @@ public final class NotificationChannel implements Parcelable {
out.attributeBoolean(null, ATT_IMP_CONVERSATION, isImportantConversation());
}
// mImportanceLockedDefaultApp and mImportanceLockedByOEM have a different source of
// truth and so aren't written to this xml file
// mImportanceLockedDefaultApp has a different source of truth and so isn't written to
// this xml file
out.endTag(null, TAG_CHANNEL);
}
@@ -1251,7 +1242,6 @@ public final class NotificationChannel implements Parcelable {
&& Arrays.equals(mVibration, that.mVibration)
&& Objects.equals(getGroup(), that.getGroup())
&& Objects.equals(getAudioAttributes(), that.getAudioAttributes())
&& mImportanceLockedByOEM == that.mImportanceLockedByOEM
&& mImportanceLockedDefaultApp == that.mImportanceLockedDefaultApp
&& mOriginalImportance == that.mOriginalImportance
&& Objects.equals(getParentChannelId(), that.getParentChannelId())
@@ -1267,7 +1257,7 @@ public final class NotificationChannel implements Parcelable {
getUserLockedFields(),
isFgServiceShown(), mVibrationEnabled, mShowBadge, isDeleted(), getDeletedTimeMs(),
getGroup(), getAudioAttributes(), isBlockable(), mAllowBubbles,
mImportanceLockedByOEM, mImportanceLockedDefaultApp, mOriginalImportance,
mImportanceLockedDefaultApp, mOriginalImportance,
mParentId, mConversationId, mDemoted, mImportantConvo);
result = 31 * result + Arrays.hashCode(mVibration);
return result;
@@ -1312,7 +1302,6 @@ public final class NotificationChannel implements Parcelable {
+ ", mAudioAttributes=" + mAudioAttributes
+ ", mBlockableSystem=" + mBlockableSystem
+ ", mAllowBubbles=" + mAllowBubbles
+ ", mImportanceLockedByOEM=" + mImportanceLockedByOEM
+ ", mImportanceLockedDefaultApp=" + mImportanceLockedDefaultApp
+ ", mOriginalImp=" + mOriginalImportance
+ ", mParent=" + mParentId

View File

@@ -60,6 +60,7 @@ import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.MathUtils;
import android.util.Property;
import android.util.Slog;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -363,9 +364,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Nullable private OnExpansionChangedListener mExpansionChangedListener;
@Nullable private Runnable mOnIntrinsicHeightReachedRunnable;
private SystemNotificationAsyncTask mSystemNotificationAsyncTask =
new SystemNotificationAsyncTask();
private float mTopRoundnessDuringLaunchAnimation;
private float mBottomRoundnessDuringLaunchAnimation;
@@ -516,46 +514,21 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mRowContentBindStage.requestRebind(mEntry, null /* callback */);
}
/**
* Caches whether or not this row contains a system notification. Note, this is only cached
* once per notification as the packageInfo can't technically change for a notification row.
*/
private void cacheIsSystemNotification() {
//TODO: This probably shouldn't be in ExpandableNotificationRow
if (mEntry != null && mEntry.mIsSystemNotification == null) {
if (mSystemNotificationAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
// Run async task once, only if it hasn't already been executed. Note this is
// executed in serial - no need to parallelize this small task.
mSystemNotificationAsyncTask.execute();
}
}
}
/**
* Returns whether this row is considered non-blockable (i.e. it's a non-blockable system notif
* or is in an allowList).
*/
public boolean getIsNonblockable() {
// If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once
// again, but in-place on the main thread this time. This should rarely ever get called.
if (mEntry != null && mEntry.mIsSystemNotification == null) {
if (DEBUG) {
Log.d(TAG, "Retrieving isSystemNotification on main thread");
}
mSystemNotificationAsyncTask.cancel(true /* mayInterruptIfRunning */);
mEntry.mIsSystemNotification = isSystemNotification(mContext, mEntry.getSbn());
if (mEntry == null || mEntry.getChannel() == null) {
Log.w(TAG, "missing entry or channel");
return true;
}
if (mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction()
&& !mEntry.getChannel().isBlockable()) {
return true;
}
boolean isNonblockable = mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction();
if (!isNonblockable && mEntry != null && mEntry.mIsSystemNotification != null) {
if (mEntry.mIsSystemNotification) {
if (mEntry.getChannel() != null && !mEntry.getChannel().isBlockable()) {
isNonblockable = true;
}
}
}
return isNonblockable;
return false;
}
private boolean isConversation() {
@@ -1626,8 +1599,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mBubblesManagerOptional = bubblesManagerOptional;
mNotificationGutsManager = gutsManager;
mMetricsLogger = metricsLogger;
cacheIsSystemNotification();
}
private void initDimens() {
@@ -3545,25 +3516,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
});
}
/**
* Background task for executing IPCs to check if the notification is a system notification. The
* output is used for both the blocking helper and the notification info.
*/
private class SystemNotificationAsyncTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... voids) {
return isSystemNotification(mContext, mEntry.getSbn());
}
@Override
protected void onPostExecute(Boolean result) {
if (mEntry != null) {
mEntry.mIsSystemNotification = result;
}
}
}
private void setTargetPoint(Point p) {
mTargetPoint = p;
}

View File

@@ -322,10 +322,21 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
ExpandableNotificationRow row =
mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
row.getEntry().getChannel().setBlockable(false);
assertTrue(row.getIsNonblockable());
}
@Test
public void testGetIsNonblockable_criticalDeviceFunction_butBlockable() throws Exception {
ExpandableNotificationRow row =
mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
row.getEntry().getChannel().setBlockable(true);
assertFalse(row.getIsNonblockable());
}
@Test
public void testCanDismissNoClear() throws Exception {
ExpandableNotificationRow row =

View File

@@ -2284,6 +2284,7 @@ public class NotificationManagerService extends SystemService {
mNotificationChannelLogger,
mAppOps,
new SysUiStatsEvent.BuilderFactory());
mPreferencesHelper.updateFixedImportance(mUm.getUsers());
mRankingHelper = new RankingHelper(getContext(),
mRankingHandler,
mPreferencesHelper,
@@ -3631,6 +3632,12 @@ public class NotificationManagerService extends SystemService {
}
}
@Override
public boolean isImportanceLocked(String pkg, int uid) {
checkCallerIsSystem();
return mPreferencesHelper.isImportanceLocked(pkg, uid);
}
@Override
public boolean canShowBadge(String pkg, int uid) {
checkCallerIsSystem();

View File

@@ -42,8 +42,10 @@ import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.metrics.LogMaker;
import android.os.Binder;
import android.os.Build;
@@ -146,7 +148,6 @@ public class PreferencesHelper implements RankingConfig {
static final boolean DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS = false;
private static final boolean DEFAULT_SHOW_BADGE = true;
private static final boolean DEFAULT_OEM_LOCKED_IMPORTANCE = false;
private static final boolean DEFAULT_APP_LOCKED_IMPORTANCE = false;
static final boolean DEFAULT_BUBBLES_ENABLED = true;
@@ -193,8 +194,6 @@ public class PreferencesHelper implements RankingConfig {
private boolean mAllowInvalidShortcuts = false;
private Map<String, List<String>> mOemLockedApps = new HashMap();
public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
ZenModeHelper zenHelper, PermissionHelper permHelper,
NotificationChannelLogger notificationChannelLogger,
@@ -411,7 +410,7 @@ public class PreferencesHelper implements RankingConfig {
channel.populateFromXml(parser);
}
channel.setImportanceLockedByCriticalDeviceFunction(
r.defaultAppLockedImportance);
r.defaultAppLockedImportance || r.fixedImportance);
if (isShortcutOk(channel) && isDeletionOk(channel)) {
r.channels.put(id, channel);
@@ -484,14 +483,6 @@ public class PreferencesHelper implements RankingConfig {
r.visibility = visibility;
r.showBadge = showBadge;
r.bubblePreference = bubblePreference;
if (mOemLockedApps.containsKey(r.pkg)) {
List<String> channels = mOemLockedApps.get(r.pkg);
if (channels == null || channels.isEmpty()) {
r.oemLockedImportance = true;
} else {
r.oemLockedChannels = channels;
}
}
try {
createDefaultChannelIfNeededLocked(r);
@@ -818,6 +809,13 @@ public class PreferencesHelper implements RankingConfig {
}
}
boolean isImportanceLocked(String pkg, int uid) {
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
return r.fixedImportance || r.defaultAppLockedImportance;
}
}
@Override
public boolean isGroupBlocked(String packageName, int uid, String groupId) {
if (groupId == null) {
@@ -1008,7 +1006,7 @@ public class PreferencesHelper implements RankingConfig {
clearLockedFieldsLocked(channel);
channel.setImportanceLockedByCriticalDeviceFunction(
r.defaultAppLockedImportance);
r.defaultAppLockedImportance || r.fixedImportance);
if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
channel.setLockscreenVisibility(
@@ -1090,8 +1088,7 @@ public class PreferencesHelper implements RankingConfig {
updatedChannel.unlockFields(updatedChannel.getUserLockedFields());
}
if ((mPermissionHelper.isPermissionFixed(r.pkg, UserHandle.getUserId(r.uid))
|| channel.isImportanceLockedByCriticalDeviceFunction())
if (channel.isImportanceLockedByCriticalDeviceFunction()
&& !(channel.isBlockable() || channel.getImportance() == IMPORTANCE_NONE)) {
updatedChannel.setImportance(channel.getImportance());
}
@@ -1267,6 +1264,28 @@ public class PreferencesHelper implements RankingConfig {
mHideSilentStatusBarIcons = hide;
}
public void updateFixedImportance(List<UserInfo> users) {
for (UserInfo user : users) {
List<PackageInfo> packages = mPm.getInstalledPackagesAsUser(
PackageManager.PackageInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY),
user.getUserHandle().getIdentifier());
for (PackageInfo pi : packages) {
boolean fixed = mPermissionHelper.isPermissionFixed(
pi.packageName, user.getUserHandle().getIdentifier());
if (fixed) {
synchronized (mPackagePreferences) {
PackagePreferences p = getOrCreatePackagePreferencesLocked(
pi.packageName, pi.applicationInfo.uid);
p.fixedImportance = true;
for (NotificationChannel channel : p.channels.values()) {
channel.setImportanceLockedByCriticalDeviceFunction(true);
}
}
}
}
}
}
public void updateDefaultApps(int userId, ArraySet<String> toRemove,
ArraySet<Pair<String, Integer>> toAdd) {
synchronized (mPackagePreferences) {
@@ -1274,8 +1293,10 @@ public class PreferencesHelper implements RankingConfig {
if (userId == UserHandle.getUserId(p.uid)) {
if (toRemove != null && toRemove.contains(p.pkg)) {
p.defaultAppLockedImportance = false;
for (NotificationChannel channel : p.channels.values()) {
channel.setImportanceLockedByCriticalDeviceFunction(false);
if (!p.fixedImportance) {
for (NotificationChannel channel : p.channels.values()) {
channel.setImportanceLockedByCriticalDeviceFunction(false);
}
}
}
}
@@ -1934,13 +1955,9 @@ public class PreferencesHelper implements RankingConfig {
pw.print(" defaultAppLocked=");
pw.print(r.defaultAppLockedImportance);
}
if (r.oemLockedImportance != DEFAULT_OEM_LOCKED_IMPORTANCE) {
pw.print(" oemLocked=");
pw.print(r.oemLockedImportance);
}
if (!r.oemLockedChannels.isEmpty()) {
pw.print(" futureLockedChannels=");
pw.print(r.oemLockedChannels);
if (r.fixedImportance != DEFAULT_APP_LOCKED_IMPORTANCE) {
pw.print(" fixedImportance=");
pw.print(r.fixedImportance);
}
pw.println();
for (NotificationChannel channel : r.channels.values()) {
@@ -2682,9 +2699,8 @@ public class PreferencesHelper implements RankingConfig {
int lockedAppFields = DEFAULT_LOCKED_APP_FIELDS;
// these fields are loaded on boot from a different source of truth and so are not
// written to notification policy xml
boolean oemLockedImportance = DEFAULT_OEM_LOCKED_IMPORTANCE;
List<String> oemLockedChannels = new ArrayList<>();
boolean defaultAppLockedImportance = DEFAULT_APP_LOCKED_IMPORTANCE;
boolean fixedImportance = DEFAULT_APP_LOCKED_IMPORTANCE;
boolean hasSentInvalidMessage = false;
boolean hasSentValidMessage = false;

View File

@@ -85,6 +85,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioAttributes;
@@ -121,6 +122,8 @@ import com.android.os.AtomsProto.PackageNotificationPreferences;
import com.android.server.UiServiceTestCase;
import com.android.server.notification.PermissionHelper.PackagePermission;
import com.google.common.collect.ImmutableList;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.Before;
@@ -3523,8 +3526,37 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testUpdateNotificationChannel_fixedPermission() {
List<UserInfo> users = ImmutableList.of(new UserInfo(UserHandle.USER_SYSTEM, "user0", 0));
when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true);
PackageInfo pm = new PackageInfo();
pm.packageName = PKG_O;
pm.applicationInfo = new ApplicationInfo();
pm.applicationInfo.uid = UID_O;
List<PackageInfo> packages = ImmutableList.of(pm);
when(mPm.getInstalledPackagesAsUser(any(), anyInt())).thenReturn(packages);
mHelper.updateFixedImportance(users);
assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O));
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_NONE);
update.setAllowBubbles(false);
mHelper.updateNotificationChannel(PKG_O, UID_O, update, true);
assertEquals(IMPORTANCE_HIGH,
mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance());
assertEquals(false,
mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble());
}
@Test
public void testUpdateNotificationChannel_defaultApp() {
ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
toAdd.add(new Pair(PKG_O, UID_O));
mHelper.updateDefaultApps(0, null, toAdd);
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
@@ -3594,6 +3626,58 @@ public class PreferencesHelperTest extends UiServiceTestCase {
mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble());
}
@Test
public void testUpdateFixedImportance_multiUser() {
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW);
NotificationChannel c = new NotificationChannel("c", "c", IMPORTANCE_DEFAULT);
// different uids, same package
mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
mHelper.createNotificationChannel(PKG_O, UID_O, b, false, false);
mHelper.createNotificationChannel(PKG_O, UserHandle.PER_USER_RANGE + 1, c, true, true);
UserInfo user = new UserInfo();
user.id = 0;
List<UserInfo> users = ImmutableList.of(user);
when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true);
PackageInfo pm = new PackageInfo();
pm.packageName = PKG_O;
pm.applicationInfo = new ApplicationInfo();
pm.applicationInfo.uid = UID_O;
List<PackageInfo> packages = ImmutableList.of(pm);
when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
mHelper.updateFixedImportance(users);
assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
.isImportanceLockedByCriticalDeviceFunction());
assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, b.getId(), false)
.isImportanceLockedByCriticalDeviceFunction());
assertFalse(mHelper.getNotificationChannel(
PKG_O, UserHandle.PER_USER_RANGE + 1, c.getId(), false)
.isImportanceLockedByCriticalDeviceFunction());
}
@Test
public void testUpdateFixedImportance_channelDoesNotExistYet() {
UserInfo user = new UserInfo();
user.id = 0;
List<UserInfo> users = ImmutableList.of(user);
when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true);
PackageInfo pm = new PackageInfo();
pm.packageName = PKG_O;
pm.applicationInfo = new ApplicationInfo();
pm.applicationInfo.uid = UID_O;
List<PackageInfo> packages = ImmutableList.of(pm);
when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
mHelper.updateFixedImportance(users);
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
.isImportanceLockedByCriticalDeviceFunction());
}
@Test
public void testUpdateDefaultApps_add_multiUser() {
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
@@ -3758,6 +3842,62 @@ public class PreferencesHelperTest extends UiServiceTestCase {
assertTrue(a.isImportanceLockedByCriticalDeviceFunction());
}
@Test
public void testUpdateFixedImportance_thenDefaultAppsRemoves() {
UserInfo user = new UserInfo();
user.id = 0;
List<UserInfo> users = ImmutableList.of(user);
when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true);
PackageInfo pm = new PackageInfo();
pm.packageName = PKG_O;
pm.applicationInfo = new ApplicationInfo();
pm.applicationInfo.uid = UID_O;
List<PackageInfo> packages = ImmutableList.of(pm);
when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
mHelper.updateFixedImportance(users);
ArraySet<String> toRemove = new ArraySet<>();
toRemove.add(PKG_O);
mHelper.updateDefaultApps(0, toRemove, null);
assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O));
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
// Still locked by permission if not role
assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
.isImportanceLockedByCriticalDeviceFunction());
}
@Test
public void testUpdateDefaultApps_thenNotFixedPermission() {
ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>();
toAdd.add(new Pair(PKG_O, UID_O));
mHelper.updateDefaultApps(0, null, toAdd);
UserInfo user = new UserInfo();
user.id = 0;
List<UserInfo> users = ImmutableList.of(user);
when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(false);
PackageInfo pm = new PackageInfo();
pm.packageName = PKG_O;
pm.applicationInfo = new ApplicationInfo();
pm.applicationInfo.uid = UID_O;
List<PackageInfo> packages = ImmutableList.of(pm);
when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages);
mHelper.updateFixedImportance(users);
assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O));
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false);
// Still locked by role if not permission
assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false)
.isImportanceLockedByCriticalDeviceFunction());
}
@Test
public void testChannelXml_backupDefaultApp() throws Exception {
NotificationChannel channel1 =