summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java21
-rw-r--r--service/java/com/android/server/wifi/WifiTrafficPoller.java8
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiTrafficPollerTest.java180
3 files changed, 205 insertions, 4 deletions
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 56a57348d..dd1fb4492 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.InterfaceConfiguration;
import android.net.MacAddress;
+import android.net.TrafficStats;
import android.net.apf.ApfCapabilities;
import android.net.wifi.RttManager;
import android.net.wifi.RttManager.ResponderConfig;
@@ -2477,6 +2478,26 @@ public class WifiNative {
}
/**
+ * Get the tx packet counts for the interface.
+ *
+ * @param ifaceName Name of the interface.
+ * @return tx packet counts
+ */
+ public long getTxPackets(@NonNull String ifaceName) {
+ return TrafficStats.getTxPackets(ifaceName);
+ }
+
+ /**
+ * Get the rx packet counts for the interface.
+ *
+ * @param ifaceName Name of the interface
+ * @return rx packet counts
+ */
+ public long getRxPackets(@NonNull String ifaceName) {
+ return TrafficStats.getRxPackets(ifaceName);
+ }
+
+ /**
* Start sending the specified keep alive packets periodically.
*
* @param ifaceName Name of the interface.
diff --git a/service/java/com/android/server/wifi/WifiTrafficPoller.java b/service/java/com/android/server/wifi/WifiTrafficPoller.java
index cd6c72d57..bcb625ed6 100644
--- a/service/java/com/android/server/wifi/WifiTrafficPoller.java
+++ b/service/java/com/android/server/wifi/WifiTrafficPoller.java
@@ -24,7 +24,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
-import android.net.TrafficStats;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
@@ -75,7 +74,8 @@ public class WifiTrafficPoller {
private boolean mVerboseLoggingEnabled = false;
- WifiTrafficPoller(Context context, Looper looper, WifiNative wifiNative) {
+ WifiTrafficPoller(@NonNull Context context, @NonNull Looper looper,
+ @NonNull WifiNative wifiNative) {
mTrafficHandler = new TrafficHandler(looper);
mWifiNative = wifiNative;
@@ -195,8 +195,8 @@ public class WifiTrafficPoller {
long preTxPkts = mTxPkts, preRxPkts = mRxPkts;
int dataActivity = WifiManager.DATA_ACTIVITY_NONE;
- mTxPkts = TrafficStats.getTxPackets(ifaceName);
- mRxPkts = TrafficStats.getRxPackets(ifaceName);
+ mTxPkts = mWifiNative.getTxPackets(ifaceName);
+ mRxPkts = mWifiNative.getRxPackets(ifaceName);
if (DBG) {
Log.d(TAG, " packet count Tx="
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiTrafficPollerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiTrafficPollerTest.java
new file mode 100644
index 000000000..40281f8ba
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/WifiTrafficPollerTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.WifiTrafficPoller}.
+ */
+@SmallTest
+public class WifiTrafficPollerTest {
+ public static final String TAG = "WifiTrafficPollerTest";
+
+ private TestLooper mLooper;
+ private Handler mHandler;
+ private WifiTrafficPoller mWifiTrafficPoller;
+ private BroadcastReceiver mReceiver;
+ private Intent mIntent;
+ private Messenger mMessenger;
+ private final static String IFNAME = "wlan0";
+ private final static long DEFAULT_PACKET_COUNT = 10;
+ private final static long TX_PACKET_COUNT = 40;
+ private final static long RX_PACKET_COUNT = 50;
+
+ final ArgumentCaptor<Message> mMessageCaptor = ArgumentCaptor.forClass(Message.class);
+ final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ @Mock Context mContext;
+ @Mock WifiNative mWifiNative;
+ @Mock NetworkInfo mNetworkInfo;
+
+ /**
+ * Called before each test
+ */
+ @Before
+ public void setUp() throws Exception {
+ // Ensure looper exists
+ mLooper = new TestLooper();
+ mHandler = spy(new Handler(mLooper.getLooper()));
+ mMessenger = new Messenger(mHandler);
+ MockitoAnnotations.initMocks(this);
+
+ when(mWifiNative.getTxPackets(any(String.class))).thenReturn(DEFAULT_PACKET_COUNT,
+ TX_PACKET_COUNT);
+ when(mWifiNative.getRxPackets(any(String.class))).thenReturn(DEFAULT_PACKET_COUNT,
+ RX_PACKET_COUNT);
+ when(mWifiNative.getClientInterfaceName()).thenReturn(IFNAME);
+
+ mWifiTrafficPoller = new WifiTrafficPoller(mContext, mLooper.getLooper(), mWifiNative);
+ // Verify the constructor registers broadcast receiver with the collect intent filters.
+ verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), argThat(
+ intentFilter -> intentFilter.hasAction(WifiManager.NETWORK_STATE_CHANGED_ACTION) &&
+ intentFilter.hasAction(Intent.ACTION_SCREEN_ON) &&
+ intentFilter.hasAction(Intent.ACTION_SCREEN_OFF)));
+ mReceiver = mBroadcastReceiverCaptor.getValue();
+
+ // For the fist call, this is required to set the DEFAULT_PACKET_COUNT to mTxPkts and
+ // mRxPkts in WifiTrafficPoll Object.
+ triggerForUpdatedInformationOfData(Intent.ACTION_SCREEN_ON,
+ NetworkInfo.DetailedState.CONNECTED);
+ }
+
+ private void registerClient() {
+ // Register Client to verify that Tx/RX packet message is properly received.
+ mWifiTrafficPoller.addClient(mMessenger);
+ mLooper.dispatchAll();
+ }
+
+ private void triggerForUpdatedInformationOfData(String actionScreen,
+ NetworkInfo.DetailedState networkState) {
+ when(mNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.DISCONNECTED);
+ mIntent = new Intent(actionScreen);
+ mReceiver.onReceive(mContext, mIntent);
+ mLooper.dispatchAll();
+
+ when(mNetworkInfo.getDetailedState()).thenReturn(networkState);
+ mIntent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mIntent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo);
+ mReceiver.onReceive(mContext, mIntent);
+ mLooper.dispatchAll();
+ }
+
+ /**
+ * Verify that StartTrafficStatsPolling should not happen in case a network is not connected
+ */
+ @Test
+ public void testNotStartTrafficStatsPollingWithDisconnected() {
+ registerClient();
+ triggerForUpdatedInformationOfData(Intent.ACTION_SCREEN_ON,
+ NetworkInfo.DetailedState.DISCONNECTED);
+
+ // Client should not get any message when the network is disconnected
+ verify(mHandler, never()).handleMessage(any(Message.class));
+ }
+
+ /**
+ * Verify that StartTrafficStatsPolling should happen in case screen is on and rx/tx packets are
+ * available.
+ */
+ @Test
+ public void testStartTrafficStatsPollingWithScreenOn() {
+ registerClient();
+ triggerForUpdatedInformationOfData(Intent.ACTION_SCREEN_ON,
+ NetworkInfo.DetailedState.CONNECTED);
+
+ // Client should get the DATA_ACTIVITY_NOTIFICATION
+ verify(mHandler).handleMessage(mMessageCaptor.capture());
+ assertEquals(WifiManager.DATA_ACTIVITY_NOTIFICATION, mMessageCaptor.getValue().what);
+ }
+
+ /**
+ * Verify that StartTrafficStatsPolling should not happen in case screen is off.
+ */
+ @Test
+ public void testNotStartTrafficStatsPollingWithScreenOff() {
+ registerClient();
+ triggerForUpdatedInformationOfData(Intent.ACTION_SCREEN_OFF,
+ NetworkInfo.DetailedState.CONNECTED);
+
+ verify(mNetworkInfo, atLeastOnce()).getDetailedState();
+ mLooper.dispatchAll();
+
+ // Client should not get any message when the screen is off
+ verify(mHandler, never()).handleMessage(any(Message.class));
+ }
+
+ /**
+ * Verify that remove client message should be handled
+ */
+ @Test
+ public void testRemoveClient() {
+ registerClient();
+ mWifiTrafficPoller.removeClient(mMessenger);
+ mLooper.dispatchAll();
+
+ triggerForUpdatedInformationOfData(Intent.ACTION_SCREEN_ON,
+ NetworkInfo.DetailedState.CONNECTED);
+
+ // Client should not get any message after the client is removed.
+ verify(mHandler, never()).handleMessage(any(Message.class));
+ }
+}