Loading android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +27 −17 Original line number Original line Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; Loading Loading @@ -72,7 +71,6 @@ import java.util.Set; * 3) The HFP active device might be different from the A2DP active device. * 3) The HFP active device might be different from the A2DP active device. * 4) The Active Device Manager always listens for ACTION_ACTIVE_DEVICE_CHANGED * 4) The Active Device Manager always listens for ACTION_ACTIVE_DEVICE_CHANGED * broadcasts for each profile: * broadcasts for each profile: * - BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED for HFP * - BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED for HearingAid * - BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED for HearingAid * - BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED for LE audio * - BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED for LE audio * If such broadcast is received (e.g., triggered indirectly by user * If such broadcast is received (e.g., triggered indirectly by user Loading Loading @@ -185,13 +183,6 @@ public class ActiveDeviceManager { } } switch (action) { switch (action) { case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: if (currentState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpConnected(device)); } else if (previousState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpDisconnected(device)); } break; case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: if (currentState == BluetoothProfile.STATE_CONNECTED) { if (currentState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHearingAidConnected(device)); mHandler.post(() -> handleHearingAidConnected(device)); Loading @@ -213,9 +204,6 @@ public class ActiveDeviceManager { mHandler.post(() -> handleHapDisconnected(device)); mHandler.post(() -> handleHapDisconnected(device)); } } break; break; case BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED: mHandler.post(() -> handleHfpActiveDeviceChanged(device)); break; case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED: case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED: mHandler.post(() -> handleHearingAidActiveDeviceChanged(device)); mHandler.post(() -> handleHearingAidActiveDeviceChanged(device)); break; break; Loading @@ -233,13 +221,13 @@ public class ActiveDeviceManager { * Called when A2DP connection state changed by A2dpStateMachine * Called when A2DP connection state changed by A2dpStateMachine * * * @param device The device of which connection state was changed * @param device The device of which connection state was changed * @param fropmState The previous connection state of the device * @param fromState The previous connection state of the device * @param toState The new connection state of the device * @param toState The new connection state of the device */ */ public void a2dpConnectionStateChanged(BluetoothDevice device, int fropmState, int toState) { public void a2dpConnectionStateChanged(BluetoothDevice device, int fromState, int toState) { if (toState == BluetoothProfile.STATE_CONNECTED) { if (toState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleA2dpConnected(device)); mHandler.post(() -> handleA2dpConnected(device)); } else if (fropmState == BluetoothProfile.STATE_CONNECTED) { } else if (fromState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleA2dpDisconnected(device)); mHandler.post(() -> handleA2dpDisconnected(device)); } } } } Loading @@ -253,6 +241,30 @@ public class ActiveDeviceManager { mHandler.post(() -> handleA2dpActiveDeviceChanged(device)); mHandler.post(() -> handleA2dpActiveDeviceChanged(device)); } } /** * Called when HFP connection state changed by HeadsetStateMachine * * @param device The device of which connection state was changed * @param prevState The previous connection state of the device * @param newState The new connection state of the device */ public void hfpConnectionStateChanged(BluetoothDevice device, int prevState, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpConnected(device)); } else if (prevState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpDisconnected(device)); } } /** * Called when HFP active state changed by HeadsetStateMachine * * @param device The device currently activated. {@code null} if no A2DP device activated */ public void hfpActiveStateChanged(BluetoothDevice device) { mHandler.post(() -> handleHfpActiveDeviceChanged(device)); } private void handleAdapterStateChanged(int currentState) { private void handleAdapterStateChanged(int currentState) { if (DBG) { if (DBG) { Log.d(TAG, "handleAdapterStateChanged: currentState=" + currentState); Log.d(TAG, "handleAdapterStateChanged: currentState=" + currentState); Loading Loading @@ -815,8 +827,6 @@ public class ActiveDeviceManager { IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); Loading android/app/src/com/android/bluetooth/hfp/HeadsetService.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -2004,6 +2004,9 @@ public class HeadsetService extends ProfileService { setActiveDevice(null); setActiveDevice(null); } } } } mAdapterService .getActiveDeviceManager() .hfpConnectionStateChanged(device, fromState, toState); } } /** /** Loading Loading @@ -2129,6 +2132,7 @@ public class HeadsetService extends ProfileService { private void broadcastActiveDevice(BluetoothDevice device) { private void broadcastActiveDevice(BluetoothDevice device) { logD("broadcastActiveDevice: " + device); logD("broadcastActiveDevice: " + device); mAdapterService.getActiveDeviceManager().hfpActiveStateChanged(device); BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED, BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED, BluetoothProfile.HEADSET, mAdapterService.obfuscateAddress(device), BluetoothProfile.HEADSET, mAdapterService.obfuscateAddress(device), mAdapterService.getMetricId(device)); mAdapterService.getMetricId(device)); Loading android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +5 −14 Original line number Original line Diff line number Diff line Loading @@ -33,7 +33,6 @@ import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; Loading Loading @@ -1185,11 +1184,8 @@ public class ActiveDeviceManagerTest { mDeviceConnectionStack.add(device); mDeviceConnectionStack.add(device); mMostRecentDevice = device; mMostRecentDevice = device; Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); mActiveDeviceManager.hfpConnectionStateChanged( intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); device, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } } /** Helper to indicate Headset disconnected for a device. */ /** Helper to indicate Headset disconnected for a device. */ Loading @@ -1200,11 +1196,8 @@ public class ActiveDeviceManagerTest { ? mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1) ? mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1) : null; : null; Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); mActiveDeviceManager.hfpConnectionStateChanged( intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } } /** Helper to indicate Headset active device changed for a device. */ /** Helper to indicate Headset active device changed for a device. */ Loading @@ -1213,9 +1206,7 @@ public class ActiveDeviceManagerTest { mDeviceConnectionStack.add(device); mDeviceConnectionStack.add(device); mMostRecentDevice = device; mMostRecentDevice = device; Intent intent = new Intent(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); mActiveDeviceManager.hfpActiveStateChanged(device); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } } /** /** Loading android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java +3 −3 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothHeadset; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; Loading @@ -50,15 +49,14 @@ import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.ActiveDeviceManager; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.hamcrest.Matchers; import org.hamcrest.Matchers; import org.junit.After; import org.junit.After; import org.junit.Assert; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Before; import org.junit.Ignore; import org.junit.Ignore; import org.junit.Rule; import org.junit.Rule; Loading Loading @@ -150,6 +148,7 @@ public class HeadsetServiceAndStateMachineTest { @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Mock private AdapterService mAdapterService; @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private DatabaseManager mDatabaseManager; @Mock private DatabaseManager mDatabaseManager; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private AudioManager mAudioManager; @Mock private AudioManager mAudioManager; Loading Loading @@ -184,6 +183,7 @@ public class HeadsetServiceAndStateMachineTest { mAdapterService).getBondedDevices(); mAdapterService).getBondedDevices(); doReturn(new BluetoothSinkAudioPolicy.Builder().build()).when(mAdapterService) doReturn(new BluetoothSinkAudioPolicy.Builder().build()).when(mAdapterService) .getRequestedAudioPolicyAsSink(any(BluetoothDevice.class)); .getRequestedAudioPolicyAsSink(any(BluetoothDevice.class)); doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); // Mock system interface // Mock system interface doNothing().when(mSystemInterface).stop(); doNothing().when(mSystemInterface).stop(); doReturn(mPhoneState).when(mSystemInterface).getHeadsetPhoneState(); doReturn(mPhoneState).when(mSystemInterface).getHeadsetPhoneState(); Loading android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java +20 −5 Original line number Original line Diff line number Diff line Loading @@ -16,16 +16,30 @@ package com.android.bluetooth.hfp; package com.android.bluetooth.hfp; import static org.mockito.Mockito.*; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothSinkAudioPolicy; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSinkAudioPolicy; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothHeadset; import android.content.Context; import android.content.Context; import android.media.AudioManager; import android.media.AudioManager; import android.os.ParcelUuid; import android.os.ParcelUuid; Loading @@ -37,15 +51,14 @@ import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.ActiveDeviceManager; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.hamcrest.Matchers; import org.hamcrest.Matchers; import org.junit.After; import org.junit.After; import org.junit.Assert; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Before; import org.junit.Rule; import org.junit.Rule; import org.junit.Test; import org.junit.Test; Loading Loading @@ -82,6 +95,7 @@ public class HeadsetServiceTest { @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Mock private AdapterService mAdapterService; @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private DatabaseManager mDatabaseManager; @Mock private DatabaseManager mDatabaseManager; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private AudioManager mAudioManager; @Mock private AudioManager mAudioManager; Loading Loading @@ -109,6 +123,7 @@ public class HeadsetServiceTest { .getRemoteUuids(any(BluetoothDevice.class)); .getRemoteUuids(any(BluetoothDevice.class)); doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService) doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService) .getBondState(any(BluetoothDevice.class)); .getBondState(any(BluetoothDevice.class)); doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); doAnswer(invocation -> { doAnswer(invocation -> { Loading Loading
android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +27 −17 Original line number Original line Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; Loading Loading @@ -72,7 +71,6 @@ import java.util.Set; * 3) The HFP active device might be different from the A2DP active device. * 3) The HFP active device might be different from the A2DP active device. * 4) The Active Device Manager always listens for ACTION_ACTIVE_DEVICE_CHANGED * 4) The Active Device Manager always listens for ACTION_ACTIVE_DEVICE_CHANGED * broadcasts for each profile: * broadcasts for each profile: * - BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED for HFP * - BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED for HearingAid * - BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED for HearingAid * - BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED for LE audio * - BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED for LE audio * If such broadcast is received (e.g., triggered indirectly by user * If such broadcast is received (e.g., triggered indirectly by user Loading Loading @@ -185,13 +183,6 @@ public class ActiveDeviceManager { } } switch (action) { switch (action) { case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED: if (currentState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpConnected(device)); } else if (previousState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpDisconnected(device)); } break; case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED: if (currentState == BluetoothProfile.STATE_CONNECTED) { if (currentState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHearingAidConnected(device)); mHandler.post(() -> handleHearingAidConnected(device)); Loading @@ -213,9 +204,6 @@ public class ActiveDeviceManager { mHandler.post(() -> handleHapDisconnected(device)); mHandler.post(() -> handleHapDisconnected(device)); } } break; break; case BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED: mHandler.post(() -> handleHfpActiveDeviceChanged(device)); break; case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED: case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED: mHandler.post(() -> handleHearingAidActiveDeviceChanged(device)); mHandler.post(() -> handleHearingAidActiveDeviceChanged(device)); break; break; Loading @@ -233,13 +221,13 @@ public class ActiveDeviceManager { * Called when A2DP connection state changed by A2dpStateMachine * Called when A2DP connection state changed by A2dpStateMachine * * * @param device The device of which connection state was changed * @param device The device of which connection state was changed * @param fropmState The previous connection state of the device * @param fromState The previous connection state of the device * @param toState The new connection state of the device * @param toState The new connection state of the device */ */ public void a2dpConnectionStateChanged(BluetoothDevice device, int fropmState, int toState) { public void a2dpConnectionStateChanged(BluetoothDevice device, int fromState, int toState) { if (toState == BluetoothProfile.STATE_CONNECTED) { if (toState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleA2dpConnected(device)); mHandler.post(() -> handleA2dpConnected(device)); } else if (fropmState == BluetoothProfile.STATE_CONNECTED) { } else if (fromState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleA2dpDisconnected(device)); mHandler.post(() -> handleA2dpDisconnected(device)); } } } } Loading @@ -253,6 +241,30 @@ public class ActiveDeviceManager { mHandler.post(() -> handleA2dpActiveDeviceChanged(device)); mHandler.post(() -> handleA2dpActiveDeviceChanged(device)); } } /** * Called when HFP connection state changed by HeadsetStateMachine * * @param device The device of which connection state was changed * @param prevState The previous connection state of the device * @param newState The new connection state of the device */ public void hfpConnectionStateChanged(BluetoothDevice device, int prevState, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpConnected(device)); } else if (prevState == BluetoothProfile.STATE_CONNECTED) { mHandler.post(() -> handleHfpDisconnected(device)); } } /** * Called when HFP active state changed by HeadsetStateMachine * * @param device The device currently activated. {@code null} if no A2DP device activated */ public void hfpActiveStateChanged(BluetoothDevice device) { mHandler.post(() -> handleHfpActiveDeviceChanged(device)); } private void handleAdapterStateChanged(int currentState) { private void handleAdapterStateChanged(int currentState) { if (DBG) { if (DBG) { Log.d(TAG, "handleAdapterStateChanged: currentState=" + currentState); Log.d(TAG, "handleAdapterStateChanged: currentState=" + currentState); Loading Loading @@ -815,8 +827,6 @@ public class ActiveDeviceManager { IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); Loading
android/app/src/com/android/bluetooth/hfp/HeadsetService.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -2004,6 +2004,9 @@ public class HeadsetService extends ProfileService { setActiveDevice(null); setActiveDevice(null); } } } } mAdapterService .getActiveDeviceManager() .hfpConnectionStateChanged(device, fromState, toState); } } /** /** Loading Loading @@ -2129,6 +2132,7 @@ public class HeadsetService extends ProfileService { private void broadcastActiveDevice(BluetoothDevice device) { private void broadcastActiveDevice(BluetoothDevice device) { logD("broadcastActiveDevice: " + device); logD("broadcastActiveDevice: " + device); mAdapterService.getActiveDeviceManager().hfpActiveStateChanged(device); BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED, BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED, BluetoothProfile.HEADSET, mAdapterService.obfuscateAddress(device), BluetoothProfile.HEADSET, mAdapterService.obfuscateAddress(device), mAdapterService.getMetricId(device)); mAdapterService.getMetricId(device)); Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +5 −14 Original line number Original line Diff line number Diff line Loading @@ -33,7 +33,6 @@ import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHapClient; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; Loading Loading @@ -1185,11 +1184,8 @@ public class ActiveDeviceManagerTest { mDeviceConnectionStack.add(device); mDeviceConnectionStack.add(device); mMostRecentDevice = device; mMostRecentDevice = device; Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); mActiveDeviceManager.hfpConnectionStateChanged( intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); device, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } } /** Helper to indicate Headset disconnected for a device. */ /** Helper to indicate Headset disconnected for a device. */ Loading @@ -1200,11 +1196,8 @@ public class ActiveDeviceManagerTest { ? mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1) ? mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1) : null; : null; Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); mActiveDeviceManager.hfpConnectionStateChanged( intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTED); intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } } /** Helper to indicate Headset active device changed for a device. */ /** Helper to indicate Headset active device changed for a device. */ Loading @@ -1213,9 +1206,7 @@ public class ActiveDeviceManagerTest { mDeviceConnectionStack.add(device); mDeviceConnectionStack.add(device); mMostRecentDevice = device; mMostRecentDevice = device; Intent intent = new Intent(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); mActiveDeviceManager.hfpActiveStateChanged(device); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent); } } /** /** Loading
android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java +3 −3 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothHeadset; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; Loading @@ -50,15 +49,14 @@ import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.ActiveDeviceManager; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.hamcrest.Matchers; import org.hamcrest.Matchers; import org.junit.After; import org.junit.After; import org.junit.Assert; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Before; import org.junit.Ignore; import org.junit.Ignore; import org.junit.Rule; import org.junit.Rule; Loading Loading @@ -150,6 +148,7 @@ public class HeadsetServiceAndStateMachineTest { @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Mock private AdapterService mAdapterService; @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private DatabaseManager mDatabaseManager; @Mock private DatabaseManager mDatabaseManager; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private AudioManager mAudioManager; @Mock private AudioManager mAudioManager; Loading Loading @@ -184,6 +183,7 @@ public class HeadsetServiceAndStateMachineTest { mAdapterService).getBondedDevices(); mAdapterService).getBondedDevices(); doReturn(new BluetoothSinkAudioPolicy.Builder().build()).when(mAdapterService) doReturn(new BluetoothSinkAudioPolicy.Builder().build()).when(mAdapterService) .getRequestedAudioPolicyAsSink(any(BluetoothDevice.class)); .getRequestedAudioPolicyAsSink(any(BluetoothDevice.class)); doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); // Mock system interface // Mock system interface doNothing().when(mSystemInterface).stop(); doNothing().when(mSystemInterface).stop(); doReturn(mPhoneState).when(mSystemInterface).getHeadsetPhoneState(); doReturn(mPhoneState).when(mSystemInterface).getHeadsetPhoneState(); Loading
android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java +20 −5 Original line number Original line Diff line number Diff line Loading @@ -16,16 +16,30 @@ package com.android.bluetooth.hfp; package com.android.bluetooth.hfp; import static org.mockito.Mockito.*; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothSinkAudioPolicy; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothSinkAudioPolicy; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothHeadset; import android.content.Context; import android.content.Context; import android.media.AudioManager; import android.media.AudioManager; import android.os.ParcelUuid; import android.os.ParcelUuid; Loading @@ -37,15 +51,14 @@ import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.ActiveDeviceManager; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.hamcrest.Matchers; import org.hamcrest.Matchers; import org.junit.After; import org.junit.After; import org.junit.Assert; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Before; import org.junit.Rule; import org.junit.Rule; import org.junit.Test; import org.junit.Test; Loading Loading @@ -82,6 +95,7 @@ public class HeadsetServiceTest { @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); @Mock private AdapterService mAdapterService; @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private DatabaseManager mDatabaseManager; @Mock private DatabaseManager mDatabaseManager; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private HeadsetSystemInterface mSystemInterface; @Mock private AudioManager mAudioManager; @Mock private AudioManager mAudioManager; Loading Loading @@ -109,6 +123,7 @@ public class HeadsetServiceTest { .getRemoteUuids(any(BluetoothDevice.class)); .getRemoteUuids(any(BluetoothDevice.class)); doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService) doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService) .getBondState(any(BluetoothDevice.class)); .getBondState(any(BluetoothDevice.class)); doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); doAnswer(invocation -> { doAnswer(invocation -> { Loading