1/*
2 * Copyright (C) 2018 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.junit.Assert.assertEquals;
20import static org.junit.Assert.assertNotNull;
21import static org.mockito.Mockito.*;
22
23import static android.telephony.TelephonyManager.CALL_STATE_IDLE;
24import static android.telephony.TelephonyManager.CALL_STATE_OFFHOOK;
25
26import android.app.test.MockAnswerUtil.AnswerWithArguments;
27import android.content.BroadcastReceiver;
28import android.content.Context;
29import android.content.IntentFilter;
30import android.content.pm.ApplicationInfo;
31import android.hardware.SensorEvent;
32import android.net.wifi.WifiManager;
33import android.os.Build;
34import android.os.test.TestLooper;
35import android.support.test.filters.SmallTest;
36import android.telephony.PhoneStateListener;
37import android.telephony.TelephonyManager;
38import android.util.Log;
39
40import com.android.internal.R;
41
42import org.junit.After;
43import org.junit.Before;
44import org.junit.Test;
45import org.junit.runner.RunWith;
46import org.junit.runners.JUnit4;
47import org.mockito.ArgumentCaptor;
48import org.mockito.InOrder;
49import org.mockito.Mock;
50import org.mockito.MockitoAnnotations;
51
52/**
53 * unit tests for {@link com.android.server.wifi.SarManager}.
54 */
55@SmallTest
56public class SarManagerTest {
57    private static final String TAG = "WifiSarManagerTest";
58    private static final String OP_PACKAGE_NAME = "com.xxx";
59
60    private void enableDebugLogs() {
61        mSarMgr.enableVerboseLogging(1);
62    }
63
64    private MockResources getMockResources() {
65        MockResources resources = new MockResources();
66        return resources;
67    }
68
69    private SarManager mSarMgr;
70    private TestLooper mLooper;
71    private MockResources mResources;
72    private PhoneStateListener mPhoneStateListener;
73
74    @Mock  private Context mContext;
75    @Mock TelephonyManager mTelephonyManager;
76    @Mock private ApplicationInfo mMockApplInfo;
77    @Mock WifiNative mWifiNative;
78
79    @Before
80    public void setUp() throws Exception {
81        Log.e(TAG, "Setting Up ...");
82
83        // Ensure Looper exists
84        mLooper = new TestLooper();
85
86        MockitoAnnotations.initMocks(this);
87
88        /* Default behavior is to return with success */
89        when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true);
90
91        mResources = getMockResources();
92
93        when(mContext.getResources()).thenReturn(mResources);
94        mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.P;
95        when(mContext.getApplicationInfo()).thenReturn(mMockApplInfo);
96        when(mContext.getOpPackageName()).thenReturn(OP_PACKAGE_NAME);
97    }
98
99    @After
100    public void cleanUp() throws Exception {
101        mSarMgr = null;
102        mLooper = null;
103        mContext = null;
104        mResources = null;
105    }
106
107    /**
108     * Helper function to set configuration for SAR and create the SAR Manager
109     *
110     */
111    private void createSarManager(boolean isSarEnabled) {
112        mResources.setBoolean(
113                R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, isSarEnabled);
114
115        mSarMgr = new SarManager(mContext, mTelephonyManager, mLooper.getLooper(),
116                mWifiNative);
117
118        if (isSarEnabled) {
119            /* Capture the PhoneStateListener */
120            ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor =
121                    ArgumentCaptor.forClass(PhoneStateListener.class);
122            verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(),
123                    eq(PhoneStateListener.LISTEN_CALL_STATE));
124            mPhoneStateListener = phoneStateListenerCaptor.getValue();
125        }
126
127        /* Enable logs from SarManager */
128        enableDebugLogs();
129    }
130
131    /**
132     * Test that we do register the telephony call state listener on devices which do support
133     * setting/resetting Tx power limit.
134     */
135    @Test
136    public void testSarMgr_enabledTxPowerScenario_registerPhone() throws Exception {
137        createSarManager(true);
138        verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_CALL_STATE));
139    }
140
141    /**
142     * Test that we do not register the telephony call state listener on devices which
143     * do not support setting/resetting Tx power limit.
144     */
145    @Test
146    public void testSarMgr_disabledTxPowerScenario_registerPhone() throws Exception {
147        createSarManager(false);
148        verify(mTelephonyManager, never()).listen(any(), anyInt());
149    }
150
151    /**
152     * Test that for devices that support setting/resetting Tx Power limits, device sets the proper
153     * Tx power scenario upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA
154     * is enabled
155     * In this case Wifi is enabled first, then off-hook is detected
156     * Expectation is to get {@link WifiNative#TX_POWER_SCENARIO_NORMAL} when WiFi is turned on
157     * followed by {@link WifiNative#TX_POWER_SCENARIO_VOICE_CALL} when OFFHOOK event is detected
158     */
159    @Test
160    public void testSarMgr_enabledTxPowerScenario_wifiOn_offHook() throws Exception {
161        createSarManager(true);
162        assertNotNull(mPhoneStateListener);
163
164        InOrder inOrder = inOrder(mWifiNative);
165
166        /* Enable WiFi State */
167        mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
168
169        inOrder.verify(mWifiNative).selectTxPowerScenario(
170                eq(WifiNative.TX_POWER_SCENARIO_NORMAL));
171
172        /* Set phone state to OFFHOOK */
173        mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, "");
174
175        inOrder.verify(mWifiNative).selectTxPowerScenario(
176                eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL));
177    }
178
179    /**
180     * Test that for devices that support setting/resetting Tx Power limits, device sets the proper
181     * Tx power scenario upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA
182     * is enabled
183     * In this case off-hook event is detected first, then wifi is turned on
184     * Expectation is to get {@link WifiNative#TX_POWER_SCENARIO_VOICE_CALL} once wifi is turned on
185     */
186    @Test
187    public void testSarMgr_enabledTxPowerScenario_offHook_wifiOn() throws Exception {
188        createSarManager(true);
189        assertNotNull(mPhoneStateListener);
190
191        /* Set phone state to OFFHOOK */
192        mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, "");
193
194        /* Enable WiFi State */
195        mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
196
197        verify(mWifiNative).selectTxPowerScenario(
198                eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL));
199    }
200
201    /**
202     * Test that for devices that support setting/resetting Tx Power limits, device sets the proper
203     * Tx power scenarios upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} and
204     * {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA is enabled
205     */
206    @Test
207    public void testSarMgr_enabledTxPowerScenario_wifiOn_offHook_onHook() throws Exception {
208        createSarManager(true);
209        assertNotNull(mPhoneStateListener);
210
211        InOrder inOrder = inOrder(mWifiNative);
212
213        /* Enable WiFi State */
214        mSarMgr.setClientWifiState(WifiManager.WIFI_STATE_ENABLED);
215
216        /* Now device should set tx power scenario to NORMAL */
217        inOrder.verify(mWifiNative).selectTxPowerScenario(
218                eq(WifiNative.TX_POWER_SCENARIO_NORMAL));
219
220        /* Set phone state to OFFHOOK */
221        mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, "");
222
223        /* Device should set tx power scenario to Voice call */
224        inOrder.verify(mWifiNative).selectTxPowerScenario(
225                eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL));
226
227        /* Set state back to ONHOOK */
228        mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, "");
229
230        /* Device should set tx power scenario to NORMAL again */
231        inOrder.verify(mWifiNative).selectTxPowerScenario(
232                eq(WifiNative.TX_POWER_SCENARIO_NORMAL));
233    }
234
235    /**
236     * Test that for devices that support setting/resetting Tx Power limits, device does not
237     * sets the Tx power scenarios upon receiving {@link TelephonyManager#CALL_STATE_OFFHOOK} and
238     * {@link TelephonyManager#CALL_STATE_OFFHOOK} when WiFi STA is disabled
239     */
240    @Test
241    public void testSarMgr_enabledTxPowerScenario_wifiOff_offHook_onHook() throws Exception {
242        createSarManager(true);
243        assertNotNull(mPhoneStateListener);
244
245        InOrder inOrder = inOrder(mWifiNative);
246
247        /* Set phone state to OFFHOOK */
248        mPhoneStateListener.onCallStateChanged(CALL_STATE_OFFHOOK, "");
249
250        /* Set state back to ONHOOK */
251        mPhoneStateListener.onCallStateChanged(CALL_STATE_IDLE, "");
252
253        /* Device should not set tx power scenario at all */
254        inOrder.verify(mWifiNative, never()).selectTxPowerScenario(anyInt());
255    }
256}
257