Adding Wifi setting to special_access settings

In the settings app, allow users to override app permission for
CHANGE_WIFI_STATE for every application that declared that permission.

Bug: 70562620
Test: compile, robotests

Manual test:
Flash build to device (walleye)
Download iPass from playstore
Open iPass and try connect to a wifi network; verify success
Open settings -> Apps & notifications -> Advanced -> Special app access
-> Wifi access
Select iPass from the list
Toggle the switch to off
Open iPass and try connect to a wifi network; verify failure

Change-Id: Ib2be4c83988a81ba7831d096c9b1980462e66903
This commit is contained in:
xshu
2018-01-31 17:40:37 -08:00
parent 87e71c96ea
commit 3f04897a19
11 changed files with 492 additions and 3 deletions

View File

@@ -9359,4 +9359,18 @@
<!-- Title for item to go to old battery settings page when clicking [CHAR LIMIT=100] -->
<string name="dev_android_o_battery_settings_title">See Android 8.0 battery settings</string>
<!-- Title for Wifi Access settings [CHAR LIMIT=35] -->
<string name="change_wifi_state_title">Toggle wifi on and off</string>
<!-- Keywords for Wifi Access settings [CHAR LIMIT=35] -->
<string name="keywords_change_wifi_state">toggle wifi on and off</string>
<!-- Apps > App Details > Advanced section string title. [CHAR LIMIT=35] -->
<string name="change_wifi_state_app_detail_title">Toggle wifi on and off</string>
<!-- Apps > App Details > Wifi access > Switch title. [CHAR LIMIT=NONE] -->
<string name="change_wifi_state_app_detail_switch">Allow toggle wifi</string>
<!-- Apps > App Details > Wifi access > Description. [CHAR LIMIT=NONE] -->
<string name="change_wifi_state_app_detail_summary">Allow this app to change wifi state including connecting to wifi and turing wifi on and off.</string>
</resources>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="change_wifi_state"
android:title="@string/change_wifi_state_app_detail_title">
<SwitchPreference
android:key="app_ops_settings_switch"
android:title="@string/change_wifi_state_app_detail_switch"/>
<Preference
android:key="app_ops_settings_preference"
android:summary="@string/change_wifi_state_app_detail_summary"
android:selectable="false"/>
</PreferenceScreen>

View File

@@ -121,4 +121,14 @@
android:value="com.android.settings.Settings$DirectoryAccessSettingsActivity" />
</Preference>
<Preference
android:key="change_wifi_state"
android:title="@string/change_wifi_state_title"
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
settings:keywords="@string/keywords_change_wifi_state">
<extra
android:name="classname"
android:value="com.android.settings.Settings$ChangeWifiStateActivity" />
</Preference>
</PreferenceScreen>

View File

@@ -128,6 +128,7 @@ public class Settings extends SettingsActivity {
public static class AppMemoryUsageActivity extends SettingsActivity { /* empty */ }
public static class OverlaySettingsActivity extends SettingsActivity { /* empty */ }
public static class WriteSettingsActivity extends SettingsActivity { /* empty */ }
public static class ChangeWifiStateActivity extends SettingsActivity { /* empty */ }
public static class AppDrawOverlaySettingsActivity extends SettingsActivity { /* empty */ }
public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ }
public static class AdvancedAppsActivity extends SettingsActivity { /* empty */ }

View File

@@ -26,6 +26,7 @@ import com.android.settings.applications.AppStatePowerBridge;
import com.android.settings.applications.AppStateDirectoryAccessBridge;
import com.android.settings.applications.AppStateUsageBridge;
import com.android.settings.applications.AppStateWriteSettingsBridge;
import com.android.settings.wifi.AppStateChangeWifiStateBridge;
import com.android.settingslib.applications.ApplicationsState;
/**
@@ -67,14 +68,15 @@ public class AppFilterRegistry {
public static final int FILTER_APPS_WRITE_SETTINGS = 11;
public static final int FILTER_APPS_INSTALL_SOURCES = 12;
public static final int FILTER_APP_HAS_DIRECTORY_ACCESS = 13;
// Next id: 14
public static final int FILTER_APP_CAN_CHANGE_WIFI_STATE = 14;
// Next id: 15
private static AppFilterRegistry sRegistry;
private final AppFilterItem[] mFilters;
private AppFilterRegistry() {
mFilters = new AppFilterItem[14];
mFilters = new AppFilterItem[15];
// High power whitelist, on
mFilters[FILTER_APPS_POWER_WHITELIST] = new AppFilterItem(
@@ -163,6 +165,11 @@ public class AppFilterRegistry {
AppStateDirectoryAccessBridge.FILTER_APP_HAS_DIRECTORY_ACCESS,
FILTER_APP_HAS_DIRECTORY_ACCESS,
R.string.filter_install_sources_apps);
mFilters[FILTER_APP_CAN_CHANGE_WIFI_STATE] = new AppFilterItem(
AppStateChangeWifiStateBridge.FILTER_CHANGE_WIFI_STATE,
FILTER_APP_CAN_CHANGE_WIFI_STATE,
R.string.filter_write_settings_apps);
}
public static AppFilterRegistry getInstance() {
@@ -187,6 +194,8 @@ public class AppFilterRegistry {
return FILTER_APPS_INSTALL_SOURCES;
case ManageApplications.LIST_TYPE_DIRECTORY_ACCESS:
return FILTER_APP_HAS_DIRECTORY_ACCESS;
case ManageApplications.LIST_TYPE_WIFI_ACCESS:
return FILTER_APP_CAN_CHANGE_WIFI_STATE;
default:
return FILTER_APPS_ALL;
}

View File

@@ -96,6 +96,8 @@ import com.android.settings.applications.appinfo.AppNotificationPreferenceContro
import com.android.settings.applications.appinfo.DrawOverlayDetails;
import com.android.settings.applications.appinfo.ExternalSourcesDetails;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.SummaryLoader;
@@ -105,6 +107,8 @@ import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.widget.LoadingViewController;
import com.android.settings.wifi.AppStateChangeWifiStateBridge;
import com.android.settings.wifi.ChangeWifiStateDetails;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -204,6 +208,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
public static final int LIST_TYPE_MOVIES = 10;
public static final int LIST_TYPE_PHOTOGRAPHY = 11;
public static final int LIST_TYPE_DIRECTORY_ACCESS = 12;
public static final int LIST_TYPE_WIFI_ACCESS = 13;
// List types that should show instant apps.
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
@@ -277,6 +282,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
} else if (className.equals(Settings.DirectoryAccessSettingsActivity.class.getName())) {
mListType = LIST_TYPE_DIRECTORY_ACCESS;
screenTitle = R.string.directory_access;
} else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) {
mListType = LIST_TYPE_WIFI_ACCESS;
screenTitle = R.string.change_wifi_state_title;
} else {
mListType = LIST_TYPE_MAIN;
}
@@ -443,6 +451,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
return MetricsEvent.MANAGE_EXTERNAL_SOURCES;
case LIST_TYPE_DIRECTORY_ACCESS:
return MetricsEvent.DIRECTORY_ACCESS;
case LIST_TYPE_WIFI_ACCESS:
return MetricsEvent.CONFIGURE_WIFI;
default:
return MetricsEvent.VIEW_UNKNOWN;
}
@@ -540,7 +550,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
case LIST_TYPE_DIRECTORY_ACCESS:
startAppInfoFragment(DirectoryAccessDetails.class, R.string.directory_access);
break;
case LIST_TYPE_WIFI_ACCESS:
startAppInfoFragment(ChangeWifiStateDetails.class, R.string.change_wifi_state_title);
break;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed
// app. Maybe when they load the list of apps that contains managed profile apps.
@@ -846,6 +858,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
mExtraInfoBridge = new AppStateInstallAppsBridge(mContext, mState, this);
} else if (mManageApplications.mListType == LIST_TYPE_DIRECTORY_ACCESS) {
mExtraInfoBridge = new AppStateDirectoryAccessBridge(mState, this);
} else if (mManageApplications.mListType == LIST_TYPE_WIFI_ACCESS) {
mExtraInfoBridge = new AppStateChangeWifiStateBridge(mContext, mState, this);
} else {
mExtraInfoBridge = null;
}
@@ -1251,6 +1265,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
case LIST_TYPE_DIRECTORY_ACCESS:
holder.setSummary(null);
break;
case LIST_TYPE_WIFI_ACCESS:
holder.setSummary(ChangeWifiStateDetails.getSummary(mContext, entry));
break;
default:
holder.updateSizeText(entry, mManageApplications.mInvalidSizeStr, mWhichSize);
break;

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import android.Manifest;
import android.app.AppOpsManager;
import android.content.Context;
import com.android.settings.applications.AppStateAppOpsBridge;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import java.util.List;
/*
* Connects info of apps that change wifi state to the ApplicationsState. Wraps around the generic
* AppStateAppOpsBridge class to tailor to the semantics of CHANGE_WIFI_STATE. Also provides app
* filters that can use the info.
*/
public class AppStateChangeWifiStateBridge extends AppStateAppOpsBridge {
private static final String TAG = "AppStateChangeWifiStateBridge";
private static final int APP_OPS_OP_CODE = AppOpsManager.OP_CHANGE_WIFI_STATE;
private static final String PM_CHANGE_WIFI_STATE = Manifest.permission.CHANGE_WIFI_STATE;
private static final String[] PM_PERMISSIONS = {
PM_CHANGE_WIFI_STATE
};
public AppStateChangeWifiStateBridge(Context context, ApplicationsState appState, Callback
callback) {
super(context, appState, callback, APP_OPS_OP_CODE, PM_PERMISSIONS);
}
@Override
protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
app.extraInfo = getWifiSettingsInfo(pkg, uid);
}
@Override
protected void loadAllExtraInfo() {
final List<AppEntry> allApps = mAppSession.getAllApps();
for (AppEntry entry : allApps) {
updateExtraInfo(entry, entry.info.packageName, entry.info.uid);
}
}
public WifiSettingsState getWifiSettingsInfo(String pkg, int uid) {
PermissionState permissionState = super.getPermissionInfo(pkg, uid);
return new WifiSettingsState(permissionState);
}
public static class WifiSettingsState extends AppStateAppOpsBridge.PermissionState {
public WifiSettingsState(PermissionState permissionState) {
super(permissionState.packageName, permissionState.userHandle);
this.packageInfo = permissionState.packageInfo;
this.appOpMode = permissionState.appOpMode;
this.permissionDeclared = permissionState.permissionDeclared;
this.staticPermissionGranted = permissionState.staticPermissionGranted;
}
}
public static final AppFilter FILTER_CHANGE_WIFI_STATE = new AppFilter() {
@Override
public void init() {
}
@Override
public boolean filterApp(AppEntry info) {
if (info == null || info.extraInfo == null) {
return false;
}
WifiSettingsState wifiSettingsState = (WifiSettingsState) info.extraInfo;
return wifiSettingsState.permissionDeclared;
}
};
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import android.Manifest.permission;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.content.Context;
import android.os.Bundle;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.AppStateChangeWifiStateBridge.WifiSettingsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_IGNORED;
public class ChangeWifiStateDetails extends AppInfoWithHeader
implements OnPreferenceChangeListener {
private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
private static final String LOG_TAG = "ChangeWifiStateDetails";
private AppStateChangeWifiStateBridge mAppBridge;
private AppOpsManager mAppOpsManager;
private SwitchPreference mSwitchPref;
private WifiSettingsState mWifiSettingsState;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Context context = getActivity();
mAppBridge = new AppStateChangeWifiStateBridge(context, mState, null);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
// find preferences
addPreferencesFromResource(R.xml.change_wifi_state_details);
mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
// set title/summary for all of them
mSwitchPref.setTitle(R.string.change_wifi_state_app_detail_switch);
// install event listeners
mSwitchPref.setOnPreferenceChangeListener(this);
}
@Override
protected AlertDialog createDialog(int id, int errorCode) {
return null;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.CONFIGURE_WIFI;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mSwitchPref) {
if (mWifiSettingsState != null && (Boolean) newValue
!= mWifiSettingsState.isPermissible()) {
setCanChangeWifiState(!mWifiSettingsState.isPermissible());
refreshUi();
}
return true;
}
return false;
}
private void setCanChangeWifiState(boolean newState) {
logSpecialPermissionChange(newState, mPackageName);
mAppOpsManager.setMode(AppOpsManager.OP_CHANGE_WIFI_STATE,
mPackageInfo.applicationInfo.uid, mPackageName, newState
? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
}
protected void logSpecialPermissionChange(boolean newState, String packageName) {
int logCategory = newState ? MetricsEvent.APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_ALLOW
: MetricsEvent.APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_DENY;
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider().action(getContext(),
logCategory, packageName);
}
@Override
protected boolean refreshUi() {
if (mPackageInfo == null || mPackageInfo.applicationInfo == null) {
return false;
}
mWifiSettingsState = mAppBridge.getWifiSettingsInfo(mPackageName,
mPackageInfo.applicationInfo.uid);
boolean canChange = mWifiSettingsState.isPermissible();
mSwitchPref.setChecked(canChange);
// you can't ask a user for a permission you didn't even declare!
mSwitchPref.setEnabled(mWifiSettingsState.permissionDeclared);
return true;
}
public static CharSequence getSummary(Context context, AppEntry entry) {
WifiSettingsState state;
if (entry.extraInfo instanceof WifiSettingsState) {
state = (WifiSettingsState) entry.extraInfo;
} else if (entry.extraInfo instanceof PermissionState) {
state = new WifiSettingsState((PermissionState) entry.extraInfo);
} else {
state = new AppStateChangeWifiStateBridge(context, null, null).getWifiSettingsInfo(
entry.info.packageName, entry.info.uid);
}
return getSummary(context, state);
}
public static CharSequence getSummary(Context context, WifiSettingsState wifiSettingsState) {
return context.getString(wifiSettingsState.isPermissible()
? R.string.app_permission_summary_allowed
: R.string.app_permission_summary_not_allowed);
}
}

View File

@@ -71,3 +71,4 @@ com.android.settings.ApnEditor
com.android.settings.UserCredentialsSettings
com.android.settings.TestingSettings
com.android.settings.applications.DirectoryAccessDetails
com.android.settings.wifi.ChangeWifiStateDetails

View File

@@ -0,0 +1,81 @@
/**
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.app.AppOpsManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AppStateChangeWifiStateBridgeTest {
@Mock
private AppEntry mEntry;
@Mock
private AppStateChangeWifiStateBridge.WifiSettingsState mState;
private Context mContext;
private AppFilter mFilter;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFilter = AppStateChangeWifiStateBridge.FILTER_CHANGE_WIFI_STATE;
}
@Test
public void testFilterApp_inputNull_returnFalse() {
assertThat(mFilter.filterApp(null)).isFalse();
}
@Test
public void testFilterApp_extraInfoNull_returnFalse() {
mEntry.extraInfo = null;
assertThat(mFilter.filterApp(mEntry)).isFalse();
}
@Test
public void testFilterApp_permissionedDeclaredTrue_returnTrue() {
mState.permissionDeclared = true;
mEntry.extraInfo = mState;
assertThat(mFilter.filterApp(mEntry)).isTrue();
}
@Test
public void testFilterApp_permissionedDeclaredFalse_returnFalse() {
mState.permissionDeclared = false;
mEntry.extraInfo = mState;
assertThat(mFilter.filterApp(mEntry)).isFalse();
}
}

View File

@@ -0,0 +1,93 @@
/**
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ChangeWifiStateDetailsTest {
private static final String PACKAGE_NAME = "app";
private FakeFeatureFactory mFeatureFactory;
private ChangeWifiStateDetails mFragment;
private Context mContext;
@Mock
private AppEntry mAppEntry;
@Mock
private AppStateChangeWifiStateBridge.WifiSettingsState mState;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFeatureFactory = FakeFeatureFactory.setupForTest();
mFragment = new ChangeWifiStateDetails();
}
@Test
public void testLogSpecialPermissionChange_setTrue_returnAllow() {
mFragment.logSpecialPermissionChange(true /*newState*/, PACKAGE_NAME);
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_ALLOW),
eq(PACKAGE_NAME));
}
@Test
public void testLogSpecialPermissionChange_setFalse_returnDeny() {
mFragment.logSpecialPermissionChange(false /*newState*/, PACKAGE_NAME);
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_DENY),
eq(PACKAGE_NAME));
}
@Test
public void testGetSummary_permissibleTrue_returnAllowed() {
when(mState.isPermissible()).thenReturn(true);
assertThat(mFragment.getSummary(mContext, mState)).isEqualTo(
mContext.getString(R.string.app_permission_summary_allowed));
}
@Test
public void testGetSummary_permissibleFalse_returnNotAllowed() {
when(mState.isPermissible()).thenReturn(false);
assertThat(mFragment.getSummary(mContext, mState)).isEqualTo(
mContext.getString(R.string.app_permission_summary_not_allowed));
}
}