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 package com.android.server.deviceidle;
17 
18 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
24 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
26 
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertTrue;
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.ArgumentMatchers.anyBoolean;
31 import static org.mockito.ArgumentMatchers.eq;
32 
33 import android.bluetooth.BluetoothDevice;
34 import android.bluetooth.BluetoothManager;
35 import android.bluetooth.BluetoothProfile;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.os.Handler;
39 
40 import androidx.test.runner.AndroidJUnit4;
41 
42 import com.android.server.DeviceIdleInternal;
43 
44 import org.junit.After;
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.mockito.Answers;
49 import org.mockito.InOrder;
50 import org.mockito.Mock;
51 import org.mockito.MockitoSession;
52 import org.mockito.quality.Strictness;
53 
54 import java.util.Arrays;
55 
56 /**
57  * Tests for {@link com.android.server.deviceidle.BluetoothConstraint}.
58  */
59 @RunWith(AndroidJUnit4.class)
60 public class BluetoothConstraintTest {
61 
62     private MockitoSession mMockingSession;
63 
64     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
65     private Context mContext;
66 
67     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
68     private Handler mHandler;
69 
70     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
71     private BluetoothManager mBluetoothManager;
72 
73     @Mock
74     private DeviceIdleInternal mDeviceIdleService;
75 
76     private BluetoothConstraint mConstraint;
77 
78     @Before
setUp()79     public void setUp() {
80         mMockingSession = mockitoSession()
81                 .initMocks(this)
82                 .strictness(Strictness.LENIENT)
83                 .startMocking();
84         doReturn(mBluetoothManager)
85                 .when(mContext).getSystemService(BluetoothManager.class);
86         mConstraint = new BluetoothConstraint(mContext, mHandler, mDeviceIdleService);
87     }
88 
89     @After
tearDown()90     public void tearDown() {
91         if (mMockingSession != null) {
92             mMockingSession.finishMocking();
93         }
94     }
95 
96     @Test
testIsConnected_noBluetoothAdapter()97     public void testIsConnected_noBluetoothAdapter() {
98         doReturn(null).when(mBluetoothManager).getAdapter();
99         assertFalse(BluetoothConstraint.isBluetoothConnected(mBluetoothManager));
100     }
101 
102     @Test
testIsConnected_noConnectedDevice()103     public void testIsConnected_noConnectedDevice() {
104         enableBluetooth(true);
105         assertFalse(BluetoothConstraint.isBluetoothConnected(mBluetoothManager));
106     }
107 
108     @Test
testIsConnected_twoConnectedDevices()109     public void testIsConnected_twoConnectedDevices() {
110         enableBluetooth(true, mock(BluetoothDevice.class), mock(BluetoothDevice.class));
111         assertTrue(BluetoothConstraint.isBluetoothConnected(mBluetoothManager));
112     }
113 
114     @Test
testStartMonitoring_updatesActiveAtCorrectTimes()115     public void testStartMonitoring_updatesActiveAtCorrectTimes() {
116         // First setup -> no callbacks should fire.
117         BluetoothConstraint constraint = mConstraint;
118         verify(mDeviceIdleService, never()).onConstraintStateChanged(any(), anyBoolean());
119         verify(mContext, never()).registerReceiver(eq(constraint.mReceiver), any());
120 
121         InOrder order = inOrder(mDeviceIdleService);
122 
123         // No devices -> active=false should be triggered.
124         enableBluetooth(true);
125         constraint.startMonitoring();
126         order.verify(mDeviceIdleService, times(1)).onConstraintStateChanged(any(), eq(false));
127 
128         // One device -> active=true should be triggered.
129         enableBluetooth(true, mock(BluetoothDevice.class));
130         constraint.mReceiver.onReceive(
131                 mContext, new Intent(BluetoothDevice.ACTION_ACL_CONNECTED));
132         constraint.startMonitoring();
133         order.verify(mDeviceIdleService, times(1)).exitIdle(eq("bluetooth"));
134 
135         // Stop monitoring -> broadcast receiver should be unregistered.
136         constraint.stopMonitoring();
137         verify(mContext, times(1)).unregisterReceiver(eq(constraint.mReceiver));
138         order.verifyNoMoreInteractions();
139 
140     }
141 
enableBluetooth(boolean enabled, BluetoothDevice... devices)142     private void enableBluetooth(boolean enabled, BluetoothDevice... devices) {
143         when(mBluetoothManager.getAdapter().isEnabled()).thenReturn(enabled);
144         when(mBluetoothManager.getConnectedDevices(eq(BluetoothProfile.GATT)))
145                 .thenReturn(Arrays.asList(devices));
146     }
147 }
148