Merge "Add settings to configure default multipath quota." into pi-dev

This commit is contained in:
Remi NGUYEN VAN
2018-04-04 01:23:42 +00:00
committed by Android (Google) Code Review
5 changed files with 100 additions and 10 deletions

View File

@@ -9308,6 +9308,15 @@ public final class Settings {
public static final String NETWORK_METERED_MULTIPATH_PREFERENCE =
"network_metered_multipath_preference";
/**
* Default daily multipath budget used by ConnectivityManager.getMultipathPreference()
* on metered networks. This default quota is only used if quota could not be determined
* from data plan or data limit/warning set by the user.
* @hide
*/
public static final String NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES =
"network_default_daily_multipath_quota_bytes";
/**
* Network watchlist last report time.
* @hide

View File

@@ -327,6 +327,13 @@
This is the default value of that setting. -->
<integer translatable="false" name="config_networkMeteredMultipathPreference">0</integer>
<!-- Default daily multipath budget used by ConnectivityManager.getMultipathPreference()
on metered networks. This default quota only used if quota could not be determined from
data plan or data limit/warning set by the user. The value that is actually used is
controlled by Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES. This is the
default value of that setting. -->
<integer translatable="false" name="config_networkDefaultDailyMultipathQuotaBytes">2500000</integer>
<!-- List of regexpressions describing the interface (if any) that represent tetherable
USB interfaces. If the device doesn't want to support tethering over USB this should
be empty. An example would be "usb.*" -->

View File

@@ -1922,6 +1922,7 @@
<java-symbol type="integer" name="config_networkWakeupPacketMask" />
<java-symbol type="bool" name="config_apfDrop802_3Frames" />
<java-symbol type="array" name="config_apfEthTypeBlackList" />
<java-symbol type="integer" name="config_networkDefaultDailyMultipathQuotaBytes" />
<java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
<java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
<java-symbol type="integer" name="config_notificationsBatteryLedOff" />

View File

@@ -301,6 +301,7 @@ public class SettingsBackupTest {
Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES,
Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE,
Settings.Global.NETWORK_AVOID_BAD_WIFI,
Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES,
Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE,
Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME,
Settings.Global.NETWORK_PREFERENCE,

View File

@@ -24,13 +24,19 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
import android.app.usage.NetworkStatsManager;
import android.app.usage.NetworkStatsManager.UsageCallback;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
@@ -45,11 +51,15 @@ import android.net.StringNetworkSpecifier;
import android.os.BestClock;
import android.os.Handler;
import android.os.SystemClock;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.DebugUtils;
import android.util.Pair;
import android.util.Slog;
import com.android.internal.R;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -60,7 +70,6 @@ import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@@ -85,6 +94,9 @@ public class MultipathPolicyTracker {
private final Handler mHandler;
private final Clock mClock;
private final Dependencies mDeps;
private final ContentResolver mResolver;
private final SettingsObserver mSettingsObserver;
private final ConfigChangeReceiver mConfigChangeReceiver;
private ConnectivityManager mCM;
private NetworkPolicyManager mNPM;
@@ -93,8 +105,6 @@ public class MultipathPolicyTracker {
private NetworkCallback mMobileNetworkCallback;
private NetworkPolicyManager.Listener mPolicyListener;
// STOPSHIP: replace this with a configurable mechanism.
private static final long DEFAULT_DAILY_MULTIPATH_QUOTA = 2_500_000;
/**
* Divider to calculate opportunistic quota from user-set data limit or warning: 5% of user-set
@@ -118,6 +128,9 @@ public class MultipathPolicyTracker {
mHandler = handler;
mClock = deps.getClock();
mDeps = deps;
mResolver = mContext.getContentResolver();
mSettingsObserver = new SettingsObserver(mHandler);
mConfigChangeReceiver = new ConfigChangeReceiver();
// Because we are initialized by the ConnectivityService constructor, we can't touch any
// connectivity APIs. Service initialization is done in start().
}
@@ -129,6 +142,14 @@ public class MultipathPolicyTracker {
registerTrackMobileCallback();
registerNetworkPolicyListener();
final Uri defaultSettingUri =
Settings.Global.getUriFor(NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES);
mResolver.registerContentObserver(defaultSettingUri, false, mSettingsObserver);
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
mContext.registerReceiverAsUser(
mConfigChangeReceiver, UserHandle.ALL, intentFilter, null, mHandler);
}
public void shutdown() {
@@ -138,6 +159,8 @@ public class MultipathPolicyTracker {
t.shutdown();
}
mMultipathTrackers.clear();
mResolver.unregisterContentObserver(mSettingsObserver);
mContext.unregisterReceiver(mConfigChangeReceiver);
}
// Called on an arbitrary binder thread.
@@ -292,11 +315,11 @@ public class MultipathPolicyTracker {
// Fallback to user settings-based quota if not available from phone plan
if (quota == OPPORTUNISTIC_QUOTA_UNKNOWN) {
quota = getUserPolicyOpportunisticQuotaBytes();
if (DBG) Slog.d(TAG, "Opportunistic quota from user policy: " + quota + " bytes");
}
if (quota == OPPORTUNISTIC_QUOTA_UNKNOWN) {
// STOPSHIP: replace this with a configurable mechanism.
quota = DEFAULT_DAILY_MULTIPATH_QUOTA;
quota = getDefaultDailyMultipathQuotaBytes();
if (DBG) Slog.d(TAG, "Setting quota: " + quota + " bytes");
}
@@ -374,6 +397,21 @@ public class MultipathPolicyTracker {
private final ConcurrentHashMap <Network, MultipathTracker> mMultipathTrackers =
new ConcurrentHashMap<>();
private long getDefaultDailyMultipathQuotaBytes() {
final String setting = Settings.Global.getString(mContext.getContentResolver(),
NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES);
if (setting != null) {
try {
return Long.parseLong(setting);
} catch(NumberFormatException e) {
// fall through
}
}
return mContext.getResources().getInteger(
R.integer.config_networkDefaultDailyMultipathQuotaBytes);
}
// TODO: this races with app code that might respond to onAvailable() by immediately calling
// getMultipathPreference. Fix this by adding to ConnectivityService the ability to directly
// invoke NetworkCallbacks on tightly-coupled classes such as this one which run on its
@@ -415,6 +453,15 @@ public class MultipathPolicyTracker {
mCM.registerNetworkCallback(request, mMobileNetworkCallback, mHandler);
}
/**
* Update multipath budgets for all trackers. To be called on the mHandler thread.
*/
private void updateAllMultipathBudgets() {
for (MultipathTracker t : mMultipathTrackers.values()) {
t.updateMultipathBudget();
}
}
private void maybeUnregisterTrackMobileCallback() {
if (mMobileNetworkCallback != null) {
mCM.unregisterNetworkCallback(mMobileNetworkCallback);
@@ -427,11 +474,7 @@ public class MultipathPolicyTracker {
@Override
public void onMeteredIfacesChanged(String[] meteredIfaces) {
// Dispatched every time opportunistic quota is recalculated.
mHandler.post(() -> {
for (MultipathTracker t : mMultipathTrackers.values()) {
t.updateMultipathBudget();
}
});
mHandler.post(() -> updateAllMultipathBudgets());
}
};
mNPM.registerListener(mPolicyListener);
@@ -441,6 +484,35 @@ public class MultipathPolicyTracker {
mNPM.unregisterListener(mPolicyListener);
}
private final class SettingsObserver extends ContentObserver {
public SettingsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
Slog.wtf(TAG, "Should never be reached.");
}
@Override
public void onChange(boolean selfChange, Uri uri) {
if (!Settings.Global.getUriFor(NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES)
.equals(uri)) {
Slog.wtf(TAG, "Unexpected settings observation: " + uri);
}
if (DBG) Slog.d(TAG, "Settings change: updating budgets.");
updateAllMultipathBudgets();
}
}
private final class ConfigChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (DBG) Slog.d(TAG, "Configuration change: updating budgets.");
updateAllMultipathBudgets();
}
}
public void dump(IndentingPrintWriter pw) {
// Do not use in production. Access to class data is only safe on the handler thrad.
pw.println("MultipathPolicyTracker:");