Merge "Proactively disable data when over policy limit."
This commit is contained in:
@@ -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 + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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 + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user