HalDeviceManagerTest.java revision dd4dcab629d1045b08f58f699a4a09ecc8cd23e3
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
17package com.android.server.wifi;
18
19import static org.mockito.Matchers.any;
20import static org.mockito.Matchers.anyLong;
21import static org.mockito.Matchers.anyString;
22import static org.mockito.Matchers.eq;
23import static org.mockito.Mockito.inOrder;
24import static org.mockito.Mockito.mock;
25import static org.mockito.Mockito.verify;
26import static org.mockito.Mockito.verifyNoMoreInteractions;
27import static org.mockito.Mockito.when;
28
29import android.hardware.wifi.V1_0.IWifi;
30import android.hardware.wifi.V1_0.IWifiEventCallback;
31import android.hardware.wifi.V1_0.WifiStatus;
32import android.hardware.wifi.V1_0.WifiStatusCode;
33import android.hidl.manager.V1_0.IServiceManager;
34import android.hidl.manager.V1_0.IServiceNotification;
35import android.os.IHwBinder;
36import android.os.test.TestLooper;
37import android.util.Log;
38
39import org.junit.After;
40import org.junit.Before;
41import org.junit.Rule;
42import org.junit.Test;
43import org.junit.rules.ErrorCollector;
44import org.mockito.ArgumentCaptor;
45import org.mockito.InOrder;
46import org.mockito.Mock;
47import org.mockito.MockitoAnnotations;
48
49import java.io.PrintWriter;
50import java.io.StringWriter;
51
52/**
53 * Unit test harness for HalDeviceManagerTest.
54 */
55public class HalDeviceManagerTest {
56    private HalDeviceManager mDut;
57    @Mock IServiceManager mServiceManagerMock;
58    @Mock IWifi mWifiMock;
59    @Mock HalDeviceManager.ManagerStatusCallback mManagerStatusCallbackMock;
60    TestLooper mTestLooper;
61    private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor =
62            ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
63    private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor =
64            ArgumentCaptor.forClass(IServiceNotification.Stub.class);
65    private ArgumentCaptor<IWifiEventCallback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass(
66            IWifiEventCallback.class);
67    private InOrder mInOrder;
68    @Rule public ErrorCollector collector = new ErrorCollector();
69    private WifiStatus mStatusOk;
70    private WifiStatus mStatusFail;
71
72    private class HalDeviceManagerSpy extends HalDeviceManager {
73        @Override
74        protected IWifi getWifiServiceMockable() {
75            return mWifiMock;
76        }
77
78        @Override
79        protected IServiceManager getServiceManagerMockable() {
80            return mServiceManagerMock;
81        }
82    }
83
84    @Before
85    public void before() throws Exception {
86        MockitoAnnotations.initMocks(this);
87
88        mTestLooper = new TestLooper();
89
90        // initialize dummy status objects
91        mStatusOk = new WifiStatus();
92        mStatusOk.code = WifiStatusCode.SUCCESS;
93        mStatusFail = new WifiStatus();
94        mStatusFail.code = WifiStatusCode.ERROR_UNKNOWN;
95
96        when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
97                anyLong())).thenReturn(true);
98        when(mServiceManagerMock.registerForNotifications(anyString(), anyString(),
99                any(IServiceNotification.Stub.class))).thenReturn(true);
100        when(mWifiMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn(
101                true);
102        when(mWifiMock.registerEventCallback(any(IWifiEventCallback.class))).thenReturn(mStatusOk);
103        when(mWifiMock.start()).thenReturn(mStatusOk);
104        when(mWifiMock.stop()).thenReturn(mStatusOk);
105
106        mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock);
107
108        mDut = new HalDeviceManagerSpy();
109        executeAndValidateInitializationSequence();
110    }
111
112    /**
113     * Print out the dump of the device manager after each test. Not used in test validation
114     * (internal state) - but can help in debugging failed tests.
115     */
116    @After
117    public void after() throws Exception {
118        dumpDut("after: ");
119    }
120
121    /**
122     * Test basic startup flow:
123     * - IServiceManager registrations
124     * - IWifi registrations
125     * - IWifi startup delayed
126     * - Start Wi-Fi -> onStart
127     * - Stop Wi-Fi -> onStop
128     */
129    @Test
130    public void testStartStopFlow() throws Exception {
131        executeAndValidateStartupSequence();
132
133        // act: stop Wi-Fi
134        mDut.stop();
135        mTestLooper.dispatchAll();
136
137        // verify: onStop called
138        mInOrder.verify(mWifiMock).stop();
139        mInOrder.verify(mManagerStatusCallbackMock).onStop();
140
141        verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock);
142    }
143
144    /**
145     * Validate that multiple callback registrations are called and that duplicate ones are
146     * only called once.
147     */
148    @Test
149    public void testMultipleCallbackRegistrations() throws Exception {
150        // register another 2 callbacks - one of them twice
151        HalDeviceManager.ManagerStatusCallback callback1 = mock(
152                HalDeviceManager.ManagerStatusCallback.class);
153        HalDeviceManager.ManagerStatusCallback callback2 = mock(
154                HalDeviceManager.ManagerStatusCallback.class);
155        mDut.registerStatusCallback(callback2, mTestLooper.getLooper());
156        mDut.registerStatusCallback(callback1, mTestLooper.getLooper());
157        mDut.registerStatusCallback(callback2, mTestLooper.getLooper());
158
159        // startup
160        executeAndValidateStartupSequence();
161
162        // verify
163        verify(callback1).onStart();
164        verify(callback2).onStart();
165
166        verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock,
167                callback1, callback2);
168    }
169
170    /**
171     * Validate IWifi death listener and registration flow.
172     */
173    @Test
174    public void testWifiDeathAndRegistration() throws Exception {
175        executeAndValidateStartupSequence();
176
177        // act: IWifi service death
178        mDeathRecipientCaptor.getValue().serviceDied(0);
179        mTestLooper.dispatchAll();
180
181        // verify: getting onStop
182        mInOrder.verify(mManagerStatusCallbackMock).onStop();
183
184        // act: service startup
185        mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", false);
186
187        // verify: initialization of IWifi
188        mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong());
189        mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture());
190
191        // act: start
192        mDut.start();
193        mWifiEventCallbackCaptor.getValue().onStart();
194        mTestLooper.dispatchAll();
195
196        // verify: service and callback calls
197        mInOrder.verify(mWifiMock).start();
198        mInOrder.verify(mManagerStatusCallbackMock).onStart();
199
200        verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock);
201    }
202
203    /**
204     * Validate IWifi onFailure causes notification
205     */
206    @Test
207    public void testWifiFail() throws Exception {
208        executeAndValidateStartupSequence();
209
210        // act: IWifi failure
211        mWifiEventCallbackCaptor.getValue().onFailure(mStatusFail);
212        mTestLooper.dispatchAll();
213
214        // verify: getting onStop
215        mInOrder.verify(mManagerStatusCallbackMock).onStop();
216
217        // act: start again
218        mDut.start();
219        mWifiEventCallbackCaptor.getValue().onStart();
220        mTestLooper.dispatchAll();
221
222        // verify: service and callback calls
223        mInOrder.verify(mWifiMock).start();
224        mInOrder.verify(mManagerStatusCallbackMock).onStart();
225
226        verifyNoMoreInteractions(mServiceManagerMock, mWifiMock, mManagerStatusCallbackMock);
227    }
228
229
230    // utilities
231    private void dumpDut(String prefix) {
232        StringWriter sw = new StringWriter();
233        mDut.dump(null, new PrintWriter(sw), null);
234        Log.e("HalDeviceManager", prefix + sw.toString());
235    }
236
237    private void executeAndValidateInitializationSequence() throws Exception {
238        // act:
239        mDut.initialize();
240
241        // verify: service manager initialization sequence
242        mInOrder.verify(mServiceManagerMock).linkToDeath(any(IHwBinder.DeathRecipient.class),
243                anyLong());
244        mInOrder.verify(mServiceManagerMock).registerForNotifications(eq(IWifi.kInterfaceName),
245                eq(""), mServiceNotificationCaptor.capture());
246
247        // act: get the service started (which happens even when service was already up)
248        mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", true);
249
250        // verify: wifi initialization sequence
251        mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong());
252        mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture());
253    }
254
255    private void executeAndValidateStartupSequence() throws Exception {
256        // act: register listener & start Wi-Fi
257        mDut.registerStatusCallback(mManagerStatusCallbackMock, mTestLooper.getLooper());
258        mDut.start();
259
260        // verify
261        mInOrder.verify(mWifiMock).start();
262
263        // act: trigger onStart callback of IWifiEventCallback
264        mWifiEventCallbackCaptor.getValue().onStart();
265        mTestLooper.dispatchAll();
266
267        // verify: onStart called on registered listener
268        mInOrder.verify(mManagerStatusCallbackMock).onStart();
269    }
270}
271