Snap for 6450912 from 6b639d3eb3fc417ba2279b2265255b9e8c1d1157 to mainline-release
Change-Id: Ica89f4b346997c4a37ab5664a54383ac4c63c472
This commit is contained in:
@@ -134,5 +134,5 @@ java_library {
|
||||
java_library {
|
||||
name: "framework-tethering-stubs-module_libs_api",
|
||||
srcs: [":framework-tethering-stubs-srcs-module_libs_api"],
|
||||
defaults: ["framework-module-stubs-lib-defaults-systemapi"],
|
||||
defaults: ["framework-module-stubs-lib-defaults-module_libs_api"],
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel {
|
||||
* <p>If not set, the default value is null.
|
||||
*/
|
||||
public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) {
|
||||
this.clientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr);
|
||||
this.singleClientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.net.NetworkStats.SET_DEFAULT;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.NetworkStats.UID_TETHERING;
|
||||
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
|
||||
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
@@ -76,6 +77,7 @@ public class OffloadController {
|
||||
private static final boolean DBG = false;
|
||||
private static final String ANYIP = "0.0.0.0";
|
||||
private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
|
||||
private static final int DEFAULT_PERFORM_POLL_INTERVAL_MS = 5000;
|
||||
|
||||
@VisibleForTesting
|
||||
enum StatsType {
|
||||
@@ -115,11 +117,33 @@ public class OffloadController {
|
||||
// includes upstream interfaces that have a quota set.
|
||||
private HashMap<String, Long> mInterfaceQuotas = new HashMap<>();
|
||||
|
||||
// Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert
|
||||
// quota is interface independent and global for tether offload. Note that this is only
|
||||
// accessed on the handler thread and in the constructor.
|
||||
private long mRemainingAlertQuota = QUOTA_UNLIMITED;
|
||||
// Runnable that used to schedule the next stats poll.
|
||||
private final Runnable mScheduledPollingTask = () -> {
|
||||
updateStatsForCurrentUpstream();
|
||||
maybeSchedulePollingStats();
|
||||
};
|
||||
|
||||
private int mNatUpdateCallbacksReceived;
|
||||
private int mNatUpdateNetlinkErrors;
|
||||
|
||||
@NonNull
|
||||
private final Dependencies mDeps;
|
||||
|
||||
// TODO: Put more parameters in constructor into dependency object.
|
||||
static class Dependencies {
|
||||
int getPerformPollInterval() {
|
||||
// TODO: Consider make this configurable.
|
||||
return DEFAULT_PERFORM_POLL_INTERVAL_MS;
|
||||
}
|
||||
}
|
||||
|
||||
public OffloadController(Handler h, OffloadHardwareInterface hwi,
|
||||
ContentResolver contentResolver, NetworkStatsManager nsm, SharedLog log) {
|
||||
ContentResolver contentResolver, NetworkStatsManager nsm, SharedLog log,
|
||||
@NonNull Dependencies deps) {
|
||||
mHandler = h;
|
||||
mHwInterface = hwi;
|
||||
mContentResolver = contentResolver;
|
||||
@@ -135,6 +159,7 @@ public class OffloadController {
|
||||
provider = null;
|
||||
}
|
||||
mStatsProvider = provider;
|
||||
mDeps = deps;
|
||||
}
|
||||
|
||||
/** Start hardware offload. */
|
||||
@@ -240,6 +265,7 @@ public class OffloadController {
|
||||
mLog.log("tethering offload started");
|
||||
mNatUpdateCallbacksReceived = 0;
|
||||
mNatUpdateNetlinkErrors = 0;
|
||||
maybeSchedulePollingStats();
|
||||
}
|
||||
return isStarted;
|
||||
}
|
||||
@@ -255,6 +281,9 @@ public class OffloadController {
|
||||
mHwInterface.stopOffloadControl();
|
||||
mControlInitialized = false;
|
||||
mConfigInitialized = false;
|
||||
if (mHandler.hasCallbacks(mScheduledPollingTask)) {
|
||||
mHandler.removeCallbacks(mScheduledPollingTask);
|
||||
}
|
||||
if (wasStarted) mLog.log("tethering offload stopped");
|
||||
}
|
||||
|
||||
@@ -345,6 +374,11 @@ public class OffloadController {
|
||||
@Override
|
||||
public void onSetAlert(long quotaBytes) {
|
||||
// TODO: Ask offload HAL to notify alert without stopping traffic.
|
||||
// Post it to handler thread since it access remaining quota bytes.
|
||||
mHandler.post(() -> {
|
||||
updateAlertQuota(quotaBytes);
|
||||
maybeSchedulePollingStats();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,15 +400,66 @@ public class OffloadController {
|
||||
// the stats for each interface, and does not observe partial writes where rxBytes is
|
||||
// updated and txBytes is not.
|
||||
ForwardedStats diff = mHwInterface.getForwardedStats(iface);
|
||||
final long usedAlertQuota = diff.rxBytes + diff.txBytes;
|
||||
ForwardedStats base = mForwardedStats.get(iface);
|
||||
if (base != null) {
|
||||
diff.add(base);
|
||||
}
|
||||
|
||||
// Update remaining alert quota if it is still positive.
|
||||
if (mRemainingAlertQuota > 0 && usedAlertQuota > 0) {
|
||||
// Trim to zero if overshoot.
|
||||
final long newQuota = Math.max(mRemainingAlertQuota - usedAlertQuota, 0);
|
||||
updateAlertQuota(newQuota);
|
||||
}
|
||||
|
||||
mForwardedStats.put(iface, diff);
|
||||
// diff is a new object, just created by getForwardedStats(). Therefore, anyone reading from
|
||||
// mForwardedStats (i.e., any caller of getTetherStats) will see the new stats immediately.
|
||||
}
|
||||
|
||||
/**
|
||||
* Update remaining alert quota, fire the {@link NetworkStatsProvider#notifyAlertReached()}
|
||||
* callback when it reaches zero. This can be invoked either from service setting the alert, or
|
||||
* {@code maybeUpdateStats} when updating stats. Note that this can be only called on
|
||||
* handler thread.
|
||||
*
|
||||
* @param newQuota non-negative value to indicate the new quota, or
|
||||
* {@link NetworkStatsProvider#QUOTA_UNLIMITED} to indicate there is no
|
||||
* quota.
|
||||
*/
|
||||
private void updateAlertQuota(long newQuota) {
|
||||
if (newQuota < QUOTA_UNLIMITED) {
|
||||
throw new IllegalArgumentException("invalid quota value " + newQuota);
|
||||
}
|
||||
if (mRemainingAlertQuota == newQuota) return;
|
||||
|
||||
mRemainingAlertQuota = newQuota;
|
||||
if (mRemainingAlertQuota == 0) {
|
||||
mLog.i("notifyAlertReached");
|
||||
if (mStatsProvider != null) mStatsProvider.notifyAlertReached();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule polling if needed, this will be stopped if offload has been
|
||||
* stopped or remaining quota reaches zero or upstream is empty.
|
||||
* Note that this can be only called on handler thread.
|
||||
*/
|
||||
private void maybeSchedulePollingStats() {
|
||||
if (!isPollingStatsNeeded()) return;
|
||||
|
||||
if (mHandler.hasCallbacks(mScheduledPollingTask)) {
|
||||
mHandler.removeCallbacks(mScheduledPollingTask);
|
||||
}
|
||||
mHandler.postDelayed(mScheduledPollingTask, mDeps.getPerformPollInterval());
|
||||
}
|
||||
|
||||
private boolean isPollingStatsNeeded() {
|
||||
return started() && mRemainingAlertQuota > 0
|
||||
&& !TextUtils.isEmpty(currentUpstreamInterface());
|
||||
}
|
||||
|
||||
private boolean maybeUpdateDataLimit(String iface) {
|
||||
// setDataLimit may only be called while offload is occurring on this upstream.
|
||||
if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) {
|
||||
@@ -414,6 +499,8 @@ public class OffloadController {
|
||||
final String iface = currentUpstreamInterface();
|
||||
if (!TextUtils.isEmpty(iface)) mForwardedStats.putIfAbsent(iface, EMPTY_STATS);
|
||||
|
||||
maybeSchedulePollingStats();
|
||||
|
||||
// TODO: examine return code and decide what to do if programming
|
||||
// upstream parameters fails (probably just wait for a subsequent
|
||||
// onOffloadEvent() callback to tell us offload is available again and
|
||||
|
||||
@@ -308,7 +308,6 @@ public class OffloadHardwareInterface {
|
||||
return stats;
|
||||
}
|
||||
|
||||
mLog.log(logmsg + YIELDS + stats);
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ public class Tethering {
|
||||
mHandler = mTetherMasterSM.getHandler();
|
||||
mOffloadController = new OffloadController(mHandler,
|
||||
mDeps.getOffloadHardwareInterface(mHandler, mLog), mContext.getContentResolver(),
|
||||
statsManager, mLog);
|
||||
statsManager, mLog, new OffloadController.Dependencies());
|
||||
mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
|
||||
TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
|
||||
mForwardedDownstreams = new LinkedHashSet<>();
|
||||
|
||||
@@ -110,7 +110,7 @@ public class DhcpServingParamsParcelExtTest {
|
||||
@Test
|
||||
public void testSetClientAddr() {
|
||||
mParcel.setSingleClientAddr(TEST_CLIENT_ADDRESS);
|
||||
assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.clientAddr);
|
||||
assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.singleClientAddr);
|
||||
}
|
||||
|
||||
private static Inet4Address inet4Addr(String addr) {
|
||||
|
||||
@@ -116,6 +116,12 @@ public class OffloadControllerTest {
|
||||
private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor =
|
||||
ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class);
|
||||
private MockContentResolver mContentResolver;
|
||||
private OffloadController.Dependencies mDeps = new OffloadController.Dependencies() {
|
||||
@Override
|
||||
int getPerformPollInterval() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@Before public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -150,7 +156,7 @@ public class OffloadControllerTest {
|
||||
|
||||
private OffloadController makeOffloadController() throws Exception {
|
||||
OffloadController offload = new OffloadController(new Handler(Looper.getMainLooper()),
|
||||
mHardware, mContentResolver, mStatsManager, new SharedLog("test"));
|
||||
mHardware, mContentResolver, mStatsManager, new SharedLog("test"), mDeps);
|
||||
final ArgumentCaptor<OffloadController.OffloadTetheringStatsProvider>
|
||||
tetherStatsProviderCaptor =
|
||||
ArgumentCaptor.forClass(OffloadController.OffloadTetheringStatsProvider.class);
|
||||
|
||||
@@ -1689,7 +1689,7 @@ public class TetheringTest {
|
||||
final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue();
|
||||
assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress());
|
||||
assertEquals(24, params.serverAddrPrefixLength);
|
||||
assertEquals(clientAddrParceled, params.clientAddr);
|
||||
assertEquals(clientAddrParceled, params.singleClientAddr);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user