nsresult AudioManager::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) { if ((strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID) == 0) || (strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID) == 0)) { nsresult rv; int status = NS_ConvertUTF16toUTF8(aData).ToInteger(&rv); if (NS_FAILED(rv) || status > 1 || status < 0) { NS_WARNING(nsPrintfCString("Wrong data value of %s", aTopic).get()); return NS_ERROR_FAILURE; } nsAutoString tmp_address; BluetoothProfileManagerBase* profile = static_cast<BluetoothProfileManagerBase*>(aSubject); profile->GetAddress(tmp_address); nsAutoCString address = NS_ConvertUTF16toUTF8(tmp_address); audio_policy_dev_state_t audioState = status ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) { AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, audioState, address.get()); AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, audioState, address.get()); if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { String8 cmd; cmd.appendFormat("bt_samplerate=%d", kBtSampleRate); AudioSystem::setParameters(0, cmd); SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO); } else { // only force to none if the current force setting is bt_sco int32_t force; GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force); if (force == nsIAudioManager::FORCE_BT_SCO) SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE); } } else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) { AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, audioState, address.get()); if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { String8 cmd("bluetooth_enabled=true"); AudioSystem::setParameters(0, cmd); cmd.setTo("A2dpSuspended=false"); AudioSystem::setParameters(0, cmd); } } } else { NS_WARNING("Unexpected topic in AudioManager"); return NS_ERROR_FAILURE; } return NS_OK; }
void AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject, const char* aTopic, const nsCString aAddress) { #ifdef MOZ_B2G_BT bool status; if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) { BluetoothHfpManager* hfp = static_cast<BluetoothHfpManager*>(aSubject); status = hfp->IsScoConnected(); } else { BluetoothProfileManagerBase* profile = static_cast<BluetoothProfileManagerBase*>(aSubject); status = profile->IsConnected(); } audio_policy_dev_state_t audioState = status ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) { if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { String8 cmd; cmd.appendFormat("bt_samplerate=%d", kBtSampleRate); AudioSystem::setParameters(0, cmd); SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO); } else { int32_t force; GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force); if (force == nsIAudioManager::FORCE_BT_SCO) SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE); } } else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) { AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, audioState, aAddress.get()); if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { String8 cmd("bluetooth_enabled=true"); AudioSystem::setParameters(0, cmd); cmd.setTo("A2dpSuspended=false"); AudioSystem::setParameters(0, cmd); } else { String8 cmd("bluetooth_enabled=false"); AudioSystem::setParameters(0, cmd); cmd.setTo("A2dpSuspended=true"); AudioSystem::setParameters(0, cmd); } } else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) { AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, audioState, aAddress.get()); AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, audioState, aAddress.get()); } #endif }
nsresult BluetoothService::StartStopBluetooth(bool aStart, bool aIsStartup) { MOZ_ASSERT(NS_IsMainThread()); if (gInShutdown) { if (aStart) { // Don't try to start if we're already shutting down. MOZ_ASSERT(false, "Start called while in shutdown!"); return NS_ERROR_FAILURE; } if (!mBluetoothThread) { // Don't create a new thread after we've begun shutdown since bluetooth // can't be running. return NS_OK; } } if (!aStart) { BluetoothProfileManagerBase* profile; profile = BluetoothHfpManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } profile = BluetoothOppManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } profile = BluetoothA2dpManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } profile = BluetoothHidManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } } if (!mBluetoothThread) { mBluetoothThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS, NS_LITERAL_CSTRING("Bluetooth"), LazyIdleThread::ManualShutdown); } mAdapterAddedReceived = false; nsCOMPtr<nsIRunnable> runnable = new ToggleBtTask(aStart, aIsStartup); nsresult rv = mBluetoothThread->Dispatch(runnable, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
nsresult BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal( uint16_t aServiceUuid, BluetoothReplyRunnable* aRunnable) { MOZ_ASSERT(NS_IsMainThread()); if (!IsReady()) { NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!"); DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr); return NS_OK; } BluetoothProfileManagerBase* profile = BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid); if (!profile) { InfallibleTArray<BluetoothNamedValue> emptyArr; DispatchBluetoothReply(aRunnable, emptyArr, NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE)); return NS_OK; } nsTArray<nsString> deviceAddresses; if (profile->IsConnected()) { nsString address; profile->GetAddress(address); deviceAddresses.AppendElement(address); } int requestedDeviceCount = deviceAddresses.Length(); if (requestedDeviceCount == 0) { InfallibleTArray<BluetoothNamedValue> emptyArr; DispatchBluetoothReply(aRunnable, emptyArr, EmptyString()); return NS_OK; } for (int i = 0; i < requestedDeviceCount; i++) { // Retrieve all properties of devices bt_bdaddr_t addressType; StringToBdAddressType(deviceAddresses[i], &addressType); int ret = sBtInterface->get_remote_device_properties(&addressType); if (ret != BT_STATUS_SUCCESS) { DispatchBluetoothReply(aRunnable, BluetoothValue(true), NS_LITERAL_STRING("GetConnectedDeviceFailed")); return NS_OK; } } sRequestedDeviceCountArray.AppendElement(requestedDeviceCount); sGetDeviceRunnableArray.AppendElement(aRunnable); return NS_OK; }
nsresult BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal( uint16_t aServiceUuid, BluetoothReplyRunnable* aRunnable) { MOZ_ASSERT(NS_IsMainThread()); ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK); BluetoothProfileManagerBase* profile = BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid); if (!profile) { DispatchReplyError(aRunnable, NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE)); return NS_OK; } nsTArray<nsString> deviceAddresses; if (profile->IsConnected()) { nsString address; profile->GetAddress(address); deviceAddresses.AppendElement(address); } int requestedDeviceCount = deviceAddresses.Length(); if (requestedDeviceCount == 0) { InfallibleTArray<BluetoothNamedValue> emptyArr; DispatchReplySuccess(aRunnable, emptyArr); return NS_OK; } sRequestedDeviceCountArray.AppendElement(requestedDeviceCount); sGetDeviceRunnableArray.AppendElement(aRunnable); for (int i = 0; i < requestedDeviceCount; i++) { // Retrieve all properties of devices sBtInterface->GetRemoteDeviceProperties(deviceAddresses[i], new GetRemoteDevicePropertiesResultHandler(deviceAddresses[i])); } return NS_OK; }
nsresult BluetoothService::StopBluetooth(bool aIsStartup) { MOZ_ASSERT(NS_IsMainThread()); BluetoothProfileManagerBase* profile; profile = BluetoothHfpManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } else { profile->Reset(); } profile = BluetoothOppManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } profile = BluetoothA2dpManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } else { profile->Reset(); } profile = BluetoothHidManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } else { profile->Reset(); } mAdapterAddedReceived = false; /* When IsEnabled() is false, we don't switch off Bluetooth but we still * send ToggleBtAck task. One special case happens at startup stage. At * startup, the initialization of BluetoothService still has to be done * even if Bluetooth is disabled. * * Please see bug 892392 for more information. */ if (aIsStartup || sBluetoothService->IsEnabled()) { // Switch Bluetooth off if (NS_FAILED(sBluetoothService->StopInternal())) { BT_WARNING("Bluetooth service failed to stop!"); } } else { BT_WARNING("Bluetooth has already been enabled/disabled before."); nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(false); if (NS_FAILED(NS_DispatchToMainThread(runnable))) { BT_WARNING("Failed to dispatch to main thread!"); } } return NS_OK; }
void AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject, const char* aTopic, const nsCString aAddress) { #ifdef MOZ_B2G_BT bool status; if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) { BluetoothHfpManagerBase* hfp = static_cast<BluetoothHfpManagerBase*>(aSubject); status = hfp->IsScoConnected(); } else { BluetoothProfileManagerBase* profile = static_cast<BluetoothProfileManagerBase*>(aSubject); status = profile->IsConnected(); } audio_policy_dev_state_t audioState = status ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) { if (audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { String8 cmd; cmd.appendFormat("bt_samplerate=%d", kBtSampleRate); AudioSystem::setParameters(0, cmd); SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_BT_SCO); SwitchProfileData(DEVICE_BLUETOOTH, true); } else { int32_t force; GetForceForUse(nsIAudioManager::USE_COMMUNICATION, &force); if (force == nsIAudioManager::FORCE_BT_SCO) { SetForceForUse(nsIAudioManager::USE_COMMUNICATION, nsIAudioManager::FORCE_NONE); } SwitchProfileData(DEVICE_BLUETOOTH, false); } } else if (!strcmp(aTopic, BLUETOOTH_A2DP_STATUS_CHANGED_ID)) { if (audioState == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE && sA2dpSwitchDone) { MessageLoop::current()->PostDelayedTask( FROM_HERE, NewRunnableFunction(&ProcessDelayedA2dpRoute, audioState, aAddress), 1000); sA2dpSwitchDone = false; SwitchProfileData(DEVICE_BLUETOOTH, false); } else { AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, audioState, aAddress.get()); String8 cmd("bluetooth_enabled=true"); AudioSystem::setParameters(0, cmd); cmd.setTo("A2dpSuspended=false"); AudioSystem::setParameters(0, cmd); sA2dpSwitchDone = true; SwitchProfileData(DEVICE_BLUETOOTH, true); #if ANDROID_VERSION >= 17 if (AudioSystem::getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_NO_BT_A2DP) { SetForceForUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_NONE); } #endif } sBluetoothA2dpEnabled = audioState == AUDIO_POLICY_DEVICE_STATE_AVAILABLE; } else if (!strcmp(aTopic, BLUETOOTH_HFP_STATUS_CHANGED_ID)) { AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, audioState, aAddress.get()); AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, audioState, aAddress.get()); } else if (!strcmp(aTopic, BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID)) { String8 cmd; BluetoothHfpManagerBase* hfp = static_cast<BluetoothHfpManagerBase*>(aSubject); if (hfp->IsNrecEnabled()) { cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=on"); AudioSystem::setParameters(0, cmd); } else { cmd.setTo("bt_headset_name=<unknown>;bt_headset_nrec=off"); AudioSystem::setParameters(0, cmd); } } #endif }
nsresult BluetoothServiceBluedroid::StopInternal(BluetoothReplyRunnable* aRunnable) { MOZ_ASSERT(NS_IsMainThread()); BluetoothProfileManagerBase* profile; profile = BluetoothHfpManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } else { profile->Reset(); } profile = BluetoothOppManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } profile = BluetoothA2dpManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } else { profile->Reset(); } profile = BluetoothHidManager::Get(); NS_ENSURE_TRUE(profile, NS_ERROR_FAILURE); if (profile->IsConnected()) { profile->Disconnect(nullptr); } else { profile->Reset(); } // aRunnable will be a nullptr during starup and shutdown if(aRunnable) { sChangeAdapterStateRunnableArray.AppendElement(aRunnable); } nsresult ret = StopGonkBluetooth(); if (NS_FAILED(ret)) { BluetoothService::AcknowledgeToggleBt(true); // Reject Promise if(aRunnable) { DispatchReplyError(aRunnable, NS_LITERAL_STRING("StopBluetoothError")); sChangeAdapterStateRunnableArray.RemoveElement(aRunnable); } BT_LOGR("Error"); } return ret; }