OSDN Git Service

Add local-only hotspot info into tether state change broadcast
authorErik Kline <ek@google.com>
Mon, 17 Apr 2017 07:47:23 +0000 (16:47 +0900)
committerErik Kline <ek@google.com>
Thu, 20 Apr 2017 10:44:01 +0000 (19:44 +0900)
Test: as follows
    - build
    - flashed
    - booted
    - "runtest frameworks-net" passes
    - manually starting tethering shows Settings and icon updates
Bug: 31466854
Bug: 32163131

Change-Id: I938074587dfeec221c5cdb43a392802ad3fc3589

core/java/android/net/ConnectivityManager.java
services/core/java/com/android/server/connectivity/Tethering.java
tests/net/java/com/android/server/connectivity/TetheringTest.java

index 739b9dc..ac42be9 100644 (file)
@@ -301,7 +301,8 @@ public class ConnectivityManager {
     /**
      * Broadcast Action: A tetherable connection has come or gone.
      * Uses {@code ConnectivityManager.EXTRA_AVAILABLE_TETHER},
-     * {@code ConnectivityManager.EXTRA_ACTIVE_TETHER} and
+     * {@code ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY},
+     * {@code ConnectivityManager.EXTRA_ACTIVE_TETHER}, and
      * {@code ConnectivityManager.EXTRA_ERRORED_TETHER} to indicate
      * the current state of tethering.  Each include a list of
      * interface names in that state (may be empty).
@@ -320,10 +321,17 @@ public class ConnectivityManager {
 
     /**
      * @hide
+     * gives a String[] listing all the interfaces currently in local-only
+     * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
+     */
+    public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
+
+    /**
+     * @hide
      * gives a String[] listing all the interfaces currently tethered
-     * (ie, has dhcp support and packets potentially forwarded/NATed)
+     * (ie, has DHCPv4 support and packets potentially forwarded/NATed)
      */
-    public static final String EXTRA_ACTIVE_TETHER = "activeArray";
+    public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
 
     /**
      * @hide
index 460d5f9..a8cd068 100644 (file)
@@ -623,9 +623,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
     private void sendTetherStateChangedBroadcast() {
         if (!getConnectivityManager().isTetheringSupported()) return;
 
-        ArrayList<String> availableList = new ArrayList<String>();
-        ArrayList<String> activeList = new ArrayList<String>();
-        ArrayList<String> erroredList = new ArrayList<String>();
+        final ArrayList<String> availableList = new ArrayList<>();
+        final ArrayList<String> tetherList = new ArrayList<>();
+        final ArrayList<String> localOnlyList = new ArrayList<>();
+        final ArrayList<String> erroredList = new ArrayList<>();
 
         boolean wifiTethered = false;
         boolean usbTethered = false;
@@ -641,6 +642,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                     erroredList.add(iface);
                 } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
                     availableList.add(iface);
+                } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_HOTSPOT) {
+                    localOnlyList.add(iface);
                 } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
                     if (cfg.isUsb(iface)) {
                         usbTethered = true;
@@ -649,25 +652,25 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                     } else if (cfg.isBluetooth(iface)) {
                         bluetoothTethered = true;
                     }
-                    activeList.add(iface);
+                    tetherList.add(iface);
                 }
             }
         }
-        Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
-        broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+        final Intent bcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+        bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
-                availableList);
-        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
-        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
-                erroredList);
-        mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
+        bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, availableList);
+        bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
+        bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, tetherList);
+        bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList);
+        mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL);
         if (DBG) {
             Log.d(TAG, String.format(
-                    "sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]",
-                    TextUtils.join(",", availableList),
-                    TextUtils.join(",", activeList),
-                    TextUtils.join(",", erroredList)));
+                    "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]",
+                    "avail", TextUtils.join(",", availableList),
+                    "local_only", TextUtils.join(",", localOnlyList),
+                    "tether", TextUtils.join(",", tetherList),
+                    "error", TextUtils.join(",", erroredList)));
         }
 
         if (usbTethered) {
@@ -1338,7 +1341,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
             mForwardedDownstreams.remove(who);
         }
 
-        class InitialState extends TetherMasterUtilState {
+        class InitialState extends State {
             @Override
             public boolean processMessage(Message message) {
                 maybeLogMessage(this, message.what);
@@ -1516,7 +1519,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
         }
 
         class ErrorState extends State {
-            int mErrorNotification;
+            private int mErrorNotification;
+
             @Override
             public boolean processMessage(Message message) {
                 boolean retValue = true;
@@ -1534,6 +1538,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                 }
                 return retValue;
             }
+
             void notify(int msgType) {
                 mErrorNotification = msgType;
                 for (TetherInterfaceStateMachine sm : mNotifyList) {
@@ -1542,6 +1547,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
             }
 
         }
+
         class SetIpForwardingEnabledErrorState extends ErrorState {
             @Override
             public void enter() {
index e527d57..47630e2 100644 (file)
@@ -29,9 +29,11 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.hardware.usb.UsbManager;
 import android.net.ConnectivityManager;
@@ -53,12 +55,16 @@ import android.telephony.CarrierConfigManager;
 
 import com.android.internal.util.test.BroadcastInterceptingContext;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.Vector;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class TetheringTest {
@@ -81,7 +87,9 @@ public class TetheringTest {
     private final TestLooper mLooper = new TestLooper();
     private final String mTestIfname = "test_wlan0";
 
+    private Vector<Intent> mIntents;
     private BroadcastInterceptingContext mServiceContext;
+    private BroadcastReceiver mBroadcastReceiver;
     private Tethering mTethering;
 
     private class MockContext extends BroadcastInterceptingContext {
@@ -100,7 +108,8 @@ public class TetheringTest {
         }
     }
 
-    @Before public void setUp() throws Exception {
+    @Before
+    public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
                 .thenReturn(new String[0]);
@@ -118,10 +127,24 @@ public class TetheringTest {
                 .thenReturn(new InterfaceConfiguration());
 
         mServiceContext = new MockContext(mContext);
+        mIntents = new Vector<>();
+        mBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                mIntents.addElement(intent);
+            }
+        };
+        mServiceContext.registerReceiver(mBroadcastReceiver,
+                new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
         mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
                                    mLooper.getLooper(), mSystemProperties);
     }
 
+    @After
+    public void tearDown() {
+        mServiceContext.unregisterReceiver(mBroadcastReceiver);
+    }
+
     private void setupForRequiredProvisioning() {
         // Produce some acceptable looking provision app setting if requested.
         when(mResources.getStringArray(
@@ -180,6 +203,23 @@ public class TetheringTest {
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private void verifyInterfaceServingModeStarted() throws Exception {
+        verify(mNMService, times(1)).listInterfaces();
+        verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
+        verify(mNMService, times(1))
+                .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
+        verify(mNMService, times(1)).tetherInterface(mTestIfname);
+    }
+
+    private void verifyTetheringBroadcast(String ifname, String whichExtra) {
+        // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
+        final Intent bcast = mIntents.get(0);
+        assertEquals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, bcast.getAction());
+        final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
+        assertTrue(ifnames.contains(ifname));
+        mIntents.remove(bcast);
+    }
+
     @Test
     public void workingLocalOnlyHotspot() throws Exception {
         when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
@@ -193,14 +233,12 @@ public class TetheringTest {
         sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
         mLooper.dispatchAll();
 
-        verify(mNMService, times(1)).listInterfaces();
-        verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
-        verify(mNMService, times(1))
-                .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
-        verify(mNMService, times(1)).tetherInterface(mTestIfname);
+        verifyInterfaceServingModeStarted();
+        verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
         verifyNoMoreInteractions(mNMService);
+        verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY);
         // UpstreamNetworkMonitor will be started, and will register two callbacks:
         // a "listen all" and a "track default".
         verify(mConnectivityManager, times(1)).registerNetworkCallback(
@@ -252,14 +290,12 @@ public class TetheringTest {
         sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
         mLooper.dispatchAll();
 
-        verify(mNMService, times(1)).listInterfaces();
-        verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
-        verify(mNMService, times(1))
-                .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
-        verify(mNMService, times(1)).tetherInterface(mTestIfname);
+        verifyInterfaceServingModeStarted();
+        verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
         verify(mNMService, times(1)).setIpForwardingEnabled(true);
         verify(mNMService, times(1)).startTethering(any(String[].class));
         verifyNoMoreInteractions(mNMService);
+        verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_TETHER);
         // UpstreamNetworkMonitor will be started, and will register two callbacks:
         // a "listen all" and a "track default".
         verify(mConnectivityManager, times(1)).registerNetworkCallback(