OSDN Git Service

Block editing of locked down wifi network from details page.
authorPavel Grafov <pgrafov@google.com>
Wed, 8 Nov 2017 20:14:03 +0000 (20:14 +0000)
committerPavel Grafov <pgrafov@google.com>
Fri, 17 Nov 2017 18:11:25 +0000 (18:11 +0000)
Test: make ROBOTEST_FILTER=WifiDetailPreferenceControllerTest RunSettingsRoboTests
Bug: 68990370
Change-Id: Idceb064486afd93bc8b2f52d605a788520de8e56

src/com/android/settings/wifi/WifiDialog.java
src/com/android/settings/wifi/WifiSettings.java
src/com/android/settings/wifi/WifiUtils.java
src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java
tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/testutils/shadow/ShadowPackageManagerWrapper.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java

index cb3f8df..79500e0 100644 (file)
@@ -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;
index 4c87bac..cc48064 100644 (file)
@@ -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 {
 
index 7bd69db..34c86d1 100644 (file)
 
 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;
+    }
 }
index 40acfeb..70ee20d 100644 (file)
@@ -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);
     }
 
     /**
index 1609bef..ea30b56 100644 (file)
@@ -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);
index ed2eb46..8417219 100644 (file)
 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<ComponentName> 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<String> 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 (file)
index 0000000..104cd87
--- /dev/null
@@ -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 (file)
index 0000000..7a1b8c5
--- /dev/null
@@ -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<String, Integer> 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);
+    }
+}
index 6e3fa32..3a0341c 100644 (file)
@@ -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();
     }
@@ -629,6 +635,45 @@ public class WifiDetailPreferenceControllerTest {
     }
 
     @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";
         when(mockWifiInfo.isEphemeral()).thenReturn(true);