Migrate to using fixed permissions

When deciding which app/group/channel level fields are editable. If
an app has a fixed notification permission, no importance type fields
(including blocking, importance, minimizing, popping on screen, or
prioirty conversions) can be edited.

Test: Robotests
Bug: 194833441
Change-Id: Idc198ea05cd2ab6e43387ae4e8290f446ccfa0c6
This commit is contained in:
Julia Reynolds
2021-10-29 08:19:10 -04:00
parent e3f34ef7db
commit a024c10517
21 changed files with 272 additions and 211 deletions

View File

@@ -20,6 +20,7 @@ import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED;
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC;
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER; import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
import static android.os.UserHandle.USER_SYSTEM;
import android.app.INotificationManager; import android.app.INotificationManager;
import android.app.NotificationChannel; import android.app.NotificationChannel;
@@ -44,6 +45,7 @@ import android.graphics.drawable.Drawable;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.ConversationChannelWrapper; import android.service.notification.ConversationChannelWrapper;
import android.service.notification.NotificationListenerFilter; import android.service.notification.NotificationListenerFilter;
import android.text.format.DateUtils; import android.text.format.DateUtils;
@@ -112,15 +114,25 @@ public class NotificationBackend {
void recordCanBeBlocked(Context context, PackageManager pm, RoleManager rm, PackageInfo app, void recordCanBeBlocked(Context context, PackageManager pm, RoleManager rm, PackageInfo app,
AppRow row) { AppRow row) {
row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app); if (Settings.Secure.getIntForUser(context.getContentResolver(),
List<String> roles = rm.getHeldRolesFromController(app.packageName); Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 0, USER_SYSTEM) != 0) {
if (roles.contains(RoleManager.ROLE_DIALER) try {
|| roles.contains(RoleManager.ROLE_EMERGENCY)) { row.systemApp = row.lockedImportance =
row.systemApp = true; sINM.isPermissionFixed(app.packageName, row.userId);
} catch (RemoteException e) {
Log.w(TAG, "Error calling NMS", e);
}
} else {
row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app);
List<String> roles = rm.getHeldRolesFromController(app.packageName);
if (roles.contains(RoleManager.ROLE_DIALER)
|| roles.contains(RoleManager.ROLE_EMERGENCY)) {
row.systemApp = true;
}
final String[] nonBlockablePkgs = context.getResources().getStringArray(
com.android.internal.R.array.config_nonBlockableNotificationPackages);
markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName);
} }
final String[] nonBlockablePkgs = context.getResources().getStringArray(
com.android.internal.R.array.config_nonBlockableNotificationPackages);
markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName);
} }
@VisibleForTesting static void markAppRowWithBlockables(String[] nonBlockablePkgs, AppRow row, @VisibleForTesting static void markAppRowWithBlockables(String[] nonBlockablePkgs, AppRow row,
@@ -653,6 +665,11 @@ public class NotificationBackend {
return false; return false;
} }
@VisibleForTesting
void setNm(INotificationManager inm) {
sINM = inm;
}
/** /**
* NotificationsSentState contains how often an app sends notifications and how recently it sent * NotificationsSentState contains how often an app sends notifications and how recently it sent
* one. * one.

View File

@@ -80,7 +80,7 @@ public class BlockPreferenceController extends NotificationPreferenceController
} }
bar.setDisabledByAdmin(mAdmin); bar.setDisabledByAdmin(mAdmin);
if (mChannel != null && !isChannelBlockable()) { if (mChannel != null && (!isChannelBlockable() || !isChannelConfigurable(mChannel))) {
bar.setSwitchBarEnabled(false); bar.setSwitchBarEnabled(false);
} }
@@ -88,8 +88,7 @@ public class BlockPreferenceController extends NotificationPreferenceController
bar.setSwitchBarEnabled(false); bar.setSwitchBarEnabled(false);
} }
if (mChannel == null && mAppRow.systemApp if (mChannel == null && !isAppBlockable()) {
&& (!mAppRow.banned || mAppRow.lockedImportance)) {
bar.setSwitchBarEnabled(false); bar.setSwitchBarEnabled(false);
} }

View File

@@ -62,9 +62,9 @@ public class ConversationPriorityPreferenceController extends NotificationPrefer
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (mAppRow != null) { if (mAppRow != null) {
preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM()); preference.setEnabled(mAdmin == null && isChannelConfigurable(mChannel));
ConversationPriorityPreference pref = (ConversationPriorityPreference) preference; ConversationPriorityPreference pref = (ConversationPriorityPreference) preference;
pref.setConfigurable(!mChannel.isImportanceLockedByOEM()); pref.setConfigurable(isChannelConfigurable(mChannel));
pref.setImportance(mChannel.getImportance()); pref.setImportance(mChannel.getImportance());
pref.setOriginalImportance(mChannel.getOriginalImportance()); pref.setOriginalImportance(mChannel.getOriginalImportance());
pref.setPriorityConversation(mChannel.isImportantConversation()); pref.setPriorityConversation(mChannel.isImportantConversation());

View File

@@ -68,7 +68,7 @@ public class HighImportancePreferenceController extends NotificationPreferenceCo
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (mAppRow != null && mChannel != null) { if (mAppRow != null && mChannel != null) {
preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM()); preference.setEnabled(mAdmin == null && isChannelConfigurable(mChannel));
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
pref.setChecked(mChannel.getImportance() >= IMPORTANCE_HIGH); pref.setChecked(mChannel.getImportance() >= IMPORTANCE_HIGH);

View File

@@ -66,9 +66,9 @@ public class ImportancePreferenceController extends NotificationPreferenceContro
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (mAppRow!= null && mChannel != null) { if (mAppRow!= null && mChannel != null) {
preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM()); preference.setEnabled(mAdmin == null && isChannelConfigurable(mChannel));
ImportancePreference pref = (ImportancePreference) preference; ImportancePreference pref = (ImportancePreference) preference;
pref.setConfigurable(!mChannel.isImportanceLockedByOEM()); pref.setConfigurable(isChannelConfigurable(mChannel));
pref.setImportance(mChannel.getImportance()); pref.setImportance(mChannel.getImportance());
pref.setDisplayInStatusBar(mBackend.showSilentInStatusBar(mContext.getPackageName())); pref.setDisplayInStatusBar(mBackend.showSilentInStatusBar(mContext.getPackageName()));
pref.setDisplayOnLockscreen(Settings.Secure.getInt(mContext.getContentResolver(), pref.setDisplayOnLockscreen(Settings.Secure.getInt(mContext.getContentResolver(),

View File

@@ -68,7 +68,7 @@ public class MinImportancePreferenceController extends NotificationPreferenceCon
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (mAppRow != null && mChannel != null) { if (mAppRow != null && mChannel != null) {
preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM()); preference.setEnabled(mAdmin == null && isChannelConfigurable(mChannel));
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
pref.setChecked(mChannel.getImportance() == IMPORTANCE_MIN); pref.setChecked(mChannel.getImportance() == IMPORTANCE_MIN);

View File

@@ -17,6 +17,7 @@
package com.android.settings.notification.app; package com.android.settings.notification.app;
import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.os.UserHandle.USER_SYSTEM;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.NotificationChannel; import android.app.NotificationChannel;
@@ -27,6 +28,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import android.util.Log; import android.util.Log;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -62,6 +64,12 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
@Nullable @Nullable
protected ShortcutInfo mConversationInfo; protected ShortcutInfo mConversationInfo;
protected List<String> mPreferenceFilter; protected List<String> mPreferenceFilter;
boolean mMigratedPermission;
boolean overrideCanBlock;
boolean overrideCanConfigure;
boolean overrideCanBlockValue;
boolean overrideCanConfigureValue;
public NotificationPreferenceController(Context context, NotificationBackend backend) { public NotificationPreferenceController(Context context, NotificationBackend backend) {
super(context); super(context);
@@ -70,6 +78,8 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
mBackend = backend; mBackend = backend;
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mPm = mContext.getPackageManager(); mPm = mContext.getPackageManager();
mMigratedPermission = Settings.Secure.getIntForUser(context.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 0, USER_SYSTEM) != 0;
} }
/** /**
@@ -138,10 +148,18 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
} }
protected boolean isChannelBlockable(NotificationChannel channel) { protected boolean isChannelBlockable(NotificationChannel channel) {
if (overrideCanBlock) {
return overrideCanBlockValue;
}
if (overrideCanConfigure) {
return overrideCanConfigureValue;
}
if (channel != null && mAppRow != null) { if (channel != null && mAppRow != null) {
if (channel.isImportanceLockedByCriticalDeviceFunction() boolean locked = mMigratedPermission ? mAppRow.lockedImportance
|| channel.isImportanceLockedByOEM()) { : channel.isImportanceLockedByCriticalDeviceFunction()
return channel.getImportance() == IMPORTANCE_NONE; || channel.isImportanceLockedByOEM();
if (locked) {
return channel.isBlockable() || channel.getImportance() == IMPORTANCE_NONE;
} }
return channel.isBlockable() || !mAppRow.systemApp return channel.isBlockable() || !mAppRow.systemApp
@@ -150,9 +168,27 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
return false; return false;
} }
protected boolean isAppBlockable() {
if (overrideCanBlock) {
return overrideCanBlockValue;
}
if (overrideCanConfigure) {
return overrideCanConfigureValue;
}
if (mAppRow != null) {
return !mAppRow.systemApp && !mAppRow.lockedImportance;
}
return true;
}
protected boolean isChannelConfigurable(NotificationChannel channel) { protected boolean isChannelConfigurable(NotificationChannel channel) {
if (overrideCanConfigure) {
return overrideCanConfigureValue;
}
if (channel != null && mAppRow != null) { if (channel != null && mAppRow != null) {
return !channel.isImportanceLockedByOEM(); boolean locked = mMigratedPermission ? mAppRow.lockedImportance
: channel.isImportanceLockedByOEM();
return !locked || channel.isBlockable();
} }
return false; return false;
} }
@@ -162,8 +198,14 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
} }
protected boolean isChannelGroupBlockable(NotificationChannelGroup group) { protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
if (overrideCanBlock) {
return overrideCanBlockValue;
}
if (overrideCanConfigure) {
return overrideCanConfigureValue;
}
if (group != null && mAppRow != null) { if (group != null && mAppRow != null) {
if (!mAppRow.systemApp) { if (!mAppRow.systemApp && !mAppRow.lockedImportance) {
return true; return true;
} }
@@ -183,6 +225,16 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
return Objects.equals(NotificationChannel.DEFAULT_CHANNEL_ID, mChannel.getId()); return Objects.equals(NotificationChannel.DEFAULT_CHANNEL_ID, mChannel.getId());
} }
protected final void setOverrideCanBlock(boolean canBlock) {
overrideCanBlock = true;
overrideCanBlockValue = canBlock;
}
protected final void setOverrideCanConfigure(boolean canConfigure) {
overrideCanConfigure = true;
overrideCanConfigureValue = canConfigure;
}
public static final Comparator<NotificationChannelGroup> CHANNEL_GROUP_COMPARATOR = public static final Comparator<NotificationChannelGroup> CHANNEL_GROUP_COMPARATOR =
new Comparator<NotificationChannelGroup>() { new Comparator<NotificationChannelGroup>() {
@Override @Override

View File

@@ -16,6 +16,9 @@
package com.android.settings.notification; package com.android.settings.notification;
import static android.os.UserHandle.USER_SYSTEM;
import static android.provider.Settings.*;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@@ -24,6 +27,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.INotificationManager;
import android.app.role.RoleManager; import android.app.role.RoleManager;
import android.app.usage.UsageEvents; import android.app.usage.UsageEvents;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
@@ -33,6 +37,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.os.Parcel; import android.os.Parcel;
import android.provider.Settings;
import com.android.settings.notification.NotificationBackend.AppRow; import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -63,11 +68,16 @@ public class NotificationBackendTest {
@Mock @Mock
CachedBluetoothDeviceManager mCbm; CachedBluetoothDeviceManager mCbm;
ComponentName mCn = new ComponentName("a", "b"); ComponentName mCn = new ComponentName("a", "b");
@Mock
INotificationManager mInm;
NotificationBackend mNotificationBackend;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
when(mBm.getCachedDeviceManager()).thenReturn(mCbm); when(mBm.getCachedDeviceManager()).thenReturn(mCbm);
mNotificationBackend = new NotificationBackend();
mNotificationBackend.setNm(mInm);
} }
@Test @Test
@@ -101,6 +111,46 @@ public class NotificationBackendTest {
assertTrue(appRow.systemApp); assertTrue(appRow.systemApp);
} }
@Test
public void testMarkAppRow_fixedPermission() throws Exception {
Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
PackageInfo pi = new PackageInfo();
pi.packageName = "test";
pi.applicationInfo = new ApplicationInfo();
pi.applicationInfo.packageName = "test";
pi.applicationInfo.uid = 123;
when(mInm.isPermissionFixed(pi.packageName, 0)).thenReturn(true);
AppRow appRow = new NotificationBackend().loadAppRow(RuntimeEnvironment.application,
mock(PackageManager.class), mock(RoleManager.class), pi);
assertTrue(appRow.systemApp);
assertTrue(appRow.lockedImportance);
}
@Test
public void testMarkAppRow_notFixedPermission() throws Exception {
Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
PackageInfo pi = new PackageInfo();
pi.packageName = "test";
pi.applicationInfo = new ApplicationInfo();
pi.applicationInfo.packageName = "test";
pi.applicationInfo.uid = 123;
when(mInm.isPermissionFixed(pi.packageName, 0)).thenReturn(false);
AppRow appRow = new NotificationBackend().loadAppRow(RuntimeEnvironment.application,
mock(PackageManager.class), mock(RoleManager.class), pi);
assertFalse(appRow.systemApp);
assertFalse(appRow.lockedImportance);
}
@Test @Test
public void testMarkAppRow_notDefaultPackage() { public void testMarkAppRow_notDefaultPackage() {
PackageInfo pi = new PackageInfo(); PackageInfo pi = new PackageInfo();

View File

@@ -165,20 +165,6 @@ public class AllowSoundPreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void testUpdateState_notBlockable_oem() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn("");
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(mContext);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void testUpdateState_configurable() { public void testUpdateState_configurable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -217,20 +217,6 @@ public class BadgePreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void testUpdateState_channelNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn("");
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(mContext);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void testUpdateState_channel() { public void testUpdateState_channel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -200,68 +200,40 @@ public class BlockPreferenceControllerTest {
} }
@Test @Test
public void testIsEnabled_lockedApp() { public void testIsEnabled_cannotBlockAppOrGroupOrChannel() {
mController.setOverrideCanBlock(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
appRow.systemApp = true;
mController.onResume(appRow, null, null, null, null, null, null); mController.onResume(appRow, null, null, null, null, null, null);
mController.updateState(mPreference); mController.updateState(mPreference);
assertFalse(mPreference.getSwitchBar().isEnabled()); assertFalse(mPreference.getSwitchBar().isEnabled());
} }
@Test @Test
public void testIsEnabled_GroupNotBlockable() { public void testIsEnabled_importanceLocked_app() {
mController.setOverrideCanConfigure(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
mController.onResume(appRow, null, mock(NotificationChannelGroup.class), null, null, null,
null);
mController.updateState(mPreference);
assertFalse(mPreference.getSwitchBar().isEnabled());
}
@Test
public void testIsEnabled_systemAppNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
mController.onResume(appRow, null, null, null, null, null, null); mController.onResume(appRow, null, null, null, null, null, null);
mController.updateState(mPreference); mController.updateState(mPreference);
assertFalse(mPreference.getSwitchBar().isEnabled()); assertFalse(mPreference.getSwitchBar().isEnabled());
} }
@Test @Test
public void testIsEnabled_systemAppBlockable() { public void testIsEnabled_importanceLocked_group() {
mController.setOverrideCanConfigure(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true; mController.onResume(
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT); appRow, null, new NotificationChannelGroup("a", "a"), null, null, null, null);
channel.setBlockable(true);
mController.onResume(appRow, channel, null, null, null, null, null);
mController.updateState(mPreference); mController.updateState(mPreference);
assertTrue(mPreference.getSwitchBar().isEnabled());
}
@Test
public void testIsEnabled_lockedChannel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null);
mController.updateState(mPreference);
assertFalse(mPreference.getSwitchBar().isEnabled()); assertFalse(mPreference.getSwitchBar().isEnabled());
} }
@Test @Test
public void testIsEnabled_defaultAppChannel() { public void testIsEnabled_importanceLocked_channel() {
mController.setOverrideCanConfigure(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); mController.onResume(appRow, new NotificationChannel("a", "a", IMPORTANCE_LOW), null, null,
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true); null, null, null);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null);
mController.updateState(mPreference); mController.updateState(mPreference);
assertFalse(mPreference.getSwitchBar().isEnabled()); assertFalse(mPreference.getSwitchBar().isEnabled());
} }

View File

@@ -297,21 +297,6 @@ public class BubblePreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void updateState_channel_channelNotBlockable() {
Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.pkg = "a";
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(mContext);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void updateState_channel() { public void updateState_channel() {
Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);

View File

@@ -146,9 +146,9 @@ public class ConversationPriorityPreferenceControllerTest {
@Test @Test
public void testUpdateState_notConfigurable() { public void testUpdateState_notConfigurable() {
mController.setOverrideCanConfigure(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);
@@ -159,26 +159,10 @@ public class ConversationPriorityPreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_systemButConfigurable() { public void testUpdateState_Configurable() {
mController.setOverrideCanConfigure(true);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(false);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new ConversationPriorityPreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test
public void testUpdateState_defaultApp() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);

View File

@@ -138,8 +138,8 @@ public class DndPreferenceControllerTest {
@Test @Test
public void testUpdateState_notBlockable() { public void testUpdateState_notBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application); Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);

View File

@@ -166,9 +166,9 @@ public class HighImportancePreferenceControllerTest {
@Test @Test
public void testUpdateState_notConfigurable() { public void testUpdateState_notConfigurable() {
mController.setOverrideCanConfigure(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);
@@ -179,26 +179,10 @@ public class HighImportancePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_systemButConfigurable() { public void testUpdateState_Configurable() {
mController.setOverrideCanConfigure(true);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(false);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test
public void testUpdateState_defaultApp() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);

View File

@@ -183,9 +183,9 @@ public class ImportancePreferenceControllerTest {
@Test @Test
public void testUpdateState_notConfigurable() { public void testUpdateState_notConfigurable() {
mController.setOverrideCanConfigure(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);
@@ -196,26 +196,10 @@ public class ImportancePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_systemButConfigurable() { public void testUpdateState_Configurable() {
mController.setOverrideCanConfigure(true);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(false);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new ImportancePreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test
public void testUpdateState_defaultApp() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);

View File

@@ -181,19 +181,6 @@ public class LightsPreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void testUpdateState_notBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(mContext);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void testUpdateState_lightsOn() { public void testUpdateState_lightsOn() {
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);

View File

@@ -166,9 +166,9 @@ public class MinImportancePreferenceControllerTest {
@Test @Test
public void testUpdateState_notConfigurable() { public void testUpdateState_notConfigurable() {
mController.setOverrideCanConfigure(false);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);
@@ -179,26 +179,11 @@ public class MinImportancePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_systemButConfigurable() { public void testUpdateState_Configurable() {
mController.setOverrideCanConfigure(true);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(false); when(channel.isBlockable()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test
public void testUpdateState_defaultApp() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);

View File

@@ -22,6 +22,7 @@ import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.os.UserHandle.USER_SYSTEM;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@@ -38,6 +39,7 @@ import android.app.NotificationChannelGroup;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -221,6 +223,109 @@ public class NotificationPreferenceControllerTest {
verify(mBackend, times(1)).updateChannel(any(), anyInt(), any()); verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
} }
@Test
public void testIsChannelBlockable_postMigration_locked() {
Settings.Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
mController = new TestPreferenceController(mContext, mBackend);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null);
assertFalse(mController.isChannelBlockable());
}
@Test
public void testIsChannelBlockable_postMigration_locked_butChannelOff() {
Settings.Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
mController = new TestPreferenceController(mContext, mBackend);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
mController.onResume(appRow, channel, null, null, null, null, null);
assertTrue(mController.isChannelBlockable());
}
@Test
public void testIsChannelBlockable_postMigration_locked_butChannelBlockable() {
Settings.Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
mController = new TestPreferenceController(mContext, mBackend);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isBlockable()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null, null);
assertTrue(mController.isChannelBlockable());
}
@Test
public void testIsChannelGroupBlockable_postMigration_locked() {
Settings.Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
mController = new TestPreferenceController(mContext, mBackend);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
NotificationChannelGroup channelGroup = mock(NotificationChannelGroup.class);
mController.onResume(appRow, null, channelGroup, null, null, null, null);
assertFalse(mController.isChannelGroupBlockable());
}
@Test
public void testIsChannelGroupBlockable_postMigration_locked_butChannelGroupOff() {
Settings.Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
mController = new TestPreferenceController(mContext, mBackend);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
NotificationChannelGroup channelGroup = mock(NotificationChannelGroup.class);
when(channelGroup.isBlocked()).thenReturn(true);
mController.onResume(appRow, null, channelGroup, null, null, null, null);
assertTrue(mController.isChannelGroupBlockable());
}
@Test
public void testIsAppBlockable_postMigration_locked() {
Settings.Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
mController = new TestPreferenceController(mContext, mBackend);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
appRow.banned = false;
mController.onResume(appRow, null, null, null, null, null, null);
assertFalse(mController.isAppBlockable());
}
@Test
public void testIsAppBlockable_postMigration_locked_butAppOff() {
Settings.Secure.putIntForUser(RuntimeEnvironment.application.getContentResolver(),
Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 1, USER_SYSTEM);
mController = new TestPreferenceController(mContext, mBackend);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
appRow.banned = true;
mController.onResume(appRow, null, null, null, null, null, null);
assertFalse(mController.isAppBlockable());
}
@Test @Test
public void testIsBlockable_oemAllowlist() { public void testIsBlockable_oemAllowlist() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -182,20 +182,6 @@ public class SoundPreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void testUpdateState_notBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null, null, null, null);
AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
Preference pref = new NotificationSoundPreference(mContext, attributeSet);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void testUpdateState_configurable() { public void testUpdateState_configurable() {
Uri sound = Settings.System.DEFAULT_ALARM_ALERT_URI; Uri sound = Settings.System.DEFAULT_ALARM_ALERT_URI;

View File

@@ -162,10 +162,9 @@ public class VibrationPreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_notBlockable() { public void testUpdateState_blockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null, null, null, null); mController.onResume(appRow, channel, null, null, null, null, null);
Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application); Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);