1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "BluetoothService.h"
11 #include "BluetoothCommon.h"
12 #include "BluetoothA2dpManager.h"
13 #include "BluetoothHfpManager.h"
14 #include "BluetoothHidManager.h"
15 #include "BluetoothManager.h"
16 #include "BluetoothOppManager.h"
17 #include "BluetoothParent.h"
18 #if defined(MOZ_B2G_BT_BLUEDROID)
19 #include "BluetoothPbapManager.h"
20 #include "BluetoothMapSmsManager.h"
22 #include "BluetoothReplyRunnable.h"
23 #include "BluetoothServiceChildProcess.h"
24 #include "BluetoothUtils.h"
27 #include "mozilla/ClearOnShutdown.h"
28 #include "mozilla/Services.h"
29 #include "mozilla/StaticPtr.h"
30 #include "mozilla/unused.h"
31 #include "mozilla/dom/ContentParent.h"
32 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
33 #include "mozilla/dom/ipc/BlobChild.h"
34 #include "mozilla/dom/ipc/BlobParent.h"
35 #include "mozilla/ipc/UnixSocket.h"
36 #include "nsContentUtils.h"
37 #include "nsIObserverService.h"
38 #include "nsISettingsService.h"
39 #include "nsISystemMessagesInternal.h"
41 #include "nsServiceManagerUtils.h"
43 #include "mozilla/dom/SettingChangeNotificationBinding.h"
45 #if defined(MOZ_WIDGET_GONK)
46 #include "cutils/properties.h"
49 #if defined(MOZ_B2G_BT)
50 #if defined(MOZ_B2G_BT_BLUEZ)
53 * MOZ_B2G_BT and MOZ_B2G_BT_BLUEZ are both defined.
55 #include "BluetoothDBusService.h"
56 #elif defined(MOZ_B2G_BT_BLUEDROID)
59 * MOZ_B2G_BT and MOZ_B2G_BT_BLUEDROID are both defined;
60 * MOZ_B2G_BLUEZ or MOZ_B2G_DAEMON are not defined.
62 #include "BluetoothServiceBluedroid.h"
63 #elif defined(MOZ_B2G_BT_DAEMON)
65 * B2G Bluetooth daemon:
66 * MOZ_B2G_BT, MOZ_B2G_BLUEDROID and MOZ_B2G_BT_DAEMON are defined;
67 * MOZ_B2G_BLUEZ is not defined.
69 #include "BluetoothServiceBluedroid.h"
71 #elif defined(MOZ_BLUETOOTH_DBUS)
74 * MOZ_B2G_BT is not defined; MOZ_BLUETOOTH_DBUS is defined.
76 #include "BluetoothDBusService.h"
81 #define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
82 #define BLUETOOTH_ENABLED_SETTING "bluetooth.enabled"
83 #define BLUETOOTH_DEBUGGING_SETTING "bluetooth.debugging.enabled"
85 #define PROP_BLUETOOTH_ENABLED "bluetooth.isEnabled"
87 #define DEFAULT_SHUTDOWN_TIMER_MS 5000
89 bool gBluetoothDebugFlag
= false;
91 using namespace mozilla
;
92 using namespace mozilla::dom
;
93 USING_BLUETOOTH_NAMESPACE
97 StaticRefPtr
<BluetoothService
> sBluetoothService
;
99 bool sInShutdown
= false;
100 bool sToggleInProgress
= false;
105 return XRE_GetProcessType() == GeckoProcessType_Default
;
109 ShutdownTimeExceeded(nsITimer
* aTimer
, void* aClosure
)
111 MOZ_ASSERT(NS_IsMainThread());
112 *static_cast<bool*>(aClosure
) = true;
116 GetAllBluetoothActors(InfallibleTArray
<BluetoothParent
*>& aActors
)
118 MOZ_ASSERT(NS_IsMainThread());
119 MOZ_ASSERT(aActors
.IsEmpty());
121 nsAutoTArray
<ContentParent
*, 20> contentActors
;
122 ContentParent::GetAll(contentActors
);
124 for (uint32_t contentIndex
= 0;
125 contentIndex
< contentActors
.Length();
127 MOZ_ASSERT(contentActors
[contentIndex
]);
129 AutoInfallibleTArray
<PBluetoothParent
*, 5> bluetoothActors
;
130 contentActors
[contentIndex
]->ManagedPBluetoothParent(bluetoothActors
);
132 for (uint32_t bluetoothIndex
= 0;
133 bluetoothIndex
< bluetoothActors
.Length();
135 MOZ_ASSERT(bluetoothActors
[bluetoothIndex
]);
137 BluetoothParent
* actor
=
138 static_cast<BluetoothParent
*>(bluetoothActors
[bluetoothIndex
]);
139 aActors
.AppendElement(actor
);
144 } // anonymous namespace
146 BluetoothService::ToggleBtAck::ToggleBtAck(bool aEnabled
)
151 BluetoothService::ToggleBtAck::Run()
153 BluetoothService::AcknowledgeToggleBt(mEnabled
);
158 class BluetoothService::StartupTask MOZ_FINAL
: public nsISettingsServiceCallback
163 NS_IMETHOD
Handle(const nsAString
& aName
, JS::Handle
<JS::Value
> aResult
)
165 MOZ_ASSERT(NS_IsMainThread());
167 if (!aResult
.isBoolean()) {
168 BT_WARNING("Setting for '" BLUETOOTH_ENABLED_SETTING
"' is not a boolean!");
172 // It is theoretically possible to shut down before the first settings check
173 // has completed (though extremely unlikely).
174 if (sBluetoothService
) {
175 return sBluetoothService
->HandleStartupSettingsCheck(aResult
.toBoolean());
181 NS_IMETHOD
HandleError(const nsAString
& aName
)
183 BT_WARNING("Unable to get value for '" BLUETOOTH_ENABLED_SETTING
"'");
188 NS_IMPL_ISUPPORTS(BluetoothService::StartupTask
, nsISettingsServiceCallback
);
190 NS_IMPL_ISUPPORTS(BluetoothService
, nsIObserver
)
193 BluetoothService::IsToggling() const
195 return sToggleInProgress
;
198 BluetoothService::~BluetoothService()
204 RemoveObserversExceptBluetoothManager
205 (const nsAString
& key
,
206 nsAutoPtr
<BluetoothSignalObserverList
>& value
,
209 if (!key
.EqualsLiteral(KEY_MANAGER
)) {
210 return PL_DHASH_REMOVE
;
213 return PL_DHASH_NEXT
;
218 BluetoothService::Create()
220 #if defined(MOZ_B2G_BT)
221 if (!IsMainProcess()) {
222 return BluetoothServiceChildProcess::Create();
225 #if defined(MOZ_B2G_BT_BLUEZ)
226 return new BluetoothDBusService();
227 #elif defined(MOZ_B2G_BT_BLUEDROID)
228 return new BluetoothServiceBluedroid();
229 #elif defined(MOZ_B2G_BT_DAEMON)
230 return new BluetoothServiceBluedroid();
232 #elif defined(MOZ_BLUETOOTH_DBUS)
233 return new BluetoothDBusService();
236 BT_WARNING("No platform support for bluetooth!");
241 BluetoothService::Init()
243 MOZ_ASSERT(NS_IsMainThread());
245 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
246 NS_ENSURE_TRUE(obs
, false);
248 if (NS_FAILED(obs
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
,
250 BT_WARNING("Failed to add shutdown observer!");
254 // Only the main process should observe bluetooth settings changes.
255 if (IsMainProcess() &&
256 NS_FAILED(obs
->AddObserver(this, MOZSETTINGS_CHANGED_ID
, false))) {
257 BT_WARNING("Failed to add settings change observer!");
265 BluetoothService::Cleanup()
267 MOZ_ASSERT(NS_IsMainThread());
269 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
271 (NS_FAILED(obs
->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) ||
272 NS_FAILED(obs
->RemoveObserver(this, MOZSETTINGS_CHANGED_ID
)))) {
273 BT_WARNING("Can't unregister observers!");
278 BluetoothService::RegisterBluetoothSignalHandler(
279 const nsAString
& aNodeName
,
280 BluetoothSignalObserver
* aHandler
)
282 MOZ_ASSERT(NS_IsMainThread());
283 MOZ_ASSERT(aHandler
);
285 BT_LOGD("[S] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aNodeName
).get());
287 BluetoothSignalObserverList
* ol
;
288 if (!mBluetoothSignalObserverTable
.Get(aNodeName
, &ol
)) {
289 ol
= new BluetoothSignalObserverList();
290 mBluetoothSignalObserverTable
.Put(aNodeName
, ol
);
293 ol
->AddObserver(aHandler
);
297 BluetoothService::UnregisterBluetoothSignalHandler(
298 const nsAString
& aNodeName
,
299 BluetoothSignalObserver
* aHandler
)
301 MOZ_ASSERT(NS_IsMainThread());
302 MOZ_ASSERT(aHandler
);
304 BT_LOGD("[S] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aNodeName
).get());
306 BluetoothSignalObserverList
* ol
;
307 if (mBluetoothSignalObserverTable
.Get(aNodeName
, &ol
)) {
308 ol
->RemoveObserver(aHandler
);
309 // We shouldn't have duplicate instances in the ObserverList, but there's
310 // no appropriate way to do duplication check while registering, so
311 // assertions are added here.
312 MOZ_ASSERT(!ol
->RemoveObserver(aHandler
));
313 if (ol
->Length() == 0) {
314 mBluetoothSignalObserverTable
.Remove(aNodeName
);
318 BT_WARNING("Node was never registered!");
323 RemoveAllSignalHandlers(const nsAString
& aKey
,
324 nsAutoPtr
<BluetoothSignalObserverList
>& aData
,
327 BluetoothSignalObserver
* handler
= static_cast<BluetoothSignalObserver
*>(aUserArg
);
328 aData
->RemoveObserver(handler
);
329 // We shouldn't have duplicate instances in the ObserverList, but there's
330 // no appropriate way to do duplication check while registering, so
331 // assertions are added here.
332 MOZ_ASSERT(!aData
->RemoveObserver(handler
));
333 return aData
->Length() ? PL_DHASH_NEXT
: PL_DHASH_REMOVE
;
337 BluetoothService::UnregisterAllSignalHandlers(BluetoothSignalObserver
* aHandler
)
339 MOZ_ASSERT(NS_IsMainThread());
340 MOZ_ASSERT(aHandler
);
342 mBluetoothSignalObserverTable
.Enumerate(RemoveAllSignalHandlers
, aHandler
);
346 BluetoothService::DistributeSignal(const BluetoothSignal
& aSignal
)
348 MOZ_ASSERT(NS_IsMainThread());
350 if (aSignal
.path().EqualsLiteral(KEY_LOCAL_AGENT
)) {
353 } else if (aSignal
.path().EqualsLiteral(KEY_REMOTE_AGENT
)) {
358 BluetoothSignalObserverList
* ol
;
359 if (!mBluetoothSignalObserverTable
.Get(aSignal
.path(), &ol
)) {
361 nsAutoCString
msg("No observer registered for path ");
362 msg
.Append(NS_ConvertUTF16toUTF8(aSignal
.path()));
363 BT_WARNING(msg
.get());
367 MOZ_ASSERT(ol
->Length());
368 ol
->Broadcast(aSignal
);
372 BluetoothService::StartBluetooth(bool aIsStartup
)
374 MOZ_ASSERT(NS_IsMainThread());
377 // Don't try to start if we're already shutting down.
378 MOZ_ASSERT(false, "Start called while in shutdown!");
379 return NS_ERROR_FAILURE
;
382 mAdapterAddedReceived
= false;
384 /* When IsEnabled() is true, we don't switch on Bluetooth but we still
385 * send ToggleBtAck task. One special case happens at startup stage. At
386 * startup, the initialization of BluetoothService still has to be done
387 * even if Bluetooth is already enabled.
389 * Please see bug 892392 for more information.
391 if (aIsStartup
|| !sBluetoothService
->IsEnabled()) {
392 // Switch Bluetooth on
393 if (NS_FAILED(sBluetoothService
->StartInternal())) {
394 BT_WARNING("Bluetooth service failed to start!");
397 BT_WARNING("Bluetooth has already been enabled before.");
398 nsRefPtr
<nsRunnable
> runnable
= new BluetoothService::ToggleBtAck(true);
399 if (NS_FAILED(NS_DispatchToMainThread(runnable
))) {
400 BT_WARNING("Failed to dispatch to main thread!");
408 BluetoothService::StopBluetooth(bool aIsStartup
)
410 MOZ_ASSERT(NS_IsMainThread());
412 static BluetoothProfileManagerBase
* sProfiles
[] = {
413 BluetoothHfpManager::Get(),
414 BluetoothA2dpManager::Get(),
415 BluetoothOppManager::Get(),
416 #if defined(MOZ_B2G_BT_BLUEDROID)
417 BluetoothPbapManager::Get(),
418 BluetoothMapSmsManager::Get(),
420 BluetoothHidManager::Get()
423 // Disconnect all connected profiles
424 for (uint8_t i
= 0; i
< MOZ_ARRAY_LENGTH(sProfiles
); i
++) {
425 nsCString profileName
;
426 sProfiles
[i
]->GetName(profileName
);
428 if (NS_WARN_IF(!sProfiles
[i
])) {
429 BT_LOGR("Profile manager [%s] is null", profileName
.get());
430 return NS_ERROR_FAILURE
;
433 if (sProfiles
[i
]->IsConnected()) {
434 sProfiles
[i
]->Disconnect(nullptr);
435 } else if (!profileName
.EqualsLiteral("OPP") &&
436 !profileName
.EqualsLiteral("PBAP") &&
437 !profileName
.EqualsLiteral("MapSms")) {
438 sProfiles
[i
]->Reset();
442 mAdapterAddedReceived
= false;
444 /* When IsEnabled() is false, we don't switch off Bluetooth but we still
445 * send ToggleBtAck task. One special case happens at startup stage. At
446 * startup, the initialization of BluetoothService still has to be done
447 * even if Bluetooth is disabled.
449 * Please see bug 892392 for more information.
451 if (aIsStartup
|| sBluetoothService
->IsEnabled()) {
452 // Switch Bluetooth off
453 if (NS_FAILED(sBluetoothService
->StopInternal())) {
454 BT_WARNING("Bluetooth service failed to stop!");
457 BT_WARNING("Bluetooth has already been enabled/disabled before.");
458 nsRefPtr
<nsRunnable
> runnable
= new BluetoothService::ToggleBtAck(false);
459 if (NS_FAILED(NS_DispatchToMainThread(runnable
))) {
460 BT_WARNING("Failed to dispatch to main thread!");
468 BluetoothService::StartStopBluetooth(bool aStart
, bool aIsStartup
)
472 rv
= StartBluetooth(aIsStartup
);
474 rv
= StopBluetooth(aIsStartup
);
480 BluetoothService::SetEnabled(bool aEnabled
)
482 MOZ_ASSERT(NS_IsMainThread());
484 AutoInfallibleTArray
<BluetoothParent
*, 10> childActors
;
485 GetAllBluetoothActors(childActors
);
487 for (uint32_t index
= 0; index
< childActors
.Length(); index
++) {
488 unused
<< childActors
[index
]->SendEnabled(aEnabled
);
493 * Remove all handlers except BluetoothManager when turning off bluetooth
494 * since it is possible that the event 'onAdapterAdded' would be fired after
495 * BluetoothManagers of child process are registered. Please see Bug 827759
498 mBluetoothSignalObserverTable
.Enumerate(
499 RemoveObserversExceptBluetoothManager
, nullptr);
503 * mEnabled: real status of bluetooth
504 * aEnabled: expected status of bluetooth
506 if (mEnabled
== aEnabled
) {
507 BT_WARNING("Bluetooth has already been enabled/disabled before "
508 "or the toggling is failed.");
515 BluetoothService::HandleStartup()
517 MOZ_ASSERT(NS_IsMainThread());
518 MOZ_ASSERT(!sToggleInProgress
);
520 nsCOMPtr
<nsISettingsService
> settings
=
521 do_GetService("@mozilla.org/settingsService;1");
522 NS_ENSURE_TRUE(settings
, NS_ERROR_UNEXPECTED
);
524 nsCOMPtr
<nsISettingsServiceLock
> settingsLock
;
525 nsresult rv
= settings
->CreateLock(nullptr, getter_AddRefs(settingsLock
));
526 NS_ENSURE_SUCCESS(rv
, rv
);
528 nsRefPtr
<StartupTask
> callback
= new StartupTask();
529 rv
= settingsLock
->Get(BLUETOOTH_ENABLED_SETTING
, callback
);
530 NS_ENSURE_SUCCESS(rv
, rv
);
532 sToggleInProgress
= true;
537 BluetoothService::HandleStartupSettingsCheck(bool aEnable
)
539 MOZ_ASSERT(NS_IsMainThread());
540 return StartStopBluetooth(aEnable
, true);
544 BluetoothService::HandleSettingsChanged(nsISupports
* aSubject
)
546 MOZ_ASSERT(NS_IsMainThread());
548 // The string that we're interested in will be a JSON string that looks like:
549 // {"key":"bluetooth.enabled","value":true}
551 RootedDictionary
<SettingChangeNotification
> setting(nsContentUtils::RootingCx());
552 if (!WrappedJSToDictionary(aSubject
, setting
)) {
555 if (setting
.mKey
.EqualsASCII(BLUETOOTH_DEBUGGING_SETTING
)) {
556 if (!setting
.mValue
.isBoolean()) {
557 MOZ_ASSERT(false, "Expecting a boolean for 'bluetooth.debugging.enabled'!");
558 return NS_ERROR_UNEXPECTED
;
561 SWITCH_BT_DEBUG(setting
.mValue
.toBoolean());
566 // Second, check if the string is BLUETOOTH_ENABLED_SETTING
567 if (!setting
.mKey
.EqualsASCII(BLUETOOTH_ENABLED_SETTING
)) {
570 if (!setting
.mValue
.isBoolean()) {
571 MOZ_ASSERT(false, "Expecting a boolean for 'bluetooth.enabled'!");
572 return NS_ERROR_UNEXPECTED
;
574 // Ignore bluetooth toggling request since toggling is already in progress.
575 if (sToggleInProgress
) {
576 BT_LOGR("Ignore bluetooth toggling request since toggling is already in progress");
580 sToggleInProgress
= true;
582 nsresult rv
= StartStopBluetooth(setting
.mValue
.toBoolean(), false);
583 NS_ENSURE_SUCCESS(rv
, rv
);
589 BluetoothService::HandleShutdown()
591 MOZ_ASSERT(NS_IsMainThread());
593 // This is a two phase shutdown. First we notify all child processes that
594 // bluetooth is going away, and then we wait for them to acknowledge. Then we
595 // close down all the bluetooth machinery.
601 AutoInfallibleTArray
<BluetoothParent
*, 10> childActors
;
602 GetAllBluetoothActors(childActors
);
604 if (!childActors
.IsEmpty()) {
605 // Notify child processes that they should stop using bluetooth now.
606 for (uint32_t index
= 0; index
< childActors
.Length(); index
++) {
607 childActors
[index
]->BeginShutdown();
610 // Create a timer to ensure that we don't wait forever for a child process
611 // or the bluetooth threads to finish. If we don't get a timer or can't use
612 // it for some reason then we skip all the waiting entirely since we really
613 // can't afford to hang on shutdown.
614 nsCOMPtr
<nsITimer
> timer
= do_CreateInstance(NS_TIMER_CONTRACTID
);
618 bool timeExceeded
= false;
620 if (NS_SUCCEEDED(timer
->InitWithFuncCallback(ShutdownTimeExceeded
,
622 DEFAULT_SHUTDOWN_TIMER_MS
,
623 nsITimer::TYPE_ONE_SHOT
))) {
624 nsIThread
* currentThread
= NS_GetCurrentThread();
625 MOZ_ASSERT(currentThread
);
627 // Wait for those child processes to acknowledge.
628 while (!timeExceeded
&& !childActors
.IsEmpty()) {
629 if (!NS_ProcessNextEvent(currentThread
)) {
630 MOZ_ASSERT(false, "Something horribly wrong here!");
633 GetAllBluetoothActors(childActors
);
636 if (NS_FAILED(timer
->Cancel())) {
637 MOZ_CRASH("Failed to cancel shutdown timer, this will crash!");
641 MOZ_ASSERT(false, "Failed to initialize shutdown timer!");
646 if (IsEnabled() && NS_FAILED(StopBluetooth(false))) {
647 MOZ_ASSERT(false, "Failed to deliver stop message!");
655 BluetoothService::Get()
657 MOZ_ASSERT(NS_IsMainThread());
659 // If we already exist, exit early
660 if (sBluetoothService
) {
661 return sBluetoothService
;
664 // If we're in shutdown, don't create a new instance
666 BT_WARNING("BluetoothService can't be created during shutdown");
670 // Create new instance, register, return
671 sBluetoothService
= BluetoothService::Create();
672 NS_ENSURE_TRUE(sBluetoothService
, nullptr);
674 if (!sBluetoothService
->Init()) {
675 sBluetoothService
->Cleanup();
679 ClearOnShutdown(&sBluetoothService
);
680 return sBluetoothService
;
684 BluetoothService::Observe(nsISupports
* aSubject
, const char* aTopic
,
685 const char16_t
* aData
)
687 MOZ_ASSERT(NS_IsMainThread());
689 if (!strcmp(aTopic
, "profile-after-change")) {
690 return HandleStartup();
693 if (!strcmp(aTopic
, MOZSETTINGS_CHANGED_ID
)) {
694 return HandleSettingsChanged(aSubject
);
697 if (!strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
698 return HandleShutdown();
701 MOZ_ASSERT(false, "BluetoothService got unexpected topic!");
702 return NS_ERROR_UNEXPECTED
;
706 BluetoothService::TryFiringAdapterAdded()
708 MOZ_ASSERT(NS_IsMainThread());
710 if (IsToggling() || !mAdapterAddedReceived
) {
714 BluetoothSignal
signal(NS_LITERAL_STRING("AdapterAdded"),
715 NS_LITERAL_STRING(KEY_MANAGER
), true);
716 DistributeSignal(signal
);
720 BluetoothService::AdapterAddedReceived()
722 MOZ_ASSERT(NS_IsMainThread());
724 mAdapterAddedReceived
= true;
728 BluetoothService::Notify(const BluetoothSignal
& aData
)
730 nsString type
= NS_LITERAL_STRING("bluetooth-pairing-request");
732 AutoSafeJSContext cx
;
733 JS::Rooted
<JSObject
*> obj(cx
, JS_NewObject(cx
, nullptr, JS::NullPtr(),
735 NS_ENSURE_TRUE_VOID(obj
);
737 if (!SetJsObject(cx
, aData
.value(), obj
)) {
738 BT_WARNING("Failed to set properties of system message!");
742 BT_LOGD("[S] %s: %s", __FUNCTION__
, NS_ConvertUTF16toUTF8(aData
.name()).get());
744 if (aData
.name().EqualsLiteral("RequestConfirmation")) {
745 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 4,
746 "RequestConfirmation: Wrong length of parameters");
747 } else if (aData
.name().EqualsLiteral("RequestPinCode")) {
748 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 3,
749 "RequestPinCode: Wrong length of parameters");
750 } else if (aData
.name().EqualsLiteral("RequestPasskey")) {
751 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 3,
752 "RequestPinCode: Wrong length of parameters");
753 } else if (aData
.name().EqualsLiteral("Cancel")) {
754 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 0,
755 "Cancel: Wrong length of parameters");
756 type
.AssignLiteral("bluetooth-cancel");
757 } else if (aData
.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID
)) {
758 MOZ_ASSERT(aData
.value().get_ArrayOfBluetoothNamedValue().Length() == 1,
759 "pairedstatuschanged: Wrong length of parameters");
760 type
.AssignLiteral("bluetooth-pairedstatuschanged");
762 nsCString warningMsg
;
763 warningMsg
.AssignLiteral("Not handling service signal: ");
764 warningMsg
.Append(NS_ConvertUTF16toUTF8(aData
.name()));
765 BT_WARNING(warningMsg
.get());
769 nsCOMPtr
<nsISystemMessagesInternal
> systemMessenger
=
770 do_GetService("@mozilla.org/system-message-internal;1");
771 NS_ENSURE_TRUE_VOID(systemMessenger
);
773 JS::Rooted
<JS::Value
> value(cx
, JS::ObjectValue(*obj
));
774 systemMessenger
->BroadcastMessage(type
, value
,
775 JS::UndefinedHandleValue
);
779 BluetoothService::AcknowledgeToggleBt(bool aEnabled
)
781 MOZ_ASSERT(NS_IsMainThread());
783 #if defined(MOZ_WIDGET_GONK)
784 // This is requested in Bug 836516. With settings this property, WLAN
785 // firmware could be aware of Bluetooth has been turned on/off, so that
786 // the mechanism of handling coexistence of WIFI and Bluetooth could be
789 // In the future, we may have our own way instead of setting a system
790 // property to let firmware developers be able to sense that Bluetooth
792 if (property_set(PROP_BLUETOOTH_ENABLED
, aEnabled
? "true" : "false") != 0) {
793 BT_WARNING("Failed to set bluetooth enabled property");
798 sBluetoothService
= nullptr;
802 NS_ENSURE_TRUE_VOID(sBluetoothService
);
804 sBluetoothService
->CompleteToggleBt(aEnabled
);
808 BluetoothService::CompleteToggleBt(bool aEnabled
)
810 MOZ_ASSERT(NS_IsMainThread());
812 // Update |mEnabled| of |BluetoothService| object since
813 // |StartInternal| and |StopInternal| have been already
815 SetEnabled(aEnabled
);
816 sToggleInProgress
= false;
818 nsAutoString signalName
;
819 signalName
= aEnabled
? NS_LITERAL_STRING("Enabled")
820 : NS_LITERAL_STRING("Disabled");
821 BluetoothSignal
signal(signalName
, NS_LITERAL_STRING(KEY_MANAGER
), true);
822 DistributeSignal(signal
);
824 // Event 'AdapterAdded' has to be fired after firing 'Enabled'
825 TryFiringAdapterAdded();