1 /* 2 * Copyright 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 com.android.bluetooth.pbap; 18 19 import static org.mockito.Mockito.*; 20 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothDevice; 23 import android.bluetooth.BluetoothProfile; 24 import android.bluetooth.BluetoothSocket; 25 import android.content.Context; 26 import android.os.Handler; 27 import android.os.HandlerThread; 28 29 import androidx.test.InstrumentationRegistry; 30 import androidx.test.filters.MediumTest; 31 import androidx.test.runner.AndroidJUnit4; 32 33 import com.android.bluetooth.R; 34 import com.android.bluetooth.TestUtils; 35 import com.android.bluetooth.btservice.AdapterService; 36 37 import org.hamcrest.core.IsInstanceOf; 38 import org.junit.After; 39 import org.junit.Assert; 40 import org.junit.Assume; 41 import org.junit.Before; 42 import org.junit.Ignore; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.Mock; 46 import org.mockito.MockitoAnnotations; 47 48 @MediumTest 49 @RunWith(AndroidJUnit4.class) 50 public class PbapStateMachineTest { 51 private static final int TEST_NOTIFICATION_ID = 1000000; 52 53 private Context mTargetContext; 54 private BluetoothAdapter mAdapter; 55 private HandlerThread mHandlerThread; 56 private PbapStateMachine mPbapStateMachine; 57 private BluetoothDevice mTestDevice; 58 private Handler mHandler; 59 private BluetoothSocket mSocket; 60 private BluetoothPbapService mBluetoothPbapService; 61 62 @Mock private AdapterService mAdapterService; 63 64 @Before setUp()65 public void setUp() throws Exception { 66 mTargetContext = InstrumentationRegistry.getTargetContext(); 67 Assume.assumeTrue("Ignore test when BluetoothPbapService is not enabled", 68 mTargetContext.getResources().getBoolean(R.bool.profile_supported_pbap)); 69 MockitoAnnotations.initMocks(this); 70 TestUtils.setAdapterService(mAdapterService); 71 // This line must be called to make sure relevant objects are initialized properly 72 mAdapter = BluetoothAdapter.getDefaultAdapter(); 73 // Get a device for testing 74 mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); 75 76 mHandlerThread = new HandlerThread("PbapTestHandlerThread"); 77 mHandlerThread.start(); 78 mHandler = new Handler(mHandlerThread.getLooper()); 79 mBluetoothPbapService = mock(BluetoothPbapService.class); 80 doNothing().when(mBluetoothPbapService).checkOrGetPhonebookPermission(any()); 81 mPbapStateMachine = PbapStateMachine.make(mBluetoothPbapService, mHandlerThread.getLooper(), 82 mTestDevice, mSocket, mBluetoothPbapService, mHandler, TEST_NOTIFICATION_ID); 83 } 84 85 @After tearDown()86 public void tearDown() throws Exception { 87 if (!mTargetContext.getResources().getBoolean(R.bool.profile_supported_pbap)) { 88 return; 89 } 90 mHandlerThread.quitSafely(); 91 TestUtils.clearAdapterService(mAdapterService); 92 } 93 94 /** 95 * Test that initial state is WaitingForAuth 96 */ 97 @Test testInitialState()98 public void testInitialState() { 99 Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, 100 mPbapStateMachine.getConnectionState()); 101 Assert.assertThat(mPbapStateMachine.getCurrentState(), 102 IsInstanceOf.instanceOf(PbapStateMachine.WaitingForAuth.class)); 103 } 104 105 /** 106 * Test state transition from WaitingForAuth to Finished when the user rejected 107 */ 108 @Ignore("Class BluetoothSocket is final and cannot be mocked. b/71512958: re-enable it.") 109 @Test testStateTransition_WaitingForAuthToFinished()110 public void testStateTransition_WaitingForAuthToFinished() throws Exception { 111 mPbapStateMachine.sendMessage(PbapStateMachine.REJECTED); 112 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 113 mPbapStateMachine.getConnectionState()); 114 Assert.assertThat(mPbapStateMachine.getCurrentState(), 115 IsInstanceOf.instanceOf(PbapStateMachine.Finished.class)); 116 } 117 118 /** 119 * Test state transition from WaitingForAuth to Finished when the user rejected 120 */ 121 @Ignore("Class BluetoothSocket is final and cannot be mocked. b/71512958: re-enable it.") 122 @Test testStateTransition_WaitingForAuthToConnected()123 public void testStateTransition_WaitingForAuthToConnected() throws Exception { 124 mPbapStateMachine.sendMessage(PbapStateMachine.AUTHORIZED); 125 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 126 mPbapStateMachine.getConnectionState()); 127 Assert.assertThat(mPbapStateMachine.getCurrentState(), 128 IsInstanceOf.instanceOf(PbapStateMachine.Connected.class)); 129 } 130 131 /** 132 * Test state transition from Connected to Finished when the OBEX server is done 133 */ 134 @Ignore("Class BluetoothSocket is final and cannot be mocked. b/71512958: re-enable it.") 135 @Test testStateTransition_ConnectedToFinished()136 public void testStateTransition_ConnectedToFinished() throws Exception { 137 mPbapStateMachine.sendMessage(PbapStateMachine.AUTHORIZED); 138 Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, 139 mPbapStateMachine.getConnectionState()); 140 Assert.assertThat(mPbapStateMachine.getCurrentState(), 141 IsInstanceOf.instanceOf(PbapStateMachine.Connected.class)); 142 143 // PBAP OBEX transport is done. 144 mPbapStateMachine.sendMessage(PbapStateMachine.DISCONNECT); 145 Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, 146 mPbapStateMachine.getConnectionState()); 147 Assert.assertThat(mPbapStateMachine.getCurrentState(), 148 IsInstanceOf.instanceOf(PbapStateMachine.Finished.class)); 149 } 150 } 151