Fix visibility and editability of importance fields

- Block field should always be visible
- Locked by OEM: cannot block or change importance
- Locked by default app: cannot block, can change importance
- Locked by system app: cannot block, can change importance
- system app but blockable: can block, can change importance

Test: robotests
Fixes: 131248127
Change-Id: Ifa718c84573dd5125aefa4f672a79dc4f267d515
This commit is contained in:
Julia Reynolds
2019-04-26 12:56:50 -04:00
parent 2f2a3c4055
commit a540fa56d4
24 changed files with 293 additions and 194 deletions

View File

@@ -459,7 +459,7 @@ public class NotificationChannelSlice implements CustomSliceable {
private boolean isChannelConfigurable(NotificationChannel channel, private boolean isChannelConfigurable(NotificationChannel channel,
NotificationBackend.AppRow appRow) { NotificationBackend.AppRow appRow) {
if (channel != null && appRow != null) { if (channel != null && appRow != null) {
return !TextUtils.equals(channel.getId(), appRow.lockedChannelId); return !channel.isImportanceLockedByOEM();
} }
return false; return false;

View File

@@ -16,6 +16,7 @@
package com.android.settings.homepage.contextualcards.slices; package com.android.settings.homepage.contextualcards.slices;
import android.app.role.RoleManager;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
@@ -46,7 +47,7 @@ class NotificationMultiChannelAppRow implements Callable<NotificationBackend.App
mPackageInfo.applicationInfo.packageName, mPackageInfo.applicationInfo.uid); mPackageInfo.applicationInfo.packageName, mPackageInfo.applicationInfo.uid);
if (channelCount > 1) { if (channelCount > 1) {
return mNotificationBackend.loadAppRow(mContext, mContext.getPackageManager(), return mNotificationBackend.loadAppRow(mContext, mContext.getPackageManager(),
mPackageInfo); mContext.getSystemService(RoleManager.class), mPackageInfo);
} }
return null; return null;
} }

View File

@@ -54,13 +54,7 @@ public class BlockPreferenceController extends NotificationPreferenceController
if (mAppRow == null) { if (mAppRow == null) {
return false; return false;
} }
if (mChannel != null) { return true;
return isChannelBlockable();
} else if (mChannelGroup != null) {
return isChannelGroupBlockable();
} else {
return !mAppRow.systemApp || (mAppRow.systemApp && mAppRow.banned);
}
} }
public void updateState(Preference preference) { public void updateState(Preference preference) {
@@ -78,6 +72,19 @@ public class BlockPreferenceController extends NotificationPreferenceController
} }
bar.setDisabledByAdmin(mAdmin); bar.setDisabledByAdmin(mAdmin);
if (mChannel != null && !isChannelBlockable()) {
bar.setEnabled(false);
}
if (mChannelGroup != null && !isChannelGroupBlockable()) {
bar.setEnabled(false);
}
if (mChannel == null && mAppRow.systemApp
&& (!mAppRow.banned || mAppRow.lockedImportance)) {
bar.setEnabled(false);
}
if (mChannel != null) { if (mChannel != null) {
bar.setChecked(!mAppRow.banned bar.setChecked(!mAppRow.banned
&& mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE); && mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);

View File

@@ -62,7 +62,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 && isChannelBlockable()); preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
pref.setChecked(mChannel.getImportance() >= IMPORTANCE_HIGH); pref.setChecked(mChannel.getImportance() >= IMPORTANCE_HIGH);

View File

@@ -59,9 +59,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 && isChannelBlockable()); preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());
ImportancePreference pref = (ImportancePreference) preference; ImportancePreference pref = (ImportancePreference) preference;
pref.setConfigurable(isChannelBlockable()); pref.setConfigurable(!mChannel.isImportanceLockedByOEM());
pref.setImportance(mChannel.getImportance()); pref.setImportance(mChannel.getImportance());
pref.setDisplayInStatusBar(mBackend.showSilentInStatusBar(mContext.getPackageName())); pref.setDisplayInStatusBar(mBackend.showSilentInStatusBar(mContext.getPackageName()));
// TODO: b/128445911 pass along lock screen setting // TODO: b/128445911 pass along lock screen setting

View File

@@ -62,7 +62,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 && isChannelBlockable()); preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference; RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
pref.setChecked(mChannel.getImportance() == IMPORTANCE_MIN); pref.setChecked(mChannel.getImportance() == IMPORTANCE_MIN);

View File

@@ -21,6 +21,7 @@ import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import android.app.INotificationManager; import android.app.INotificationManager;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationChannelGroup; import android.app.NotificationChannelGroup;
import android.app.role.RoleManager;
import android.app.usage.IUsageStatsManager; import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents; import android.app.usage.UsageEvents;
import android.content.ComponentName; import android.content.ComponentName;
@@ -86,14 +87,22 @@ public class NotificationBackend {
return !systemApp || (systemApp && blocked); return !systemApp || (systemApp && blocked);
} }
public AppRow loadAppRow(Context context, PackageManager pm, PackageInfo app) { public AppRow loadAppRow(Context context, PackageManager pm,
RoleManager roleManager, PackageInfo app) {
final AppRow row = loadAppRow(context, pm, app.applicationInfo); final AppRow row = loadAppRow(context, pm, app.applicationInfo);
recordCanBeBlocked(context, pm, app, row); recordCanBeBlocked(context, pm, roleManager, app, row);
return row; return row;
} }
void recordCanBeBlocked(Context context, PackageManager pm, PackageInfo app, AppRow row) { void recordCanBeBlocked(Context context, PackageManager pm, RoleManager rm, PackageInfo app,
AppRow row) {
row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app); row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app);
List<String> roles = rm.getHeldRolesFromController(app.packageName);
if (roles.contains(RoleManager.ROLE_SMS)
|| roles.contains(RoleManager.ROLE_DIALER)
|| roles.contains(RoleManager.ROLE_EMERGENCY)) {
row.systemApp = true;
}
final String[] nonBlockablePkgs = context.getResources().getStringArray( final String[] nonBlockablePkgs = context.getResources().getStringArray(
com.android.internal.R.array.config_nonBlockableNotificationPackages); com.android.internal.R.array.config_nonBlockableNotificationPackages);
markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName); markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName);
@@ -108,10 +117,8 @@ public class NotificationBackend {
if (pkg == null) { if (pkg == null) {
continue; continue;
} else if (pkg.contains(":")) { } else if (pkg.contains(":")) {
// Interpret as channel; lock only this channel for this app. // handled by NotificationChannel.isImportanceLockedByOEM()
if (packageName.equals(pkg.split(":", 2)[0])) { continue;
row.lockedChannelId = pkg.split(":", 2 )[1];
}
} else if (packageName.equals(nonBlockablePkgs[i])) { } else if (packageName.equals(nonBlockablePkgs[i])) {
row.systemApp = row.lockedImportance = true; row.systemApp = row.lockedImportance = true;
} }
@@ -123,8 +130,9 @@ public class NotificationBackend {
try { try {
PackageInfo info = context.getPackageManager().getPackageInfo( PackageInfo info = context.getPackageManager().getPackageInfo(
app.packageName, PackageManager.GET_SIGNATURES); app.packageName, PackageManager.GET_SIGNATURES);
RoleManager rm = context.getSystemService(RoleManager.class);
final AppRow row = new AppRow(); final AppRow row = new AppRow();
recordCanBeBlocked(context, context.getPackageManager(), info, row); recordCanBeBlocked(context, context.getPackageManager(), rm, info, row);
return row.systemApp; return row.systemApp;
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
@@ -491,7 +499,6 @@ public class NotificationBackend {
public boolean first; // first app in section public boolean first; // first app in section
public boolean systemApp; public boolean systemApp;
public boolean lockedImportance; public boolean lockedImportance;
public String lockedChannelId;
public boolean showBadge; public boolean showBadge;
public boolean allowBubbles; public boolean allowBubbles;
public int userId; public int userId;

View File

@@ -110,27 +110,13 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
} }
} }
private boolean isChannelConfigurable() {
if (mAppRow != null && mAppRow.lockedImportance) {
return false;
}
if (mChannel != null && mAppRow != null) {
return !Objects.equals(mChannel.getId(), mAppRow.lockedChannelId);
}
return false;
}
protected boolean isChannelBlockable() { protected boolean isChannelBlockable() {
if (mChannel != null && mAppRow != null) { if (mChannel != null && mAppRow != null) {
if (!isChannelConfigurable()) { if (mChannel.isImportanceLockedByCriticalDeviceFunction()
|| mChannel.isImportanceLockedByOEM()) {
return mChannel.getImportance() == IMPORTANCE_NONE; return mChannel.getImportance() == IMPORTANCE_NONE;
} }
if (mChannel.isImportanceLockedByOEM()
|| mChannel.isImportanceLockedByCriticalDeviceFunction()) {
return false;
}
return mChannel.isBlockableSystem() || !mAppRow.systemApp return mChannel.isBlockableSystem() || !mAppRow.systemApp
|| mChannel.getImportance() == IMPORTANCE_NONE; || mChannel.getImportance() == IMPORTANCE_NONE;
} }

View File

@@ -25,6 +25,7 @@ import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationChannelGroup; import android.app.NotificationChannelGroup;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.role.RoleManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -36,7 +37,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.graphics.BlendMode; import android.graphics.BlendMode;
import android.graphics.BlendModeColorFilter; import android.graphics.BlendModeColorFilter;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.LayerDrawable;
@@ -71,6 +71,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
protected PackageManager mPm; protected PackageManager mPm;
protected NotificationBackend mBackend = new NotificationBackend(); protected NotificationBackend mBackend = new NotificationBackend();
protected NotificationManager mNm; protected NotificationManager mNm;
protected RoleManager mRm;
protected Context mContext; protected Context mContext;
protected int mUid; protected int mUid;
@@ -101,6 +102,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
mPm = getPackageManager(); mPm = getPackageManager();
mNm = NotificationManager.from(mContext); mNm = NotificationManager.from(mContext);
mRm = mContext.getSystemService(RoleManager.class);
mPkg = mArgs != null && mArgs.containsKey(AppInfoBase.ARG_PACKAGE_NAME) mPkg = mArgs != null && mArgs.containsKey(AppInfoBase.ARG_PACKAGE_NAME)
? mArgs.getString(AppInfoBase.ARG_PACKAGE_NAME) ? mArgs.getString(AppInfoBase.ARG_PACKAGE_NAME)
@@ -195,7 +197,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
} }
private void loadAppRow() { private void loadAppRow() {
mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo); mAppRow = mBackend.loadAppRow(mContext, mPm, mRm, mPkgInfo);
} }
private void loadChannelGroup() { private void loadChannelGroup() {
@@ -342,7 +344,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
protected boolean isChannelConfigurable(NotificationChannel channel) { protected boolean isChannelConfigurable(NotificationChannel channel) {
if (channel != null && mAppRow != null) { if (channel != null && mAppRow != null) {
return !channel.getId().equals(mAppRow.lockedChannelId); return !channel.isImportanceLockedByOEM();
} }
return false; return false;
} }
@@ -353,6 +355,14 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
return true; return true;
} }
if (channel.isImportanceLockedByCriticalDeviceFunction()) {
return false;
}
if (channel.isImportanceLockedByOEM()) {
return false;
}
return channel.isBlockableSystem() return channel.isBlockableSystem()
|| channel.getImportance() == NotificationManager.IMPORTANCE_NONE; || channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
} }

View File

@@ -30,6 +30,7 @@ import static org.robolectric.Shadows.shadowOf;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationChannelGroup; import android.app.NotificationChannelGroup;
import android.app.role.RoleManager;
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.PackageInfo;
@@ -345,7 +346,7 @@ public class NotificationChannelSliceTest {
doReturn(buildNotificationChannelGroups(channels)).when(mNotificationBackend).getGroups( doReturn(buildNotificationChannelGroups(channels)).when(mNotificationBackend).getGroups(
any(String.class), any(int.class)); any(String.class), any(int.class));
doReturn(appRow).when(mNotificationBackend).loadAppRow(any(Context.class), doReturn(appRow).when(mNotificationBackend).loadAppRow(any(Context.class),
any(PackageManager.class), any(PackageInfo.class)); any(PackageManager.class), any(RoleManager.class), any(PackageInfo.class));
doReturn(channelCount).when(mNotificationBackend).getChannelCount( doReturn(channelCount).when(mNotificationBackend).getChannelCount(
any(String.class), any(int.class)); any(String.class), any(int.class));
} }

View File

@@ -21,6 +21,7 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.app.role.RoleManager;
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.PackageInfo;
@@ -65,7 +66,7 @@ public class NotificationMultiChannelAppRowTest {
mNotificationMultiChannelAppRow.call(); mNotificationMultiChannelAppRow.call();
verify(mNotificationBackend).loadAppRow(any(Context.class), any(PackageManager.class), verify(mNotificationBackend).loadAppRow(any(Context.class), any(PackageManager.class),
any(PackageInfo.class)); any(RoleManager.class), any(PackageInfo.class));
} }
@Test @Test
@@ -76,6 +77,6 @@ public class NotificationMultiChannelAppRowTest {
mNotificationMultiChannelAppRow.call(); mNotificationMultiChannelAppRow.call();
verify(mNotificationBackend, never()).loadAppRow(any(Context.class), verify(mNotificationBackend, never()).loadAppRow(any(Context.class),
any(PackageManager.class), any(PackageInfo.class)); any(PackageManager.class), any(RoleManager.class), any(PackageInfo.class));
} }
} }

View File

@@ -139,12 +139,11 @@ public class AllowSoundPreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_notBlockable() { public void testUpdateState_notBlockable_oem() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.getId()).thenReturn("");
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(mContext); Preference pref = new RestrictedSwitchPreference(mContext);

View File

@@ -188,11 +188,10 @@ public class BadgePreferenceControllerTest {
@Test @Test
public void testUpdateState_channelNotBlockable() { public void testUpdateState_channelNotBlockable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.getId()).thenReturn("");
when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(mContext); Preference pref = new RestrictedSwitchPreference(mContext);
@@ -204,7 +203,6 @@ public class BadgePreferenceControllerTest {
@Test @Test
public void testUpdateState_channel() { public void testUpdateState_channel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = "a";
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.canShowBadge()).thenReturn(true); when(channel.canShowBadge()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);

View File

@@ -101,23 +101,23 @@ public class BlockPreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_notIfChannelNotBlockable() { public void testIsAvailable_channelNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true; appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
assertFalse(mController.isAvailable()); assertTrue(mController.isAvailable());
} }
@Test @Test
public void testIsAvailable_notIfChannelNonDefault() { public void testIsAvailable_channelNonDefault() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true; appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
assertFalse(mController.isAvailable()); assertTrue(mController.isAvailable());
} }
@Test @Test
@@ -131,19 +131,19 @@ public class BlockPreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_notIfGroupNotBlockable() { public void testIsAvailable_GroupNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true; appRow.systemApp = true;
mController.onResume(appRow, null, mock(NotificationChannelGroup.class), null); mController.onResume(appRow, null, mock(NotificationChannelGroup.class), null);
assertFalse(mController.isAvailable()); assertTrue(mController.isAvailable());
} }
@Test @Test
public void testIsAvailable_notIfAppNotBlockable() { public void testIsAvailable_AppNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true; appRow.systemApp = true;
mController.onResume(appRow, null, null, null); mController.onResume(appRow, null, null, null);
assertFalse(mController.isAvailable()); assertTrue(mController.isAvailable());
} }
@Test @Test
@@ -160,13 +160,99 @@ public class BlockPreferenceControllerTest {
public void testIsAvailable_nonSystemApp() { public void testIsAvailable_nonSystemApp() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = false; appRow.systemApp = false;
appRow.lockedChannelId = "not this";
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
assertTrue(mController.isAvailable()); assertTrue(mController.isAvailable());
} }
@Test
public void testIsEnabled_lockedApp() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedImportance = true;
appRow.systemApp = true;
mController.onResume(appRow, null, null, null);
mController.updateState(mPreference);
assertFalse(mSwitch.isEnabled());
}
@Test
public void testIsEnabled_GroupNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
mController.onResume(appRow, null, mock(NotificationChannelGroup.class), null);
mController.updateState(mPreference);
assertFalse(mSwitch.isEnabled());
}
@Test
public void testIsEnabled_systemAppNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
mController.onResume(appRow, null, null, null);
mController.updateState(mPreference);
assertFalse(mSwitch.isEnabled());
}
@Test
public void testIsEnabled_systemAppBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
channel.setBlockableSystem(true);
mController.onResume(appRow, channel, null, null);
mController.updateState(mPreference);
assertTrue(mSwitch.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);
mController.updateState(mPreference);
assertFalse(mSwitch.isEnabled());
}
@Test
public void testIsEnabled_defaultAppChannel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null);
mController.updateState(mPreference);
assertFalse(mSwitch.isEnabled());
}
@Test
public void testIsEnabled_channel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null);
mController.updateState(mPreference);
assertTrue(mSwitch.isEnabled());
}
@Test
public void testIsEnabled_app() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
mController.onResume(appRow, null, null, null);
mController.updateState(mPreference);
assertTrue(mSwitch.isEnabled());
}
@Test @Test
public void testUpdateState_app() { public void testUpdateState_app() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -203,11 +203,9 @@ public class BubblePreferenceControllerTest {
@Test @Test
public void testUpdateState_channelNotBlockable() { public void testUpdateState_channelNotBlockable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(mContext); Preference pref = new RestrictedSwitchPreference(mContext);
@@ -219,7 +217,6 @@ public class BubblePreferenceControllerTest {
@Test @Test
public void testUpdateState_channel() { public void testUpdateState_channel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = "a";
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.canBubble()).thenReturn(true); when(channel.canBubble()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);

View File

@@ -111,11 +111,9 @@ public class DndPreferenceControllerTest {
@Test @Test
public void testUpdateState_notBlockable() { public void testUpdateState_notBlockable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application); Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);

View File

@@ -142,11 +142,9 @@ public class HighImportancePreferenceControllerTest {
@Test @Test
public void testUpdateState_notConfigurable() { public void testUpdateState_notConfigurable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
@@ -156,6 +154,36 @@ public class HighImportancePreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void testUpdateState_systemButConfigurable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(false);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, 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);
mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void testUpdateState_high() { public void testUpdateState_high() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -159,11 +159,9 @@ public class ImportancePreferenceControllerTest {
@Test @Test
public void testUpdateState_notConfigurable() { public void testUpdateState_notConfigurable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
@@ -173,6 +171,36 @@ public class ImportancePreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void testUpdateState_systemButConfigurable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(false);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, 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);
mController.onResume(appRow, channel, null, null);
Preference pref = new ImportancePreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void testUpdateState() { public void testUpdateState() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -159,11 +159,9 @@ public class LightsPreferenceControllerTest {
@Test @Test
public void testUpdateState_notBlockable() { public void testUpdateState_notBlockable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(mContext); Preference pref = new RestrictedSwitchPreference(mContext);

View File

@@ -142,11 +142,9 @@ public class MinImportancePreferenceControllerTest {
@Test @Test
public void testUpdateState_notConfigurable() { public void testUpdateState_notConfigurable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
@@ -156,6 +154,36 @@ public class MinImportancePreferenceControllerTest {
assertFalse(pref.isEnabled()); assertFalse(pref.isEnabled());
} }
@Test
public void testUpdateState_systemButConfigurable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.isImportanceLockedByOEM()).thenReturn(false);
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
mController.onResume(appRow, channel, 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);
mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test @Test
public void testUpdateState_min() { public void testUpdateState_min() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -18,22 +18,28 @@ package com.android.settings.notification;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.role.RoleManager;
import android.app.usage.UsageEvents; import android.app.usage.UsageEvents;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Parcel; import android.os.Parcel;
import com.android.settings.notification.NotificationBackend.AppRow; import com.android.settings.notification.NotificationBackend.AppRow;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class NotificationBackendTest { public class NotificationBackendTest {
@@ -50,81 +56,40 @@ public class NotificationBackendTest {
// This package has a package lock but no locked channels // This package has a package lock but no locked channels
assertTrue(appRow.lockedImportance); assertTrue(appRow.lockedImportance);
assertNull(appRow.lockedChannelId);
} }
@Test @Test
public void testMarkAppRow_unblockableChannelOrPkg() { public void testMarkAppRow_defaultPackage() {
String channelBlockName = "foo.bar.pkgWithChannel"; PackageInfo pi = new PackageInfo();
String pkgBlockName = "foo.bar.pkgBlock"; pi.packageName = "test";
String[] nonBlockablePkgs = new String[2]; pi.applicationInfo = new ApplicationInfo();
nonBlockablePkgs[0] = pkgBlockName; pi.applicationInfo.packageName = "test";
nonBlockablePkgs[1] = channelBlockName + ":SpecificChannel"; List<String> roles = new ArrayList<>();
roles.add(RoleManager.ROLE_DIALER);
RoleManager rm = mock(RoleManager.class);
when(rm.getHeldRolesFromController(anyString())).thenReturn(roles);
// This package has a channel level lock but no full package lock AppRow appRow = new NotificationBackend().loadAppRow(RuntimeEnvironment.application,
AppRow channelBlockApp = new AppRow(); mock(PackageManager.class), rm, pi);
channelBlockApp.pkg = channelBlockName;
NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, channelBlockApp,
channelBlockName);
assertFalse(channelBlockApp.lockedImportance);
assertEquals("SpecificChannel", channelBlockApp.lockedChannelId);
// This other package has the reverse assertTrue(appRow.systemApp);
AppRow pkgBlock = new AppRow();
pkgBlock.pkg = pkgBlockName;
NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, pkgBlock, pkgBlockName);
assertTrue(pkgBlock.lockedImportance);
assertNull(pkgBlock.lockedChannelId);
// This third package has no locks at all
AppRow otherAppRow = new AppRow();
otherAppRow.pkg ="foo.bar.nothingBlocked";
NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, otherAppRow,
"foo.bar.nothingBlocked");
assertFalse(otherAppRow.lockedImportance);
assertNull(otherAppRow.lockedChannelId);
} }
@Test @Test
public void testMarkAppRow_unblockableChannelAndPkg() { public void testMarkAppRow_notDefaultPackage() {
AppRow appRow = new AppRow(); PackageInfo pi = new PackageInfo();
String packageName = "foo.bar.unblockable"; pi.packageName = "test";
appRow.pkg = packageName; pi.applicationInfo = new ApplicationInfo();
String[] nonBlockablePkgs = new String[2]; pi.applicationInfo.packageName = "test";
nonBlockablePkgs[0] = "foo.bar.unblockable"; List<String> roles = new ArrayList<>();
nonBlockablePkgs[1] = "foo.bar.unblockable:SpecificChannel"; roles.add(RoleManager.ROLE_HOME);
NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName); RoleManager rm = mock(RoleManager.class);
when(rm.getHeldRolesFromController(anyString())).thenReturn(roles);
// This package has both a channel lock and a package lock AppRow appRow = new NotificationBackend().loadAppRow(RuntimeEnvironment.application,
assertTrue(appRow.lockedImportance); mock(PackageManager.class), rm, pi);
assertEquals("SpecificChannel", appRow.lockedChannelId);
}
@Test assertFalse(appRow.systemApp);
public void testMarkAppRow_channelNameWithColons() {
AppRow appRow = new AppRow();
String packageName = "foo.bar.unblockable";
String channelName = "SpecificChannel:1234:abc:defg";
appRow.pkg = packageName;
String[] nonBlockablePkgs = new String[1];
nonBlockablePkgs[0] = packageName + ":" + channelName;
NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName);
assertEquals(channelName, appRow.lockedChannelId);
}
@Test
public void testMarkAppRow_blocklistWithNullEntries() {
AppRow appRow = new AppRow();
String packageName = "foo.bar.unblockable";
appRow.pkg = packageName;
String[] nonBlockablePkgs = new String[6]; // extra long list with some entries left null
nonBlockablePkgs[2] = "foo.bar.unblockable";
nonBlockablePkgs[4] = "foo.bar.unblockable:SpecificChannel";
NotificationBackend.markAppRowWithBlockables(nonBlockablePkgs, appRow, packageName);
assertTrue(appRow.lockedImportance);
assertEquals("SpecificChannel", appRow.lockedChannelId);
} }
@Test @Test

View File

@@ -203,36 +203,29 @@ public class NotificationPreferenceControllerTest {
} }
@Test @Test
public void testIsBlockable_channelLevelWhitelist() { public void testIsBlockable_oemWhitelist() {
String sameId = "bananas";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = sameId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(sameId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
assertFalse(mController.isChannelBlockable()); assertFalse(mController.isChannelBlockable());
when(channel.getId()).thenReturn("something new"); when(channel.isImportanceLockedByOEM()).thenReturn(false);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
assertTrue(mController.isChannelBlockable()); assertTrue(mController.isChannelBlockable());
} }
@Test @Test
public void testIsBlockable_appLevelWhitelist() { public void testIsBlockable_defaultApp() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = "something";
appRow.lockedImportance = true;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW); when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
assertFalse(mController.isChannelBlockable()); assertFalse(mController.isChannelBlockable());
appRow.lockedImportance = false;
mController.onResume(appRow, mock(NotificationChannel.class), null, null);
assertTrue(mController.isChannelBlockable());
} }
@Test @Test
@@ -281,34 +274,6 @@ public class NotificationPreferenceControllerTest {
assertTrue(mController.isChannelBlockable()); assertTrue(mController.isChannelBlockable());
} }
@Test
public void testIsChannelBlockable_notConfigurable() {
String sameId = "apples";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = false;
appRow.lockedChannelId = sameId;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(sameId);
when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
mController.onResume(appRow, channel, null, null);
assertFalse(mController.isChannelBlockable());
}
@Test
public void testIsChannelBlockable_notConfigurableButBlocked() {
String sameId = "apples";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = false;
appRow.lockedChannelId = sameId;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(sameId);
when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
mController.onResume(appRow, channel, null, null);
assertTrue(mController.isChannelBlockable());
}
@Test @Test
public void testIsChannelGroupBlockable_nonSystemBlockable() { public void testIsChannelGroupBlockable_nonSystemBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();

View File

@@ -162,11 +162,9 @@ public class SoundPreferenceControllerTest {
@Test @Test
public void testUpdateState_notBlockable() { public void testUpdateState_notBlockable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
AttributeSet attributeSet = Robolectric.buildAttributeSet().build(); AttributeSet attributeSet = Robolectric.buildAttributeSet().build();

View File

@@ -141,11 +141,9 @@ public class VibrationPreferenceControllerTest {
@Test @Test
public void testUpdateState_notBlockable() { public void testUpdateState_notBlockable() {
String lockedId = "locked";
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.lockedChannelId = lockedId;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(lockedId); when(channel.isImportanceLockedByOEM()).thenReturn(true);
mController.onResume(appRow, channel, null, null); mController.onResume(appRow, channel, null, null);
Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application); Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);