Apply restricted settings to notification access.

Bug: 202130031
Test: Able to boot without error
Test: When app is installed by PackageInstaller app, notification
access is being restricted. The restriction is being removed after
turing it restricted settings off for that app.

Change-Id: I9c1fbc80dd2ca4cc483a60dfa9d043aaa99cde87
This commit is contained in:
Ricky Wai
2022-02-09 15:32:57 +00:00
parent 5ff63a569c
commit d09d62a55e
4 changed files with 54 additions and 6 deletions

View File

@@ -26,7 +26,7 @@
android:layout="@layout/settings_entity_header" android:layout="@layout/settings_entity_header"
settings:controller="com.android.settings.applications.specialaccess.notificationaccess.HeaderPreferenceController"/> settings:controller="com.android.settings.applications.specialaccess.notificationaccess.HeaderPreferenceController"/>
<com.android.settings.widget.FilterTouchesSwitchPreference <com.android.settingslib.RestrictedSwitchPreference
android:key="notification_access_switch" android:key="notification_access_switch"
android:title="@string/notification_access_detail_switch" android:title="@string/notification_access_detail_switch"
settings:controller="com.android.settings.applications.specialaccess.notificationaccess.ApprovalPreferenceController"/> settings:controller="com.android.settings.applications.specialaccess.notificationaccess.ApprovalPreferenceController"/>

View File

@@ -27,10 +27,10 @@ import android.os.AsyncTask;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
public class ApprovalPreferenceController extends BasePreferenceController { public class ApprovalPreferenceController extends BasePreferenceController {
@@ -78,9 +78,11 @@ public class ApprovalPreferenceController extends BasePreferenceController {
@Override @Override
public void updateState(Preference pref) { public void updateState(Preference pref) {
final SwitchPreference preference = (SwitchPreference) pref; final RestrictedSwitchPreference preference =
(RestrictedSwitchPreference) pref;
final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm); final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm);
preference.setChecked(isServiceEnabled(mCn)); final boolean isEnabled = isServiceEnabled(mCn);
preference.setChecked(isEnabled);
preference.setOnPreferenceChangeListener((p, newValue) -> { preference.setOnPreferenceChangeListener((p, newValue) -> {
final boolean access = (Boolean) newValue; final boolean access = (Boolean) newValue;
if (!access) { if (!access) {
@@ -103,6 +105,7 @@ public class ApprovalPreferenceController extends BasePreferenceController {
return false; return false;
} }
}); });
preference.updateState(mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isEnabled);
} }
public void disable(final ComponentName cn) { public void disable(final ComponentName cn) {

View File

@@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeast;
@@ -31,6 +33,7 @@ import static java.util.Collections.singletonList;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityShortcutInfo; import android.accessibilityservice.AccessibilityShortcutInfo;
import android.app.AppOpsManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
@@ -110,6 +113,8 @@ public class AccessibilitySettingsTest {
@Mock @Mock
private PreferenceManager mPreferenceManager; private PreferenceManager mPreferenceManager;
private ShadowAccessibilityManager mShadowAccessibilityManager; private ShadowAccessibilityManager mShadowAccessibilityManager;
@Mock
private AppOpsManager mAppOpsManager;
@Before @Before
public void setup() { public void setup() {
@@ -121,6 +126,9 @@ public class AccessibilitySettingsTest {
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
mContext.setTheme(R.style.Theme_AppCompat); mContext.setTheme(R.style.Theme_AppCompat);
when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
when(mAppOpsManager.noteOpNoThrow(eq(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS),
anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ALLOWED);
} }
@Test @Test

View File

@@ -18,12 +18,15 @@ package com.android.settings.applications.specialaccess.notificationaccess;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@@ -31,12 +34,12 @@ 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 androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -55,6 +58,8 @@ public class ApprovalPreferenceControllerTest {
@Mock @Mock
NotificationManager mNm; NotificationManager mNm;
@Mock @Mock
AppOpsManager mAppOpsManager;
@Mock
PackageManager mPm; PackageManager mPm;
PackageInfo mPkgInfo; PackageInfo mPkgInfo;
ComponentName mCn = new ComponentName("a", "b"); ComponentName mCn = new ComponentName("a", "b");
@@ -75,15 +80,47 @@ public class ApprovalPreferenceControllerTest {
mController.setNm(mNm); mController.setNm(mNm);
mController.setParent(mFragment); mController.setParent(mFragment);
mController.setPkgInfo(mPkgInfo); mController.setPkgInfo(mPkgInfo);
} }
@Test @Test
public void updateState_checked() { public void updateState_checked() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ALLOWED);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true); when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
SwitchPreference pref = new SwitchPreference(mContext); RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
mContext);
pref.setAppOps(mAppOpsManager);
mController.updateState(pref); mController.updateState(pref);
assertThat(pref.isChecked()).isTrue(); assertThat(pref.isChecked()).isTrue();
assertThat(pref.isEnabled()).isTrue();
}
@Test
public void restrictedSettings_appOpsDisabled() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ERRORED);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(false);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
mContext);
pref.setAppOps(mAppOpsManager);
mController.updateState(pref);
assertThat(pref.isEnabled()).isFalse();
}
@Test
public void restrictedSettings_serviceAlreadyEnabled() {
when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
AppOpsManager.MODE_ERRORED);
when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
mContext);
pref.setAppOps(mAppOpsManager);
mController.updateState(pref);
assertThat(pref.isEnabled()).isTrue();
} }
@Test @Test