Device Policy Manager changes to enable Global Proxy.
Change-Id: I8489df7d28e4c5312e10d5cecc8e2a182413a034
This commit is contained in:
@@ -34339,6 +34339,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getGlobalProxyAdmin"
|
||||
return="android.content.ComponentName"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getMaximumFailedPasswordsForWipe"
|
||||
return="int"
|
||||
abstract="false"
|
||||
@@ -34558,6 +34569,23 @@
|
||||
<parameter name="flags" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGlobalProxy"
|
||||
return="android.content.ComponentName"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="admin" type="android.content.ComponentName">
|
||||
</parameter>
|
||||
<parameter name="proxySpec" type="java.net.Proxy">
|
||||
</parameter>
|
||||
<parameter name="exclusionList" type="java.util.List<java.lang.String>">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setMaximumFailedPasswordsForWipe"
|
||||
return="void"
|
||||
abstract="false"
|
||||
|
||||
@@ -103,6 +103,16 @@ public final class DeviceAdminInfo implements Parcelable {
|
||||
*/
|
||||
public static final int USES_POLICY_WIPE_DATA = 4;
|
||||
|
||||
/**
|
||||
* A type of policy that this device admin can use: able to specify the
|
||||
* device Global Proxy, via {@link DevicePolicyManager#setGlobalProxy}.
|
||||
*
|
||||
* <p>To control this policy, the device admin must have a "set-global-proxy"
|
||||
* tag in the "uses-policies" section of its meta-data.
|
||||
* @hide
|
||||
*/
|
||||
public static final int USES_POLICY_SETS_GLOBAL_PROXY = 5;
|
||||
|
||||
/** @hide */
|
||||
public static class PolicyInfo {
|
||||
public final int ident;
|
||||
@@ -138,6 +148,9 @@ public final class DeviceAdminInfo implements Parcelable {
|
||||
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_FORCE_LOCK, "force-lock",
|
||||
com.android.internal.R.string.policylab_forceLock,
|
||||
com.android.internal.R.string.policydesc_forceLock));
|
||||
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_SETS_GLOBAL_PROXY, "set-global-proxy",
|
||||
com.android.internal.R.string.policylab_setGlobalProxy,
|
||||
com.android.internal.R.string.policydesc_setGlobalProxy));
|
||||
|
||||
for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
|
||||
PolicyInfo pi = sPoliciesDisplayOrder.get(i);
|
||||
@@ -328,7 +341,7 @@ public final class DeviceAdminInfo implements Parcelable {
|
||||
* the given policy control. The possible policy identifier inputs are:
|
||||
* {@link #USES_POLICY_LIMIT_PASSWORD}, {@link #USES_POLICY_WATCH_LOGIN},
|
||||
* {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK},
|
||||
* {@link #USES_POLICY_WIPE_DATA}.
|
||||
* {@link #USES_POLICY_WIPE_DATA}, {@link #USES_POLICY_SETS_GLOBAL_PROXY}.
|
||||
*/
|
||||
public boolean usesPolicy(int policyIdent) {
|
||||
return (mUsesPolicies & (1<<policyIdent)) != 0;
|
||||
|
||||
@@ -32,6 +32,8 @@ import android.os.ServiceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -914,6 +916,93 @@ public class DevicePolicyManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by an application that is administering the device to set the
|
||||
* global proxy and exclusion list.
|
||||
* <p>
|
||||
* The calling device admin must have requested
|
||||
* {@link DeviceAdminInfo#USES_POLICY_SETS_GLOBAL_PROXY} to be able to call
|
||||
* this method; if it has not, a security exception will be thrown.
|
||||
* Only the first device admin can set the proxy. If a second admin attempts
|
||||
* to set the proxy, the {@link ComponentName} of the admin originally setting the
|
||||
* proxy will be returned. If successful in setting the proxy, null will
|
||||
* be returned.
|
||||
* The method can be called repeatedly by the device admin alrady setting the
|
||||
* proxy to update the proxy and exclusion list.
|
||||
*
|
||||
* @param admin Which {@link DeviceAdminReceiver} this request is associated
|
||||
* with.
|
||||
* @param proxySpec the global proxy desired. Must be an HTTP Proxy.
|
||||
* Pass Proxy.NO_PROXY to reset the proxy.
|
||||
* @param exclusionList a list of domains to be excluded from the global proxy.
|
||||
* @param proxyAdmins an empty, mutable list that will contain any proxy admins
|
||||
* that define a global proxy.
|
||||
* @return returns null if the proxy was successfully set, or a {@link ComponentName}
|
||||
* of the device admin that sets thew proxy otherwise.
|
||||
*/
|
||||
public ComponentName setGlobalProxy(ComponentName admin, Proxy proxySpec,
|
||||
List<String> exclusionList ) {
|
||||
if (proxySpec == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (mService != null) {
|
||||
try {
|
||||
String hostSpec;
|
||||
String exclSpec;
|
||||
if (proxySpec.equals(Proxy.NO_PROXY)) {
|
||||
hostSpec = null;
|
||||
exclSpec = null;
|
||||
} else {
|
||||
if (!proxySpec.type().equals(Proxy.Type.HTTP)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
InetSocketAddress sa = (InetSocketAddress)proxySpec.address();
|
||||
String hostName = sa.getHostName();
|
||||
int port = sa.getPort();
|
||||
StringBuilder hostBuilder = new StringBuilder();
|
||||
hostSpec = hostBuilder.append(hostName)
|
||||
.append(":").append(Integer.toString(port)).toString();
|
||||
if (exclusionList == null) {
|
||||
exclSpec = "";
|
||||
} else {
|
||||
StringBuilder listBuilder = new StringBuilder();
|
||||
boolean firstDomain = true;
|
||||
for (String exclDomain : exclusionList) {
|
||||
if (!firstDomain) {
|
||||
listBuilder = listBuilder.append(",");
|
||||
} else {
|
||||
firstDomain = false;
|
||||
}
|
||||
listBuilder = listBuilder.append(exclDomain.trim());
|
||||
}
|
||||
exclSpec = listBuilder.toString();
|
||||
}
|
||||
android.net.Proxy.validate(hostName, Integer.toString(port), exclSpec);
|
||||
}
|
||||
return mService.setGlobalProxy(admin, hostSpec, exclSpec);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public ComponentName getGlobalProxyAdmin() {
|
||||
if (mService != null) {
|
||||
try {
|
||||
return mService.getGlobalProxyAdmin();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed talking with device policy service", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -1007,4 +1096,5 @@ public class DevicePolicyManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ interface IDevicePolicyManager {
|
||||
void lockNow();
|
||||
|
||||
void wipeData(int flags);
|
||||
|
||||
ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList);
|
||||
ComponentName getGlobalProxyAdmin();
|
||||
|
||||
void setActiveAdmin(in ComponentName policyReceiver);
|
||||
boolean isAdminActive(in ComponentName policyReceiver);
|
||||
|
||||
@@ -1252,6 +1252,11 @@
|
||||
<!-- Description of policy access to wipe the user's data -->
|
||||
<string name="policydesc_wipeData">Perform a factory reset, deleting
|
||||
all of your data without any confirmation.</string>
|
||||
<string name="policylab_setGlobalProxy">Set the device global proxy</string>
|
||||
<!-- Description of policy access to wipe the user's data -->
|
||||
<string name="policydesc_setGlobalProxy">Set the device global proxy
|
||||
to be used while policy is enabled. Only the first device admin
|
||||
sets the effective global proxy.</string>
|
||||
|
||||
<!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
|
||||
<!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.IDevicePolicyManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -46,6 +47,8 @@ import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.net.Proxy;
|
||||
import android.provider.Settings;
|
||||
import android.util.Slog;
|
||||
import android.util.PrintWriterPrinter;
|
||||
import android.util.Printer;
|
||||
@@ -58,9 +61,11 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Implementation of the device policy APIs.
|
||||
@@ -105,6 +110,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
long maximumTimeToUnlock = 0;
|
||||
int maximumFailedPasswordsForWipe = 0;
|
||||
|
||||
// TODO: review implementation decisions with frameworks team
|
||||
boolean specifiesGlobalProxy = false;
|
||||
String globalProxySpec = null;
|
||||
String globalProxyExclusionList = null;
|
||||
|
||||
ActiveAdmin(DeviceAdminInfo _info) {
|
||||
info = _info;
|
||||
}
|
||||
@@ -171,6 +181,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
|
||||
out.endTag(null, "max-failed-password-wipe");
|
||||
}
|
||||
if (specifiesGlobalProxy) {
|
||||
out.startTag(null, "specifies-global-proxy");
|
||||
out.attribute(null, "value", Boolean.toString(specifiesGlobalProxy));
|
||||
out.endTag(null, "specifies_global_proxy");
|
||||
if (globalProxySpec != null) {
|
||||
out.startTag(null, "global-proxy-spec");
|
||||
out.attribute(null, "value", globalProxySpec);
|
||||
out.endTag(null, "global-proxy-spec");
|
||||
}
|
||||
if (globalProxyExclusionList != null) {
|
||||
out.startTag(null, "global-proxy-exclusion-list");
|
||||
out.attribute(null, "value", globalProxyExclusionList);
|
||||
out.endTag(null, "global-proxy-exclusion-list");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readFromXml(XmlPullParser parser)
|
||||
@@ -218,6 +243,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
} else if ("max-failed-password-wipe".equals(tag)) {
|
||||
maximumFailedPasswordsForWipe = Integer.parseInt(
|
||||
parser.getAttributeValue(null, "value"));
|
||||
} else if ("specifies-global-proxy".equals(tag)) {
|
||||
specifiesGlobalProxy = Boolean.getBoolean(
|
||||
parser.getAttributeValue(null, "value"));
|
||||
} else if ("global-proxy-spec".equals(tag)) {
|
||||
globalProxySpec =
|
||||
parser.getAttributeValue(null, "value");
|
||||
} else if ("global-proxy-exclusion-list".equals(tag)) {
|
||||
globalProxyExclusionList =
|
||||
parser.getAttributeValue(null, "value");
|
||||
} else {
|
||||
Slog.w(TAG, "Unknown admin tag: " + tag);
|
||||
}
|
||||
@@ -256,6 +290,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
pw.println(maximumTimeToUnlock);
|
||||
pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
|
||||
pw.println(maximumFailedPasswordsForWipe);
|
||||
pw.print(prefix); pw.print("specifiesGlobalProxy=");
|
||||
pw.println(specifiesGlobalProxy);
|
||||
if (globalProxySpec != null) {
|
||||
pw.print(prefix); pw.print("globalProxySpec=");
|
||||
pw.println(globalProxySpec);
|
||||
}
|
||||
if (globalProxyExclusionList != null) {
|
||||
pw.print(prefix); pw.print("globalProxyEclusionList=");
|
||||
pw.println(globalProxyExclusionList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,12 +414,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
void removeActiveAdminLocked(ComponentName adminReceiver) {
|
||||
ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
|
||||
if (admin != null) {
|
||||
boolean doProxyCleanup =
|
||||
admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
|
||||
sendAdminCommandLocked(admin,
|
||||
DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED);
|
||||
// XXX need to wait for it to complete.
|
||||
mAdminList.remove(admin);
|
||||
mAdminMap.remove(adminReceiver);
|
||||
validatePasswordOwnerLocked();
|
||||
if (doProxyCleanup) {
|
||||
resetGlobalProxy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1417,6 +1466,94 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
|
||||
String exclusionList) {
|
||||
synchronized(this) {
|
||||
if (who == null) {
|
||||
throw new NullPointerException("ComponentName is null");
|
||||
}
|
||||
|
||||
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
|
||||
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
|
||||
|
||||
// Scan through active admins and find if anyone has already
|
||||
// set the global proxy.
|
||||
final int N = mAdminList.size();
|
||||
Set<ComponentName> compSet = mAdminMap.keySet();
|
||||
for (ComponentName component : compSet) {
|
||||
ActiveAdmin ap = mAdminMap.get(component);
|
||||
if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
|
||||
// Another admin already sets the global proxy
|
||||
// Return it to the caller.
|
||||
return component;
|
||||
}
|
||||
}
|
||||
if (proxySpec == null) {
|
||||
admin.specifiesGlobalProxy = false;
|
||||
admin.globalProxySpec = null;
|
||||
admin.globalProxyExclusionList = null;
|
||||
} else {
|
||||
|
||||
admin.specifiesGlobalProxy = true;
|
||||
admin.globalProxySpec = proxySpec;
|
||||
admin.globalProxyExclusionList = exclusionList;
|
||||
}
|
||||
|
||||
// Reset the global proxy accordingly
|
||||
// Do this using system permissions, as apps cannot write to secure settings
|
||||
long origId = Binder.clearCallingIdentity();
|
||||
resetGlobalProxy();
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ComponentName getGlobalProxyAdmin() {
|
||||
synchronized(this) {
|
||||
// Scan through active admins and find if anyone has already
|
||||
// set the global proxy.
|
||||
final int N = mAdminList.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
ActiveAdmin ap = mAdminList.get(i);
|
||||
if (ap.specifiesGlobalProxy) {
|
||||
// Device admin sets the global proxy
|
||||
// Return it to the caller.
|
||||
return ap.info.getComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
// No device admin sets the global proxy.
|
||||
return null;
|
||||
}
|
||||
|
||||
private void resetGlobalProxy() {
|
||||
final int N = mAdminList.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
ActiveAdmin ap = mAdminList.get(i);
|
||||
if (ap.specifiesGlobalProxy) {
|
||||
saveGlobalProxy(ap.globalProxySpec, ap.globalProxyExclusionList);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// No device admins defining global proxies - reset global proxy settings to none
|
||||
saveGlobalProxy(null, null);
|
||||
}
|
||||
|
||||
private void saveGlobalProxy(String proxySpec, String exclusionList) {
|
||||
if (exclusionList == null) {
|
||||
exclusionList = "";
|
||||
}
|
||||
if (proxySpec == null) {
|
||||
proxySpec = "";
|
||||
}
|
||||
// Remove white spaces
|
||||
proxySpec = proxySpec.trim();
|
||||
exclusionList = exclusionList.trim();
|
||||
ContentResolver res = mContext.getContentResolver();
|
||||
Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY, proxySpec);
|
||||
Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST, exclusionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
||||
|
||||
Reference in New Issue
Block a user