diff options
| -rw-r--r-- | api/current.txt | 4 | ||||
| -rw-r--r-- | core/java/android/net/ConnectivityManager.java | 22 | ||||
| -rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 4 | ||||
| -rw-r--r-- | core/java/android/provider/Settings.java | 1 | ||||
| -rwxr-xr-x | core/res/res/values/strings.xml | 7 | ||||
| -rw-r--r-- | services/java/com/android/server/ConnectivityService.java | 47 | ||||
| -rw-r--r-- | services/java/com/android/server/net/NetworkPolicyManagerService.java | 127 |
7 files changed, 120 insertions, 92 deletions
diff --git a/api/current.txt b/api/current.txt index c70cea85bfd0..3a20260f230d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11400,7 +11400,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); @@ -17049,7 +17049,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"; diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index eb9cd213dd8e..68e80ff7d262 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -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; @@ -494,16 +495,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; } /** @@ -516,11 +520,9 @@ public class ConnectivityManager { * @see #getBackgroundDataSetting() * @hide */ + @Deprecated public void setBackgroundDataSetting(boolean allowBackgroundData) { - try { - mService.setBackgroundDataSetting(allowBackgroundData); - } catch (RemoteException e) { - } + // ignored } /** diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index f3912005a667..1b95b60a536d 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -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); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f8702b9d9117..a380efcc7338 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -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"; /** diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 7d6d25c840e4..4f62f126958b 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3073,7 +3073,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> @@ -3084,6 +3084,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> diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index acfc7a4d9522..2bb952ee8b2d 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -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; @@ -213,13 +211,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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(), @@ -1226,35 +1214,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { } /** - * @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() */ public boolean getMobileDataEnabled() { @@ -2268,12 +2227,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); diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 9c3d166c5481..14d966511d6f 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -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() { @@ -402,6 +414,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. */ private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { @@ -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 { } /** + * Show ongoing notification to reflect that {@link #mRestrictBackground} + * has been enabled. + */ + 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(); + 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) { - final String tag = buildNotificationTag(policy, 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); + 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( |