Merge "Show dialog when user tries to edit a locked down WiFi config"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5546cc4..72adf4e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1333,6 +1333,8 @@
     <!-- Wifi Internal 5GHz as an universal itendifier for 5GHz band -->
     <string name="wifi_band_5ghz" translatable="false">5GHz</string>
 
+    <!-- Wifi Alert message when tapping on a preference for a config locked down by device owner. [CHAR LIMIT=200] -->
+    <string name="wifi_alert_lockdown_by_device_owner"><xliff:g id="app_name">%1$s</xliff:g> manages your device and has disabled modifying and deleting this Wi-Fi network. For more information, contact your administrator.</string>
 
     <!-- NFC settings -->
     <!-- Used in the 1st-level settings screen to turn on NFC -->
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index 6726717..04094b3 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -156,8 +156,13 @@
                     mAccessPointSavedState = null;
                 }
                 mSelectedAccessPoint = mDlgAccessPoint;
+
+                // Hide forget button if config editing is locked down
+                final boolean hideForgetButton = WifiSettings.isCreatorDeviceOwner(getActivity(),
+                        mDlgAccessPoint.getConfig());
                 mDialog = new WifiDialog(getActivity(), this, mDlgAccessPoint,
-                        false /* not editting */, true /* hide the submit button */);
+                        false /* not editting */, true /* hide the submit button */,
+                        hideForgetButton);
                 return mDialog;
 
         }
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 1503c63..ee53887 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -315,6 +315,13 @@
         return (level > -1 && level < mLevels.length) ? mLevels[level] : null;
     }
 
+    void hideForgetButton() {
+        Button forget = mConfigUi.getForgetButton();
+        if (forget == null) return;
+
+        forget.setVisibility(View.GONE);
+    }
+
     void hideSubmitButton() {
         Button submit = mConfigUi.getSubmitButton();
         if (submit == null) return;
diff --git a/src/com/android/settings/wifi/WifiDialog.java b/src/com/android/settings/wifi/WifiDialog.java
index 1e8a981..c18baf5 100644
--- a/src/com/android/settings/wifi/WifiDialog.java
+++ b/src/com/android/settings/wifi/WifiDialog.java
@@ -37,11 +37,14 @@
     private View mView;
     private WifiConfigController mController;
     private boolean mHideSubmitButton;
+    private boolean mHideForgetButton;
 
     public WifiDialog(Context context, DialogInterface.OnClickListener listener,
-            AccessPoint accessPoint, boolean edit, boolean hideSubmitButton) {
+            AccessPoint accessPoint, boolean edit, boolean hideSubmitButton,
+            boolean hideForgetButton) {
         this(context, listener, accessPoint, edit);
         mHideSubmitButton = hideSubmitButton;
+        mHideForgetButton = hideForgetButton;
     }
 
     public WifiDialog(Context context, DialogInterface.OnClickListener listener,
@@ -51,6 +54,7 @@
         mListener = listener;
         mAccessPoint = accessPoint;
         mHideSubmitButton = false;
+        mHideForgetButton = false;
     }
 
     @Override
@@ -73,6 +77,10 @@
              * visibility. Right after creation, update button visibility */
             mController.enableSubmitIfAppropriate();
         }
+
+        if (mHideForgetButton) {
+            mController.hideForgetButton();
+        }
     }
 
     public void onRestoreInstanceState(Bundle savedInstanceState) {
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index f46edac..c947456 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -20,10 +20,17 @@
 import static android.os.UserManager.DISALLOW_CONFIG_WIFI;
 
 import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AppGlobals;
 import android.app.Dialog;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -35,6 +42,8 @@
 import android.net.wifi.WpsInfo;
 import android.nfc.NfcAdapter;
 import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
 import android.preference.Preference;
 import android.preference.PreferenceScreen;
 import android.text.Spannable;
@@ -417,6 +426,12 @@
                     menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect);
                 }
 
+                WifiConfiguration config = mSelectedAccessPoint.getConfig();
+                // Device Owner created configs are uneditable
+                if (isCreatorDeviceOwner(getActivity(), config)) {
+                    return;
+                }
+
                 if (mSelectedAccessPoint.isSaved() || mSelectedAccessPoint.isEphemeral()) {
                     // Allow forgetting a network if either the network is saved or ephemerally
                     // connected. (In the latter case, "forget" blacklists the network so it won't
@@ -493,6 +508,31 @@
     }
 
     private void showDialog(AccessPoint accessPoint, boolean edit) {
+        WifiConfiguration config = accessPoint.getConfig();
+        if (isCreatorDeviceOwner(getActivity(), config) && accessPoint.isActive()) {
+            final int userId = UserHandle.getUserId(config.creatorUid);
+            final PackageManager pm = getActivity().getPackageManager();
+            final IPackageManager ipm = AppGlobals.getPackageManager();
+            String appName = pm.getNameForUid(config.creatorUid);
+            try {
+                final ApplicationInfo appInfo = ipm.getApplicationInfo(appName, /* flags */ 0,
+                        userId);
+                final CharSequence label = pm.getApplicationLabel(appInfo);
+                if (label != null) {
+                    appName = label.toString();
+                }
+            } catch (RemoteException e) {
+                // leave appName as packageName
+            }
+            final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+            builder.setTitle(accessPoint.getSsid())
+                    .setMessage(getString(R.string.wifi_alert_lockdown_by_device_owner,
+                            appName))
+                    .setPositiveButton(android.R.string.ok, null)
+                    .show();
+            return;
+        }
+
         if (mDialog != null) {
             removeDialog(WIFI_DIALOG_ID);
             mDialog = null;
@@ -521,7 +561,10 @@
                 }
                 // If it's null, fine, it's for Add Network
                 mSelectedAccessPoint = ap;
-                mDialog = new WifiDialog(getActivity(), this, ap, mDlgEdit);
+                mDialog = new WifiDialog(getActivity(), this, ap, mDlgEdit,
+                        /* no hide submit/connect */ false,
+                        /* hide forget if config locked down */ isCreatorDeviceOwner(getActivity(),
+                                ap.getConfig()));
                 return mDialog;
             case WPS_PBC_DIALOG_ID:
                 return new WpsDialog(getActivity(), WpsInfo.PBC);
@@ -826,4 +869,29 @@
                 return result;
             }
         };
+
+    /**
+     * Returns the true if the app that created this config is the device owner of the device.
+     * @param config The WiFi config.
+     * @return creator package name or null if creator package is not device owner.
+     */
+    static boolean isCreatorDeviceOwner(Context context, WifiConfiguration config) {
+        if (config == null) {
+            return false;
+        }
+        final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        final String deviceOwnerPackageName = dpm.getDeviceOwner();
+        if (deviceOwnerPackageName == null) {
+            return false;
+        }
+        final PackageManager pm = context.getPackageManager();
+        try {
+            final int deviceOwnerUid = pm.getPackageUid(deviceOwnerPackageName,
+                    UserHandle.getUserId(config.creatorUid));
+            return deviceOwnerUid == config.creatorUid;
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+    }
 }