Enabling users toset the Global Proxy from wireless settings.

Change-Id: Ie9b37e4c8e042fab738d2181878e93d7d2645834
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7b15e3f..b0da109 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -729,11 +729,10 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="ProxySelector" android:label="@string/proxy_settings_label"
-                android:theme="@android:style/Theme.Dialog">
+        <activity android:name="ProxySelector" android:label="@string/proxy_settings_label">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEVELOPMENT_PREFERENCE" />
+                <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.VOICE_LAUNCH" />
             </intent-filter>
         </activity>
diff --git a/res/layout/proxy.xml b/res/layout/proxy.xml
index 3ecbb80..76f200e 100644
--- a/res/layout/proxy.xml
+++ b/res/layout/proxy.xml
@@ -22,7 +22,8 @@
     android:paddingLeft="6dip"
     android:paddingRight="6dip"
     android:paddingBottom="3dip"
-    android:layout_width="match_parent" android:layout_height="wrap_content">
+    android:layout_width="match_parent" android:layout_height="wrap_content"
+    android:scrollbars="vertical" >
 
     <TextView
         android:textStyle="bold"
@@ -46,11 +47,27 @@
         android:layout_width="wrap_content" android:layout_height="wrap_content"
         android:text="@string/proxy_port_label" />
 
-    <EditText android:id="@+id/port" 
+    <EditText android:id="@+id/port"
         android:numeric="integer"
+        android:maxLines="1"
+        android:layout_marginTop="2dip"
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:scrollHorizontally="true" />
+
+    <TextView
+        android:textStyle="bold"
+        android:maxLines="1"
+        android:layout_marginTop="4dip"
+        android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:text="@string/proxy_exclusionlist_label" />
+
+    <EditText android:id="@+id/exclusionlist"
         android:maxLines="1" 
         android:layout_marginTop="2dip"
         android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:autoText="false"
+        android:capitalize="none"
+        android:singleLine="true"
         android:scrollHorizontally="true" />
 
     <LinearLayout 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a725166..71970d0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -292,14 +292,20 @@
     <!-- Used for diagnostic screens, precise translation is not necessary -->
     <string name="intent_sender_account_label">Account: </string>
 
+    <!-- HTTP proxy settings title -->
+    <string name="proxy_settings_title">Proxy Settings</string>
+    <!-- HTTP proxy settings summary -->
+    <string name="proxy_settings_summary">Set the global HTTP proxy and exclusion lists</string>
     <!-- HTTP proxy settings. Button to clear the proxy box. -->
     <string name="proxy_clear_text">Clear</string>
     <!-- HTTP proxy settings. The port number label. -->
     <string name="proxy_port_label">Port</string>
+    <!-- HTTP proxy settings. The exclusion list label. -->
+    <string name="proxy_exclusionlist_label">No Proxy for</string>
     <!-- HTTP proxy settings. The button to restore the defaults. -->
     <string name="proxy_defaultView_text">Restore defaults</string>
     <!-- HTTP proxy settings. The button to save. -->
-    <string name="proxy_action_text">Save</string>
+    <string name="proxy_action_text">Done</string>
     <!-- HTTP proxy settings. The text field for the hostname -->
     <string name="proxy_hostname_label">Hostname</string>
     <!-- HTTP proxy settings. Title if there is an error-->
@@ -308,6 +314,8 @@
     <string name="proxy_error_dismiss">OK</string>
     <!-- HTTP proxy settings. The error if the hostname is not valid -->
     <string name="proxy_error_invalid_host">The hostname you typed is not valid.</string>
+    <!-- HTTP proxy settings. The error if the exclusion list is not valid -->
+    <string name="proxy_error_invalid_exclusion_list">The exclusion list you typed is not properly formatted. Please enter a comma-separated list of excluded domains.</string>
     <!-- HTTP proxy settings. Error msg -->
     <string name="proxy_error_empty_port">You must complete the port field.</string>
     <!-- HTTP proxy settings. Error msg -->
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index 7c91d50..13b8344 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -86,4 +86,14 @@
             android:targetClass="com.android.phone.Settings" />
     </PreferenceScreen>
 
+    <PreferenceScreen
+        android:key="proxy_settings"
+        android:title="@string/proxy_settings_title"
+        android:summary="@string/proxy_settings_summary" >
+        <intent
+            android:action="android.intent.action.MAIN"
+            android:targetPackage="com.android.settings"
+            android:targetClass="com.android.settings.ProxySelector" />
+    </PreferenceScreen>
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/ProxySelector.java b/src/com/android/settings/ProxySelector.java
index 66c81c6..9e19600 100644
--- a/src/com/android/settings/ProxySelector.java
+++ b/src/com/android/settings/ProxySelector.java
@@ -18,8 +18,10 @@
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.admin.DevicePolicyManager;
 import android.app.Dialog;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
 import android.net.Proxy;
 import android.os.Bundle;
@@ -28,6 +30,7 @@
 import android.text.Spannable;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnFocusChangeListener;
@@ -62,16 +65,24 @@
 public class ProxySelector extends Activity
 {
     private final static String LOGTAG = "Settings";
+    private View mInitialView;
+    private LayoutInflater mInflater;
+    boolean mUserSetGlobalProxy;
 
     EditText    mHostnameField;
     EditText    mPortField;
+    EditText    mExclusionListField;
     Button      mOKButton;
+    DevicePolicyManager mDPM;
 
     // Matches blank input, ips, and domain names
     private static final String HOSTNAME_REGEXP = "^$|^[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*$";
     private static final Pattern HOSTNAME_PATTERN;
+    private static final String EXCLLIST_REGEXP = "$|^(.?[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*)+(,(.?[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*))*$";
+    private static final Pattern EXCLLIST_PATTERN;
     static {
         HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
+        EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
     }
 
     private static final int ERROR_DIALOG_ID = 0;
@@ -81,8 +92,16 @@
 
         if (android.util.Config.LOGV) Log.v(LOGTAG, "[ProxySelector] onStart");
 
-        setContentView(R.layout.proxy);
+        mInflater = LayoutInflater.from(this);
+        if (mInitialView == null) {
+            mInitialView = mInflater.inflate(R.layout.proxy, null);
+        }
+        mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
+        mUserSetGlobalProxy = (mDPM.getGlobalProxyAdmin() == null);
+
+        setContentView(mInitialView);
         initView();
+        // TODO: Populate based on connection status
         populateFields(false);
     }
 
@@ -91,7 +110,8 @@
         if (id == ERROR_DIALOG_ID) {
             String hostname = mHostnameField.getText().toString().trim();
             String portStr = mPortField.getText().toString().trim();
-            String msg = getString(validate(hostname, portStr));
+            String exclList = mExclusionListField.getText().toString().trim();
+            String msg = getString(validate(hostname, portStr, exclList));
 
             return new AlertDialog.Builder(this)
                     .setTitle(R.string.proxy_error)
@@ -109,7 +129,8 @@
         if (id == ERROR_DIALOG_ID) {
             String hostname = mHostnameField.getText().toString().trim();
             String portStr = mPortField.getText().toString().trim();
-            String msg = getString(validate(hostname, portStr));
+            String exclList = mExclusionListField.getText().toString().trim();
+            String msg = getString(validate(hostname, portStr, exclList));
             ((AlertDialog)dialog).setMessage(msg);
         }
     }
@@ -123,27 +144,41 @@
         mPortField.setOnClickListener(mOKHandler);
         mPortField.setOnFocusChangeListener(mOnFocusChangeHandler);
 
+        mExclusionListField = (EditText)findViewById(R.id.exclusionlist);
+        mExclusionListField.setOnFocusChangeListener(mOnFocusChangeHandler);
+
         mOKButton = (Button)findViewById(R.id.action);
         mOKButton.setOnClickListener(mOKHandler);
 
-        Button b = (Button)findViewById(R.id.clear);
-        b.setOnClickListener(mClearHandler);
+        Button clearButton = (Button)findViewById(R.id.clear);
+        clearButton.setOnClickListener(mClearHandler);
 
-        b = (Button)findViewById(R.id.defaultView);
-        b.setOnClickListener(mDefaultHandler);
-    }
+        Button defButton = (Button)findViewById(R.id.defaultView);
+        defButton.setOnClickListener(mDefaultHandler);
+
+        // Disable UI if the Global Proxy is being controlled by a Device Admin
+        mHostnameField.setEnabled(mUserSetGlobalProxy);
+        mPortField.setEnabled(mUserSetGlobalProxy);
+        mExclusionListField.setEnabled(mUserSetGlobalProxy);
+        mOKButton.setEnabled(mUserSetGlobalProxy);
+        clearButton.setEnabled(mUserSetGlobalProxy);
+        defButton.setEnabled(mUserSetGlobalProxy);
+}
 
     void populateFields(boolean useDefault) {
         String hostname = null;
         int port = -1;
+        String exclList = null;
         if (useDefault) {
             // Use the default proxy settings provided by the carrier
             hostname = Proxy.getDefaultHost();
             port = Proxy.getDefaultPort();
         } else {
             // Use the last setting given by the user
+            ContentResolver res = getContentResolver();
             hostname = Proxy.getHost(this);
             port = Proxy.getPort(this);
+            exclList = Settings.Secure.getString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST);
         }
 
         if (hostname == null) {
@@ -155,6 +190,8 @@
         String portStr = port == -1 ? "" : Integer.toString(port);
         mPortField.setText(portStr);
 
+        mExclusionListField.setText(exclList);
+
         Intent intent = getIntent();
 
         String buttonLabel = intent.getStringExtra("button-label");
@@ -172,11 +209,14 @@
      * validate syntax of hostname and port entries
      * @return 0 on success, string resource ID on failure
      */
-    int validate(String hostname, String port) {
+    int validate(String hostname, String port, String exclList) {
         Matcher match = HOSTNAME_PATTERN.matcher(hostname);
+        Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList);
 
         if (!match.matches()) return R.string.proxy_error_invalid_host;
 
+        if (!listMatch.matches()) return R.string.proxy_error_invalid_exclusion_list;
+
         if (hostname.length() > 0 && port.length() == 0) {
             return R.string.proxy_error_empty_port;
         }
@@ -205,9 +245,10 @@
 
         String hostname = mHostnameField.getText().toString().trim();
         String portStr = mPortField.getText().toString().trim();
+        String exclList = mExclusionListField.getText().toString().trim();
         int port = -1;
 
-        int result = validate(hostname, portStr);
+        int result = validate(hostname, portStr, exclList);
         if (result > 0) {
             showDialog(ERROR_DIALOG_ID);
             return false;
@@ -244,6 +285,7 @@
             hostname += ':' + portStr;
         }
         Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY, hostname);
+        Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST, exclList);
         sendBroadcast(new Intent(Proxy.PROXY_CHANGE_ACTION));
 
         return true;
@@ -261,12 +303,14 @@
             public void onClick(View v) {
                 mHostnameField.setText("");
                 mPortField.setText("");
+                mExclusionListField.setText("");
             }
         };
 
     OnClickListener mDefaultHandler = new OnClickListener() {
             public void onClick(View v) {
-                populateFields(true);
+                // TODO: populate based on connection status
+                populateFields(false);
             }
         };
 
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 78cf8cf..853fe85 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -16,6 +16,7 @@
 
 package com.android.settings;
 
+import android.app.admin.DevicePolicyManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.Intent;
@@ -45,6 +46,7 @@
     private static final String KEY_BT_SETTINGS = "bt_settings";
     private static final String KEY_VPN_SETTINGS = "vpn_settings";
     private static final String KEY_TETHER_SETTINGS = "tether_settings";
+    private static final String KEY_PROXY_SETTINGS = "proxy_settings";
     public static final String EXIT_ECM_RESULT = "exit_ecm_result";
     public static final int REQUEST_CODE_EXIT_ECM = 1;
 
@@ -118,6 +120,11 @@
             findPreference(KEY_BT_SETTINGS).setEnabled(false);
         }
 
+        // Enable Proxy selector settings if allowed.
+        Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS);
+        DevicePolicyManager mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
+        mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null);
+
         // Disable Tethering if it's not allowed
         ConnectivityManager cm =
                 (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);