Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net.wifi;
     18 
     19 import static android.net.wifi.WifiManager.HOTSPOT_FAILED;
     20 import static android.net.wifi.WifiManager.HOTSPOT_STARTED;
     21 import static android.net.wifi.WifiManager.HOTSPOT_STOPPED;
     22 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
     23 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
     24 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
     25 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
     26 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
     27 
     28 import static org.junit.Assert.assertEquals;
     29 import static org.junit.Assert.assertFalse;
     30 import static org.junit.Assert.assertNotNull;
     31 import static org.junit.Assert.assertTrue;
     32 import static org.mockito.Mockito.*;
     33 
     34 import android.content.Context;
     35 import android.content.pm.ApplicationInfo;
     36 import android.net.wifi.WifiManager.LocalOnlyHotspotCallback;
     37 import android.net.wifi.WifiManager.LocalOnlyHotspotObserver;
     38 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
     39 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
     40 import android.os.Handler;
     41 import android.os.IBinder;
     42 import android.os.Message;
     43 import android.os.Messenger;
     44 import android.os.test.TestLooper;
     45 import android.test.suitebuilder.annotation.SmallTest;
     46 
     47 import org.junit.Before;
     48 import org.junit.Test;
     49 import org.mockito.ArgumentCaptor;
     50 import org.mockito.Mock;
     51 import org.mockito.MockitoAnnotations;
     52 
     53 /**
     54  * Unit tests for {@link android.net.wifi.WifiManager}.
     55  */
     56 @SmallTest
     57 public class WifiManagerTest {
     58 
     59     private static final int ERROR_NOT_SET = -1;
     60     private static final int ERROR_TEST_REASON = 5;
     61     private static final String TEST_PACKAGE_NAME = "TestPackage";
     62 
     63     @Mock Context mContext;
     64     @Mock IWifiManager mWifiService;
     65     @Mock ApplicationInfo mApplicationInfo;
     66     @Mock WifiConfiguration mApConfig;
     67     @Mock IBinder mAppBinder;
     68 
     69     private Handler mHandler;
     70     private TestLooper mLooper;
     71     private WifiManager mWifiManager;
     72     private Messenger mWifiServiceMessenger;
     73     final ArgumentCaptor<Messenger> mMessengerCaptor = ArgumentCaptor.forClass(Messenger.class);
     74 
     75     @Before public void setUp() throws Exception {
     76         MockitoAnnotations.initMocks(this);
     77         mLooper = new TestLooper();
     78         mHandler = spy(new Handler(mLooper.getLooper()));
     79         when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
     80         when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
     81 
     82         mWifiServiceMessenger = new Messenger(mHandler);
     83         mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
     84     }
     85 
     86     /**
     87      * Check the call to startSoftAp calls WifiService to startSoftAp with the provided
     88      * WifiConfiguration.  Verify that the return value is propagated to the caller.
     89      */
     90     @Test
     91     public void testStartSoftApCallsServiceWithWifiConfig() throws Exception {
     92         when(mWifiService.startSoftAp(eq(mApConfig))).thenReturn(true);
     93         assertTrue(mWifiManager.startSoftAp(mApConfig));
     94 
     95         when(mWifiService.startSoftAp(eq(mApConfig))).thenReturn(false);
     96         assertFalse(mWifiManager.startSoftAp(mApConfig));
     97     }
     98 
     99     /**
    100      * Check the call to startSoftAp calls WifiService to startSoftAp with a null config.  Verify
    101      * that the return value is propagated to the caller.
    102      */
    103     @Test
    104     public void testStartSoftApCallsServiceWithNullConfig() throws Exception {
    105         when(mWifiService.startSoftAp(eq(null))).thenReturn(true);
    106         assertTrue(mWifiManager.startSoftAp(null));
    107 
    108         when(mWifiService.startSoftAp(eq(null))).thenReturn(false);
    109         assertFalse(mWifiManager.startSoftAp(null));
    110     }
    111 
    112     /**
    113      * Check the call to stopSoftAp calls WifiService to stopSoftAp.
    114      */
    115     @Test
    116     public void testStopSoftApCallsService() throws Exception {
    117         when(mWifiService.stopSoftAp()).thenReturn(true);
    118         assertTrue(mWifiManager.stopSoftAp());
    119 
    120         when(mWifiService.stopSoftAp()).thenReturn(false);
    121         assertFalse(mWifiManager.stopSoftAp());
    122     }
    123 
    124     /**
    125      * Test creation of a LocalOnlyHotspotReservation and verify that close properly calls
    126      * WifiService.stopLocalOnlyHotspot.
    127      */
    128     @Test
    129     public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception {
    130         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    131         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    132                 anyString())).thenReturn(REQUEST_REGISTERED);
    133         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    134 
    135         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
    136 
    137         assertEquals(mApConfig, callback.mRes.getWifiConfiguration());
    138         callback.mRes.close();
    139         verify(mWifiService).stopLocalOnlyHotspot();
    140     }
    141 
    142     /**
    143      * Verify stopLOHS is called when try-with-resources is used properly.
    144      */
    145     @Test
    146     public void testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources()
    147             throws Exception {
    148         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    149         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    150                 anyString())).thenReturn(REQUEST_REGISTERED);
    151         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    152 
    153         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
    154 
    155         try (WifiManager.LocalOnlyHotspotReservation res = callback.mRes) {
    156             assertEquals(mApConfig, res.getWifiConfiguration());
    157         }
    158 
    159         verify(mWifiService).stopLocalOnlyHotspot();
    160     }
    161 
    162     /**
    163      * Test creation of a LocalOnlyHotspotSubscription.
    164      * TODO: when registrations are tracked, verify removal on close.
    165      */
    166     @Test
    167     public void testCreationOfLocalOnlyHotspotSubscription() throws Exception {
    168         try (WifiManager.LocalOnlyHotspotSubscription sub =
    169                 mWifiManager.new LocalOnlyHotspotSubscription()) {
    170             sub.close();
    171         }
    172     }
    173 
    174     public class TestLocalOnlyHotspotCallback extends LocalOnlyHotspotCallback {
    175         public boolean mOnStartedCalled = false;
    176         public boolean mOnStoppedCalled = false;
    177         public int mFailureReason = -1;
    178         public LocalOnlyHotspotReservation mRes = null;
    179         public long mCallingThreadId = -1;
    180 
    181         @Override
    182         public void onStarted(LocalOnlyHotspotReservation r) {
    183             mRes = r;
    184             mOnStartedCalled = true;
    185             mCallingThreadId = Thread.currentThread().getId();
    186         }
    187 
    188         @Override
    189         public void onStopped() {
    190             mOnStoppedCalled = true;
    191             mCallingThreadId = Thread.currentThread().getId();
    192         }
    193 
    194         @Override
    195         public void onFailed(int reason) {
    196             mFailureReason = reason;
    197             mCallingThreadId = Thread.currentThread().getId();
    198         }
    199     }
    200 
    201     /**
    202      * Verify callback is properly plumbed when called.
    203      */
    204     @Test
    205     public void testLocalOnlyHotspotCallback() {
    206         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    207         assertFalse(callback.mOnStartedCalled);
    208         assertFalse(callback.mOnStoppedCalled);
    209         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
    210         assertEquals(null, callback.mRes);
    211 
    212         // test onStarted
    213         WifiManager.LocalOnlyHotspotReservation res =
    214                 mWifiManager.new LocalOnlyHotspotReservation(mApConfig);
    215         callback.onStarted(res);
    216         assertEquals(res, callback.mRes);
    217         assertTrue(callback.mOnStartedCalled);
    218         assertFalse(callback.mOnStoppedCalled);
    219         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
    220 
    221         // test onStopped
    222         callback.onStopped();
    223         assertEquals(res, callback.mRes);
    224         assertTrue(callback.mOnStartedCalled);
    225         assertTrue(callback.mOnStoppedCalled);
    226         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
    227 
    228         // test onFailed
    229         callback.onFailed(ERROR_TEST_REASON);
    230         assertEquals(res, callback.mRes);
    231         assertTrue(callback.mOnStartedCalled);
    232         assertTrue(callback.mOnStoppedCalled);
    233         assertEquals(ERROR_TEST_REASON, callback.mFailureReason);
    234     }
    235 
    236     public class TestLocalOnlyHotspotObserver extends LocalOnlyHotspotObserver {
    237         public boolean mOnRegistered = false;
    238         public boolean mOnStartedCalled = false;
    239         public boolean mOnStoppedCalled = false;
    240         public WifiConfiguration mConfig = null;
    241         public LocalOnlyHotspotSubscription mSub = null;
    242         public long mCallingThreadId = -1;
    243 
    244         @Override
    245         public void onRegistered(LocalOnlyHotspotSubscription sub) {
    246             mOnRegistered = true;
    247             mSub = sub;
    248             mCallingThreadId = Thread.currentThread().getId();
    249         }
    250 
    251         @Override
    252         public void onStarted(WifiConfiguration config) {
    253             mOnStartedCalled = true;
    254             mConfig = config;
    255             mCallingThreadId = Thread.currentThread().getId();
    256         }
    257 
    258         @Override
    259         public void onStopped() {
    260             mOnStoppedCalled = true;
    261             mCallingThreadId = Thread.currentThread().getId();
    262         }
    263     }
    264 
    265     /**
    266      * Verify observer is properly plumbed when called.
    267      */
    268     @Test
    269     public void testLocalOnlyHotspotObserver() {
    270         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    271         assertFalse(observer.mOnRegistered);
    272         assertFalse(observer.mOnStartedCalled);
    273         assertFalse(observer.mOnStoppedCalled);
    274         assertEquals(null, observer.mConfig);
    275         assertEquals(null, observer.mSub);
    276 
    277         WifiManager.LocalOnlyHotspotSubscription sub =
    278                 mWifiManager.new LocalOnlyHotspotSubscription();
    279         observer.onRegistered(sub);
    280         assertTrue(observer.mOnRegistered);
    281         assertFalse(observer.mOnStartedCalled);
    282         assertFalse(observer.mOnStoppedCalled);
    283         assertEquals(null, observer.mConfig);
    284         assertEquals(sub, observer.mSub);
    285 
    286         observer.onStarted(mApConfig);
    287         assertTrue(observer.mOnRegistered);
    288         assertTrue(observer.mOnStartedCalled);
    289         assertFalse(observer.mOnStoppedCalled);
    290         assertEquals(mApConfig, observer.mConfig);
    291         assertEquals(sub, observer.mSub);
    292 
    293         observer.onStopped();
    294         assertTrue(observer.mOnRegistered);
    295         assertTrue(observer.mOnStartedCalled);
    296         assertTrue(observer.mOnStoppedCalled);
    297         assertEquals(mApConfig, observer.mConfig);
    298         assertEquals(sub, observer.mSub);
    299     }
    300 
    301     /**
    302      * Verify call to startLocalOnlyHotspot goes to WifiServiceImpl.
    303      */
    304     @Test
    305     public void testStartLocalOnlyHotspot() throws Exception {
    306         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    307         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    308 
    309         verify(mWifiService)
    310                 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
    311     }
    312 
    313     /**
    314      * Verify a SecurityException is thrown for callers without proper permissions for
    315      * startLocalOnlyHotspot.
    316      */
    317     @Test(expected = SecurityException.class)
    318     public void testStartLocalOnlyHotspotThrowsSecurityException() throws Exception {
    319         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    320         doThrow(new SecurityException()).when(mWifiService)
    321                 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
    322         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    323     }
    324 
    325     /**
    326      * Verify an IllegalStateException is thrown for callers that already have a pending request for
    327      * startLocalOnlyHotspot.
    328      */
    329     @Test(expected = IllegalStateException.class)
    330     public void testStartLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
    331         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    332         doThrow(new IllegalStateException()).when(mWifiService)
    333                 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
    334         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    335     }
    336 
    337     /**
    338      * Verify that the handler provided by the caller is used for the callbacks.
    339      */
    340     @Test
    341     public void testCorrectLooperIsUsedForHandler() throws Exception {
    342         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    343         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    344                 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
    345         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    346         mLooper.dispatchAll();
    347         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
    348         verify(mContext, never()).getMainLooper();
    349     }
    350 
    351     /**
    352      * Verify that the main looper's thread is used if a handler is not provided by the reqiestomg
    353      * application.
    354      */
    355     @Test
    356     public void testMainLooperIsUsedWhenHandlerNotProvided() throws Exception {
    357         // record thread from looper.getThread and check ids.
    358         TestLooper altLooper = new TestLooper();
    359         when(mContext.getMainLooper()).thenReturn(altLooper.getLooper());
    360         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    361         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    362                 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
    363         mWifiManager.startLocalOnlyHotspot(callback, null);
    364         altLooper.dispatchAll();
    365         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
    366         assertEquals(altLooper.getLooper().getThread().getId(), callback.mCallingThreadId);
    367         verify(mContext).getMainLooper();
    368     }
    369 
    370     /**
    371      * Verify the LOHS onStarted callback is triggered when WifiManager receives a HOTSPOT_STARTED
    372      * message from WifiServiceImpl.
    373      */
    374     @Test
    375     public void testOnStartedIsCalledWithReservation() throws Exception {
    376         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    377         TestLooper callbackLooper = new TestLooper();
    378         Handler callbackHandler = new Handler(callbackLooper.getLooper());
    379         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
    380                   any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
    381         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
    382         callbackLooper.dispatchAll();
    383         mLooper.dispatchAll();
    384         assertFalse(callback.mOnStartedCalled);
    385         assertEquals(null, callback.mRes);
    386         // now trigger the callback
    387         Message msg = new Message();
    388         msg.what = HOTSPOT_STARTED;
    389         msg.obj = mApConfig;
    390         mMessengerCaptor.getValue().send(msg);
    391         mLooper.dispatchAll();
    392         callbackLooper.dispatchAll();
    393         assertTrue(callback.mOnStartedCalled);
    394         assertEquals(mApConfig, callback.mRes.getWifiConfiguration());
    395     }
    396 
    397     /**
    398      * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_STARTED message with a null
    399      * config.
    400      */
    401     @Test
    402     public void testOnStartedIsCalledWithNullConfig() throws Exception {
    403         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    404         TestLooper callbackLooper = new TestLooper();
    405         Handler callbackHandler = new Handler(callbackLooper.getLooper());
    406         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
    407                   any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
    408         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
    409         callbackLooper.dispatchAll();
    410         mLooper.dispatchAll();
    411         assertFalse(callback.mOnStartedCalled);
    412         assertEquals(null, callback.mRes);
    413         // now trigger the callback
    414         Message msg = new Message();
    415         msg.what = HOTSPOT_STARTED;
    416         mMessengerCaptor.getValue().send(msg);
    417         mLooper.dispatchAll();
    418         callbackLooper.dispatchAll();
    419         assertFalse(callback.mOnStartedCalled);
    420         assertEquals(ERROR_GENERIC, callback.mFailureReason);
    421     }
    422 
    423     /**
    424      * Verify onStopped is called if WifiServiceImpl sends a HOTSPOT_STOPPED message.
    425      */
    426     @Test
    427     public void testOnStoppedIsCalled() throws Exception {
    428         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    429         TestLooper callbackLooper = new TestLooper();
    430         Handler callbackHandler = new Handler(callbackLooper.getLooper());
    431         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
    432                   any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
    433         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
    434         callbackLooper.dispatchAll();
    435         mLooper.dispatchAll();
    436         assertFalse(callback.mOnStoppedCalled);
    437         // now trigger the callback
    438         Message msg = new Message();
    439         msg.what = HOTSPOT_STOPPED;
    440         mMessengerCaptor.getValue().send(msg);
    441         mLooper.dispatchAll();
    442         callbackLooper.dispatchAll();
    443         assertTrue(callback.mOnStoppedCalled);
    444     }
    445 
    446     /**
    447      * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_FAILED message.
    448      */
    449     @Test
    450     public void testOnFailedIsCalled() throws Exception {
    451         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    452         TestLooper callbackLooper = new TestLooper();
    453         Handler callbackHandler = new Handler(callbackLooper.getLooper());
    454         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
    455                   any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
    456         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
    457         callbackLooper.dispatchAll();
    458         mLooper.dispatchAll();
    459         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
    460         // now trigger the callback
    461         Message msg = new Message();
    462         msg.what = HOTSPOT_FAILED;
    463         msg.arg1 = ERROR_NO_CHANNEL;
    464         mMessengerCaptor.getValue().send(msg);
    465         mLooper.dispatchAll();
    466         callbackLooper.dispatchAll();
    467         assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
    468     }
    469 
    470     /**
    471      * Verify callback triggered from startLocalOnlyHotspot with an incompatible mode failure.
    472      */
    473     @Test
    474     public void testLocalOnlyHotspotCallbackFullOnIncompatibleMode() throws Exception {
    475         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    476         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    477                 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
    478         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    479         mLooper.dispatchAll();
    480         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
    481         assertFalse(callback.mOnStartedCalled);
    482         assertFalse(callback.mOnStoppedCalled);
    483         assertEquals(null, callback.mRes);
    484     }
    485 
    486     /**
    487      * Verify callback triggered from startLocalOnlyHotspot with a tethering disallowed failure.
    488      */
    489     @Test
    490     public void testLocalOnlyHotspotCallbackFullOnTetheringDisallowed() throws Exception {
    491         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    492         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    493                 anyString())).thenReturn(ERROR_TETHERING_DISALLOWED);
    494         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    495         mLooper.dispatchAll();
    496         assertEquals(ERROR_TETHERING_DISALLOWED, callback.mFailureReason);
    497         assertFalse(callback.mOnStartedCalled);
    498         assertFalse(callback.mOnStoppedCalled);
    499         assertEquals(null, callback.mRes);
    500     }
    501 
    502     /**
    503      * Verify a SecurityException resulting from an application without necessary permissions will
    504      * bubble up through the call to start LocalOnlyHotspot and will not trigger other callbacks.
    505      */
    506     @Test(expected = SecurityException.class)
    507     public void testLocalOnlyHotspotCallbackFullOnSecurityException() throws Exception {
    508         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    509         doThrow(new SecurityException()).when(mWifiService)
    510                 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
    511         try {
    512             mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    513         } catch (SecurityException e) {
    514             assertEquals(ERROR_NOT_SET, callback.mFailureReason);
    515             assertFalse(callback.mOnStartedCalled);
    516             assertFalse(callback.mOnStoppedCalled);
    517             assertEquals(null, callback.mRes);
    518             throw e;
    519         }
    520 
    521     }
    522 
    523     /**
    524      * Verify the handler passed to startLocalOnlyHotspot is correctly used for callbacks when
    525      * SoftApMode fails due to a underlying error.
    526      */
    527     @Test
    528     public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception {
    529         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    530         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    531                 anyString())).thenReturn(REQUEST_REGISTERED);
    532         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    533         mLooper.dispatchAll();
    534         //assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
    535         assertFalse(callback.mOnStartedCalled);
    536         assertFalse(callback.mOnStoppedCalled);
    537         assertEquals(null, callback.mRes);
    538     }
    539 
    540     /**
    541      * Verify that the call to cancel a LOHS request does call stopLOHS.
    542      */
    543     @Test
    544     public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception {
    545         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    546         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    547                 anyString())).thenReturn(REQUEST_REGISTERED);
    548         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    549         mWifiManager.cancelLocalOnlyHotspotRequest();
    550         verify(mWifiService).stopLocalOnlyHotspot();
    551     }
    552 
    553     /**
    554      * Verify that we do not crash if cancelLocalOnlyHotspotRequest is called without an existing
    555      * callback stored.
    556      */
    557     @Test
    558     public void testCancelLocalOnlyHotspotReturnsWithoutExistingRequest() {
    559         mWifiManager.cancelLocalOnlyHotspotRequest();
    560     }
    561 
    562     /**
    563      * Verify that the callback is not triggered if the LOHS request was already cancelled.
    564      */
    565     @Test
    566     public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception {
    567         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    568         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    569                 anyString())).thenReturn(REQUEST_REGISTERED);
    570         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    571         mWifiManager.cancelLocalOnlyHotspotRequest();
    572         verify(mWifiService).stopLocalOnlyHotspot();
    573         mLooper.dispatchAll();
    574         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
    575         assertFalse(callback.mOnStartedCalled);
    576         assertFalse(callback.mOnStoppedCalled);
    577         assertEquals(null, callback.mRes);
    578     }
    579 
    580     /**
    581      * Verify that calling cancel LOHS request does not crash if an error callback was already
    582      * handled.
    583      */
    584     @Test
    585     public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception {
    586         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
    587         when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
    588                 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
    589         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
    590         mLooper.dispatchAll();
    591         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
    592         assertFalse(callback.mOnStartedCalled);
    593         assertFalse(callback.mOnStoppedCalled);
    594         assertEquals(null, callback.mRes);
    595         mWifiManager.cancelLocalOnlyHotspotRequest();
    596         verify(mWifiService, never()).stopLocalOnlyHotspot();
    597     }
    598 
    599     /**
    600      * Verify the watchLocalOnlyHotspot call goes to WifiServiceImpl.
    601      */
    602     public void testWatchLocalOnlyHotspot() throws Exception {
    603         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    604 
    605         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
    606         verify(mWifiService).startWatchLocalOnlyHotspot(any(Messenger.class), any(IBinder.class));
    607     }
    608 
    609     /**
    610      * Verify a SecurityException is thrown for callers without proper permissions for
    611      * startWatchLocalOnlyHotspot.
    612      */
    613     @Test(expected = SecurityException.class)
    614     public void testStartWatchLocalOnlyHotspotThrowsSecurityException() throws Exception {
    615         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    616         doThrow(new SecurityException()).when(mWifiService)
    617                 .startWatchLocalOnlyHotspot(any(Messenger.class), any(IBinder.class));
    618         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
    619     }
    620 
    621     /**
    622      * Verify an IllegalStateException is thrown for callers that already have a pending request for
    623      * watchLocalOnlyHotspot.
    624      */
    625     @Test(expected = IllegalStateException.class)
    626     public void testStartWatchLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
    627         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    628         doThrow(new IllegalStateException()).when(mWifiService)
    629                 .startWatchLocalOnlyHotspot(any(Messenger.class), any(IBinder.class));
    630         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
    631     }
    632 
    633     /**
    634      * Verify that the handler provided by the caller is used for the observer.
    635      */
    636     @Test
    637     public void testCorrectLooperIsUsedForObserverHandler() throws Exception {
    638         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    639         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
    640         mLooper.dispatchAll();
    641         assertTrue(observer.mOnRegistered);
    642         verify(mContext, never()).getMainLooper();
    643     }
    644 
    645     /**
    646      * Verify that the main looper's thread is used if a handler is not provided by the requesting
    647      * application.
    648      */
    649     @Test
    650     public void testMainLooperIsUsedWhenHandlerNotProvidedForObserver() throws Exception {
    651         // record thread from looper.getThread and check ids.
    652         TestLooper altLooper = new TestLooper();
    653         when(mContext.getMainLooper()).thenReturn(altLooper.getLooper());
    654         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    655         mWifiManager.watchLocalOnlyHotspot(observer, null);
    656         altLooper.dispatchAll();
    657         assertTrue(observer.mOnRegistered);
    658         assertEquals(altLooper.getLooper().getThread().getId(), observer.mCallingThreadId);
    659         verify(mContext).getMainLooper();
    660     }
    661 
    662     /**
    663      * Verify the LOHS onRegistered observer callback is triggered when WifiManager receives a
    664      * HOTSPOT_OBSERVER_REGISTERED message from WifiServiceImpl.
    665      */
    666     @Test
    667     public void testOnRegisteredIsCalledWithSubscription() throws Exception {
    668         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    669         TestLooper observerLooper = new TestLooper();
    670         Handler observerHandler = new Handler(observerLooper.getLooper());
    671         assertFalse(observer.mOnRegistered);
    672         assertEquals(null, observer.mSub);
    673         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
    674         verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(),
    675                   any(IBinder.class));
    676         // now trigger the callback
    677         observerLooper.dispatchAll();
    678         mLooper.dispatchAll();
    679         assertTrue(observer.mOnRegistered);
    680         assertNotNull(observer.mSub);
    681     }
    682 
    683     /**
    684      * Verify the LOHS onStarted observer callback is triggered when WifiManager receives a
    685      * HOTSPOT_STARTED message from WifiServiceImpl.
    686      */
    687     @Test
    688     public void testObserverOnStartedIsCalledWithWifiConfig() throws Exception {
    689         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    690         TestLooper observerLooper = new TestLooper();
    691         Handler observerHandler = new Handler(observerLooper.getLooper());
    692         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
    693         verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(),
    694                   any(IBinder.class));
    695         observerLooper.dispatchAll();
    696         mLooper.dispatchAll();
    697         assertFalse(observer.mOnStartedCalled);
    698         // now trigger the callback
    699         Message msg = new Message();
    700         msg.what = HOTSPOT_STARTED;
    701         msg.obj = mApConfig;
    702         mMessengerCaptor.getValue().send(msg);
    703         mLooper.dispatchAll();
    704         observerLooper.dispatchAll();
    705         assertTrue(observer.mOnStartedCalled);
    706         assertEquals(mApConfig, observer.mConfig);
    707     }
    708 
    709     /**
    710      * Verify the LOHS onStarted observer callback is triggered not when WifiManager receives a
    711      * HOTSPOT_STARTED message from WifiServiceImpl with a null config.
    712      */
    713     @Test
    714     public void testObserverOnStartedNotCalledWithNullConfig() throws Exception {
    715         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    716         TestLooper observerLooper = new TestLooper();
    717         Handler observerHandler = new Handler(observerLooper.getLooper());
    718         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
    719         verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(),
    720                   any(IBinder.class));
    721         observerLooper.dispatchAll();
    722         mLooper.dispatchAll();
    723         assertFalse(observer.mOnStartedCalled);
    724         // now trigger the callback
    725         Message msg = new Message();
    726         msg.what = HOTSPOT_STARTED;
    727         mMessengerCaptor.getValue().send(msg);
    728         mLooper.dispatchAll();
    729         observerLooper.dispatchAll();
    730         assertFalse(observer.mOnStartedCalled);
    731         assertEquals(null, observer.mConfig);
    732     }
    733 
    734 
    735     /**
    736      * Verify the LOHS onStopped observer callback is triggered when WifiManager receives a
    737      * HOTSPOT_STOPPED message from WifiServiceImpl.
    738      */
    739     @Test
    740     public void testObserverOnStoppedIsCalled() throws Exception {
    741         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    742         TestLooper observerLooper = new TestLooper();
    743         Handler observerHandler = new Handler(observerLooper.getLooper());
    744         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
    745         verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(),
    746                   any(IBinder.class));
    747         observerLooper.dispatchAll();
    748         mLooper.dispatchAll();
    749         assertFalse(observer.mOnStoppedCalled);
    750         // now trigger the callback
    751         Message msg = new Message();
    752         msg.what = HOTSPOT_STOPPED;
    753         mMessengerCaptor.getValue().send(msg);
    754         mLooper.dispatchAll();
    755         observerLooper.dispatchAll();
    756         assertTrue(observer.mOnStoppedCalled);
    757     }
    758 
    759     /**
    760      * Verify WifiServiceImpl is not called if there is not a registered LOHS observer callback.
    761      */
    762     @Test
    763     public void testUnregisterWifiServiceImplNotCalledWithoutRegisteredObserver() throws Exception {
    764         mWifiManager.unregisterLocalOnlyHotspotObserver();
    765         verifyZeroInteractions(mWifiService);
    766     }
    767 
    768     /**
    769      * Verify WifiServiceImpl is called when there is a registered LOHS observer callback.
    770      */
    771     @Test
    772     public void testUnregisterWifiServiceImplCalledWithRegisteredObserver() throws Exception {
    773         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
    774         TestLooper observerLooper = new TestLooper();
    775         Handler observerHandler = new Handler(observerLooper.getLooper());
    776         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
    777         mWifiManager.unregisterLocalOnlyHotspotObserver();
    778         verify(mWifiService).stopWatchLocalOnlyHotspot();
    779     }
    780 
    781     /**
    782      * Verify that calls to setWifiApEnabled return false.
    783      */
    784     @Test
    785     public void testSetWifiApEnabledReturnsFalse() throws Exception {
    786         assertFalse(mWifiManager.setWifiApEnabled(null, true));
    787         assertFalse(mWifiManager.setWifiApEnabled(null, false));
    788         verify(mWifiService, never()).setWifiApEnabled(any(), anyBoolean());
    789     }
    790 }
    791