Merge "Policy and rules work for ConnectivityManager."
This commit is contained in:
@@ -110,6 +110,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/net/IConnectivityManager.aidl \
|
||||
core/java/android/net/INetworkManagementEventObserver.aidl \
|
||||
core/java/android/net/IThrottleManager.aidl \
|
||||
core/java/android/net/INetworkPolicyListener.aidl \
|
||||
core/java/android/net/INetworkPolicyManager.aidl \
|
||||
core/java/android/nfc/ILlcpConnectionlessSocket.aidl \
|
||||
core/java/android/nfc/ILlcpServiceSocket.aidl \
|
||||
|
||||
@@ -11041,6 +11041,7 @@ package android.net {
|
||||
method public static android.net.NetworkInfo.DetailedState valueOf(java.lang.String);
|
||||
method public static final android.net.NetworkInfo.DetailedState[] values();
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState BLOCKED;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTED;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTING;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.os.Binder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* Class that answers queries about the state of network connectivity. It also
|
||||
@@ -40,8 +39,9 @@ import java.net.UnknownHostException;
|
||||
* state of the available networks</li>
|
||||
* </ol>
|
||||
*/
|
||||
public class ConnectivityManager
|
||||
{
|
||||
public class ConnectivityManager {
|
||||
private static final String TAG = "ConnectivityManager";
|
||||
|
||||
/**
|
||||
* A change in network connectivity has occurred. A connection has either
|
||||
* been established or lost. The NetworkInfo for the affected network is
|
||||
@@ -109,7 +109,7 @@ public class ConnectivityManager
|
||||
* The lookup key for an int that provides information about
|
||||
* our connection to the internet at large. 0 indicates no connection,
|
||||
* 100 indicates a great connection. Retrieve it with
|
||||
* {@link android.content.Intent@getIntExtra(String)}.
|
||||
* {@link android.content.Intent#getIntExtra(String, int)}.
|
||||
* {@hide}
|
||||
*/
|
||||
public static final String EXTRA_INET_CONDITION = "inetCondition";
|
||||
@@ -120,13 +120,12 @@ public class ConnectivityManager
|
||||
* <p>
|
||||
* If an application uses the network in the background, it should listen
|
||||
* for this broadcast and stop using the background data if the value is
|
||||
* false.
|
||||
* {@code false}.
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED =
|
||||
"android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
|
||||
|
||||
|
||||
/**
|
||||
* Broadcast Action: The network connection may not be good
|
||||
* uses {@code ConnectivityManager.EXTRA_INET_CONDITION} and
|
||||
@@ -255,7 +254,7 @@ public class ConnectivityManager
|
||||
|
||||
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
|
||||
|
||||
private IConnectivityManager mService;
|
||||
private final IConnectivityManager mService;
|
||||
|
||||
static public boolean isNetworkTypeValid(int networkType) {
|
||||
return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
|
||||
@@ -284,6 +283,15 @@ public class ConnectivityManager
|
||||
}
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public NetworkInfo getActiveNetworkInfoForUid(int uid) {
|
||||
try {
|
||||
return mService.getActiveNetworkInfoForUid(uid);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkInfo getNetworkInfo(int networkType) {
|
||||
try {
|
||||
return mService.getNetworkInfo(networkType);
|
||||
@@ -300,7 +308,7 @@ public class ConnectivityManager
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
/** {@hide} */
|
||||
public LinkProperties getActiveLinkProperties() {
|
||||
try {
|
||||
return mService.getActiveLinkProperties();
|
||||
@@ -309,7 +317,7 @@ public class ConnectivityManager
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
/** {@hide} */
|
||||
public LinkProperties getLinkProperties(int networkType) {
|
||||
try {
|
||||
return mService.getLinkProperties(networkType);
|
||||
@@ -478,20 +486,12 @@ public class ConnectivityManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't allow use of default constructor.
|
||||
*/
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
private ConnectivityManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public ConnectivityManager(IConnectivityManager service) {
|
||||
if (service == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"ConnectivityManager() cannot be constructed with null service");
|
||||
throw new IllegalArgumentException("missing IConnectivityManager");
|
||||
}
|
||||
mService = service;
|
||||
}
|
||||
|
||||
@@ -33,13 +33,11 @@ interface IConnectivityManager
|
||||
int getNetworkPreference();
|
||||
|
||||
NetworkInfo getActiveNetworkInfo();
|
||||
|
||||
NetworkInfo getActiveNetworkInfoForUid(int uid);
|
||||
NetworkInfo getNetworkInfo(int networkType);
|
||||
|
||||
NetworkInfo[] getAllNetworkInfo();
|
||||
|
||||
LinkProperties getActiveLinkProperties();
|
||||
|
||||
LinkProperties getLinkProperties(int networkType);
|
||||
|
||||
boolean setRadios(boolean onOff);
|
||||
|
||||
24
core/java/android/net/INetworkPolicyListener.aidl
Normal file
24
core/java/android/net/INetworkPolicyListener.aidl
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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 android.net;
|
||||
|
||||
/** {@hide} */
|
||||
oneway interface INetworkPolicyListener {
|
||||
|
||||
void onRulesChanged(int uid, int uidRules);
|
||||
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.net;
|
||||
|
||||
import android.net.INetworkPolicyListener;
|
||||
|
||||
/**
|
||||
* Interface that creates and modifies network policy rules.
|
||||
*
|
||||
@@ -26,6 +28,9 @@ interface INetworkPolicyManager {
|
||||
void setUidPolicy(int uid, int policy);
|
||||
int getUidPolicy(int uid);
|
||||
|
||||
void registerListener(INetworkPolicyListener listener);
|
||||
void unregisterListener(INetworkPolicyListener listener);
|
||||
|
||||
// TODO: build API to surface stats details for settings UI
|
||||
|
||||
}
|
||||
|
||||
@@ -74,7 +74,9 @@ public class NetworkInfo implements Parcelable {
|
||||
/** IP traffic not available. */
|
||||
DISCONNECTED,
|
||||
/** Attempt to connect failed. */
|
||||
FAILED
|
||||
FAILED,
|
||||
/** Access to this network is blocked. */
|
||||
BLOCKED
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,6 +98,7 @@ public class NetworkInfo implements Parcelable {
|
||||
stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING);
|
||||
stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
|
||||
stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
|
||||
stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
|
||||
}
|
||||
|
||||
private int mNetworkType;
|
||||
@@ -138,6 +141,23 @@ public class NetworkInfo implements Parcelable {
|
||||
mIsRoaming = false;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public NetworkInfo(NetworkInfo source) {
|
||||
if (source != null) {
|
||||
mNetworkType = source.mNetworkType;
|
||||
mSubtype = source.mSubtype;
|
||||
mTypeName = source.mTypeName;
|
||||
mSubtypeName = source.mSubtypeName;
|
||||
mState = source.mState;
|
||||
mDetailedState = source.mDetailedState;
|
||||
mReason = source.mReason;
|
||||
mExtraInfo = source.mExtraInfo;
|
||||
mIsFailover = source.mIsFailover;
|
||||
mIsRoaming = source.mIsRoaming;
|
||||
mIsAvailable = source.mIsAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports the type of network (currently mobile or Wi-Fi) to which the
|
||||
* info in this object pertains.
|
||||
|
||||
@@ -28,12 +28,13 @@ public class NetworkPolicyManager {
|
||||
|
||||
/** No specific network policy, use system default. */
|
||||
public static final int POLICY_NONE = 0x0;
|
||||
/** Reject network usage when application in background. */
|
||||
public static final int POLICY_REJECT_BACKGROUND = 0x1;
|
||||
/** Reject network usage on paid network connections. */
|
||||
public static final int POLICY_REJECT_PAID = 0x2;
|
||||
/** Application should conserve data. */
|
||||
public static final int POLICY_CONSERVE_DATA = 0x4;
|
||||
/** Reject network usage on paid networks when application in background. */
|
||||
public static final int POLICY_REJECT_PAID_BACKGROUND = 0x1;
|
||||
|
||||
/** All network traffic should be allowed. */
|
||||
public static final int RULE_ALLOW_ALL = 0x0;
|
||||
/** Reject traffic on paid networks. */
|
||||
public static final int RULE_REJECT_PAID = 0x1;
|
||||
|
||||
private INetworkPolicyManager mService;
|
||||
|
||||
@@ -51,9 +52,8 @@ public class NetworkPolicyManager {
|
||||
/**
|
||||
* Set policy flags for specific UID.
|
||||
*
|
||||
* @param policy {@link #POLICY_NONE} or combination of
|
||||
* {@link #POLICY_REJECT_BACKGROUND}, {@link #POLICY_REJECT_PAID},
|
||||
* or {@link #POLICY_CONSERVE_DATA}.
|
||||
* @param policy {@link #POLICY_NONE} or combination of flags like
|
||||
* {@link #POLICY_REJECT_PAID_BACKGROUND}.
|
||||
*/
|
||||
public void setUidPolicy(int uid, int policy) {
|
||||
try {
|
||||
@@ -69,5 +69,4 @@ public class NetworkPolicyManager {
|
||||
return POLICY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
|
||||
import static android.net.ConnectivityManager.isNetworkTypeValid;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
|
||||
import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
|
||||
|
||||
import android.bluetooth.BluetoothTetheringDataTracker;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -26,11 +31,13 @@ import android.net.ConnectivityManager;
|
||||
import android.net.DummyDataStateTracker;
|
||||
import android.net.EthernetDataTracker;
|
||||
import android.net.IConnectivityManager;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.INetworkPolicyListener;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.MobileDataStateTracker;
|
||||
import android.net.NetworkConfig;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkInfo.DetailedState;
|
||||
import android.net.NetworkStateTracker;
|
||||
import android.net.NetworkUtils;
|
||||
import android.net.Proxy;
|
||||
@@ -54,6 +61,7 @@ import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.EventLog;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.telephony.Phone;
|
||||
import com.android.server.connectivity.Tethering;
|
||||
@@ -62,13 +70,12 @@ import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -78,6 +85,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
private static final boolean DBG = true;
|
||||
private static final String TAG = "ConnectivityService";
|
||||
|
||||
private static final boolean LOGD_RULES = false;
|
||||
|
||||
// how long to wait before switching back to a radio's default network
|
||||
private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
|
||||
// system property that can override the above value
|
||||
@@ -91,6 +100,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
private Tethering mTethering;
|
||||
private boolean mTetheringConfigValid = false;
|
||||
|
||||
/** Currently active network rules by UID. */
|
||||
private SparseIntArray mUidRules = new SparseIntArray();
|
||||
|
||||
/**
|
||||
* Sometimes we want to refer to the individual network state
|
||||
* trackers separately, and sometimes we just want to treat them
|
||||
@@ -128,6 +140,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
|
||||
|
||||
private INetworkManagementService mNetd;
|
||||
private INetworkPolicyManager mPolicyManager;
|
||||
|
||||
private static final int ENABLED = 1;
|
||||
private static final int DISABLED = 0;
|
||||
@@ -250,14 +263,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
RadioAttributes[] mRadioAttributes;
|
||||
|
||||
public static synchronized ConnectivityService getInstance(Context context) {
|
||||
if (sServiceInstance == null) {
|
||||
sServiceInstance = new ConnectivityService(context);
|
||||
}
|
||||
return sServiceInstance;
|
||||
}
|
||||
|
||||
private ConnectivityService(Context context) {
|
||||
public ConnectivityService(
|
||||
Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
|
||||
if (DBG) log("ConnectivityService starting up");
|
||||
|
||||
HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
|
||||
@@ -290,9 +297,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
loge("Error setting defaultDns using " + dns);
|
||||
}
|
||||
|
||||
mContext = context;
|
||||
mContext = checkNotNull(context, "missing Context");
|
||||
mNetd = checkNotNull(netd, "missing INetworkManagementService");
|
||||
mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
|
||||
|
||||
PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
|
||||
try {
|
||||
mPolicyManager.registerListener(mPolicyListener);
|
||||
} catch (RemoteException e) {
|
||||
// ouch, no rules updates means some processes may never get network
|
||||
Slog.e(TAG, "unable to register INetworkPolicyListener", e);
|
||||
}
|
||||
|
||||
final PowerManager powerManager = (PowerManager) context.getSystemService(
|
||||
Context.POWER_SERVICE);
|
||||
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||
mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_networkTransitionTimeout);
|
||||
@@ -535,6 +552,32 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if UID is blocked from using the given {@link NetworkInfo}.
|
||||
*/
|
||||
private boolean isNetworkBlocked(NetworkInfo info, int uid) {
|
||||
synchronized (mUidRules) {
|
||||
return isNetworkBlockedLocked(info, uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if UID is blocked from using the given {@link NetworkInfo}.
|
||||
*/
|
||||
private boolean isNetworkBlockedLocked(NetworkInfo info, int uid) {
|
||||
// TODO: expand definition of "paid" network to cover tethered or paid
|
||||
// hotspot use cases.
|
||||
final boolean networkIsPaid = info.getType() != ConnectivityManager.TYPE_WIFI;
|
||||
final int uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
|
||||
|
||||
if (networkIsPaid && (uidRules & RULE_REJECT_PAID) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// no restrictive rules; network is visible
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return NetworkInfo for the active (i.e., connected) network interface.
|
||||
* It is assumed that at most one network is active at a time. If more
|
||||
@@ -542,26 +585,60 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
* @return the info for the active network, or {@code null} if none is
|
||||
* active
|
||||
*/
|
||||
@Override
|
||||
public NetworkInfo getActiveNetworkInfo() {
|
||||
return getNetworkInfo(mActiveDefaultNetwork);
|
||||
enforceAccessPermission();
|
||||
final int uid = Binder.getCallingUid();
|
||||
return getNetworkInfo(mActiveDefaultNetwork, uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkInfo getActiveNetworkInfoForUid(int uid) {
|
||||
enforceConnectivityInternalPermission();
|
||||
return getNetworkInfo(mActiveDefaultNetwork, uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkInfo getNetworkInfo(int networkType) {
|
||||
enforceAccessPermission();
|
||||
if (ConnectivityManager.isNetworkTypeValid(networkType)) {
|
||||
NetworkStateTracker t = mNetTrackers[networkType];
|
||||
if (t != null)
|
||||
return t.getNetworkInfo();
|
||||
}
|
||||
return null;
|
||||
final int uid = Binder.getCallingUid();
|
||||
return getNetworkInfo(networkType, uid);
|
||||
}
|
||||
|
||||
private NetworkInfo getNetworkInfo(int networkType, int uid) {
|
||||
NetworkInfo info = null;
|
||||
if (isNetworkTypeValid(networkType)) {
|
||||
final NetworkStateTracker tracker = mNetTrackers[networkType];
|
||||
if (tracker != null) {
|
||||
info = tracker.getNetworkInfo();
|
||||
if (isNetworkBlocked(info, uid)) {
|
||||
// network is blocked; clone and override state
|
||||
info = new NetworkInfo(info);
|
||||
info.setDetailedState(DetailedState.BLOCKED, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkInfo[] getAllNetworkInfo() {
|
||||
enforceAccessPermission();
|
||||
NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
|
||||
final int uid = Binder.getCallingUid();
|
||||
final NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
|
||||
int i = 0;
|
||||
for (NetworkStateTracker t : mNetTrackers) {
|
||||
if(t != null) result[i++] = t.getNetworkInfo();
|
||||
synchronized (mUidRules) {
|
||||
for (NetworkStateTracker tracker : mNetTrackers) {
|
||||
if (tracker != null) {
|
||||
NetworkInfo info = tracker.getNetworkInfo();
|
||||
if (isNetworkBlockedLocked(info, uid)) {
|
||||
// network is blocked; clone and override state
|
||||
info = new NetworkInfo(info);
|
||||
info.setDetailedState(DetailedState.BLOCKED, null, null);
|
||||
}
|
||||
result[i++] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -574,15 +651,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
* @return the ip properties for the active network, or {@code null} if
|
||||
* none is active
|
||||
*/
|
||||
@Override
|
||||
public LinkProperties getActiveLinkProperties() {
|
||||
return getLinkProperties(mActiveDefaultNetwork);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkProperties getLinkProperties(int networkType) {
|
||||
enforceAccessPermission();
|
||||
if (ConnectivityManager.isNetworkTypeValid(networkType)) {
|
||||
NetworkStateTracker t = mNetTrackers[networkType];
|
||||
if (t != null) return t.getLinkProperties();
|
||||
if (isNetworkTypeValid(networkType)) {
|
||||
final NetworkStateTracker tracker = mNetTrackers[networkType];
|
||||
if (tracker != null) {
|
||||
return tracker.getLinkProperties();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1027,6 +1108,30 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
|
||||
@Override
|
||||
public void onRulesChanged(int uid, int uidRules) {
|
||||
// only someone like NPMS should only be calling us
|
||||
// TODO: create permission for modifying data policy
|
||||
mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
|
||||
|
||||
if (LOGD_RULES) {
|
||||
Slog.d(TAG, "onRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
|
||||
}
|
||||
|
||||
synchronized (mUidRules) {
|
||||
// skip update when we've already applied rules
|
||||
final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
|
||||
if (oldRules == uidRules) return;
|
||||
|
||||
mUidRules.put(uid, uidRules);
|
||||
}
|
||||
|
||||
// TODO: dispatch into NMS to push rules towards kernel module
|
||||
// TODO: notify UID when it has requested targeted updates
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @see ConnectivityManager#setMobileDataEnabled(boolean)
|
||||
*/
|
||||
@@ -1284,9 +1389,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
|
||||
void systemReady() {
|
||||
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
|
||||
mNetd = INetworkManagementService.Stub.asInterface(b);
|
||||
|
||||
synchronized(this) {
|
||||
mSystemReady = true;
|
||||
if (mInitialBroadcast != null) {
|
||||
@@ -2255,4 +2357,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
return networkType;
|
||||
}
|
||||
|
||||
private static <T> T checkNotNull(T value, String message) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException(message);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,19 +16,6 @@
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import com.android.server.accessibility.AccessibilityManagerService;
|
||||
import com.android.server.am.ActivityManagerService;
|
||||
import com.android.server.net.NetworkPolicyManagerService;
|
||||
import com.android.server.pm.PackageManagerService;
|
||||
import com.android.server.usb.UsbService;
|
||||
import com.android.server.wm.WindowManagerService;
|
||||
import com.android.internal.app.ShutdownThread;
|
||||
import com.android.internal.os.BinderInternal;
|
||||
import com.android.internal.os.SamplingProfilerIntegration;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
import dalvik.system.Zygote;
|
||||
|
||||
import android.accounts.AccountManagerService;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
@@ -41,25 +28,34 @@ import android.content.pm.IPackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.ContentObserver;
|
||||
import android.media.AudioService;
|
||||
import android.os.Build;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.StrictMode;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Contacts.People;
|
||||
import android.provider.Settings;
|
||||
import android.server.BluetoothA2dpService;
|
||||
import android.server.BluetoothService;
|
||||
import android.server.search.SearchManagerService;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.app.ShutdownThread;
|
||||
import com.android.internal.os.BinderInternal;
|
||||
import com.android.internal.os.SamplingProfilerIntegration;
|
||||
import com.android.server.accessibility.AccessibilityManagerService;
|
||||
import com.android.server.am.ActivityManagerService;
|
||||
import com.android.server.net.NetworkPolicyManagerService;
|
||||
import com.android.server.pm.PackageManagerService;
|
||||
import com.android.server.usb.UsbService;
|
||||
import com.android.server.wm.WindowManagerService;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
import dalvik.system.Zygote;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
@@ -120,6 +116,7 @@ class ServerThread extends Thread {
|
||||
LightsService lights = null;
|
||||
PowerManagerService power = null;
|
||||
BatteryService battery = null;
|
||||
NetworkManagementService networkManagement = null;
|
||||
NetworkPolicyManagerService networkPolicy = null;
|
||||
ConnectivityService connectivity = null;
|
||||
IPackageManager pm = null;
|
||||
@@ -294,16 +291,15 @@ class ServerThread extends Thread {
|
||||
|
||||
try {
|
||||
Slog.i(TAG, "NetworkManagement Service");
|
||||
ServiceManager.addService(
|
||||
Context.NETWORKMANAGEMENT_SERVICE,
|
||||
NetworkManagementService.create(context));
|
||||
networkManagement = NetworkManagementService.create(context);
|
||||
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
|
||||
} catch (Throwable e) {
|
||||
Slog.e(TAG, "Failure starting NetworkManagement Service", e);
|
||||
}
|
||||
|
||||
try {
|
||||
Slog.i(TAG, "Connectivity Service");
|
||||
connectivity = ConnectivityService.getInstance(context);
|
||||
connectivity = new ConnectivityService(context, networkManagement, networkPolicy);
|
||||
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
|
||||
} catch (Throwable e) {
|
||||
Slog.e(TAG, "Failure starting Connectivity Service", e);
|
||||
|
||||
@@ -19,8 +19,9 @@ package com.android.server.net;
|
||||
import static android.Manifest.permission.MANAGE_APP_TOKENS;
|
||||
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
|
||||
import static android.net.NetworkPolicyManager.POLICY_NONE;
|
||||
import static android.net.NetworkPolicyManager.POLICY_REJECT_BACKGROUND;
|
||||
import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID;
|
||||
import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
|
||||
import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
|
||||
|
||||
import android.app.IActivityManager;
|
||||
import android.app.IProcessObserver;
|
||||
@@ -28,8 +29,11 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.INetworkPolicyListener;
|
||||
import android.net.INetworkPolicyManager;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
@@ -40,6 +44,10 @@ import android.util.SparseIntArray;
|
||||
/**
|
||||
* Service that maintains low-level network policy rules and collects usage
|
||||
* statistics to drive those rules.
|
||||
* <p>
|
||||
* Derives active rules by combining a given policy with other system status,
|
||||
* and delivers to listeners, such as {@link ConnectivityManager}, for
|
||||
* enforcement.
|
||||
*/
|
||||
public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
private static final String TAG = "NetworkPolicy";
|
||||
@@ -51,19 +59,27 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
|
||||
private Object mRulesLock = new Object();
|
||||
|
||||
private boolean mScreenOn = false;
|
||||
private boolean mScreenOn;
|
||||
|
||||
/** Current network policy for each UID. */
|
||||
private SparseIntArray mUidPolicy = new SparseIntArray();
|
||||
/** Current derived network rules for each UID. */
|
||||
private SparseIntArray mUidRules = new SparseIntArray();
|
||||
|
||||
/** Foreground at both UID and PID granularity. */
|
||||
private SparseBooleanArray mUidForeground = new SparseBooleanArray();
|
||||
private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
|
||||
SparseBooleanArray>();
|
||||
|
||||
private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
|
||||
INetworkPolicyListener>();
|
||||
|
||||
// TODO: periodically poll network stats and write to disk
|
||||
// TODO: save/restore policy information from disk
|
||||
|
||||
// TODO: keep whitelist of system-critical services that should never have
|
||||
// rules enforced, such as system, phone, and radio UIDs.
|
||||
|
||||
public NetworkPolicyManagerService(
|
||||
Context context, IActivityManager activityManager, IPowerManager powerManager) {
|
||||
mContext = checkNotNull(context, "missing context");
|
||||
@@ -158,12 +174,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
|
||||
@Override
|
||||
public void setUidPolicy(int uid, int policy) {
|
||||
// TODO: create permission for modifying data policy
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
UPDATE_DEVICE_STATS, "requires UPDATE_DEVICE_STATS permission");
|
||||
|
||||
final int oldPolicy;
|
||||
synchronized (mRulesLock) {
|
||||
oldPolicy = getUidPolicy(uid);
|
||||
mUidPolicy.put(uid, policy);
|
||||
}
|
||||
|
||||
// TODO: consider dispatching BACKGROUND_DATA_SETTING broadcast
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -173,6 +194,36 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerListener(INetworkPolicyListener listener) {
|
||||
mListeners.register(listener);
|
||||
|
||||
synchronized (mRulesLock) {
|
||||
// dispatch any existing rules to new listeners
|
||||
final int size = mUidRules.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int uid = mUidRules.keyAt(i);
|
||||
final int uidRules = mUidRules.valueAt(i);
|
||||
if (uidRules != RULE_ALLOW_ALL) {
|
||||
try {
|
||||
listener.onRulesChanged(uid, uidRules);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterListener(INetworkPolicyListener listener) {
|
||||
mListeners.unregister(listener);
|
||||
}
|
||||
|
||||
private boolean isUidForegroundL(int uid) {
|
||||
// only really in foreground when screen is also on
|
||||
return mUidForeground.get(uid, false) && mScreenOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Foreground for PID changed; recompute foreground at UID level. If
|
||||
* changed, will trigger {@link #updateRulesForUidL(int)}.
|
||||
@@ -223,22 +274,33 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
|
||||
private void updateRulesForUidL(int uid) {
|
||||
// only really in foreground when screen on
|
||||
final boolean uidForeground = mUidForeground.get(uid, false) && mScreenOn;
|
||||
final int uidPolicy = getUidPolicy(uid);
|
||||
final boolean uidForeground = isUidForegroundL(uid);
|
||||
|
||||
if (LOGD) {
|
||||
Log.d(TAG, "updateRulesForUid(uid=" + uid + ") found foreground=" + uidForeground
|
||||
+ " and policy=" + uidPolicy);
|
||||
// derive active rules based on policy and active state
|
||||
int uidRules = RULE_ALLOW_ALL;
|
||||
if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
|
||||
// uid in background, and policy says to block paid data
|
||||
uidRules = RULE_REJECT_PAID;
|
||||
}
|
||||
|
||||
if (!uidForeground && (uidPolicy & POLICY_REJECT_BACKGROUND) != 0) {
|
||||
// TODO: build updated rules and push to NMS
|
||||
} else if ((uidPolicy & POLICY_REJECT_PAID) != 0) {
|
||||
// TODO: build updated rules and push to NMS
|
||||
} else {
|
||||
// TODO: build updated rules and push to NMS
|
||||
// TODO: only dispatch when rules actually change
|
||||
|
||||
// record rule locally to dispatch to new listeners
|
||||
mUidRules.put(uid, uidRules);
|
||||
|
||||
// dispatch changed rule to existing listeners
|
||||
final int length = mListeners.beginBroadcast();
|
||||
for (int i = 0; i < length; i++) {
|
||||
final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
|
||||
if (listener != null) {
|
||||
try {
|
||||
listener.onRulesChanged(uid, uidRules);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
mListeners.finishBroadcast();
|
||||
}
|
||||
|
||||
private static <T> T checkNotNull(T value, String message) {
|
||||
|
||||
Reference in New Issue
Block a user