Loading android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +86 −53 Original line number Diff line number Diff line Loading @@ -80,13 +80,15 @@ class PhonePolicy { private static final int MESSAGE_ADAPTER_STATE_TURNED_ON = 4; // Timeouts private static final int CONNECT_OTHER_PROFILES_TIMEOUT = 6000; // 6s @VisibleForTesting static int sConnectOtherProfilesTimeoutMillis = 6000; // 6s private final AdapterService mAdapterService; private final ServiceFactory mFactory; private final Handler mHandler; private final HashSet<BluetoothDevice> mHeadsetRetrySet = new HashSet<>(); private final HashSet<BluetoothDevice> mA2dpRetrySet = new HashSet<>(); private final HashSet<BluetoothDevice> mConnectOtherProfilesDeviceSet = new HashSet<>(); // Broadcast receiver for all changes to states of various profiles private final BroadcastReceiver mReceiver = new BroadcastReceiver() { Loading Loading @@ -167,12 +169,14 @@ class PhonePolicy { } break; case MESSAGE_CONNECT_OTHER_PROFILES: case MESSAGE_CONNECT_OTHER_PROFILES: { // Called when we try connect some profiles in processConnectOtherProfiles but // we send a delayed message to try connecting the remaining profiles processConnectOtherProfiles((BluetoothDevice) msg.obj); BluetoothDevice device = (BluetoothDevice) msg.obj; processConnectOtherProfiles(device); mConnectOtherProfilesDeviceSet.remove(device); break; } case MESSAGE_ADAPTER_STATE_TURNED_ON: // Call auto connect when adapter switches state to ON resetStates(); Loading Loading @@ -254,8 +258,8 @@ class PhonePolicy { int prevState) { debugLog("processProfileStateChanged, device=" + device + ", profile=" + profileId + ", " + prevState + " -> " + nextState); if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET)) && ( nextState == BluetoothProfile.STATE_CONNECTED)) { if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET))) { if (nextState == BluetoothProfile.STATE_CONNECTED) { switch (profileId) { case BluetoothProfile.A2DP: mA2dpRetrySet.remove(device); Loading @@ -265,7 +269,13 @@ class PhonePolicy { break; } connectOtherProfile(device); setProfileAutoConnectionPriority(device, profileId); setProfileAutoConnectionPriority(device, profileId, true); } if (prevState == BluetoothProfile.STATE_CONNECTING && nextState == BluetoothProfile.STATE_DISCONNECTED) { setProfileAutoConnectionPriority(device, profileId, false); } } } Loading Loading @@ -341,12 +351,18 @@ class PhonePolicy { } private void connectOtherProfile(BluetoothDevice device) { if ((!mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES)) && (!mAdapterService.isQuietModeEnabled())) { if (mAdapterService.isQuietModeEnabled()) { debugLog("connectOtherProfile: in quiet mode, skip connect other profile " + device); return; } if (mConnectOtherProfilesDeviceSet.contains(device)) { debugLog("connectOtherProfile: already scheduled callback for " + device); return; } mConnectOtherProfilesDeviceSet.add(device); Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES); m.obj = device; mHandler.sendMessageDelayed(m, CONNECT_OTHER_PROFILES_TIMEOUT); } mHandler.sendMessageDelayed(m, sConnectOtherProfilesTimeoutMillis); } // This function is called whenever a profile is connected. This allows any other bluetooth Loading @@ -363,6 +379,7 @@ class PhonePolicy { A2dpService a2dpService = mFactory.getA2dpService(); PanService panService = mFactory.getPanService(); boolean atLeastOneProfileConnectedForDevice = false; boolean allProfilesEmpty = true; List<BluetoothDevice> a2dpConnDevList = null; List<BluetoothDevice> hsConnDevList = null; Loading @@ -370,38 +387,45 @@ class PhonePolicy { if (hsService != null) { hsConnDevList = hsService.getConnectedDevices(); allProfilesEmpty = allProfilesEmpty && hsConnDevList.isEmpty(); allProfilesEmpty &= hsConnDevList.isEmpty(); atLeastOneProfileConnectedForDevice |= hsConnDevList.contains(device); } if (a2dpService != null) { a2dpConnDevList = a2dpService.getConnectedDevices(); allProfilesEmpty = allProfilesEmpty && a2dpConnDevList.isEmpty(); allProfilesEmpty &= a2dpConnDevList.isEmpty(); atLeastOneProfileConnectedForDevice |= a2dpConnDevList.contains(device); } if (panService != null) { panConnDevList = panService.getConnectedDevices(); allProfilesEmpty = allProfilesEmpty && panConnDevList.isEmpty(); allProfilesEmpty &= panConnDevList.isEmpty(); atLeastOneProfileConnectedForDevice |= panConnDevList.contains(device); } if (allProfilesEmpty) { // considered as fully disconnected, don't bother connecting others. if (!atLeastOneProfileConnectedForDevice) { // Consider this device as fully disconnected, don't bother connecting others debugLog("processConnectOtherProfiles, all profiles disconnected for " + device); // reset retry status so that in the next round we can start retrying connections again mHeadsetRetrySet.remove(device); mA2dpRetrySet.remove(device); if (allProfilesEmpty) { debugLog("processConnectOtherProfiles, all profiles disconnected for all devices"); // reset retry status so that in the next round we can start retrying connections resetStates(); } return; } if (hsService != null) { if (!mHeadsetRetrySet.contains(device) && ( hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && ( hsService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { if (!mHeadsetRetrySet.contains(device) && (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && (hsService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { debugLog("Retrying connection to Headset with device " + device); mHeadsetRetrySet.add(device); hsService.connect(device); } } if (a2dpService != null) { if (!mA2dpRetrySet.contains(device) && ( a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && ( a2dpService.getConnectionState(device) if (!mA2dpRetrySet.contains(device) && (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && (a2dpService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { debugLog("Retrying connection to A2DP with device " + device); mA2dpRetrySet.add(device); Loading @@ -420,51 +444,60 @@ class PhonePolicy { } } private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId) { private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId, boolean autoConnect) { debugLog("setProfileAutoConnectionPriority: device=" + device + ", profile=" + profileId + ", autoConnect=" + autoConnect); switch (profileId) { case BluetoothProfile.HEADSET: case BluetoothProfile.HEADSET: { HeadsetService hsService = mFactory.getHeadsetService(); if ((hsService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))) { List<BluetoothDevice> deviceList = hsService.getConnectedDevices(); adjustOtherHeadsetPriorities(hsService, deviceList); if (hsService == null) { warnLog("setProfileAutoConnectionPriority: HEADSET service is null"); break; } removeAutoConnectFromDisconnectedHeadsets(hsService); if (autoConnect) { hsService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT); } break; case BluetoothProfile.A2DP: } case BluetoothProfile.A2DP: { A2dpService a2dpService = mFactory.getA2dpService(); if ((a2dpService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT != a2dpService.getPriority(device))) { List<BluetoothDevice> deviceList = a2dpService.getConnectedDevices(); adjustOtherSinkPriorities(a2dpService, deviceList); if (a2dpService == null) { warnLog("setProfileAutoConnectionPriority: A2DP service is null"); break; } removeAutoConnectFromDisconnectedA2dpSinks(a2dpService); if (autoConnect) { a2dpService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT); } break; } default: Log.w(TAG, "Tried to set AutoConnect priority on invalid profile " + profileId); break; } } private void adjustOtherHeadsetPriorities(HeadsetService hsService, List<BluetoothDevice> connectedDeviceList) { private void removeAutoConnectFromDisconnectedHeadsets(HeadsetService hsService) { List<BluetoothDevice> connectedDeviceList = hsService.getConnectedDevices(); for (BluetoothDevice device : mAdapterService.getBondedDevices()) { if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && !connectedDeviceList.contains(device)) { debugLog("adjustOtherHeadsetPriorities, device " + device + " PRIORITY_ON"); debugLog("removeAutoConnectFromDisconnectedHeadsets, device " + device + " PRIORITY_ON"); hsService.setPriority(device, BluetoothProfile.PRIORITY_ON); } } } private void adjustOtherSinkPriorities(A2dpService a2dpService, List<BluetoothDevice> connectedDeviceList) { private void removeAutoConnectFromDisconnectedA2dpSinks(A2dpService a2dpService) { List<BluetoothDevice> connectedDeviceList = a2dpService.getConnectedDevices(); for (BluetoothDevice device : mAdapterService.getBondedDevices()) { if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && !connectedDeviceList.contains(device)) { debugLog("adjustOtherSinkPriorities, device " + device + " PRIORITY_ON"); debugLog("removeAutoConnectFromDisconnectedA2dpSinks, device " + device + " PRIORITY_ON"); a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); } } Loading android/app/src/com/android/bluetooth/hfp/AtPhonebook.java +2 −0 Original line number Diff line number Diff line Loading @@ -119,11 +119,13 @@ public class AtPhonebook { Calls.TYPE + "=" + Calls.OUTGOING_TYPE, null, Calls.DEFAULT_SORT_ORDER + " LIMIT 1"); if (cursor == null) { Log.w(TAG, "getLastDialledNumber, cursor is null"); return null; } if (cursor.getCount() < 1) { cursor.close(); Log.w(TAG, "getLastDialledNumber, cursor.getCount is 0"); return null; } cursor.moveToNext(); Loading android/app/src/com/android/bluetooth/hfp/HeadsetService.java +9 −2 Original line number Diff line number Diff line Loading @@ -1274,7 +1274,8 @@ public class HeadsetService extends ProfileService { * @param dialNumber number to dial * @return true on successful dial out */ boolean dialOutgoingCall(BluetoothDevice fromDevice, String dialNumber) { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean dialOutgoingCall(BluetoothDevice fromDevice, String dialNumber) { synchronized (mStateMachines) { Log.i(TAG, "dialOutgoingCall: from " + fromDevice); if (!isOnStateMachineThread()) { Loading Loading @@ -1306,7 +1307,13 @@ public class HeadsetService extends ProfileService { } } boolean hasDeviceInitiatedDialingOut() { /** * Check if any connected headset has started dialing calls * * @return true if some device has started dialing calls */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean hasDeviceInitiatedDialingOut() { synchronized (mStateMachines) { return mDialingOutTimeoutEvent != null; } Loading android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +10 −9 Original line number Diff line number Diff line Loading @@ -1826,20 +1826,21 @@ public class HeadsetStateMachine extends StateMachine { // HSP +CKPD command private void processKeyPressed(BluetoothDevice device) { final HeadsetPhoneState phoneState = mSystemInterface.getHeadsetPhoneState(); if (phoneState.getCallState() == HeadsetHalConstants.CALL_STATE_INCOMING) { if (mSystemInterface.isRinging()) { mSystemInterface.answerCall(device); } else if (phoneState.getNumActiveCall() > 0) { if (getAudioState() != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { mHeadsetService.setActiveDevice(mDevice); mSystemInterface.getAudioManager().setParameters("A2dpSuspended=true"); if (!mNativeInterface.connectAudio(mDevice)) { mSystemInterface.getAudioManager().setParameters("A2dpSuspended=false"); Log.w(TAG, "processKeyPressed: failed to connectAudio to " + mDevice); } else if (mSystemInterface.isInCall()) { if (getAudioState() == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { // Should connect audio as well if (!mHeadsetService.setActiveDevice(mDevice)) { Log.w(TAG, "processKeyPressed, failed to set active device to " + mDevice); } } else { mSystemInterface.hangupCall(device); } } else if (getAudioState() != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { if (!mNativeInterface.disconnectAudio(mDevice)) { Log.w(TAG, "processKeyPressed, failed to disconnect audio from " + mDevice); } } else { // We have already replied OK to this HSP command, no feedback is needed if (mHeadsetService.hasDeviceInitiatedDialingOut()) { Loading android/app/src/com/android/bluetooth/newavrcp/MediaPlayerWrapper.java +31 −25 Original line number Diff line number Diff line Loading @@ -278,9 +278,36 @@ class MediaPlayerWrapper { d("Controller for " + mPackageName + " was updated."); } private void sendMediaUpdate() { MediaData newData = new MediaData( Util.toMetadata(getMetadata()), getPlaybackState(), Util.toMetadataList(getQueue())); if (newData.equals(mCurrentData)) { // This may happen if the controller is fully synced by the time the // first update is completed Log.v(TAG, "Trying to update with last sent metadata"); return; } synchronized (mCallbackLock) { if (mRegisteredCallback == null) { Log.e(TAG, mPackageName + "Trying to send an update with no registered callback"); return; } Log.v(TAG, "trySendMediaUpdate(): Metadata has been updated for " + mPackageName); mRegisteredCallback.mediaUpdatedCallback(newData); } mCurrentData = newData; } class TimeoutHandler extends Handler { private static final int MSG_TIMEOUT = 0; private static final long CALLBACK_TIMEOUT_MS = 1000; private static final long CALLBACK_TIMEOUT_MS = 2000; TimeoutHandler(Looper looper) { super(looper); Loading @@ -301,6 +328,8 @@ class MediaPlayerWrapper { Log.e(TAG, " └ QueueItem(" + i + "): " + current_queue.get(i)); } sendMediaUpdate(); // TODO(apanicke): Add metric collection here. if (sTesting) Log.wtfStack(TAG, "Crashing the stack"); Loading Loading @@ -342,30 +371,7 @@ class MediaPlayerWrapper { } } MediaData newData = new MediaData( Util.toMetadata(getMetadata()), getPlaybackState(), Util.toMetadataList(getQueue())); if (newData.equals(mCurrentData)) { // This may happen if the controller is fully synced by the time the // first update is completed Log.v(TAG, "Trying to update with last sent metadata"); return; } synchronized (mCallbackLock) { if (mRegisteredCallback == null) { Log.e(TAG, mPackageName + "Trying to send an update with no registered callback"); return; } Log.v(TAG, "trySendMediaUpdate(): Metadata has been updated for " + mPackageName); mRegisteredCallback.mediaUpdatedCallback(newData); } mCurrentData = newData; sendMediaUpdate(); } @Override Loading Loading
android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +86 −53 Original line number Diff line number Diff line Loading @@ -80,13 +80,15 @@ class PhonePolicy { private static final int MESSAGE_ADAPTER_STATE_TURNED_ON = 4; // Timeouts private static final int CONNECT_OTHER_PROFILES_TIMEOUT = 6000; // 6s @VisibleForTesting static int sConnectOtherProfilesTimeoutMillis = 6000; // 6s private final AdapterService mAdapterService; private final ServiceFactory mFactory; private final Handler mHandler; private final HashSet<BluetoothDevice> mHeadsetRetrySet = new HashSet<>(); private final HashSet<BluetoothDevice> mA2dpRetrySet = new HashSet<>(); private final HashSet<BluetoothDevice> mConnectOtherProfilesDeviceSet = new HashSet<>(); // Broadcast receiver for all changes to states of various profiles private final BroadcastReceiver mReceiver = new BroadcastReceiver() { Loading Loading @@ -167,12 +169,14 @@ class PhonePolicy { } break; case MESSAGE_CONNECT_OTHER_PROFILES: case MESSAGE_CONNECT_OTHER_PROFILES: { // Called when we try connect some profiles in processConnectOtherProfiles but // we send a delayed message to try connecting the remaining profiles processConnectOtherProfiles((BluetoothDevice) msg.obj); BluetoothDevice device = (BluetoothDevice) msg.obj; processConnectOtherProfiles(device); mConnectOtherProfilesDeviceSet.remove(device); break; } case MESSAGE_ADAPTER_STATE_TURNED_ON: // Call auto connect when adapter switches state to ON resetStates(); Loading Loading @@ -254,8 +258,8 @@ class PhonePolicy { int prevState) { debugLog("processProfileStateChanged, device=" + device + ", profile=" + profileId + ", " + prevState + " -> " + nextState); if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET)) && ( nextState == BluetoothProfile.STATE_CONNECTED)) { if (((profileId == BluetoothProfile.A2DP) || (profileId == BluetoothProfile.HEADSET))) { if (nextState == BluetoothProfile.STATE_CONNECTED) { switch (profileId) { case BluetoothProfile.A2DP: mA2dpRetrySet.remove(device); Loading @@ -265,7 +269,13 @@ class PhonePolicy { break; } connectOtherProfile(device); setProfileAutoConnectionPriority(device, profileId); setProfileAutoConnectionPriority(device, profileId, true); } if (prevState == BluetoothProfile.STATE_CONNECTING && nextState == BluetoothProfile.STATE_DISCONNECTED) { setProfileAutoConnectionPriority(device, profileId, false); } } } Loading Loading @@ -341,12 +351,18 @@ class PhonePolicy { } private void connectOtherProfile(BluetoothDevice device) { if ((!mHandler.hasMessages(MESSAGE_CONNECT_OTHER_PROFILES)) && (!mAdapterService.isQuietModeEnabled())) { if (mAdapterService.isQuietModeEnabled()) { debugLog("connectOtherProfile: in quiet mode, skip connect other profile " + device); return; } if (mConnectOtherProfilesDeviceSet.contains(device)) { debugLog("connectOtherProfile: already scheduled callback for " + device); return; } mConnectOtherProfilesDeviceSet.add(device); Message m = mHandler.obtainMessage(MESSAGE_CONNECT_OTHER_PROFILES); m.obj = device; mHandler.sendMessageDelayed(m, CONNECT_OTHER_PROFILES_TIMEOUT); } mHandler.sendMessageDelayed(m, sConnectOtherProfilesTimeoutMillis); } // This function is called whenever a profile is connected. This allows any other bluetooth Loading @@ -363,6 +379,7 @@ class PhonePolicy { A2dpService a2dpService = mFactory.getA2dpService(); PanService panService = mFactory.getPanService(); boolean atLeastOneProfileConnectedForDevice = false; boolean allProfilesEmpty = true; List<BluetoothDevice> a2dpConnDevList = null; List<BluetoothDevice> hsConnDevList = null; Loading @@ -370,38 +387,45 @@ class PhonePolicy { if (hsService != null) { hsConnDevList = hsService.getConnectedDevices(); allProfilesEmpty = allProfilesEmpty && hsConnDevList.isEmpty(); allProfilesEmpty &= hsConnDevList.isEmpty(); atLeastOneProfileConnectedForDevice |= hsConnDevList.contains(device); } if (a2dpService != null) { a2dpConnDevList = a2dpService.getConnectedDevices(); allProfilesEmpty = allProfilesEmpty && a2dpConnDevList.isEmpty(); allProfilesEmpty &= a2dpConnDevList.isEmpty(); atLeastOneProfileConnectedForDevice |= a2dpConnDevList.contains(device); } if (panService != null) { panConnDevList = panService.getConnectedDevices(); allProfilesEmpty = allProfilesEmpty && panConnDevList.isEmpty(); allProfilesEmpty &= panConnDevList.isEmpty(); atLeastOneProfileConnectedForDevice |= panConnDevList.contains(device); } if (allProfilesEmpty) { // considered as fully disconnected, don't bother connecting others. if (!atLeastOneProfileConnectedForDevice) { // Consider this device as fully disconnected, don't bother connecting others debugLog("processConnectOtherProfiles, all profiles disconnected for " + device); // reset retry status so that in the next round we can start retrying connections again mHeadsetRetrySet.remove(device); mA2dpRetrySet.remove(device); if (allProfilesEmpty) { debugLog("processConnectOtherProfiles, all profiles disconnected for all devices"); // reset retry status so that in the next round we can start retrying connections resetStates(); } return; } if (hsService != null) { if (!mHeadsetRetrySet.contains(device) && ( hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && ( hsService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { if (!mHeadsetRetrySet.contains(device) && (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && (hsService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { debugLog("Retrying connection to Headset with device " + device); mHeadsetRetrySet.add(device); hsService.connect(device); } } if (a2dpService != null) { if (!mA2dpRetrySet.contains(device) && ( a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && ( a2dpService.getConnectionState(device) if (!mA2dpRetrySet.contains(device) && (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_ON) && (a2dpService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { debugLog("Retrying connection to A2DP with device " + device); mA2dpRetrySet.add(device); Loading @@ -420,51 +444,60 @@ class PhonePolicy { } } private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId) { private void setProfileAutoConnectionPriority(BluetoothDevice device, int profileId, boolean autoConnect) { debugLog("setProfileAutoConnectionPriority: device=" + device + ", profile=" + profileId + ", autoConnect=" + autoConnect); switch (profileId) { case BluetoothProfile.HEADSET: case BluetoothProfile.HEADSET: { HeadsetService hsService = mFactory.getHeadsetService(); if ((hsService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT != hsService.getPriority(device))) { List<BluetoothDevice> deviceList = hsService.getConnectedDevices(); adjustOtherHeadsetPriorities(hsService, deviceList); if (hsService == null) { warnLog("setProfileAutoConnectionPriority: HEADSET service is null"); break; } removeAutoConnectFromDisconnectedHeadsets(hsService); if (autoConnect) { hsService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT); } break; case BluetoothProfile.A2DP: } case BluetoothProfile.A2DP: { A2dpService a2dpService = mFactory.getA2dpService(); if ((a2dpService != null) && (BluetoothProfile.PRIORITY_AUTO_CONNECT != a2dpService.getPriority(device))) { List<BluetoothDevice> deviceList = a2dpService.getConnectedDevices(); adjustOtherSinkPriorities(a2dpService, deviceList); if (a2dpService == null) { warnLog("setProfileAutoConnectionPriority: A2DP service is null"); break; } removeAutoConnectFromDisconnectedA2dpSinks(a2dpService); if (autoConnect) { a2dpService.setPriority(device, BluetoothProfile.PRIORITY_AUTO_CONNECT); } break; } default: Log.w(TAG, "Tried to set AutoConnect priority on invalid profile " + profileId); break; } } private void adjustOtherHeadsetPriorities(HeadsetService hsService, List<BluetoothDevice> connectedDeviceList) { private void removeAutoConnectFromDisconnectedHeadsets(HeadsetService hsService) { List<BluetoothDevice> connectedDeviceList = hsService.getConnectedDevices(); for (BluetoothDevice device : mAdapterService.getBondedDevices()) { if (hsService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && !connectedDeviceList.contains(device)) { debugLog("adjustOtherHeadsetPriorities, device " + device + " PRIORITY_ON"); debugLog("removeAutoConnectFromDisconnectedHeadsets, device " + device + " PRIORITY_ON"); hsService.setPriority(device, BluetoothProfile.PRIORITY_ON); } } } private void adjustOtherSinkPriorities(A2dpService a2dpService, List<BluetoothDevice> connectedDeviceList) { private void removeAutoConnectFromDisconnectedA2dpSinks(A2dpService a2dpService) { List<BluetoothDevice> connectedDeviceList = a2dpService.getConnectedDevices(); for (BluetoothDevice device : mAdapterService.getBondedDevices()) { if (a2dpService.getPriority(device) >= BluetoothProfile.PRIORITY_AUTO_CONNECT && !connectedDeviceList.contains(device)) { debugLog("adjustOtherSinkPriorities, device " + device + " PRIORITY_ON"); debugLog("removeAutoConnectFromDisconnectedA2dpSinks, device " + device + " PRIORITY_ON"); a2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); } } Loading
android/app/src/com/android/bluetooth/hfp/AtPhonebook.java +2 −0 Original line number Diff line number Diff line Loading @@ -119,11 +119,13 @@ public class AtPhonebook { Calls.TYPE + "=" + Calls.OUTGOING_TYPE, null, Calls.DEFAULT_SORT_ORDER + " LIMIT 1"); if (cursor == null) { Log.w(TAG, "getLastDialledNumber, cursor is null"); return null; } if (cursor.getCount() < 1) { cursor.close(); Log.w(TAG, "getLastDialledNumber, cursor.getCount is 0"); return null; } cursor.moveToNext(); Loading
android/app/src/com/android/bluetooth/hfp/HeadsetService.java +9 −2 Original line number Diff line number Diff line Loading @@ -1274,7 +1274,8 @@ public class HeadsetService extends ProfileService { * @param dialNumber number to dial * @return true on successful dial out */ boolean dialOutgoingCall(BluetoothDevice fromDevice, String dialNumber) { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean dialOutgoingCall(BluetoothDevice fromDevice, String dialNumber) { synchronized (mStateMachines) { Log.i(TAG, "dialOutgoingCall: from " + fromDevice); if (!isOnStateMachineThread()) { Loading Loading @@ -1306,7 +1307,13 @@ public class HeadsetService extends ProfileService { } } boolean hasDeviceInitiatedDialingOut() { /** * Check if any connected headset has started dialing calls * * @return true if some device has started dialing calls */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public boolean hasDeviceInitiatedDialingOut() { synchronized (mStateMachines) { return mDialingOutTimeoutEvent != null; } Loading
android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +10 −9 Original line number Diff line number Diff line Loading @@ -1826,20 +1826,21 @@ public class HeadsetStateMachine extends StateMachine { // HSP +CKPD command private void processKeyPressed(BluetoothDevice device) { final HeadsetPhoneState phoneState = mSystemInterface.getHeadsetPhoneState(); if (phoneState.getCallState() == HeadsetHalConstants.CALL_STATE_INCOMING) { if (mSystemInterface.isRinging()) { mSystemInterface.answerCall(device); } else if (phoneState.getNumActiveCall() > 0) { if (getAudioState() != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { mHeadsetService.setActiveDevice(mDevice); mSystemInterface.getAudioManager().setParameters("A2dpSuspended=true"); if (!mNativeInterface.connectAudio(mDevice)) { mSystemInterface.getAudioManager().setParameters("A2dpSuspended=false"); Log.w(TAG, "processKeyPressed: failed to connectAudio to " + mDevice); } else if (mSystemInterface.isInCall()) { if (getAudioState() == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { // Should connect audio as well if (!mHeadsetService.setActiveDevice(mDevice)) { Log.w(TAG, "processKeyPressed, failed to set active device to " + mDevice); } } else { mSystemInterface.hangupCall(device); } } else if (getAudioState() != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { if (!mNativeInterface.disconnectAudio(mDevice)) { Log.w(TAG, "processKeyPressed, failed to disconnect audio from " + mDevice); } } else { // We have already replied OK to this HSP command, no feedback is needed if (mHeadsetService.hasDeviceInitiatedDialingOut()) { Loading
android/app/src/com/android/bluetooth/newavrcp/MediaPlayerWrapper.java +31 −25 Original line number Diff line number Diff line Loading @@ -278,9 +278,36 @@ class MediaPlayerWrapper { d("Controller for " + mPackageName + " was updated."); } private void sendMediaUpdate() { MediaData newData = new MediaData( Util.toMetadata(getMetadata()), getPlaybackState(), Util.toMetadataList(getQueue())); if (newData.equals(mCurrentData)) { // This may happen if the controller is fully synced by the time the // first update is completed Log.v(TAG, "Trying to update with last sent metadata"); return; } synchronized (mCallbackLock) { if (mRegisteredCallback == null) { Log.e(TAG, mPackageName + "Trying to send an update with no registered callback"); return; } Log.v(TAG, "trySendMediaUpdate(): Metadata has been updated for " + mPackageName); mRegisteredCallback.mediaUpdatedCallback(newData); } mCurrentData = newData; } class TimeoutHandler extends Handler { private static final int MSG_TIMEOUT = 0; private static final long CALLBACK_TIMEOUT_MS = 1000; private static final long CALLBACK_TIMEOUT_MS = 2000; TimeoutHandler(Looper looper) { super(looper); Loading @@ -301,6 +328,8 @@ class MediaPlayerWrapper { Log.e(TAG, " └ QueueItem(" + i + "): " + current_queue.get(i)); } sendMediaUpdate(); // TODO(apanicke): Add metric collection here. if (sTesting) Log.wtfStack(TAG, "Crashing the stack"); Loading Loading @@ -342,30 +371,7 @@ class MediaPlayerWrapper { } } MediaData newData = new MediaData( Util.toMetadata(getMetadata()), getPlaybackState(), Util.toMetadataList(getQueue())); if (newData.equals(mCurrentData)) { // This may happen if the controller is fully synced by the time the // first update is completed Log.v(TAG, "Trying to update with last sent metadata"); return; } synchronized (mCallbackLock) { if (mRegisteredCallback == null) { Log.e(TAG, mPackageName + "Trying to send an update with no registered callback"); return; } Log.v(TAG, "trySendMediaUpdate(): Metadata has been updated for " + mPackageName); mRegisteredCallback.mediaUpdatedCallback(newData); } mCurrentData = newData; sendMediaUpdate(); } @Override Loading