Merge "Tell the system when tethering offload hits a limit." into oc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c3e7f875b4
@@ -219,6 +219,21 @@ interface INetworkManagementService
|
||||
*/
|
||||
void unregisterTetheringStatsProvider(ITetheringStatsProvider provider);
|
||||
|
||||
/**
|
||||
* Reports that a tethering provider has reached a data limit.
|
||||
*
|
||||
* Currently triggers a global alert, which causes NetworkStatsService to poll counters and
|
||||
* re-evaluate data usage.
|
||||
*
|
||||
* This does not take an interface name because:
|
||||
* 1. The tethering offload stats provider cannot reliably determine the interface on which the
|
||||
* limit was reached, because the HAL does not provide it.
|
||||
* 2. Firing an interface-specific alert instead of a global alert isn't really useful since in
|
||||
* all cases of interest, the system responds to both in the same way - it polls stats, and
|
||||
* then notifies NetworkPolicyManagerService of the fact.
|
||||
*/
|
||||
void tetherLimitReached(ITetheringStatsProvider provider);
|
||||
|
||||
/**
|
||||
** PPPD
|
||||
**/
|
||||
|
||||
@@ -547,6 +547,18 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tetherLimitReached(ITetheringStatsProvider provider) {
|
||||
mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
|
||||
synchronized(mTetheringStatsProviders) {
|
||||
if (!mTetheringStatsProviders.containsKey(provider)) {
|
||||
return;
|
||||
}
|
||||
// No current code examines the interface parameter in a global alert. Just pass null.
|
||||
notifyLimitReached(LIMIT_GLOBAL_ALERT, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Sync the state of the given chain with the native daemon.
|
||||
private void syncFirewallChainLocked(int chain, String name) {
|
||||
SparseIntArray rules;
|
||||
|
||||
@@ -60,6 +60,8 @@ public class OffloadController {
|
||||
private final Handler mHandler;
|
||||
private final OffloadHardwareInterface mHwInterface;
|
||||
private final ContentResolver mContentResolver;
|
||||
private final INetworkManagementService mNms;
|
||||
private final ITetheringStatsProvider mStatsProvider;
|
||||
private final SharedLog mLog;
|
||||
private boolean mConfigInitialized;
|
||||
private boolean mControlInitialized;
|
||||
@@ -89,13 +91,14 @@ public class OffloadController {
|
||||
mHandler = h;
|
||||
mHwInterface = hwi;
|
||||
mContentResolver = contentResolver;
|
||||
mNms = nms;
|
||||
mStatsProvider = new OffloadTetheringStatsProvider();
|
||||
mLog = log.forSubComponent(TAG);
|
||||
mExemptPrefixes = new HashSet<>();
|
||||
mLastLocalPrefixStrs = new HashSet<>();
|
||||
|
||||
try {
|
||||
nms.registerTetheringStatsProvider(
|
||||
new OffloadTetheringStatsProvider(), getClass().getSimpleName());
|
||||
mNms.registerTetheringStatsProvider(mStatsProvider, getClass().getSimpleName());
|
||||
} catch (RemoteException e) {
|
||||
mLog.e("Cannot register offload stats provider: " + e);
|
||||
}
|
||||
@@ -150,7 +153,26 @@ public class OffloadController {
|
||||
@Override
|
||||
public void onStoppedLimitReached() {
|
||||
mLog.log("onStoppedLimitReached");
|
||||
// Poll for statistics and notify NetworkStats
|
||||
|
||||
// We cannot reliably determine on which interface the limit was reached,
|
||||
// because the HAL interface does not specify it. We cannot just use the
|
||||
// current upstream, because that might have changed since the time that
|
||||
// the HAL queued the callback.
|
||||
// TODO: rev the HAL so that it provides an interface name.
|
||||
|
||||
// Fetch current stats, so that when our notification reaches
|
||||
// NetworkStatsService and triggers a poll, we will respond with
|
||||
// current data (which will be above the limit that was reached).
|
||||
// Note that if we just changed upstream, this is unnecessary but harmless.
|
||||
// The stats for the previous upstream were already updated on this thread
|
||||
// just after the upstream was changed, so they are also up-to-date.
|
||||
updateStatsForCurrentUpstream();
|
||||
|
||||
try {
|
||||
mNms.tetherLimitReached(mStatsProvider);
|
||||
} catch (RemoteException e) {
|
||||
mLog.e("Cannot report data limit reached: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -85,6 +85,8 @@ public class OffloadControllerTest {
|
||||
ArgumentCaptor.forClass(ArrayList.class);
|
||||
private final ArgumentCaptor<ITetheringStatsProvider.Stub> mTetherStatsProviderCaptor =
|
||||
ArgumentCaptor.forClass(ITetheringStatsProvider.Stub.class);
|
||||
private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor =
|
||||
ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class);
|
||||
private MockContentResolver mContentResolver;
|
||||
|
||||
@Before public void setUp() {
|
||||
@@ -103,7 +105,7 @@ public class OffloadControllerTest {
|
||||
|
||||
private void setupFunctioningHardwareInterface() {
|
||||
when(mHardware.initOffloadConfig()).thenReturn(true);
|
||||
when(mHardware.initOffloadControl(any(OffloadHardwareInterface.ControlCallback.class)))
|
||||
when(mHardware.initOffloadControl(mControlCallbackCaptor.capture()))
|
||||
.thenReturn(true);
|
||||
when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats());
|
||||
}
|
||||
@@ -489,4 +491,17 @@ public class OffloadControllerTest {
|
||||
waitForIdle();
|
||||
inOrder.verify(mHardware).stopOffloadControl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDataLimitCallback() throws Exception {
|
||||
setupFunctioningHardwareInterface();
|
||||
enableOffload();
|
||||
|
||||
final OffloadController offload = makeOffloadController();
|
||||
offload.start();
|
||||
|
||||
OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
|
||||
callback.onStoppedLimitReached();
|
||||
verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user