Merge "Add device-owner based setting of global proxy."
diff --git a/api/current.txt b/api/current.txt
index d29580b..fc662a6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5231,6 +5231,7 @@
     method public void setProfileEnabled(android.content.ComponentName);
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setRecommendedGlobalProxy(android.content.ComponentName, android.net.ProxyInfo);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void wipeData(int);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 57e0f63..785987f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.RestrictionsManager;
+import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Process;
@@ -1276,6 +1277,32 @@
     }
 
     /**
+     * Set a network-independent global HTTP proxy.  This is not normally what you want
+     * for typical HTTP proxies - they are generally network dependent.  However if you're
+     * doing something unusual like general internal filtering this may be useful.  On
+     * a private network where the proxy is not accessible, you may break HTTP using this.
+     *
+     * <p>This method requires the caller to be the device owner.
+     *
+     * <p>This proxy is only a recommendation and it is possible that some apps will ignore it.
+     * @see ProxyInfo
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated
+     *            with.
+     * @param proxyInfo The a {@link ProxyInfo} object defining the new global
+     *        HTTP proxy.  A {@code null} value will clear the global HTTP proxy.
+     */
+    public void setRecommendedGlobalProxy(ComponentName admin, ProxyInfo proxyInfo) {
+        if (mService != null) {
+            try {
+                mService.setRecommendedGlobalProxy(admin, proxyInfo);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
      * Returns the component name setting the global proxy.
      * @return ComponentName object of the device admin that set the global proxy, or
      *            null if no admin has set the proxy.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7d7a312..3d80869 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.RemoteCallback;
 import android.os.UserHandle;
@@ -78,6 +79,7 @@
 
     ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList, int userHandle);
     ComponentName getGlobalProxyAdmin(int userHandle);
+    void setRecommendedGlobalProxy(in ComponentName admin, in ProxyInfo proxyInfo);
 
     int setStorageEncryption(in ComponentName who, boolean encrypt, int userHandle);
     boolean getStorageEncryption(in ComponentName who, int userHandle);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a0b75b5..8ca437f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.net.ConnectivityManager;
 import android.net.ProxyInfo;
 import android.os.Binder;
 import android.os.Bundle;
@@ -2722,6 +2723,20 @@
         return null;
     }
 
+    public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) {
+        synchronized (this) {
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        }
+        long token = Binder.clearCallingIdentity();
+        try {
+            ConnectivityManager connectivityManager = (ConnectivityManager)
+                    mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+            connectivityManager.setGlobalProxy(proxyInfo);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private void resetGlobalProxyLocked(DevicePolicyData policy) {
         final int N = policy.mAdminList.size();
         for (int i = 0; i < N; i++) {