Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9515b36f authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by android-build-merger
Browse files

Merge "Tell the system when tethering offload hits a limit." into oc-mr1-dev

am: c3e7f875

Change-Id: I026e6aa9e7b371f316c0d97c3cf5e78abc1f5263
parents 337ee077 c3e7f875
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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
     **/
+12 −0
Original line number Diff line number Diff line
@@ -550,6 +550,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;
+25 −3
Original line number Diff line number Diff line
@@ -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
+16 −1
Original line number Diff line number Diff line
@@ -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());
    }
}