Merge "Fix blockable system notifications" into tm-dev am: ddfeaa18f7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18292722

Change-Id: I8f405714bc497688d8f214b19c07658ddeff9163
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Julia Reynolds
2022-05-12 12:28:09 +00:00
committed by Automerger Merge Worker
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 setDemoted(boolean);
method public void setFgServiceShown(boolean); method public void setFgServiceShown(boolean);
method public void setImportanceLockedByCriticalDeviceFunction(boolean); method public void setImportanceLockedByCriticalDeviceFunction(boolean);
method public void setImportanceLockedByOEM(boolean);
method public void setImportantConversation(boolean); method public void setImportantConversation(boolean);
method public void setOriginalImportance(int); method public void setOriginalImportance(int);
} }

View File

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

View File

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

View File

@@ -60,6 +60,7 @@ import android.util.IndentingPrintWriter;
import android.util.Log; import android.util.Log;
import android.util.MathUtils; import android.util.MathUtils;
import android.util.Property; import android.util.Property;
import android.util.Slog;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
@@ -363,9 +364,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Nullable private OnExpansionChangedListener mExpansionChangedListener; @Nullable private OnExpansionChangedListener mExpansionChangedListener;
@Nullable private Runnable mOnIntrinsicHeightReachedRunnable; @Nullable private Runnable mOnIntrinsicHeightReachedRunnable;
private SystemNotificationAsyncTask mSystemNotificationAsyncTask =
new SystemNotificationAsyncTask();
private float mTopRoundnessDuringLaunchAnimation; private float mTopRoundnessDuringLaunchAnimation;
private float mBottomRoundnessDuringLaunchAnimation; private float mBottomRoundnessDuringLaunchAnimation;
@@ -516,46 +514,21 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mRowContentBindStage.requestRebind(mEntry, null /* callback */); 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 * Returns whether this row is considered non-blockable (i.e. it's a non-blockable system notif
* or is in an allowList). * or is in an allowList).
*/ */
public boolean getIsNonblockable() { public boolean getIsNonblockable() {
// If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once if (mEntry == null || mEntry.getChannel() == null) {
// again, but in-place on the main thread this time. This should rarely ever get called. Log.w(TAG, "missing entry or channel");
if (mEntry != null && mEntry.mIsSystemNotification == null) { return true;
if (DEBUG) { }
Log.d(TAG, "Retrieving isSystemNotification on main thread"); if (mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction()
} && !mEntry.getChannel().isBlockable()) {
mSystemNotificationAsyncTask.cancel(true /* mayInterruptIfRunning */); return true;
mEntry.mIsSystemNotification = isSystemNotification(mContext, mEntry.getSbn());
} }
boolean isNonblockable = mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction(); return false;
if (!isNonblockable && mEntry != null && mEntry.mIsSystemNotification != null) {
if (mEntry.mIsSystemNotification) {
if (mEntry.getChannel() != null && !mEntry.getChannel().isBlockable()) {
isNonblockable = true;
}
}
}
return isNonblockable;
} }
private boolean isConversation() { private boolean isConversation() {
@@ -1626,8 +1599,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mBubblesManagerOptional = bubblesManagerOptional; mBubblesManagerOptional = bubblesManagerOptional;
mNotificationGutsManager = gutsManager; mNotificationGutsManager = gutsManager;
mMetricsLogger = metricsLogger; mMetricsLogger = metricsLogger;
cacheIsSystemNotification();
} }
private void initDimens() { 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) { private void setTargetPoint(Point p) {
mTargetPoint = p; mTargetPoint = p;
} }

View File

@@ -322,10 +322,21 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
ExpandableNotificationRow row = ExpandableNotificationRow row =
mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification()); mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true); row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
row.getEntry().getChannel().setBlockable(false);
assertTrue(row.getIsNonblockable()); 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 @Test
public void testCanDismissNoClear() throws Exception { public void testCanDismissNoClear() throws Exception {
ExpandableNotificationRow row = ExpandableNotificationRow row =

View File

@@ -2284,6 +2284,7 @@ public class NotificationManagerService extends SystemService {
mNotificationChannelLogger, mNotificationChannelLogger,
mAppOps, mAppOps,
new SysUiStatsEvent.BuilderFactory()); new SysUiStatsEvent.BuilderFactory());
mPreferencesHelper.updateFixedImportance(mUm.getUsers());
mRankingHelper = new RankingHelper(getContext(), mRankingHelper = new RankingHelper(getContext(),
mRankingHandler, mRankingHandler,
mPreferencesHelper, 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 @Override
public boolean canShowBadge(String pkg, int uid) { public boolean canShowBadge(String pkg, int uid) {
checkCallerIsSystem(); checkCallerIsSystem();

View File

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

View File

@@ -85,6 +85,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.Signature; import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Color; import android.graphics.Color;
import android.media.AudioAttributes; import android.media.AudioAttributes;
@@ -121,6 +122,8 @@ import com.android.os.AtomsProto.PackageNotificationPreferences;
import com.android.server.UiServiceTestCase; import com.android.server.UiServiceTestCase;
import com.android.server.notification.PermissionHelper.PackagePermission; import com.android.server.notification.PermissionHelper.PackagePermission;
import com.google.common.collect.ImmutableList;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.junit.Before; import org.junit.Before;
@@ -3523,8 +3526,37 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test @Test
public void testUpdateNotificationChannel_fixedPermission() { public void testUpdateNotificationChannel_fixedPermission() {
List<UserInfo> users = ImmutableList.of(new UserInfo(UserHandle.USER_SYSTEM, "user0", 0));
when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true); 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); NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 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()); 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 @Test
public void testUpdateDefaultApps_add_multiUser() { public void testUpdateDefaultApps_add_multiUser() {
NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH);
@@ -3758,6 +3842,62 @@ public class PreferencesHelperTest extends UiServiceTestCase {
assertTrue(a.isImportanceLockedByCriticalDeviceFunction()); 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 @Test
public void testChannelXml_backupDefaultApp() throws Exception { public void testChannelXml_backupDefaultApp() throws Exception {
NotificationChannel channel1 = NotificationChannel channel1 =