Merge "Background data notification, API clean up."

This commit is contained in:
Jeff Sharkey
2011-08-18 15:01:10 -07:00
committed by Android (Google) Code Review
7 changed files with 123 additions and 95 deletions

View File

@@ -11431,7 +11431,7 @@ package android.net {
method public android.net.NetworkInfo getActiveNetworkInfo();
method public android.net.NetworkQuotaInfo getActiveNetworkQuotaInfo();
method public android.net.NetworkInfo[] getAllNetworkInfo();
method public boolean getBackgroundDataSetting();
method public deprecated boolean getBackgroundDataSetting();
method public android.net.NetworkInfo getNetworkInfo(int);
method public int getNetworkPreference();
method public static boolean isNetworkTypeValid(int);
@@ -17087,7 +17087,7 @@ package android.provider {
field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
field public static final java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
field public static final java.lang.String ANDROID_ID = "android_id";
field public static final java.lang.String BACKGROUND_DATA = "background_data";
field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data";
field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_ROAMING = "data_roaming";

View File

@@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.RemoteException;
import java.net.InetAddress;
@@ -503,16 +504,19 @@ public class ConnectivityManager {
* <p>
* All applications that have background services that use the network
* should listen to {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
* <p>
* As of {@link VERSION_CODES#ICE_CREAM_SANDWICH}, availability of
* background data depends on several combined factors, and this method will
* always return {@code true}. Instead, when background data is unavailable,
* {@link #getActiveNetworkInfo()} will now appear disconnected.
*
* @return Whether background data usage is allowed.
*/
@Deprecated
public boolean getBackgroundDataSetting() {
try {
return mService.getBackgroundDataSetting();
} catch (RemoteException e) {
// Err on the side of safety
return false;
}
// assume that background data is allowed; final authority is
// NetworkInfo which may be blocked.
return true;
}
/**
@@ -525,11 +529,9 @@ public class ConnectivityManager {
* @see #getBackgroundDataSetting()
* @hide
*/
@Deprecated
public void setBackgroundDataSetting(boolean allowBackgroundData) {
try {
mService.setBackgroundDataSetting(allowBackgroundData);
} catch (RemoteException e) {
}
// ignored
}
/**

View File

@@ -63,10 +63,6 @@ interface IConnectivityManager
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
boolean getBackgroundDataSetting();
void setBackgroundDataSetting(boolean allowBackgroundData);
boolean getMobileDataEnabled();
void setMobileDataEnabled(boolean enabled);

View File

@@ -3081,6 +3081,7 @@ public final class Settings {
* Whether background data usage is allowed by the user. See
* ConnectivityManager for more info.
*/
@Deprecated
public static final String BACKGROUND_DATA = "background_data";
/**

View File

@@ -3099,7 +3099,7 @@
<!-- 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 body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
<string name="data_usage_limit_body">tap to enable</string>
<string name="data_usage_limit_body">Touch to enable</string>
<!-- Notification title when 2G-3G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_3g_limit_snoozed_title">2G-3G data limit exceeded</string>
@@ -3110,6 +3110,11 @@
<!-- 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>
<!-- Notification title when background data usage is limited. [CHAR LIMIT=32] -->
<string name="data_usage_restricted_title">Background data restricted</string>
<!-- Notification body when background data usage is limited. [CHAR LIMIT=32] -->
<string name="data_usage_restricted_body">Touch to remove restriction</string>
<!-- SSL Certificate dialogs -->
<!-- Title for an SSL Certificate dialog -->
<string name="ssl_certificate">Security certificate</string>

View File

@@ -163,8 +163,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private boolean mTestMode;
private static ConnectivityService sServiceInstance;
private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
private INetworkManagementService mNetd;
private INetworkPolicyManager mPolicyManager;
@@ -212,13 +210,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private static final int EVENT_INET_CONDITION_HOLD_END =
MAX_NETWORK_STATE_TRACKER_EVENT + 5;
/**
* used internally to set the background data preference
* arg1 = TRUE for enabled, FALSE for disabled
*/
private static final int EVENT_SET_BACKGROUND_DATA =
MAX_NETWORK_STATE_TRACKER_EVENT + 6;
/**
* used internally to set enable/disable cellular data
* arg1 = ENBALED or DISABLED
@@ -317,9 +308,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
handlerThread.start();
mHandler = new MyHandler(handlerThread.getLooper());
mBackgroundDataEnabled.set(Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.BACKGROUND_DATA, 1) == 1);
// setup our unique device name
if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
String id = Settings.Secure.getString(context.getContentResolver(),
@@ -1208,35 +1196,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return true;
}
/**
* @see ConnectivityManager#getBackgroundDataSetting()
*/
public boolean getBackgroundDataSetting() {
return mBackgroundDataEnabled.get();
}
/**
* @see ConnectivityManager#setBackgroundDataSetting(boolean)
*/
public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
"ConnectivityService");
mBackgroundDataEnabled.set(allowBackgroundDataUsage);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
(allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
}
private void handleSetBackgroundData(boolean enabled) {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
Intent broadcast = new Intent(
ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
mContext.sendBroadcast(broadcast);
}
/**
* @see ConnectivityManager#getMobileDataEnabled()
*/
@@ -2273,12 +2232,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
handleSetNetworkPreference(preference);
break;
}
case EVENT_SET_BACKGROUND_DATA:
{
boolean enabled = (msg.arg1 == ENABLED);
handleSetBackgroundData(enabled);
break;
}
case EVENT_SET_MOBILE_DATA:
{
boolean enabled = (msg.arg1 == ENABLED);

View File

@@ -89,6 +89,7 @@ import android.os.IPowerManager;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.format.Formatter;
import android.text.format.Time;
@@ -168,6 +169,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final String ATTR_UID = "uid";
private static final String ATTR_POLICY = "policy";
private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
// @VisibleForTesting
public static final String ACTION_ALLOW_BACKGROUND =
"com.android.server.action.ACTION_ALLOW_BACKGROUND";
private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
private static final int MSG_RULES_CHANGED = 0x1;
@@ -185,8 +192,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private final Object mRulesLock = new Object();
private boolean mScreenOn;
private boolean mRestrictBackground;
private volatile boolean mScreenOn;
private volatile boolean mRestrictBackground;
/** Defined network policies. */
private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
@@ -265,6 +272,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (mRestrictBackground) {
updateRulesForRestrictBackgroundLocked();
updateNotificationsLocked();
}
}
@@ -309,6 +317,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.registerReceiver(
mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
// listen for restrict background changes from notifications
final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
}
private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
@@ -401,6 +413,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
};
/**
* Receiver that watches for {@link Notification} control of
* {@link #mRestrictBackground}.
*/
private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified MANAGE_NETWORK_POLICY
// permission above.
setRestrictBackground(false);
}
};
/**
* Observer that watches for {@link INetworkManagementService} alerts.
*/
@@ -494,6 +520,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
notifyUnderLimitLocked(policy.template);
}
}
// ongoing notification when restricting background data
if (mRestrictBackground) {
enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
} else {
cancelNotification(TAG_ALLOW_BACKGROUND);
}
}
/**
@@ -614,16 +647,52 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
* Cancel any notification for combined {@link NetworkPolicy} and specific
* type, like {@link #TYPE_LIMIT}.
* Show ongoing notification to reflect that {@link #mRestrictBackground}
* has been enabled.
*/
private void cancelNotification(NetworkPolicy policy, int type) {
final String tag = buildNotificationTag(policy, type);
private void enqueueRestrictedNotification(String tag) {
final Resources res = mContext.getResources();
final Notification.Builder builder = new Notification.Builder(mContext);
final CharSequence title = res.getText(R.string.data_usage_restricted_title);
final CharSequence body = res.getString(R.string.data_usage_restricted_body);
builder.setOnlyAlertOnce(true);
builder.setOngoing(true);
builder.setSmallIcon(R.drawable.ic_menu_info_details);
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
final Intent intent = buildAllowBackgroundDataIntent();
builder.setContentIntent(
PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
// TODO: move to NotificationManager once we can mock it
try {
final String packageName = mContext.getPackageName();
mNotifManager.cancelNotificationWithTag(packageName, tag, 0x0);
final int[] idReceived = new int[1];
mNotifManager.enqueueNotificationWithTag(packageName, tag,
0x0, builder.getNotification(), idReceived);
} 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 {
final String packageName = mContext.getPackageName();
mNotifManager.cancelNotificationWithTag(
packageName, tag, 0x0);
} catch (RemoteException e) {
Slog.w(TAG, "problem during enqueueNotification: " + e);
}
@@ -731,15 +800,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
final boolean hasWarning = policy.warningBytes != WARNING_DISABLED;
if (hasLimit || hasWarning) {
final long quotaBytes;
if (hasLimit) {
// remaining "quota" is based on usage in current cycle
quotaBytes = Math.max(0, policy.limitBytes - total);
} else {
// to track warning alert later, use a high quota
quotaBytes = Long.MAX_VALUE;
}
if (hasLimit) {
// remaining "quota" is based on usage in current cycle
final long quotaBytes = Math.max(0, policy.limitBytes - total);
if (ifaces.length > 1) {
// TODO: switch to shared quota once NMS supports
@@ -754,16 +817,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
}
if (hasWarning) {
final long alertBytes = Math.max(0, policy.warningBytes - total);
for (String iface : ifaces) {
removeInterfaceAlert(iface);
if (alertBytes > 0) {
setInterfaceAlert(iface, alertBytes);
}
}
}
}
// remove quota on any trailing interfaces
@@ -839,11 +892,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mRestrictBackground = readBooleanAttribute(
in, ATTR_RESTRICT_BACKGROUND);
} else {
try {
mRestrictBackground = !mConnManager.getBackgroundDataSetting();
} catch (RemoteException e) {
mRestrictBackground = false;
}
mRestrictBackground = false;
}
} else if (TAG_NETWORK_POLICY.equals(tag)) {
@@ -879,6 +928,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} catch (FileNotFoundException e) {
// missing policy is okay, probably first boot
upgradeLegacyBackgroundData();
} catch (IOException e) {
Slog.e(TAG, "problem reading network stats", e);
} catch (XmlPullParserException e) {
@@ -888,6 +938,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
/**
* Upgrade legacy background data flags, notifying listeners of one last
* change to always-true.
*/
private void upgradeLegacyBackgroundData() {
mRestrictBackground = Settings.Secure.getInt(
mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
// kick off one last broadcast if restricted
if (mRestrictBackground) {
final Intent broadcast = new Intent(
ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
mContext.sendBroadcast(broadcast);
}
}
private void writePolicyLocked() {
if (LOGV) Slog.v(TAG, "writePolicyLocked()");
@@ -1057,6 +1123,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
synchronized (mRulesLock) {
mRestrictBackground = restrictBackground;
updateRulesForRestrictBackgroundLocked();
updateNotificationsLocked();
writePolicyLocked();
}
}
@@ -1420,6 +1487,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return telephony.getSubscriberId();
}
private static Intent buildAllowBackgroundDataIntent() {
return new Intent(ACTION_ALLOW_BACKGROUND);
}
private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
final Intent intent = new Intent();
intent.setComponent(new ComponentName(