From d4292256406d374e923335d1c97752da2909ad7b Mon Sep 17 00:00:00 2001 From: Pavel Grafov Date: Wed, 8 Nov 2017 20:14:03 +0000 Subject: [PATCH] Block editing of locked down wifi network from details page. Test: make ROBOTEST_FILTER=WifiDetailPreferenceControllerTest RunSettingsRoboTests Bug: 68990370 Change-Id: Idceb064486afd93bc8b2f52d605a788520de8e56 --- src/com/android/settings/wifi/WifiDialog.java | 3 +- .../android/settings/wifi/WifiSettings.java | 64 +------------------ src/com/android/settings/wifi/WifiUtils.java | 54 ++++++++++++++++ .../WifiDetailPreferenceController.java | 16 +++-- .../details/WifiNetworkDetailsFragment.java | 10 ++- .../wrapper/DevicePolicyManagerWrapper.java | 54 ++++++++++------ .../ShadowDevicePolicyManagerWrapper.java | 51 +++++++++++++++ .../shadow/ShadowPackageManagerWrapper.java | 47 ++++++++++++++ .../WifiDetailPreferenceControllerTest.java | 51 ++++++++++++++- 9 files changed, 257 insertions(+), 93 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowPackageManagerWrapper.java diff --git a/src/com/android/settings/wifi/WifiDialog.java b/src/com/android/settings/wifi/WifiDialog.java index cb3f8df1e77..79500e0b7ad 100644 --- a/src/com/android/settings/wifi/WifiDialog.java +++ b/src/com/android/settings/wifi/WifiDialog.java @@ -119,8 +119,7 @@ public class WifiDialog extends AlertDialog implements WifiConfigUiBase, DialogI mListener.onSubmit(this); break; case BUTTON_FORGET: - if (WifiSettings.isEditabilityLockedDown( - getContext(), mAccessPoint.getConfig())) { + if (WifiUtils.isNetworkLockedDown(getContext(), mAccessPoint.getConfig())) { RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), RestrictedLockUtils.getDeviceOwner(getContext())); return; diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index 4c87bac0427..cc48064710b 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -21,13 +21,9 @@ import static android.os.UserManager.DISALLOW_CONFIG_WIFI; import android.annotation.NonNull; import android.app.Activity; import android.app.Dialog; -import android.app.admin.DevicePolicyManager; -import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.NetworkInfo; @@ -491,7 +487,7 @@ public class WifiSettings extends RestrictedSettingsFragment WifiConfiguration config = mSelectedAccessPoint.getConfig(); // Some configs are ineditable - if (isEditabilityLockedDown(getActivity(), config)) { + if (WifiUtils.isNetworkLockedDown(getActivity(), config)) { return; } @@ -594,7 +590,7 @@ public class WifiSettings extends RestrictedSettingsFragment private void showDialog(AccessPoint accessPoint, int dialogMode) { if (accessPoint != null) { WifiConfiguration config = accessPoint.getConfig(); - if (isEditabilityLockedDown(getActivity(), config) && accessPoint.isActive()) { + if (WifiUtils.isNetworkLockedDown(getActivity(), config) && accessPoint.isActive()) { RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(), RestrictedLockUtils.getDeviceOwner(getActivity())); return; @@ -1120,62 +1116,6 @@ public class WifiSettings extends RestrictedSettingsFragment } }; - /** - * Returns true if the config is not editable through Settings. - * @param context Context of caller - * @param config The WiFi config. - * @return true if the config is not editable through Settings. - */ - public static boolean isEditabilityLockedDown(Context context, WifiConfiguration config) { - return !canModifyNetwork(context, config); - } - - /** - * This method is a stripped version of WifiConfigStore.canModifyNetwork. - * TODO: refactor to have only one method. - * @param context Context of caller - * @param config The WiFi config. - * @return true if Settings can modify the config. - */ - static boolean canModifyNetwork(Context context, WifiConfiguration config) { - if (config == null) { - return true; - } - - final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( - Context.DEVICE_POLICY_SERVICE); - - // Check if device has DPM capability. If it has and dpm is still null, then we - // treat this case with suspicion and bail out. - final PackageManager pm = context.getPackageManager(); - if (pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN) && dpm == null) { - return false; - } - - boolean isConfigEligibleForLockdown = false; - if (dpm != null) { - final ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnAnyUser(); - if (deviceOwner != null) { - final int deviceOwnerUserId = dpm.getDeviceOwnerUserId(); - try { - final int deviceOwnerUid = pm.getPackageUidAsUser(deviceOwner.getPackageName(), - deviceOwnerUserId); - isConfigEligibleForLockdown = deviceOwnerUid == config.creatorUid; - } catch (NameNotFoundException e) { - // don't care - } - } - } - if (!isConfigEligibleForLockdown) { - return true; - } - - final ContentResolver resolver = context.getContentResolver(); - final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver, - Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0; - return !isLockdownFeatureEnabled; - } - private static class SummaryProvider implements SummaryLoader.SummaryProvider, OnSummaryChangeListener { diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java index 7bd69dbfdd8..34c86d17054 100644 --- a/src/com/android/settings/wifi/WifiUtils.java +++ b/src/com/android/settings/wifi/WifiUtils.java @@ -16,8 +16,18 @@ package com.android.settings.wifi; +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.pm.PackageManager; +import android.net.wifi.WifiConfiguration; +import android.provider.Settings; import android.text.TextUtils; +import com.android.settings.wrapper.DevicePolicyManagerWrapper; +import com.android.settingslib.wrapper.PackageManagerWrapper; + public class WifiUtils { private static final int SSID_ASCII_MIN_LENGTH = 1; @@ -47,4 +57,48 @@ public class WifiUtils { final int length = password.length(); return length >= PASSWORD_MIN_LENGTH && length <= PASSWORD_MAX_LENGTH; } + + /** + * This method is a stripped and negated version of WifiConfigStore.canModifyNetwork. + * @param context Context of caller + * @param config The WiFi config. + * @return true if Settings cannot modify the config due to lockDown. + */ + public static boolean isNetworkLockedDown(Context context, WifiConfiguration config) { + if (config == null) { + return false; + } + + final DevicePolicyManagerWrapper dpm = DevicePolicyManagerWrapper.from(context); + final PackageManagerWrapper pm = new PackageManagerWrapper(context.getPackageManager()); + + // Check if device has DPM capability. If it has and dpm is still null, then we + // treat this case with suspicion and bail out. + if (pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN) && dpm == null) { + return true; + } + + boolean isConfigEligibleForLockdown = false; + if (dpm != null) { + final ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnAnyUser(); + if (deviceOwner != null) { + final int deviceOwnerUserId = dpm.getDeviceOwnerUserId(); + try { + final int deviceOwnerUid = pm.getPackageUidAsUser(deviceOwner.getPackageName(), + deviceOwnerUserId); + isConfigEligibleForLockdown = deviceOwnerUid == config.creatorUid; + } catch (PackageManager.NameNotFoundException e) { + // don't care + } + } + } + if (!isConfigEligibleForLockdown) { + return false; + } + + final ContentResolver resolver = context.getContentResolver(); + final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver, + Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0; + return isLockdownFeatureEnabled; + } } diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java index 40acfeb4e02..70ee20de03d 100644 --- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java @@ -19,8 +19,6 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; -import static com.android.settings.wifi.WifiSettings.isEditabilityLockedDown; - import android.app.Activity; import android.app.Fragment; import android.content.BroadcastReceiver; @@ -62,6 +60,7 @@ import com.android.settings.widget.EntityHeaderController; import com.android.settings.wifi.WifiDetailPreference; import com.android.settings.wifi.WifiDialog; import com.android.settings.wifi.WifiDialog.WifiDialogListener; +import com.android.settings.wifi.WifiUtils; import com.android.settings.wrapper.ConnectivityManagerWrapper; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -280,8 +279,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController mButtonsPref = ((ActionButtonPreference) screen.findPreference(KEY_BUTTONS_PREF)) .setButton1Text(R.string.forget) .setButton1Positive(false) - .setButton2Text(R.string.support_sign_in_button_text) .setButton1OnClickListener(view -> forgetNetwork()) + .setButton2Text(R.string.support_sign_in_button_text) .setButton2Positive(true) .setButton2OnClickListener(view -> signIntoNetwork()); @@ -498,9 +497,14 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController * Returns whether the network represented by this preference can be forgotten. */ private boolean canForgetNetwork() { - // TODO(65396674): create test for the locked down scenario - return (mWifiInfo != null && mWifiInfo.isEphemeral()) - || (mWifiConfig != null && !isEditabilityLockedDown(mContext, mWifiConfig)); + return (mWifiInfo != null && mWifiInfo.isEphemeral()) || canModifyNetwork(); + } + + /** + * Returns whether the network represented by this preference can be modified. + */ + public boolean canModifyNetwork() { + return mWifiConfig != null && !WifiUtils.isNetworkLockedDown(mContext, mWifiConfig); } /** diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java index 1609bef2980..ea30b562f3c 100644 --- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java +++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java @@ -27,6 +27,7 @@ import android.os.Looper; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; + import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; @@ -34,8 +35,10 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.wifi.WifiConfigUiBase; import com.android.settings.wifi.WifiDialog; import com.android.settings.wrapper.ConnectivityManagerWrapper; +import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.wifi.AccessPoint; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -105,7 +108,12 @@ public class WifiNetworkDetailsFragment extends DashboardFragment { public boolean onOptionsItemSelected(MenuItem menuItem) { switch (menuItem.getItemId()) { case Menu.FIRST: - showDialog(WIFI_DIALOG_ID); + if (!mWifiDetailPreferenceController.canModifyNetwork()) { + RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), + RestrictedLockUtils.getDeviceOwner(getContext())); + } else { + showDialog(WIFI_DIALOG_ID); + } return true; default: return super.onOptionsItemSelected(menuItem); diff --git a/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java b/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java index ed2eb462ae4..8417219b07c 100644 --- a/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java +++ b/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java @@ -17,11 +17,12 @@ package com.android.settings.wrapper; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.os.UserHandle; -import android.support.annotation.Nullable; import java.util.List; @@ -38,10 +39,16 @@ public class DevicePolicyManagerWrapper { mDpm = dpm; } + public static @Nullable DevicePolicyManagerWrapper from(Context context) { + DevicePolicyManager dpm = + (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); + return dpm == null ? null : new DevicePolicyManagerWrapper(dpm); + } + /** * Calls {@code DevicePolicyManager.getActiveAdminsAsUser()}. * - * @see android.app.admin.DevicePolicyManager#getActiveAdminsAsUser + * @see DevicePolicyManager#getActiveAdminsAsUser */ public @Nullable List getActiveAdminsAsUser(int userId) { return mDpm.getActiveAdminsAsUser(userId); @@ -50,7 +57,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getMaximumFailedPasswordsForWipe()}. * - * @see android.app.admin.DevicePolicyManager#getMaximumFailedPasswordsForWipe + * @see DevicePolicyManager#getMaximumFailedPasswordsForWipe */ public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int userHandle) { return mDpm.getMaximumFailedPasswordsForWipe(admin, userHandle); @@ -59,7 +66,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getDeviceOwnerComponentOnCallingUser()}. * - * @see android.app.admin.DevicePolicyManager#getDeviceOwnerComponentOnCallingUser + * @see DevicePolicyManager#getDeviceOwnerComponentOnCallingUser */ public ComponentName getDeviceOwnerComponentOnCallingUser() { return mDpm.getDeviceOwnerComponentOnCallingUser(); @@ -68,7 +75,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getDeviceOwnerComponentOnAnyUser()}. * - * @see android.app.admin.DevicePolicyManager#getDeviceOwnerComponentOnAnyUser + * @see DevicePolicyManager#getDeviceOwnerComponentOnAnyUser */ public ComponentName getDeviceOwnerComponentOnAnyUser() { return mDpm.getDeviceOwnerComponentOnAnyUser(); @@ -77,7 +84,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getProfileOwnerAsUser()}. * - * @see android.app.admin.DevicePolicyManager#getProfileOwnerAsUser + * @see DevicePolicyManager#getProfileOwnerAsUser */ public @Nullable ComponentName getProfileOwnerAsUser(final int userId) { return mDpm.getProfileOwnerAsUser(userId); @@ -86,7 +93,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getDeviceOwnerNameOnAnyUser()}. * - * @see android.app.admin.DevicePolicyManager#getDeviceOwnerNameOnAnyUser + * @see DevicePolicyManager#getDeviceOwnerNameOnAnyUser */ public CharSequence getDeviceOwnerOrganizationName() { return mDpm.getDeviceOwnerOrganizationName(); @@ -95,7 +102,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getPermissionGrantState()}. * - * @see android.app.admin.DevicePolicyManager#getPermissionGrantState + * @see DevicePolicyManager#getPermissionGrantState */ public int getPermissionGrantState(@Nullable ComponentName admin, String packageName, String permission) { @@ -105,7 +112,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.isSecurityLoggingEnabled()}. * - * @see android.app.admin.DevicePolicyManager#isSecurityLoggingEnabled + * @see DevicePolicyManager#isSecurityLoggingEnabled */ public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) { return mDpm.isSecurityLoggingEnabled(admin); @@ -114,7 +121,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.isNetworkLoggingEnabled()}. * - * @see android.app.admin.DevicePolicyManager#isNetworkLoggingEnabled + * @see DevicePolicyManager#isNetworkLoggingEnabled */ public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) { return mDpm.isNetworkLoggingEnabled(admin); @@ -123,7 +130,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getLastSecurityLogRetrievalTime()}. * - * @see android.app.admin.DevicePolicyManager#getLastSecurityLogRetrievalTime + * @see DevicePolicyManager#getLastSecurityLogRetrievalTime */ public long getLastSecurityLogRetrievalTime() { return mDpm.getLastSecurityLogRetrievalTime(); @@ -132,7 +139,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getLastBugReportRequestTime()}. * - * @see android.app.admin.DevicePolicyManager#getLastBugReportRequestTime + * @see DevicePolicyManager#getLastBugReportRequestTime */ public long getLastBugReportRequestTime() { return mDpm.getLastBugReportRequestTime(); @@ -141,7 +148,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getLastNetworkLogRetrievalTime()}. * - * @see android.app.admin.DevicePolicyManager#getLastNetworkLogRetrievalTime + * @see DevicePolicyManager#getLastNetworkLogRetrievalTime */ public long getLastNetworkLogRetrievalTime() { return mDpm.getLastNetworkLogRetrievalTime(); @@ -150,7 +157,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.isCurrentInputMethodSetByOwner()}. * - * @see android.app.admin.DevicePolicyManager#isCurrentInputMethodSetByOwner + * @see DevicePolicyManager#isCurrentInputMethodSetByOwner */ public boolean isCurrentInputMethodSetByOwner() { return mDpm.isCurrentInputMethodSetByOwner(); @@ -159,7 +166,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.getOwnerInstalledCaCerts()}. * - * @see android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts + * @see DevicePolicyManager#getOwnerInstalledCaCerts */ public List getOwnerInstalledCaCerts(@NonNull UserHandle user) { return mDpm.getOwnerInstalledCaCerts(user); @@ -168,7 +175,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.isDeviceOwnerAppOnAnyUser()}. * - * @see android.app.admin.DevicePolicyManager#isDeviceOwnerAppOnAnyUser + * @see DevicePolicyManager#isDeviceOwnerAppOnAnyUser */ public boolean isDeviceOwnerAppOnAnyUser(String packageName) { return mDpm.isDeviceOwnerAppOnAnyUser(packageName); @@ -177,7 +184,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.packageHasActiveAdmins()}. * - * @see android.app.admin.DevicePolicyManager#packageHasActiveAdmins + * @see DevicePolicyManager#packageHasActiveAdmins */ public boolean packageHasActiveAdmins(String packageName) { return mDpm.packageHasActiveAdmins(packageName); @@ -186,7 +193,7 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.isUninstallInQueue()}. * - * @see android.app.admin.DevicePolicyManager#isUninstallInQueue + * @see DevicePolicyManager#isUninstallInQueue */ public boolean isUninstallInQueue(String packageName) { return mDpm.isUninstallInQueue(packageName); @@ -195,9 +202,18 @@ public class DevicePolicyManagerWrapper { /** * Calls {@code DevicePolicyManager.createAdminSupportIntent()}. * - * @see android.app.admin.DevicePolicyManager#createAdminSupportIntent + * @see DevicePolicyManager#createAdminSupportIntent(String) */ public Intent createAdminSupportIntent(@NonNull String restriction) { return mDpm.createAdminSupportIntent(restriction); } + + /** + * Calls {@code DevicePolicyManager#getDeviceOwnerUserId()}. + * + * @see DevicePolicyManager#getDeviceOwnerUserId() + */ + public int getDeviceOwnerUserId() { + return mDpm.getDeviceOwnerUserId(); + } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java new file mode 100644 index 00000000000..104cd870359 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2017 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.testutils.shadow; + +import android.content.ComponentName; + +import com.android.settings.wrapper.DevicePolicyManagerWrapper; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +/** + * Shadow for {@link DevicePolicyManagerWrapper} to allow stubbing hidden methods. + */ +@Implements(DevicePolicyManagerWrapper.class) +public class ShadowDevicePolicyManagerWrapper { + private static ComponentName deviceOComponentName = null; + private static int deviceOwnerUserId = -1; + + @Implementation + public ComponentName getDeviceOwnerComponentOnAnyUser() { + return deviceOComponentName; + } + + @Implementation + public int getDeviceOwnerUserId() { + return deviceOwnerUserId; + } + + public static void setDeviceOComponentName(ComponentName deviceOComponentName) { + ShadowDevicePolicyManagerWrapper.deviceOComponentName = deviceOComponentName; + } + + public static void setDeviceOwnerUserId(int deviceOwnerUserId) { + ShadowDevicePolicyManagerWrapper.deviceOwnerUserId = deviceOwnerUserId; + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPackageManagerWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPackageManagerWrapper.java new file mode 100644 index 00000000000..7a1b8c5728c --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPackageManagerWrapper.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2017 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.testutils.shadow; + +import android.content.pm.PackageManager.NameNotFoundException; + +import com.android.settingslib.wrapper.PackageManagerWrapper; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +import java.util.HashMap; + +/** + * Shadow for {@link PackageManagerWrapper} to allow stubbing hidden methods. + */ +@Implements(PackageManagerWrapper.class) +public class ShadowPackageManagerWrapper { + private static final HashMap packageUids = new HashMap<>(); + + @Implementation + public int getPackageUidAsUser(String packageName, int userId) throws NameNotFoundException { + Integer res = packageUids.get(packageName + userId); + if (res == null) { + throw new NameNotFoundException(); + } + return res; + } + + public static void setPackageUidAsUser(String packageName, int userId, int uid) { + packageUids.put(packageName + userId, uid); + } +} diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java index 6e3fa322d99..3a0341c7be9 100644 --- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java @@ -33,6 +33,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Activity; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.drawable.ColorDrawable; @@ -51,6 +52,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Handler; +import android.provider.Settings; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceScreen; @@ -64,7 +66,9 @@ import com.android.settings.TestConfig; import com.android.settings.applications.LayoutPreference; import com.android.settings.core.instrumentation.MetricsFeatureProvider; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowDevicePolicyManagerWrapper; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; +import com.android.settings.testutils.shadow.ShadowPackageManagerWrapper; import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreferenceTest; import com.android.settings.widget.EntityHeaderController; @@ -94,7 +98,11 @@ import java.util.stream.Collectors; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, - shadows = ShadowEntityHeaderController.class) + shadows = { + ShadowDevicePolicyManagerWrapper.class, + ShadowEntityHeaderController.class, + ShadowPackageManagerWrapper.class, + }) public class WifiDetailPreferenceControllerTest { private static final int LEVEL = 1; @@ -238,8 +246,6 @@ public class WifiDetailPreferenceControllerTest { when(mockHeaderController.setSummary(anyString())).thenReturn(mockHeaderController); when(mockIconInjector.getIcon(anyInt())).thenReturn(new ColorDrawable()); - doReturn(null).when(mContext).getSystemService(eq(Context.DEVICE_POLICY_SERVICE)); - setupMockedPreferenceScreen(); mController = newWifiDetailPreferenceController(); } @@ -628,6 +634,45 @@ public class WifiDetailPreferenceControllerTest { verify(mockButtonsPref).setButton1Visible(true); } + @Test + public void canForgetNetwork_lockedDown() { + lockDownNetwork(); + + displayAndResume(); + + verify(mockButtonsPref).setButton1Visible(false); + } + + @Test + public void canModifyNetwork_saved() { + assertThat(mController.canModifyNetwork()).isTrue(); + } + + @Test + public void canModifyNetwork_lockedDown() { + lockDownNetwork(); + + assertThat(mController.canModifyNetwork()).isFalse(); + } + + /** + * Pretends that current network is locked down by device owner. + */ + private void lockDownNetwork() { + final int doUserId = 123; + final int doUid = 1234; + String doPackage = "some.package"; + + mockWifiConfig.creatorUid = doUid; + ComponentName doComponent = new ComponentName(doPackage, "some.Class"); + ShadowPackageManagerWrapper.setPackageUidAsUser(doPackage, doUserId, doUid); + ShadowDevicePolicyManagerWrapper.setDeviceOComponentName(doComponent); + ShadowDevicePolicyManagerWrapper.setDeviceOwnerUserId(doUserId); + + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 1); + } + @Test public void forgetNetwork_ephemeral() { String ssid = "ssid";