Merge "Proactively disable data when over policy limit."

This commit is contained in:
Jeff Sharkey
2011-08-23 21:26:51 -07:00
committed by Android (Google) Code Review
14 changed files with 482 additions and 272 deletions

View File

@@ -19,7 +19,6 @@ package android.bluetooth;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfoInternal;
import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
@@ -30,7 +29,6 @@ import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.net.InetAddress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -184,11 +182,14 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
return -1;
}
/**
* @param enabled
*/
public void setDataEnable(boolean enabled) {
android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
@Override
public void setUserDataEnable(boolean enabled) {
Log.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
}
@Override
public void setPolicyDataEnable(boolean enabled) {
Log.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
}
/**

View File

@@ -19,9 +19,6 @@ package android.net;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo;
import android.net.LinkProperties;
import android.util.Slog;
/**
@@ -168,7 +165,14 @@ public class DummyDataStateTracker implements NetworkStateTracker {
return true;
}
public void setDataEnable(boolean enabled) {
@Override
public void setUserDataEnable(boolean enabled) {
// ignored
}
@Override
public void setPolicyDataEnable(boolean enabled) {
// ignored
}
@Override

View File

@@ -17,15 +17,7 @@
package android.net;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfoInternal;
import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -34,7 +26,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import java.net.InetAddress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -302,11 +293,14 @@ public class EthernetDataTracker implements NetworkStateTracker {
return -1;
}
/**
* @param enabled
*/
public void setDataEnable(boolean enabled) {
Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
@Override
public void setUserDataEnable(boolean enabled) {
Log.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
}
@Override
public void setPolicyDataEnable(boolean enabled) {
Log.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
}
/**

View File

@@ -64,9 +64,11 @@ interface IConnectivityManager
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
boolean getMobileDataEnabled();
void setMobileDataEnabled(boolean enabled);
/** Policy control over specific {@link NetworkStateTracker}. */
void setPolicyDataEnable(int networkType, boolean enabled);
int tether(String iface);
int untether(String iface);

View File

@@ -16,19 +16,26 @@
package android.net;
import static com.android.internal.telephony.DataConnectionTracker.CMD_SET_POLICY_DATA_ENABLE;
import static com.android.internal.telephony.DataConnectionTracker.CMD_SET_USER_DATA_ENABLE;
import static com.android.internal.telephony.DataConnectionTracker.DISABLED;
import static com.android.internal.telephony.DataConnectionTracker.ENABLED;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo.DetailedState;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.ServiceManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.ITelephony;
@@ -36,13 +43,6 @@ import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.AsyncChannel;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo;
import android.net.LinkProperties;
import android.telephony.TelephonyManager;
import android.util.Slog;
import android.text.TextUtils;
/**
* Track the state of mobile data connectivity. This is done by
* receiving broadcast intents from the Phone process whenever
@@ -452,17 +452,22 @@ public class MobileDataStateTracker implements NetworkStateTracker {
return false;
}
/**
* @param enabled
*/
public void setDataEnable(boolean enabled) {
try {
if (DBG) log("setDataEnable: E enabled=" + enabled);
mDataConnectionTrackerAc.sendMessage(DataConnectionTracker.CMD_SET_DATA_ENABLE,
enabled ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED);
if (VDBG) log("setDataEnable: X enabled=" + enabled);
} catch (Exception e) {
loge("setDataEnable: X mAc was null" + e);
@Override
public void setUserDataEnable(boolean enabled) {
if (DBG) log("setUserDataEnable: E enabled=" + enabled);
final AsyncChannel channel = mDataConnectionTrackerAc;
if (channel != null) {
channel.sendMessage(CMD_SET_USER_DATA_ENABLE, enabled ? ENABLED : DISABLED);
}
if (VDBG) log("setUserDataEnable: X enabled=" + enabled);
}
@Override
public void setPolicyDataEnable(boolean enabled) {
if (DBG) log("setPolicyDataEnable(enabled=" + enabled + ")");
final AsyncChannel channel = mDataConnectionTrackerAc;
if (channel != null) {
channel.sendMessage(CMD_SET_POLICY_DATA_ENABLE, enabled ? ENABLED : DISABLED);
}
}

View File

@@ -136,9 +136,17 @@ public interface NetworkStateTracker {
public boolean isAvailable();
/**
* @param enabled
* User control of data connection through this network, typically persisted
* internally.
*/
public void setDataEnable(boolean enabled);
public void setUserDataEnable(boolean enabled);
/**
* Policy control of data connection through this network, typically not
* persisted internally. Usually used when {@link NetworkPolicy#limitBytes}
* is passed.
*/
public void setPolicyDataEnable(boolean enabled);
/**
* -------------------------------------------------------------

View File

@@ -3163,6 +3163,8 @@
<string name="data_usage_4g_limit_title">4G data disabled</string>
<!-- Notification title when mobile data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
<string name="data_usage_mobile_limit_title">Mobile data disabled</string>
<!-- Notification title when Wi-Fi data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
<string name="data_usage_wifi_limit_title">Wi-Fi data disabled</string>
<!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
<string name="data_usage_limit_body">Touch to enable</string>
@@ -3172,6 +3174,8 @@
<string name="data_usage_4g_limit_snoozed_title">4G data limit exceeded</string>
<!-- Notification title when mobile data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_mobile_limit_snoozed_title">Mobile data limit exceeded</string>
<!-- Notification title when Wi-Fi data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_wifi_limit_snoozed_title">Wi-Fi data limit exceeded</string>
<!-- Notification body when data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_limit_snoozed_body"><xliff:g id="size" example="3.8GB">%s</xliff:g> over specified limit</string>

View File

@@ -72,7 +72,6 @@ import com.android.internal.net.VpnConfig;
import com.android.internal.telephony.Phone;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -89,7 +88,6 @@ import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @hide
@@ -251,6 +249,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private static final int EVENT_SEND_STICKY_BROADCAST_INTENT =
MAX_NETWORK_STATE_TRACKER_EVENT + 12;
/**
* Used internally to
* {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
*/
private static final int EVENT_SET_POLICY_DATA_ENABLE = MAX_NETWORK_STATE_TRACKER_EVENT + 13;
private Handler mHandler;
// list of DeathRecipients used to make sure features are turned off when
@@ -1282,7 +1286,25 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (VDBG) {
log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled);
}
mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled);
mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled);
}
}
@Override
public void setPolicyDataEnable(int networkType, boolean enabled) {
// only someone like NPMS should only be calling us
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
mHandler.sendMessage(mHandler.obtainMessage(
EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED)));
}
private void handleSetPolicyDataEnable(int networkType, boolean enabled) {
if (isNetworkTypeValid(networkType)) {
final NetworkStateTracker tracker = mNetTrackers[networkType];
if (tracker != null) {
tracker.setPolicyDataEnable(enabled);
}
}
}
@@ -2263,6 +2285,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
sendStickyBroadcast(intent);
break;
}
case EVENT_SET_POLICY_DATA_ENABLE: {
final int networkType = msg.arg1;
final boolean enabled = msg.arg2 == ENABLED;
handleSetPolicyDataEnable(networkType, enabled);
}
}
}
}

View File

@@ -27,7 +27,10 @@ import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -40,8 +43,11 @@ import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.dumpPolicy;
import static android.net.NetworkPolicyManager.dumpRules;
import static android.net.NetworkPolicyManager.isUidValidForPolicy;
import static android.net.NetworkTemplate.MATCH_ETHERNET;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -104,6 +110,7 @@ import android.util.Xml;
import com.android.internal.R;
import com.android.internal.os.AtomicFile;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Objects;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;
@@ -129,8 +136,8 @@ import java.util.List;
import libcore.io.IoUtils;
/**
* Service that maintains low-level network policy rules and collects usage
* statistics to drive those rules.
* Service that maintains low-level network policy rules, using
* {@link NetworkStatsService} 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
@@ -195,6 +202,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private volatile boolean mScreenOn;
private volatile boolean mRestrictBackground;
private final boolean mSuppressDefaultPolicy;
/** Defined network policies. */
private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
/** Currently active network rules for ifaces. */
@@ -210,6 +219,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** Set of over-limit templates that have been notified. */
private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
/** Set of currently active {@link Notification} tags. */
private HashSet<String> mActiveNotifs = Sets.newHashSet();
/** Current values from {@link #setPolicyDataEnable(int, boolean)}. */
private SparseBooleanArray mActiveNetworkEnabled = new SparseBooleanArray();
/** Foreground at both UID and PID granularity. */
private SparseBooleanArray mUidForeground = new SparseBooleanArray();
private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
@@ -232,7 +246,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
IPowerManager powerManager, INetworkStatsService networkStats,
INetworkManagementService networkManagement) {
this(context, activityManager, powerManager, networkStats, networkManagement,
NtpTrustedTime.getInstance(context), getSystemDir());
NtpTrustedTime.getInstance(context), getSystemDir(), false);
}
private static File getSystemDir() {
@@ -241,8 +255,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
IPowerManager powerManager, INetworkStatsService networkStats,
INetworkManagementService networkManagement,
TrustedTime time, File systemDir) {
INetworkManagementService networkManagement, TrustedTime time, File systemDir,
boolean suppressDefaultPolicy) {
mContext = checkNotNull(context, "missing context");
mActivityManager = checkNotNull(activityManager, "missing activityManager");
mPowerManager = checkNotNull(powerManager, "missing powerManager");
@@ -254,6 +268,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
mSuppressDefaultPolicy = suppressDefaultPolicy;
mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
}
@@ -408,6 +424,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// READ_NETWORK_USAGE_HISTORY permission above.
synchronized (mRulesLock) {
updateNetworkEnabledLocked();
updateNotificationsLocked();
}
}
@@ -446,6 +463,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Slog.w(TAG, "problem updating network stats");
}
updateNetworkEnabledLocked();
updateNotificationsLocked();
}
}
@@ -459,74 +477,70 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private void updateNotificationsLocked() {
if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
// try refreshing time source when stale
if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
mTime.forceRefresh();
}
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
// keep track of previously active notifications
final HashSet<String> beforeNotifs = Sets.newHashSet();
beforeNotifs.addAll(mActiveNotifs);
mActiveNotifs.clear();
// TODO: when switching to kernel notifications, compute next future
// cycle boundary to recompute notifications.
// examine stats for each active policy
for (NetworkPolicy policy : mNetworkRules.keySet()) {
final long currentTime = currentTimeMillis(true);
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// ignore policies that aren't relevant to user
if (!isTemplateRelevant(policy.template)) continue;
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
final long totalBytes;
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
policy.template, start, end);
final NetworkStats.Entry entry = stats.getValues(0, null);
totalBytes = entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
}
final long totalBytes = getTotalBytes(policy.template, start, end);
if (totalBytes == UNKNOWN_BYTES) continue;
if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
cancelNotification(policy, TYPE_WARNING);
if (policy.lastSnooze >= start) {
cancelNotification(policy, TYPE_LIMIT);
enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
} else {
cancelNotification(policy, TYPE_LIMIT_SNOOZED);
enqueueNotification(policy, TYPE_LIMIT, totalBytes);
notifyOverLimitLocked(policy.template);
}
} else {
cancelNotification(policy, TYPE_LIMIT);
cancelNotification(policy, TYPE_LIMIT_SNOOZED);
notifyUnderLimitLocked(policy.template);
if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
enqueueNotification(policy, TYPE_WARNING, totalBytes);
} else {
cancelNotification(policy, TYPE_WARNING);
}
}
}
// clear notifications for non-active policies
for (NetworkPolicy policy : mNetworkPolicy.values()) {
if (!mNetworkRules.containsKey(policy)) {
cancelNotification(policy, TYPE_WARNING);
cancelNotification(policy, TYPE_LIMIT);
cancelNotification(policy, TYPE_LIMIT_SNOOZED);
notifyUnderLimitLocked(policy.template);
}
}
// ongoing notification when restricting background data
if (mRestrictBackground) {
enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
} else {
cancelNotification(TAG_ALLOW_BACKGROUND);
}
// cancel stale notifications that we didn't renew above
for (String tag : beforeNotifs) {
if (!mActiveNotifs.contains(tag)) {
cancelNotification(tag);
}
}
}
/**
* Test if given {@link NetworkTemplate} is relevant to user based on
* current device state, such as when {@link #getActiveSubscriberId()}
* matches. This is regardless of data connection status.
*/
private boolean isTemplateRelevant(NetworkTemplate template) {
switch (template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
// mobile templates are relevant when subscriberid is active
return Objects.equal(getActiveSubscriberId(), template.getSubscriberId());
}
return true;
}
/**
@@ -590,9 +604,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case MATCH_MOBILE_4G:
title = res.getText(R.string.data_usage_4g_limit_title);
break;
default:
case MATCH_MOBILE_ALL:
title = res.getText(R.string.data_usage_mobile_limit_title);
break;
case MATCH_WIFI:
title = res.getText(R.string.data_usage_wifi_limit_title);
break;
default:
title = null;
break;
}
builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block);
@@ -618,9 +638,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case MATCH_MOBILE_4G:
title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
break;
default:
case MATCH_MOBILE_ALL:
title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
break;
case MATCH_WIFI:
title = res.getText(R.string.data_usage_wifi_limit_snoozed_title);
break;
default:
title = null;
break;
}
builder.setSmallIcon(R.drawable.ic_menu_info_details);
@@ -641,6 +667,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int[] idReceived = new int[1];
mNotifManager.enqueueNotificationWithTag(
packageName, tag, 0x0, builder.getNotification(), idReceived);
mActiveNotifs.add(tag);
} catch (RemoteException e) {
Slog.w(TAG, "problem during enqueueNotification: " + e);
}
@@ -674,19 +701,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int[] idReceived = new int[1];
mNotifManager.enqueueNotificationWithTag(packageName, tag,
0x0, builder.getNotification(), idReceived);
mActiveNotifs.add(tag);
} catch (RemoteException e) {
Slog.w(TAG, "problem during enqueueNotification: " + e);
}
}
/**
* Cancel any notification for combined {@link NetworkPolicy} and specific
* type, like {@link #TYPE_LIMIT}.
*/
private void cancelNotification(NetworkPolicy policy, int type) {
cancelNotification(buildNotificationTag(policy, type));
}
private void cancelNotification(String tag) {
// TODO: move to NotificationManager once we can mock it
try {
@@ -709,12 +729,72 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// permission above.
synchronized (mRulesLock) {
ensureActiveMobilePolicyLocked();
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
}
}
};
/**
* Proactively control network data connections when they exceed
* {@link NetworkPolicy#limitBytes}.
*/
private void updateNetworkEnabledLocked() {
if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
// TODO: reset any policy-disabled networks when any policy is removed
// completely, which is currently rare case.
final long currentTime = currentTimeMillis(true);
for (NetworkPolicy policy : mNetworkPolicy.values()) {
// shortcut when policy has no limit
if (policy.limitBytes == LIMIT_DISABLED) {
setNetworkTemplateEnabled(policy.template, true);
continue;
}
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
final long totalBytes = getTotalBytes(policy.template, start, end);
if (totalBytes == UNKNOWN_BYTES) continue;
// disable data connection when over limit and not snoozed
final boolean overLimit = policy.limitBytes != LIMIT_DISABLED
&& totalBytes > policy.limitBytes && policy.lastSnooze < start;
setNetworkTemplateEnabled(policy.template, !overLimit);
}
}
/**
* Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}
* for the given {@link NetworkTemplate}.
*/
private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
if (LOGD) Slog.d(TAG, "setting template=" + template + " enabled=" + enabled);
switch (template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
// TODO: offer more granular control over radio states once
// 4965893 is available.
if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) {
setPolicyDataEnable(TYPE_MOBILE, enabled);
setPolicyDataEnable(TYPE_WIMAX, enabled);
}
break;
case MATCH_WIFI:
setPolicyDataEnable(TYPE_WIFI, enabled);
break;
case MATCH_ETHERNET:
setPolicyDataEnable(TYPE_ETHERNET, enabled);
break;
default:
throw new IllegalArgumentException("unexpected template");
}
}
/**
* Examine all connected {@link NetworkState}, looking for
* {@link NetworkPolicy} that need to be enforced. When matches found, set
@@ -763,34 +843,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
// try refreshing time source when stale
if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
mTime.forceRefresh();
}
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
final HashSet<String> newMeteredIfaces = Sets.newHashSet();
// apply each policy that we found ifaces for; compute remaining data
// based on current cycle and historical stats, and push to kernel.
final long currentTime = currentTimeMillis(true);
for (NetworkPolicy policy : mNetworkRules.keySet()) {
final String[] ifaces = mNetworkRules.get(policy);
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
final NetworkStats stats;
final long total;
try {
stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
final NetworkStats.Entry entry = stats.getValues(0, null);
total = entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
}
final long totalBytes = getTotalBytes(policy.template, start, end);
if (totalBytes == UNKNOWN_BYTES) continue;
if (LOGD) {
Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
@@ -798,11 +863,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
final boolean hasWarning = policy.warningBytes != WARNING_DISABLED;
if (hasLimit) {
// remaining "quota" is based on usage in current cycle
final long quotaBytes = Math.max(0, policy.limitBytes - total);
final long quotaBytes;
if (policy.lastSnooze >= start) {
// snoozing past quota, but we still need to restrict apps,
// so push really high quota.
quotaBytes = Long.MAX_VALUE;
} else {
// remaining "quota" bytes are based on total usage in
// current cycle. kernel doesn't like 0-byte rules, so we
// set 1-byte quota and disable the radio later.
quotaBytes = Math.max(1, policy.limitBytes - totalBytes);
}
if (ifaces.length > 1) {
// TODO: switch to shared quota once NMS supports
@@ -811,10 +883,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (String iface : ifaces) {
removeInterfaceQuota(iface);
if (quotaBytes > 0) {
setInterfaceQuota(iface, quotaBytes);
newMeteredIfaces.add(iface);
}
setInterfaceQuota(iface, quotaBytes);
newMeteredIfaces.add(iface);
}
}
}
@@ -837,6 +907,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
*/
private void ensureActiveMobilePolicyLocked() {
if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
if (mSuppressDefaultPolicy) return;
final String subscriberId = getActiveSubscriberId();
final NetworkIdentity probeIdent = new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
@@ -1073,6 +1145,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetworkPolicy.put(policy.template, policy);
}
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
writePolicyLocked();
@@ -1093,14 +1166,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public void snoozePolicy(NetworkTemplate template) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
// try refreshing time source when stale
if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
mTime.forceRefresh();
}
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
final long currentTime = currentTimeMillis(true);
synchronized (mRulesLock) {
// find and snooze local policy that matches
final NetworkPolicy policy = mNetworkPolicy.get(template);
@@ -1110,6 +1176,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
policy.lastSnooze = currentTime;
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
writePolicyLocked();
@@ -1173,22 +1240,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return null;
}
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
final long currentTime = currentTimeMillis(false);
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
// find total bytes used under policy
long totalBytes = 0;
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
policy.template, start, end);
final NetworkStats.Entry entry = stats.getValues(0, null);
totalBytes = entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + policy.template);
}
final long totalBytes = getTotalBytes(policy.template, start, end);
if (totalBytes == UNKNOWN_BYTES) return null;
// report soft and hard limits under policy
final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
@@ -1481,12 +1540,54 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
/**
* Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)},
* dispatching only when actually changed.
*/
private void setPolicyDataEnable(int networkType, boolean enabled) {
synchronized (mActiveNetworkEnabled) {
final boolean prevEnabled = mActiveNetworkEnabled.get(networkType, true);
if (prevEnabled == enabled) return;
try {
mConnManager.setPolicyDataEnable(networkType, enabled);
} catch (RemoteException e) {
Slog.e(TAG, "problem setting network enabled", e);
}
mActiveNetworkEnabled.put(networkType, enabled);
}
}
private String getActiveSubscriberId() {
final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
Context.TELEPHONY_SERVICE);
return telephony.getSubscriberId();
}
private static final long UNKNOWN_BYTES = -1;
private long getTotalBytes(NetworkTemplate template, long start, long end) {
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
template, start, end);
final NetworkStats.Entry entry = stats.getValues(0, null);
return entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + template);
return UNKNOWN_BYTES;
}
}
private long currentTimeMillis(boolean allowRefresh) {
// try refreshing time source when stale
if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE && allowRefresh) {
mTime.forceRefresh();
}
return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
}
private static Intent buildAllowBackgroundDataIntent() {
return new Intent(ACTION_ALLOW_BACKGROUND);
}

View File

@@ -79,6 +79,7 @@ import com.google.common.util.concurrent.AbstractFuture;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IExpectationSetters;
import java.io.File;
import java.util.LinkedHashSet;
@@ -87,6 +88,8 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import libcore.io.IoUtils;
/**
* Tests for {@link NetworkPolicyManagerService}.
*/
@@ -117,6 +120,9 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
private Binder mStubBinder = new Binder();
private long mStartTime;
private long mElapsedRealtime;
private static final int UID_A = android.os.Process.FIRST_APPLICATION_UID + 800;
private static final int UID_B = android.os.Process.FIRST_APPLICATION_UID + 801;
@@ -128,6 +134,8 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
public void setUp() throws Exception {
super.setUp();
setCurrentTimeMillis(TEST_START);
// intercept various broadcasts, and pretend that uids have packages
mServiceContext = new BroadcastInterceptingContext(getContext()) {
@Override
@@ -160,8 +168,8 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
};
mPolicyDir = getContext().getFilesDir();
for (File file : mPolicyDir.listFiles()) {
file.delete();
if (mPolicyDir.exists()) {
IoUtils.deleteContents(mPolicyDir);
}
mActivityManager = createMock(IActivityManager.class);
@@ -173,9 +181,8 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
mConnManager = createMock(IConnectivityManager.class);
mNotifManager = createMock(INotificationManager.class);
mService = new NetworkPolicyManagerService(
mServiceContext, mActivityManager, mPowerManager, mStatsService,
mNetworkManager, mTime, mPolicyDir);
mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mPowerManager,
mStatsService, mNetworkManager, mTime, mPolicyDir, true);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
@@ -198,7 +205,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
// expect to answer screen status during systemReady()
expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
expectTime(System.currentTimeMillis());
expectCurrentTime();
replay();
mService.systemReady();
@@ -485,7 +492,6 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
}
public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
long elapsedRealtime = 0;
NetworkState[] state = null;
NetworkStats stats = null;
Future<Void> future;
@@ -494,11 +500,13 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
final long TIME_MAR_10 = 1173484800000L;
final int CYCLE_DAY = 15;
setCurrentTimeMillis(TIME_MAR_10);
// first, pretend that wifi network comes online. no policy active,
// which means we shouldn't push limit to interface.
state = new NetworkState[] { buildWifi() };
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expectTime(TIME_MAR_10 + elapsedRealtime);
expectCurrentTime();
expectClearNotifications();
future = expectMeteredIfacesChanged();
@@ -510,10 +518,10 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
// now change cycle to be on 15th, and test in early march, to verify we
// pick cycle day in previous month.
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expectTime(TIME_MAR_10 + elapsedRealtime);
expectCurrentTime();
// pretend that 512 bytes total have happened
stats = new NetworkStats(elapsedRealtime, 1)
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
.andReturn(stats).atLeastOnce();
@@ -521,8 +529,6 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
// TODO: consider making strongly ordered mock
expectRemoveInterfaceQuota(TEST_IFACE);
expectSetInterfaceQuota(TEST_IFACE, 1536L);
expectRemoveInterfaceAlert(TEST_IFACE);
expectSetInterfaceAlert(TEST_IFACE, 512L);
expectClearNotifications();
future = expectMeteredIfacesChanged(TEST_IFACE);
@@ -558,8 +564,6 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
}
public void testOverWarningLimitNotification() throws Exception {
long elapsedRealtime = 0;
long currentTime = 0;
NetworkState[] state = null;
NetworkStats stats = null;
Future<Void> future;
@@ -569,14 +573,18 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
final long TIME_MAR_10 = 1173484800000L;
final int CYCLE_DAY = 15;
setCurrentTimeMillis(TIME_MAR_10);
// assign wifi policy
elapsedRealtime = 0;
currentTime = TIME_MAR_10 + elapsedRealtime;
state = new NetworkState[] {};
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
{
expectTime(currentTime);
expectCurrentTime();
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
.andReturn(stats).atLeastOnce();
expectClearNotifications();
future = expectMeteredIfacesChanged();
@@ -589,22 +597,19 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
}
// bring up wifi network
elapsedRealtime += MINUTE_IN_MILLIS;
currentTime = TIME_MAR_10 + elapsedRealtime;
stats = new NetworkStats(elapsedRealtime, 1)
.addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
incrementCurrentTime(MINUTE_IN_MILLIS);
state = new NetworkState[] { buildWifi() };
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
{
expectTime(currentTime);
expectCurrentTime();
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
.andReturn(stats).atLeastOnce();
expectRemoveInterfaceQuota(TEST_IFACE);
expectSetInterfaceQuota(TEST_IFACE, 2048L);
expectRemoveInterfaceAlert(TEST_IFACE);
expectSetInterfaceAlert(TEST_IFACE, 1024L);
expectClearNotifications();
future = expectMeteredIfacesChanged(TEST_IFACE);
@@ -616,14 +621,13 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
}
// go over warning, which should kick notification
elapsedRealtime += MINUTE_IN_MILLIS;
currentTime = TIME_MAR_10 + elapsedRealtime;
stats = new NetworkStats(elapsedRealtime, 1)
incrementCurrentTime(MINUTE_IN_MILLIS);
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 1536L, 15L, 0L, 0L);
{
expectTime(currentTime);
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
expectCurrentTime();
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
.andReturn(stats).atLeastOnce();
expectForceUpdate();
@@ -637,15 +641,15 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
}
// go over limit, which should kick notification and dialog
elapsedRealtime += MINUTE_IN_MILLIS;
currentTime = TIME_MAR_10 + elapsedRealtime;
stats = new NetworkStats(elapsedRealtime, 1)
incrementCurrentTime(MINUTE_IN_MILLIS);
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 5120L, 512L, 0L, 0L);
{
expectTime(currentTime);
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
expectCurrentTime();
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
.andReturn(stats).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, false).atLeastOnce();
expectForceUpdate();
expectClearNotifications();
@@ -658,21 +662,23 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
}
// now snooze policy, which should remove quota
elapsedRealtime += MINUTE_IN_MILLIS;
currentTime = TIME_MAR_10 + elapsedRealtime;
incrementCurrentTime(MINUTE_IN_MILLIS);
{
expectTime(currentTime);
expectCurrentTime();
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
.andReturn(stats).atLeastOnce();
expectPolicyDataEnable(TYPE_WIFI, true).atLeastOnce();
// snoozed interface still has high quota so background data is
// still restricted.
expectRemoveInterfaceQuota(TEST_IFACE);
expectRemoveInterfaceAlert(TEST_IFACE);
expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
expectClearNotifications();
tag = expectEnqueueNotification();
future = expectMeteredIfacesChanged();
future = expectMeteredIfacesChanged(TEST_IFACE);
replay();
mService.snoozePolicy(sTemplateWifi);
@@ -700,10 +706,10 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
return new NetworkState(info, prop, null);
}
private void expectTime(long currentTime) throws Exception {
private void expectCurrentTime() throws Exception {
expect(mTime.forceRefresh()).andReturn(false).anyTimes();
expect(mTime.hasCache()).andReturn(true).anyTimes();
expect(mTime.currentTimeMillis()).andReturn(currentTime).anyTimes();
expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
}
@@ -770,6 +776,12 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
return future;
}
private <T> IExpectationSetters<T> expectPolicyDataEnable(int type, boolean enabled)
throws Exception {
mConnManager.setPolicyDataEnable(type, enabled);
return expectLastCall();
}
private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
@Override
public Void get() throws InterruptedException, ExecutionException {
@@ -818,6 +830,23 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
private long getElapsedRealtime() {
return mElapsedRealtime;
}
private void setCurrentTimeMillis(long currentTimeMillis) {
mStartTime = currentTimeMillis;
mElapsedRealtime = 0L;
}
private long currentTimeMillis() {
return mStartTime + mElapsedRealtime;
}
private void incrementCurrentTime(long duration) {
mElapsedRealtime += duration;
}
private void replay() {
EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
mNetworkManager, mTime, mConnManager, mNotifManager);

View File

@@ -36,8 +36,8 @@ import android.os.Messenger;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.telephony.ServiceState;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.ServiceState;
import android.text.TextUtils;
import android.util.Log;
@@ -126,9 +126,10 @@ public abstract class DataConnectionTracker extends Handler {
protected static final int EVENT_RESTART_RADIO = BASE + 26;
protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
protected static final int EVENT_RESET_DONE = BASE + 28;
public static final int CMD_SET_DATA_ENABLE = BASE + 29;
public static final int CMD_SET_USER_DATA_ENABLE = BASE + 29;
public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 30;
public static final int CMD_SET_DEPENDENCY_MET = BASE + 31;
public static final int CMD_SET_POLICY_DATA_ENABLE = BASE + 32;
/***** Constants *****/
@@ -153,6 +154,8 @@ public abstract class DataConnectionTracker extends Handler {
protected static final int APN_DELAY_MILLIS =
SystemProperties.getInt("persist.radio.apn_delay", 5000);
protected Object mDataEnabledLock = new Object();
// responds to the setInternalDataEnabled call - used internally to turn off data
// for example during emergency calls
protected boolean mInternalDataEnabled = true;
@@ -160,11 +163,12 @@ public abstract class DataConnectionTracker extends Handler {
// responds to public (user) API to enable/disable data use
// independent of mInternalDataEnabled and requests for APN access
// persisted
protected boolean mDataEnabled = true;
protected boolean mUserDataEnabled = true;
protected boolean mPolicyDataEnabled = true;
protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
protected int enabledCount = 0;
private int enabledCount = 0;
/* Currently requested APN type (TODO: This should probably be a parameter not a member) */
protected String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
@@ -408,8 +412,8 @@ public abstract class DataConnectionTracker extends Handler {
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(INTENT_SET_FAIL_DATA_SETUP_COUNTER);
mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(),
Settings.Secure.MOBILE_DATA, 1) == 1;
mUserDataEnabled = Settings.Secure.getInt(
mPhone.getContext().getContentResolver(), Settings.Secure.MOBILE_DATA, 1) == 1;
// TODO: Why is this registering the phone as the receiver of the intent
// and not its own handler?
@@ -630,13 +634,12 @@ public abstract class DataConnectionTracker extends Handler {
onResetDone((AsyncResult) msg.obj);
break;
}
case CMD_SET_DATA_ENABLE: {
boolean enabled = (msg.arg1 == ENABLED) ? true : false;
if (DBG) log("CMD_SET_DATA_ENABLE enabled=" + enabled);
onSetDataEnabled(enabled);
case CMD_SET_USER_DATA_ENABLE: {
final boolean enabled = (msg.arg1 == ENABLED) ? true : false;
if (DBG) log("CMD_SET_USER_DATA_ENABLE enabled=" + enabled);
onSetUserDataEnabled(enabled);
break;
}
case CMD_SET_DEPENDENCY_MET: {
boolean met = (msg.arg1 == ENABLED) ? true : false;
if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
@@ -649,7 +652,11 @@ public abstract class DataConnectionTracker extends Handler {
}
break;
}
case CMD_SET_POLICY_DATA_ENABLE: {
final boolean enabled = (msg.arg1 == ENABLED) ? true : false;
onSetPolicyDataEnabled(enabled);
break;
}
default:
Log.e("DATA", "Unidentified event msg=" + msg);
break;
@@ -662,8 +669,12 @@ public abstract class DataConnectionTracker extends Handler {
* @return {@code false} if data connectivity has been explicitly disabled,
* {@code true} otherwise.
*/
public synchronized boolean getAnyDataEnabled() {
boolean result = (mInternalDataEnabled && mDataEnabled && (enabledCount != 0));
public boolean getAnyDataEnabled() {
final boolean result;
synchronized (mDataEnabledLock) {
result = (mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled
&& (enabledCount != 0));
}
if (!result && DBG) log("getAnyDataEnabled " + result);
return result;
}
@@ -985,18 +996,18 @@ public abstract class DataConnectionTracker extends Handler {
return true;
}
protected void onSetInternalDataEnabled(boolean enable) {
boolean prevEnabled = getAnyDataEnabled();
if (mInternalDataEnabled != enable) {
synchronized (this) {
mInternalDataEnabled = enable;
}
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
cleanUpAllConnections(null);
protected void onSetInternalDataEnabled(boolean enabled) {
synchronized (mDataEnabledLock) {
final boolean prevEnabled = getAnyDataEnabled();
if (mInternalDataEnabled != enabled) {
mInternalDataEnabled = enabled;
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
cleanUpAllConnections(null);
}
}
}
}
@@ -1010,20 +1021,20 @@ public abstract class DataConnectionTracker extends Handler {
public abstract boolean isAnyActiveDataConnections();
protected void onSetDataEnabled(boolean enable) {
boolean prevEnabled = getAnyDataEnabled();
if (mDataEnabled != enable) {
synchronized (this) {
mDataEnabled = enable;
}
Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
Settings.Secure.MOBILE_DATA, enable ? 1 : 0);
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
protected void onSetUserDataEnabled(boolean enabled) {
synchronized (mDataEnabledLock) {
final boolean prevEnabled = getAnyDataEnabled();
if (mUserDataEnabled != enabled) {
mUserDataEnabled = enabled;
Settings.Secure.putInt(mPhone.getContext().getContentResolver(),
Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
}
}
}
}
@@ -1032,6 +1043,23 @@ public abstract class DataConnectionTracker extends Handler {
protected void onSetDependencyMet(String apnType, boolean met) {
}
protected void onSetPolicyDataEnabled(boolean enabled) {
synchronized (mDataEnabledLock) {
final boolean prevEnabled = getAnyDataEnabled();
if (mPolicyDataEnabled != enabled) {
mPolicyDataEnabled = enabled;
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
}
}
}
}
}
protected String getReryConfig(boolean forDefault) {
int rt = mPhone.getServiceState().getRadioTechnology();

View File

@@ -175,6 +175,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override
protected boolean isDataAllowed() {
final boolean internalDataEnabled;
synchronized (mDataEnabledLock) {
internalDataEnabled = mInternalDataEnabled;
}
int psState = mCdmaPhone.mSST.getCurrentDataConnectionState();
boolean roaming = (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled());
boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
@@ -187,7 +192,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
(mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
mPhone.getState() == Phone.State.IDLE) &&
!roaming &&
mInternalDataEnabled &&
internalDataEnabled &&
desiredPowerState &&
!mPendingRestartRadio &&
!mCdmaPhone.needsOtaServiceProvisioning();
@@ -205,7 +210,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState();
}
if (roaming) reason += " - Roaming";
if (!mInternalDataEnabled) reason += " - mInternalDataEnabled= false";
if (!internalDataEnabled) reason += " - mInternalDataEnabled= false";
if (!desiredPowerState) reason += " - desiredPowerState= false";
if (mPendingRestartRadio) reason += " - mPendingRestartRadio= true";
if (mCdmaPhone.needsOtaServiceProvisioning()) reason += " - needs Provisioning";

View File

@@ -27,14 +27,14 @@ import android.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.LinkProperties.CompareResult;
import android.net.NetworkConfig;
import android.net.NetworkUtils;
import android.net.ProxyProperties;
import android.net.TrafficStats;
import android.net.Uri;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkConfig;
import android.os.AsyncResult;
import android.os.Message;
import android.os.SystemClock;
@@ -49,34 +49,27 @@ import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
import android.preference.PreferenceManager;
import com.android.internal.R;
import com.android.internal.telephony.ApnContext;
import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnection.UpdateLinkPropertyResult;
import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
import com.android.internal.util.AsyncChannel;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* {@hide}
@@ -523,16 +516,18 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* {@code true} otherwise.
*/
@Override
public synchronized boolean getAnyDataEnabled() {
if (!(mInternalDataEnabled && mDataEnabled)) return false;
for (ApnContext apnContext : mApnContexts.values()) {
// Make sure we dont have a context that going down
// and is explicitly disabled.
if (isDataAllowed(apnContext)) {
return true;
public boolean getAnyDataEnabled() {
synchronized (mDataEnabledLock) {
if (!(mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled)) return false;
for (ApnContext apnContext : mApnContexts.values()) {
// Make sure we dont have a context that going down
// and is explicitly disabled.
if (isDataAllowed(apnContext)) {
return true;
}
}
return false;
}
return false;
}
private boolean isDataAllowed(ApnContext apnContext) {
@@ -570,6 +565,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected boolean isDataAllowed() {
final boolean internalDataEnabled;
synchronized (mDataEnabledLock) {
internalDataEnabled = mInternalDataEnabled;
}
int gprsState = mPhone.getServiceStateTracker().getCurrentDataConnectionState();
boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
@@ -577,7 +577,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
(gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
mPhone.mIccRecords.getRecordsLoaded() &&
mPhone.getState() == Phone.State.IDLE &&
mInternalDataEnabled &&
internalDataEnabled &&
(!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
!mIsPsRestricted &&
desiredPowerState;
@@ -590,7 +590,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mPhone.getState() != Phone.State.IDLE) {
reason += " - PhoneState= " + mPhone.getState();
}
if (!mInternalDataEnabled) reason += " - mInternalDataEnabled= false";
if (!internalDataEnabled) reason += " - mInternalDataEnabled= false";
if (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled()) {
reason += " - Roaming and data roaming not enabled";
}

View File

@@ -16,23 +16,20 @@
package android.net.wifi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.LinkCapabilities;
import android.net.NetworkInfo;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkStateTracker;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Handler;
import android.os.Message;
import android.util.Slog;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Track the state of wifi for connectivity service.
@@ -44,6 +41,8 @@ public class WifiStateTracker implements NetworkStateTracker {
private static final String NETWORKTYPE = "WIFI";
private static final String TAG = "WifiStateTracker";
private static final boolean LOGV = true;
private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
@@ -135,11 +134,14 @@ public class WifiStateTracker implements NetworkStateTracker {
return mNetworkInfo.isAvailable();
}
/**
* @param enabled
*/
public void setDataEnable(boolean enabled) {
android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
@Override
public void setUserDataEnable(boolean enabled) {
Slog.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
}
@Override
public void setPolicyDataEnable(boolean enabled) {
Slog.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
}
/**