diff --git a/CLOBBER b/CLOBBER index d4cdfaff33de..37b2285a1c32 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,9 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Merge day clobber \ No newline at end of file +Bug 1105308 - Cleanup BluetoothUtils.{cpp,h} + +This patch set moves some files around and requires a rebuild +of the build system's dependency information. + +Merge day clobber diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 3149c3038f12..ab9b5ebce8f6 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index ad8196404bb1..fa56509b363c 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + @@ -97,7 +97,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 12d14140982b..815ac732a393 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 966506b445ef..58ee7a860bdd 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index ad8196404bb1..fa56509b363c 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + @@ -97,7 +97,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 794a4ac6f703..4e7975e007a2 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index af9ca23883e1..a0ef726996c2 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 802938f5e75f..f143f8477ea5 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "eb65c4355e0a16dc5cd203c5c007fd7e3bf0e4b2", + "revision": "c65e0f2f00a05a78a57eecb1185c6420b7984d36", "repo_path": "integration/gaia-central" } diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 14d96f08af35..5be33da37257 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 0d8c274fec0f..65461620cff2 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 28dbbedf4eb5..ae6db6eae670 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index de4c0a9bb513..0af5d9c33d8f 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.cpp b/dom/bluetooth/BluetoothUtils.cpp similarity index 82% rename from dom/bluetooth/bluedroid/BluetoothUtils.cpp rename to dom/bluetooth/BluetoothUtils.cpp index 7054cb6f13b5..c52ff5b58a77 100644 --- a/dom/bluetooth/bluedroid/BluetoothUtils.cpp +++ b/dom/bluetooth/BluetoothUtils.cpp @@ -4,33 +4,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "base/basictypes.h" - +#include "BluetoothUtils.h" #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" -#include "BluetoothServiceBluedroid.h" -#include "BluetoothUtils.h" #include "jsapi.h" -#include "mozilla/Scoped.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "nsContentUtils.h" -#include "nsIScriptContext.h" #include "nsISystemMessagesInternal.h" -#include "nsString.h" -#include "nsTArray.h" #include "nsServiceManagerUtils.h" BEGIN_BLUETOOTH_NAMESPACE -uint16_t -UuidToServiceClassInt(const BluetoothUuid& mUuid) -{ - // extract short UUID 0000xxxx-0000-1000-8000-00805f9b34fb - uint16_t shortUuid; - memcpy(&shortUuid, mUuid.mUuid + 2, sizeof(uint16_t)); - return ntohs(shortUuid); -} - bool SetJsObject(JSContext* aContext, const BluetoothValue& aValue, @@ -123,6 +107,37 @@ BroadcastSystemMessage(const nsAString& aType, return true; } +bool +BroadcastSystemMessage(const nsAString& aType, + const InfallibleTArray& aData) +{ + mozilla::AutoSafeJSContext cx; + NS_ASSERTION(!::JS_IsExceptionPending(cx), + "Shouldn't get here when an exception is pending!"); + + JS::Rooted obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), + JS::NullPtr())); + if (!obj) { + BT_WARNING("Failed to new JSObject for system message!"); + return false; + } + + if (!SetJsObject(cx, aData, obj)) { + BT_WARNING("Failed to set properties of system message!"); + return false; + } + + nsCOMPtr systemMessenger = + do_GetService("@mozilla.org/system-message-internal;1"); + NS_ENSURE_TRUE(systemMessenger, false); + + JS::Rooted value(cx, JS::ObjectValue(*obj)); + systemMessenger->BroadcastMessage(aType, value, + JS::UndefinedHandleValue); + + return true; +} + void DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, const BluetoothValue& aValue, diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.h b/dom/bluetooth/BluetoothUtils.h similarity index 82% rename from dom/bluetooth/bluedroid/BluetoothUtils.h rename to dom/bluetooth/BluetoothUtils.h index 6d141a44e31e..41449762e551 100644 --- a/dom/bluetooth/bluedroid/BluetoothUtils.h +++ b/dom/bluetooth/BluetoothUtils.h @@ -4,8 +4,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef mozilla_dom_bluetooth_bluetoothutils_h__ -#define mozilla_dom_bluetooth_bluetoothutils_h__ +#ifndef mozilla_dom_bluetooth_bluetoothutils_h +#define mozilla_dom_bluetooth_bluetoothutils_h #include "BluetoothCommon.h" #include "js/TypeDecls.h" @@ -16,9 +16,6 @@ class BluetoothNamedValue; class BluetoothValue; class BluetoothReplyRunnable; -uint16_t -UuidToServiceClassInt(const BluetoothUuid& mUuid); - bool SetJsObject(JSContext* aContext, const BluetoothValue& aValue, @@ -28,6 +25,10 @@ bool BroadcastSystemMessage(const nsAString& aType, const BluetoothValue& aData); +bool +BroadcastSystemMessage(const nsAString& aType, + const InfallibleTArray& aData); + void DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, const BluetoothValue& aValue, diff --git a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp index fd73749c6f6e..81ead9071a5b 100644 --- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp +++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp @@ -1098,6 +1098,15 @@ BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable) { } +uint16_t +BluetoothServiceBluedroid::UuidToServiceClassInt(const BluetoothUuid& mUuid) +{ + // extract short UUID 0000xxxx-0000-1000-8000-00805f9b34fb + uint16_t shortUuid; + memcpy(&shortUuid, mUuid.mUuid + 2, sizeof(uint16_t)); + return ntohs(shortUuid); +} + // // Bluetooth notifications // diff --git a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h index 1979fcc34a4a..f9f3c0dc00f7 100644 --- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h +++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h @@ -221,6 +221,8 @@ protected: static ControlPlayStatus PlayStatusStringToControlPlayStatus( const nsAString& aPlayStatus); + + uint16_t UuidToServiceClassInt(const BluetoothUuid& mUuid); }; END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluez/BluetoothDBusService.cpp b/dom/bluetooth/bluez/BluetoothDBusService.cpp index 838e62941e32..f4abdef747fc 100644 --- a/dom/bluetooth/bluez/BluetoothDBusService.cpp +++ b/dom/bluetooth/bluez/BluetoothDBusService.cpp @@ -392,6 +392,37 @@ BluetoothDBusService::~BluetoothDBusService() sGetPropertyMonitor = nullptr; } +static nsString +GetObjectPathFromAddress(const nsAString& aAdapterPath, + const nsAString& aDeviceAddress) +{ + // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, + // and the adapter path would be the first part of the object path, according + // to the example above, it's /org/bluez/2906/hci0. + nsString devicePath(aAdapterPath); + devicePath.AppendLiteral("/dev_"); + devicePath.Append(aDeviceAddress); + devicePath.ReplaceChar(':', '_'); + return devicePath; +} + +static nsString +GetAddressFromObjectPath(const nsAString& aObjectPath) +{ + // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, + // and the adapter path would be the first part of the object path, according + // to the example above, it's /org/bluez/2906/hci0. + nsString address(aObjectPath); + int addressHead = address.RFind("/") + 5; + + MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == (int)address.Length()); + + address.Cut(0, addressHead); + address.ReplaceChar('_', ':'); + + return address; +} + static bool GetConnectedDevicesFilter(const BluetoothValue& aValue) { diff --git a/dom/bluetooth/bluez/BluetoothHfpManager.cpp b/dom/bluetooth/bluez/BluetoothHfpManager.cpp index e6b3e5c0fd17..9460d11b361c 100644 --- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp +++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp @@ -690,6 +690,28 @@ BluetoothHfpManager::HandleShutdown() sBluetoothHfpManager = nullptr; } +void +BluetoothHfpManager::ParseAtCommand(const nsACString& aAtCommand, + const int aStart, + nsTArray& aRetValues) +{ + int length = aAtCommand.Length(); + int begin = aStart; + + for (int i = aStart; i < length; ++i) { + // Use ',' as separator + if (aAtCommand[i] == ',') { + nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin)); + aRetValues.AppendElement(tmp); + + begin = i + 1; + } + } + + nsCString tmp(nsDependentCSubstring(aAtCommand, begin)); + aRetValues.AppendElement(tmp); +} + // Virtual function of class SocketConsumer void BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket, diff --git a/dom/bluetooth/bluez/BluetoothHfpManager.h b/dom/bluetooth/bluez/BluetoothHfpManager.h index 2de35b57a22f..2a96fec639a7 100644 --- a/dom/bluetooth/bluez/BluetoothHfpManager.h +++ b/dom/bluetooth/bluez/BluetoothHfpManager.h @@ -132,6 +132,9 @@ public: #endif private: + void ParseAtCommand(const nsACString& aAtCommand, const int aStart, + nsTArray& aRetValues); + class CloseScoTask; class GetVolumeTask; #ifdef MOZ_B2G_RIL diff --git a/dom/bluetooth/bluez/BluetoothUtils.cpp b/dom/bluetooth/bluez/BluetoothUtils.cpp deleted file mode 100644 index d4120082d9ea..000000000000 --- a/dom/bluetooth/bluez/BluetoothUtils.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "base/basictypes.h" - -#include "BluetoothReplyRunnable.h" -#include "BluetoothService.h" -#include "BluetoothUtils.h" -#include "jsapi.h" -#include "mozilla/Scoped.h" -#include "mozilla/dom/bluetooth/BluetoothTypes.h" -#include "nsContentUtils.h" -#include "nsIScriptContext.h" -#include "nsISystemMessagesInternal.h" -#include "nsString.h" -#include "nsTArray.h" -#include "nsServiceManagerUtils.h" - -BEGIN_BLUETOOTH_NAMESPACE - -bool -SetJsObject(JSContext* aContext, - const BluetoothValue& aValue, - JS::Handle aObj) -{ - MOZ_ASSERT(aContext && aObj); - - if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) { - BT_WARNING("SetJsObject: Invalid parameter type"); - return false; - } - - const nsTArray& arr = - aValue.get_ArrayOfBluetoothNamedValue(); - - for (uint32_t i = 0; i < arr.Length(); i++) { - JS::Rooted val(aContext); - const BluetoothValue& v = arr[i].value(); - - switch(v.type()) { - case BluetoothValue::TnsString: { - JSString* jsData = JS_NewUCStringCopyN(aContext, - v.get_nsString().BeginReading(), - v.get_nsString().Length()); - NS_ENSURE_TRUE(jsData, false); - val = STRING_TO_JSVAL(jsData); - break; - } - case BluetoothValue::Tuint32_t: - val = INT_TO_JSVAL(v.get_uint32_t()); - break; - case BluetoothValue::Tbool: - val = BOOLEAN_TO_JSVAL(v.get_bool()); - break; - default: - BT_WARNING("SetJsObject: Parameter is not handled"); - break; - } - - if (!JS_SetProperty(aContext, aObj, - NS_ConvertUTF16toUTF8(arr[i].name()).get(), - val)) { - BT_WARNING("Failed to set property"); - return false; - } - } - - return true; -} - -nsString -GetObjectPathFromAddress(const nsAString& aAdapterPath, - const nsAString& aDeviceAddress) -{ - // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, - // and the adapter path would be the first part of the object path, according - // to the example above, it's /org/bluez/2906/hci0. - nsString devicePath(aAdapterPath); - devicePath.AppendLiteral("/dev_"); - devicePath.Append(aDeviceAddress); - devicePath.ReplaceChar(':', '_'); - return devicePath; -} - -nsString -GetAddressFromObjectPath(const nsAString& aObjectPath) -{ - // The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1, - // and the adapter path would be the first part of the object path, according - // to the example above, it's /org/bluez/2906/hci0. - nsString address(aObjectPath); - int addressHead = address.RFind("/") + 5; - - MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == (int)address.Length()); - - address.Cut(0, addressHead); - address.ReplaceChar('_', ':'); - - return address; -} - -bool -BroadcastSystemMessage(const nsAString& aType, - const InfallibleTArray& aData) -{ - mozilla::AutoSafeJSContext cx; - NS_ASSERTION(!::JS_IsExceptionPending(cx), - "Shouldn't get here when an exception is pending!"); - - JS::Rooted obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), - JS::NullPtr())); - if (!obj) { - BT_WARNING("Failed to new JSObject for system message!"); - return false; - } - - if (!SetJsObject(cx, aData, obj)) { - BT_WARNING("Failed to set properties of system message!"); - return false; - } - - nsCOMPtr systemMessenger = - do_GetService("@mozilla.org/system-message-internal;1"); - NS_ENSURE_TRUE(systemMessenger, false); - - JS::Rooted value(cx, JS::ObjectValue(*obj)); - systemMessenger->BroadcastMessage(aType, value, - JS::UndefinedHandleValue); - - return true; -} - -void -DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, - const BluetoothValue& aValue, - const nsAString& aErrorStr) -{ - // Reply will be deleted by the runnable after running on main thread - BluetoothReply* reply; - if (!aErrorStr.IsEmpty()) { - nsString err(aErrorStr); - reply = new BluetoothReply(BluetoothReplyError(err)); - } else { - MOZ_ASSERT(aValue.type() != BluetoothValue::T__None); - reply = new BluetoothReply(BluetoothReplySuccess(aValue)); - } - - aRunnable->SetReply(reply); - if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } -} - -void -ParseAtCommand(const nsACString& aAtCommand, const int aStart, - nsTArray& aRetValues) -{ - int length = aAtCommand.Length(); - int begin = aStart; - - for (int i = aStart; i < length; ++i) { - // Use ',' as separator - if (aAtCommand[i] == ',') { - nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin)); - aRetValues.AppendElement(tmp); - - begin = i + 1; - } - } - - nsCString tmp(nsDependentCSubstring(aAtCommand, begin)); - aRetValues.AppendElement(tmp); -} - -void -DispatchStatusChangedEvent(const nsAString& aType, - const nsAString& aAddress, - bool aStatus) -{ - MOZ_ASSERT(NS_IsMainThread()); - - InfallibleTArray data; - data.AppendElement( - BluetoothNamedValue(NS_LITERAL_STRING("address"), nsString(aAddress))); - data.AppendElement( - BluetoothNamedValue(NS_LITERAL_STRING("status"), aStatus)); - - BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data); - - BluetoothService* bs = BluetoothService::Get(); - NS_ENSURE_TRUE_VOID(bs); - bs->DistributeSignal(signal); -} - -END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluez/BluetoothUtils.h b/dom/bluetooth/bluez/BluetoothUtils.h deleted file mode 100644 index 2156207f1d4f..000000000000 --- a/dom/bluetooth/bluez/BluetoothUtils.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_bluetooth_bluetoothutils_h__ -#define mozilla_dom_bluetooth_bluetoothutils_h__ - -#include "BluetoothCommon.h" -#include "js/TypeDecls.h" - -BEGIN_BLUETOOTH_NAMESPACE - -class BluetoothNamedValue; -class BluetoothValue; -class BluetoothReplyRunnable; - -bool -SetJsObject(JSContext* aContext, - const BluetoothValue& aValue, - JS::Handle aObj); - -nsString -GetObjectPathFromAddress(const nsAString& aAdapterPath, - const nsAString& aDeviceAddress); - -nsString -GetAddressFromObjectPath(const nsAString& aObjectPath); - -bool -BroadcastSystemMessage(const nsAString& aType, - const InfallibleTArray& aData); - -void -DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable, - const BluetoothValue& aValue, - const nsAString& aErrorStr); - -void -ParseAtCommand(const nsACString& aAtCommand, const int aStart, - nsTArray& aRetValues); - -void -DispatchStatusChangedEvent(const nsAString& aType, - const nsAString& aDeviceAddress, - bool aStatus); - -END_BLUETOOTH_NAMESPACE - -#endif diff --git a/dom/bluetooth/moz.build b/dom/bluetooth/moz.build index 585be1865c67..50c91a62ba17 100644 --- a/dom/bluetooth/moz.build +++ b/dom/bluetooth/moz.build @@ -15,6 +15,7 @@ if CONFIG['MOZ_B2G_BT']: 'BluetoothPropertyContainer.cpp', 'BluetoothReplyRunnable.cpp', 'BluetoothService.cpp', + 'BluetoothUtils.cpp', 'BluetoothUuid.cpp', 'ipc/BluetoothChild.cpp', 'ipc/BluetoothParent.cpp', @@ -36,8 +37,7 @@ if CONFIG['MOZ_B2G_BT']: 'bluez/BluetoothHfpManager.cpp', 'bluez/BluetoothOppManager.cpp', 'bluez/BluetoothSocket.cpp', - 'bluez/BluetoothUnixSocketConnector.cpp', - 'bluez/BluetoothUtils.cpp', + 'bluez/BluetoothUnixSocketConnector.cpp' ] LOCAL_INCLUDES += [ 'bluez', @@ -60,8 +60,7 @@ if CONFIG['MOZ_B2G_BT']: 'bluedroid/BluetoothServiceBluedroid.cpp', 'bluedroid/BluetoothSocket.cpp', 'bluedroid/BluetoothSocketHALInterface.cpp', - 'bluedroid/BluetoothSocketMessageWatcher.cpp', - 'bluedroid/BluetoothUtils.cpp', + 'bluedroid/BluetoothSocketMessageWatcher.cpp' ] LOCAL_INCLUDES += [ 'bluedroid', diff --git a/dom/bluetooth2/BluetoothService.cpp b/dom/bluetooth2/BluetoothService.cpp index a209a9fd09e9..1a95101cd14b 100644 --- a/dom/bluetooth2/BluetoothService.cpp +++ b/dom/bluetooth2/BluetoothService.cpp @@ -145,34 +145,7 @@ BluetoothService::ToggleBtAck::ToggleBtAck(bool aEnabled) NS_METHOD BluetoothService::ToggleBtAck::Run() { - MOZ_ASSERT(NS_IsMainThread()); - - // This is requested in Bug 836516. With settings this property, WLAN - // firmware could be aware of Bluetooth has been turned on/off, so that the - // mecahnism of handling coexistence of WIFI and Bluetooth could be started. - // - // In the future, we may have our own way instead of setting a system - // property to let firmware developers be able to sense that Bluetooth has - // been toggled. -#if defined(MOZ_WIDGET_GONK) - if (property_set(PROP_BLUETOOTH_ENABLED, mEnabled ? "true" : "false") != 0) { - BT_WARNING("Failed to set bluetooth enabled property"); - } -#endif - - NS_ENSURE_TRUE(sBluetoothService, NS_OK); - - if (sInShutdown) { - sBluetoothService = nullptr; - return NS_OK; - } - - // Update mEnabled of BluetoothService object since - // StartInternal/StopInternal have been already done. - sBluetoothService->SetEnabled(mEnabled); - sToggleInProgress = false; - - sBluetoothService->FireAdapterStateChanged(mEnabled); + BluetoothService::AcknowledgeToggleBt(mEnabled); return NS_OK; } @@ -709,3 +682,45 @@ BluetoothService::FireAdapterStateChanged(bool aEnable) NS_LITERAL_STRING(KEY_ADAPTER), value); DistributeSignal(signal); } + +void +BluetoothService::AcknowledgeToggleBt(bool aEnabled) +{ + MOZ_ASSERT(NS_IsMainThread()); + +#if defined(MOZ_WIDGET_GONK) + // This is requested in Bug 836516. With settings this property, WLAN + // firmware could be aware of Bluetooth has been turned on/off, so that the + // mecahnism of handling coexistence of WIFI and Bluetooth could be started. + // + // In the future, we may have our own way instead of setting a system + // property to let firmware developers be able to sense that Bluetooth has + // been toggled. + if (property_set(PROP_BLUETOOTH_ENABLED, aEnabled ? "true" : "false") != 0) { + BT_WARNING("Failed to set bluetooth enabled property"); + } +#endif + + if (sInShutdown) { + sBluetoothService = nullptr; + return; + } + + NS_ENSURE_TRUE_VOID(sBluetoothService); + + sBluetoothService->CompleteToggleBt(aEnabled); +} + +void +BluetoothService::CompleteToggleBt(bool aEnabled) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // Update |mEnabled| of |BluetoothService| object since + // |StartInternal| and |StopInternal| have been already + // done. + SetEnabled(aEnabled); + sToggleInProgress = false; + + FireAdapterStateChanged(aEnabled); +} diff --git a/dom/bluetooth2/BluetoothService.h b/dom/bluetooth2/BluetoothService.h index 8d72b492a0d2..56092a432865 100644 --- a/dom/bluetooth2/BluetoothService.h +++ b/dom/bluetooth2/BluetoothService.h @@ -315,6 +315,8 @@ public: bool IsToggling() const; + static void AcknowledgeToggleBt(bool aEnabled); + void FireAdapterStateChanged(bool aEnable); nsresult EnableDisable(bool aEnable, BluetoothReplyRunnable* aRunnable); @@ -392,6 +394,8 @@ protected: static BluetoothService* Create(); + void CompleteToggleBt(bool aEnabled); + typedef nsClassHashtable BluetoothSignalObserverTable; diff --git a/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.cpp b/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.cpp new file mode 100644 index 000000000000..506c776c11d1 --- /dev/null +++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.cpp @@ -0,0 +1,1240 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "BluetoothDaemonHandsfreeInterface.h" +#include "BluetoothDaemonSetupInterface.h" +#include "mozilla/unused.h" + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Handsfree module +// + +BluetoothHandsfreeNotificationHandler* + BluetoothDaemonHandsfreeModule::sNotificationHandler; + +void +BluetoothDaemonHandsfreeModule::SetNotificationHandler( + BluetoothHandsfreeNotificationHandler* aNotificationHandler) +{ + sNotificationHandler = aNotificationHandler; +} + +nsresult +BluetoothDaemonHandsfreeModule::Send(BluetoothDaemonPDU* aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + aRes->AddRef(); // Keep reference for response + return Send(aPDU, static_cast(aRes)); +} + +void +BluetoothDaemonHandsfreeModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData) +{ + static void (BluetoothDaemonHandsfreeModule::* const HandleOp[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = { + INIT_ARRAY_AT(0, &BluetoothDaemonHandsfreeModule::HandleRsp), + INIT_ARRAY_AT(1, &BluetoothDaemonHandsfreeModule::HandleNtf), + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + // Negate twice to map bit to 0/1 + unsigned long isNtf = !!(aHeader.mOpcode & 0x80); + + (this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData); +} + +// Commands +// + +nsresult +BluetoothDaemonHandsfreeModule::ConnectCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONNECT, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::DisconnectCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DISCONNECT, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::ConnectAudioCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONNECT_AUDIO, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::DisconnectAudioCmd( + const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DISCONNECT_AUDIO, + 6)); // Address + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::StartVoiceRecognitionCmd( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_START_VOICE_RECOGNITION, + 0)); // No payload + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::StopVoiceRecognitionCmd( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_STOP_VOICE_RECOGNITION, + 0)); // No payload + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::VolumeControlCmd( + BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_VOLUME_CONTROL, + 1 + // Volume type + 1)); // Volume + + nsresult rv = PackPDU(aType, PackConversion(aVolume), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::DeviceStatusNotificationCmd( + BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_DEVICE_STATUS_NOTIFICATION, + 1 + // Network state + 1 + // Service type + 1 + // Signal strength + 1)); // Battery level + + nsresult rv = PackPDU(aNtkState, aSvcType, + PackConversion(aSignal), + PackConversion(aBattChg), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::CopsResponseCmd( + const char* aCops, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_COPS_RESPONSE, + 0)); // Dynamically allocated + + nsresult rv = PackPDU(PackCString0(nsDependentCString(aCops)), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::CindResponseCmd( + int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CIND_RESPONSE, + 1 + // Service + 1 + // # Active + 1 + // # Held + 1 + // Call state + 1 + // Signal strength + 1 + // Roaming + 1)); // Battery level + + nsresult rv = PackPDU(PackConversion(aSvc), + PackConversion(aNumActive), + PackConversion(aNumHeld), + aCallSetupState, + PackConversion(aSignal), + PackConversion(aRoam), + PackConversion(aBattChg), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::FormattedAtResponseCmd( + const char* aRsp, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_FORMATTED_AT_RESPONSE, + 0)); // Dynamically allocated + + nsresult rv = PackPDU(PackCString0(nsDependentCString(aRsp)), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::AtResponseCmd( + BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_AT_RESPONSE, + 1 + // AT Response code + 1)); // Error code + + nsresult rv = PackPDU(aResponseCode, + PackConversion(aErrorCode), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::ClccResponseCmd( + int aIndex, + BluetoothHandsfreeCallDirection aDir, BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + NS_ConvertUTF16toUTF8 number(aNumber); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLCC_RESPONSE, + 1 + // Call index + 1 + // Call direction + 1 + // Call state + 1 + // Call mode + 1 + // Call MPTY + 1 + // Address type + number.Length() + 1)); // Number string + \0 + + nsresult rv = PackPDU(PackConversion(aIndex), + aDir, aState, aMode, aMpty, aType, + PackCString0(number), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +nsresult +BluetoothDaemonHandsfreeModule::PhoneStateChangeCmd( + int aNumActive, int aNumHeld, BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + NS_ConvertUTF16toUTF8 number(aNumber); + + nsAutoPtr pdu( + new BluetoothDaemonPDU(SERVICE_ID, OPCODE_PHONE_STATE_CHANGE, + 1 + // # Active + 1 + // # Held + 1 + // Call state + 1 + // Address type + number.Length() + 1)); // Number string + \0 + + nsresult rv = PackPDU(PackConversion(aNumActive), + PackConversion(aNumHeld), + aCallSetupState, aType, + PackCString0(NS_ConvertUTF16toUTF8(aNumber)), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return NS_OK; +} + +// Responses +// + +void +BluetoothDaemonHandsfreeModule::ErrorRsp( + const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, BluetoothHandsfreeResultHandler* aRes) +{ + ErrorRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::OnError, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ConnectRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::Connect, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DisconnectRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::Disconnect, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ConnectAudioRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::ConnectAudio, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DisconnectAudioRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::DisconnectAudio, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::StartVoiceRecognitionRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::StopVoiceRecognitionRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::VolumeControlRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::VolumeControl, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DeviceStatusNotificationRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::DeviceStatusNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CopsResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::CopsResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CindResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::CindResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::FormattedAtResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::AtResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::AtResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ClccResponseRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::ClccResponse, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::PhoneStateChangeRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::HandleRsp( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + static void (BluetoothDaemonHandsfreeModule::* const HandleRsp[])( + const BluetoothDaemonPDUHeader&, + BluetoothDaemonPDU&, + BluetoothHandsfreeResultHandler*) = { + INIT_ARRAY_AT(OPCODE_ERROR, + &BluetoothDaemonHandsfreeModule::ErrorRsp), + INIT_ARRAY_AT(OPCODE_CONNECT, + &BluetoothDaemonHandsfreeModule::ConnectRsp), + INIT_ARRAY_AT(OPCODE_DISCONNECT, + &BluetoothDaemonHandsfreeModule::DisconnectRsp), + INIT_ARRAY_AT(OPCODE_CONNECT_AUDIO, + &BluetoothDaemonHandsfreeModule::ConnectAudioRsp), + INIT_ARRAY_AT(OPCODE_DISCONNECT_AUDIO, + &BluetoothDaemonHandsfreeModule::DisconnectAudioRsp), + INIT_ARRAY_AT(OPCODE_START_VOICE_RECOGNITION, + &BluetoothDaemonHandsfreeModule::StartVoiceRecognitionRsp), + INIT_ARRAY_AT(OPCODE_STOP_VOICE_RECOGNITION, + &BluetoothDaemonHandsfreeModule::StopVoiceRecognitionRsp), + INIT_ARRAY_AT(OPCODE_VOLUME_CONTROL, + &BluetoothDaemonHandsfreeModule::VolumeControlRsp), + INIT_ARRAY_AT(OPCODE_DEVICE_STATUS_NOTIFICATION, + &BluetoothDaemonHandsfreeModule::DeviceStatusNotificationRsp), + INIT_ARRAY_AT(OPCODE_COPS_RESPONSE, + &BluetoothDaemonHandsfreeModule::CopsResponseRsp), + INIT_ARRAY_AT(OPCODE_CIND_RESPONSE, + &BluetoothDaemonHandsfreeModule::CindResponseRsp), + INIT_ARRAY_AT(OPCODE_FORMATTED_AT_RESPONSE, + &BluetoothDaemonHandsfreeModule::FormattedAtResponseRsp), + INIT_ARRAY_AT(OPCODE_AT_RESPONSE, + &BluetoothDaemonHandsfreeModule::AtResponseRsp), + INIT_ARRAY_AT(OPCODE_CLCC_RESPONSE, + &BluetoothDaemonHandsfreeModule::ClccResponseRsp), + INIT_ARRAY_AT(OPCODE_PHONE_STATE_CHANGE, + &BluetoothDaemonHandsfreeModule::PhoneStateChangeRsp) + }; + + MOZ_ASSERT(!NS_IsMainThread()); // I/O thread + + if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) || + NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { + return; + } + + nsRefPtr res = + already_AddRefed( + static_cast(aUserData)); + + if (!res) { + return; // Return early if no result handler has been set for response + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); +} + +// Notifications +// + +// Returns the current notification handler to a notification runnable +class BluetoothDaemonHandsfreeModule::NotificationHandlerWrapper MOZ_FINAL +{ +public: + typedef BluetoothHandsfreeNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sNotificationHandler; + } +}; + +// Init operator class for ConnectionStateNotification +class BluetoothDaemonHandsfreeModule::ConnectionStateInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + ConnectionStateInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothHandsfreeConnectionState& aArg1, + nsString& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read state */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::ConnectionStateNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + ConnectionStateNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification, + ConnectionStateInitOp(aPDU)); +} + +// Init operator class for AudioStateNotification +class BluetoothDaemonHandsfreeModule::AudioStateInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + AudioStateInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothHandsfreeAudioState& aArg1, + nsString& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read state */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::AudioStateNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + AudioStateNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::AudioStateNotification, + AudioStateInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + VoiceRecognitionNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::AnswerCallNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + AnswerCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::AnswerCallNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::HangupCallNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + HangupCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::HangupCallNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for VolumeNotification +class BluetoothDaemonHandsfreeModule::VolumeInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + VolumeInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothHandsfreeVolumeType& aArg1, int& aArg2) const + { + BluetoothDaemonPDU& pdu = GetPDU(); + + /* Read volume type */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read volume */ + rv = UnpackPDU(pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::VolumeNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + VolumeNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VolumeNotification, + VolumeInitOp(aPDU)); +} + +// Init operator class for DialCallNotification +class BluetoothDaemonHandsfreeModule::DialCallInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + DialCallInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsString& aArg1) const + { + /* Read number */ + nsresult rv = UnpackPDU(GetPDU(), UnpackString0(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::DialCallNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + DialCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DialCallNotification, + DialCallInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::DtmfNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + DtmfNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DtmfNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::NRECNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + NRECNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::NRECNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CallHoldNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CallHoldNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CallHoldNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CnumNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CnumNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CnumNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CindNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CindNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CindNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::CopsNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + CopsNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CopsNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::ClccNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + ClccNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::ClccNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for UnknownAtNotification +class BluetoothDaemonHandsfreeModule::UnknownAtInitOp MOZ_FINAL + : private PDUInitOp +{ +public: + UnknownAtInitOp(BluetoothDaemonPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsCString& aArg1) const + { + /* Read string */ + nsresult rv = UnpackPDU(GetPDU(), UnpackCString0(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonHandsfreeModule::UnknownAtNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + UnknownAtNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::UnknownAtNotification, + UnknownAtInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::KeyPressedNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU) +{ + KeyPressedNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::KeyPressedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonHandsfreeModule::HandleNtf( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + static void (BluetoothDaemonHandsfreeModule::* const HandleNtf[])( + const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = { + INIT_ARRAY_AT(0, &BluetoothDaemonHandsfreeModule::ConnectionStateNtf), + INIT_ARRAY_AT(1, &BluetoothDaemonHandsfreeModule::AudioStateNtf), + INIT_ARRAY_AT(2, &BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf), + INIT_ARRAY_AT(3, &BluetoothDaemonHandsfreeModule::AnswerCallNtf), + INIT_ARRAY_AT(4, &BluetoothDaemonHandsfreeModule::HangupCallNtf), + INIT_ARRAY_AT(5, &BluetoothDaemonHandsfreeModule::VolumeNtf), + INIT_ARRAY_AT(6, &BluetoothDaemonHandsfreeModule::DialCallNtf), + INIT_ARRAY_AT(7, &BluetoothDaemonHandsfreeModule::DtmfNtf), + INIT_ARRAY_AT(8, &BluetoothDaemonHandsfreeModule::NRECNtf), + INIT_ARRAY_AT(9, &BluetoothDaemonHandsfreeModule::CallHoldNtf), + INIT_ARRAY_AT(10, &BluetoothDaemonHandsfreeModule::CnumNtf), + INIT_ARRAY_AT(11, &BluetoothDaemonHandsfreeModule::CindNtf), + INIT_ARRAY_AT(12, &BluetoothDaemonHandsfreeModule::CopsNtf), + INIT_ARRAY_AT(13, &BluetoothDaemonHandsfreeModule::ClccNtf), + INIT_ARRAY_AT(14, &BluetoothDaemonHandsfreeModule::UnknownAtNtf), + INIT_ARRAY_AT(15, &BluetoothDaemonHandsfreeModule::KeyPressedNtf) + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + uint8_t index = aHeader.mOpcode - 0x81; + + if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) || + NS_WARN_IF(!HandleNtf[index])) { + return; + } + + (this->*(HandleNtf[index]))(aHeader, aPDU); +} + +// +// Handsfree interface +// + +BluetoothDaemonHandsfreeInterface::BluetoothDaemonHandsfreeInterface( + BluetoothDaemonHandsfreeModule* aModule) + : mModule(aModule) +{ } + +BluetoothDaemonHandsfreeInterface::~BluetoothDaemonHandsfreeInterface() +{ } + +class BluetoothDaemonHandsfreeInterface::InitResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + InitResultHandler(BluetoothHandsfreeResultHandler* aRes) + : mRes(aRes) + { + MOZ_ASSERT(mRes); + } + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + mRes->OnError(aStatus); + } + + void RegisterModule() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + mRes->Init(); + } + +private: + nsRefPtr mRes; +}; + +void +BluetoothDaemonHandsfreeInterface::Init( + BluetoothHandsfreeNotificationHandler* aNotificationHandler, + BluetoothHandsfreeResultHandler* aRes) +{ + // Set notification handler _before_ registering the module. It could + // happen that we receive notifications, before the result handler runs. + mModule->SetNotificationHandler(aNotificationHandler); + + InitResultHandler* res; + + if (aRes) { + res = new InitResultHandler(aRes); + } else { + // We don't need a result handler if the caller is not interested. + res = nullptr; + } + + nsresult rv = mModule->RegisterModule( + BluetoothDaemonHandsfreeModule::SERVICE_ID, MODE_NARROWBAND_SPEECH, res); + + if (NS_FAILED(rv) && aRes) { + DispatchError(aRes, STATUS_FAIL); + } +} + +class BluetoothDaemonHandsfreeInterface::CleanupResultHandler MOZ_FINAL + : public BluetoothSetupResultHandler +{ +public: + CleanupResultHandler(BluetoothDaemonHandsfreeModule* aModule, + BluetoothHandsfreeResultHandler* aRes) + : mModule(aModule) + , mRes(aRes) + { + MOZ_ASSERT(mModule); + } + + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + if (mRes) { + mRes->OnError(aStatus); + } + } + + void UnregisterModule() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + // Clear notification handler _after_ module has been + // unregistered. While unregistering the module, we might + // still receive notifications. + mModule->SetNotificationHandler(nullptr); + + if (mRes) { + mRes->Cleanup(); + } + } + +private: + BluetoothDaemonHandsfreeModule* mModule; + nsRefPtr mRes; +}; + +void +BluetoothDaemonHandsfreeInterface::Cleanup( + BluetoothHandsfreeResultHandler* aRes) +{ + mModule->UnregisterModule(BluetoothDaemonHandsfreeModule::SERVICE_ID, + new CleanupResultHandler(mModule, aRes)); +} + +/* Connect / Disconnect */ + +void +BluetoothDaemonHandsfreeInterface::Connect( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ConnectCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::Disconnect( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->DisconnectCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::ConnectAudio( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ConnectAudioCmd(aBdAddr, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::DisconnectAudio( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->DisconnectAudioCmd(aBdAddr, aRes); +} + +/* Voice Recognition */ + +void +BluetoothDaemonHandsfreeInterface::StartVoiceRecognition( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->StartVoiceRecognitionCmd(aRes); +} + +void +BluetoothDaemonHandsfreeInterface::StopVoiceRecognition( + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->StopVoiceRecognitionCmd(aRes); +} + +/* Volume */ + +void +BluetoothDaemonHandsfreeInterface::VolumeControl( + BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->VolumeControlCmd(aType, aVolume, aRes); +} + +/* Device status */ + +void +BluetoothDaemonHandsfreeInterface::DeviceStatusNotification( + BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->DeviceStatusNotificationCmd(aNtkState, aSvcType, aSignal, + aBattChg, aRes); +} + +/* Responses */ + +void +BluetoothDaemonHandsfreeInterface::CopsResponse( + const char* aCops, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->CopsResponseCmd(aCops, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::CindResponse( + int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->CindResponseCmd(aSvc, aNumActive, aNumHeld, aCallSetupState, + aSignal, aRoam, aBattChg, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::FormattedAtResponse( + const char* aRsp, BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->FormattedAtResponseCmd(aRsp, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::AtResponse( + BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->AtResponseCmd(aResponseCode, aErrorCode, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::ClccResponse( + int aIndex, BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->ClccResponseCmd(aIndex, aDir, aState, aMode, aMpty, aNumber, + aType, aRes); +} + +/* Phone State */ + +void +BluetoothDaemonHandsfreeInterface::PhoneStateChange( + int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + mModule->PhoneStateChangeCmd(aNumActive, aNumHeld, aCallSetupState, aNumber, + aType, aRes); +} + +void +BluetoothDaemonHandsfreeInterface::DispatchError( + BluetoothHandsfreeResultHandler* aRes, BluetoothStatus aStatus) +{ + BluetoothResultRunnable1::Dispatch( + aRes, &BluetoothHandsfreeResultHandler::OnError, + ConstantInitOp1(aStatus)); +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.h b/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.h new file mode 100644 index 000000000000..d0938d5b09ee --- /dev/null +++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.h @@ -0,0 +1,412 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_bluetooth_bluetoothdaemonhandsfreeinterface_h +#define mozilla_dom_bluetooth_bluetoothdaemonhandsfreeinterface_h + +#include "BluetoothDaemonHelpers.h" +#include "BluetoothInterface.h" +#include "BluetoothInterfaceHelpers.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothSetupResultHandler; + +class BluetoothDaemonHandsfreeModule +{ +public: + enum { + SERVICE_ID = 0x05 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_CONNECT = 0x01, + OPCODE_DISCONNECT = 0x02, + OPCODE_CONNECT_AUDIO = 0x03, + OPCODE_DISCONNECT_AUDIO = 0x04, + OPCODE_START_VOICE_RECOGNITION = 0x05, + OPCODE_STOP_VOICE_RECOGNITION =0x06, + OPCODE_VOLUME_CONTROL = 0x07, + OPCODE_DEVICE_STATUS_NOTIFICATION = 0x08, + OPCODE_COPS_RESPONSE = 0x09, + OPCODE_CIND_RESPONSE = 0x0a, + OPCODE_FORMATTED_AT_RESPONSE = 0x0b, + OPCODE_AT_RESPONSE = 0x0c, + OPCODE_CLCC_RESPONSE = 0x0d, + OPCODE_PHONE_STATE_CHANGE = 0x0e + }; + + virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0; + + virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) = 0; + + virtual nsresult UnregisterModule(uint8_t aId, + BluetoothSetupResultHandler* aRes) = 0; + + void SetNotificationHandler( + BluetoothHandsfreeNotificationHandler* aNotificationHandler); + + // + // Commands + // + + nsresult ConnectCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + nsresult DisconnectCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + nsresult ConnectAudioCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + nsresult DisconnectAudioCmd(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + + /* Voice Recognition */ + + nsresult StartVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes); + nsresult StopVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes); + + /* Volume */ + + nsresult VolumeControlCmd(BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes); + + /* Device status */ + + nsresult DeviceStatusNotificationCmd( + BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, + int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + + /* Responses */ + + nsresult CopsResponseCmd(const char* aCops, + BluetoothHandsfreeResultHandler* aRes); + nsresult CindResponseCmd(int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + nsresult FormattedAtResponseCmd(const char* aRsp, + BluetoothHandsfreeResultHandler* aRes); + nsresult AtResponseCmd(BluetoothHandsfreeAtResponse aResponseCode, + int aErrorCode, + BluetoothHandsfreeResultHandler* aRes); + nsresult ClccResponseCmd(int aIndex, BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + + /* Phone State */ + + nsresult PhoneStateChangeCmd(int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + +protected: + nsresult Send(BluetoothDaemonPDU* aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void HandleSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); + + // + // Responses + // + + typedef BluetoothResultRunnable0 + ResultRunnable; + + typedef BluetoothResultRunnable1 + ErrorRunnable; + + void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void DisconnectRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void ConnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void DisconnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void StartVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void StopVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void VolumeControlRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void DeviceStatusNotificationRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void CopsResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void CindResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void FormattedAtResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void AtResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void ClccResponseRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void PhoneStateChangeRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeResultHandler* aRes); + + void HandleRsp(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + void* aUserData); + + // + // Notifications + // + + class NotificationHandlerWrapper; + + typedef BluetoothNotificationRunnable2 + ConnectionStateNotification; + + typedef BluetoothNotificationRunnable2 + AudioStateNotification; + + typedef BluetoothNotificationRunnable1 + VoiceRecognitionNotification; + + typedef BluetoothNotificationRunnable0 + AnswerCallNotification; + + typedef BluetoothNotificationRunnable0 + HangupCallNotification; + + typedef BluetoothNotificationRunnable2 + VolumeNotification; + + typedef BluetoothNotificationRunnable1 + DialCallNotification; + + typedef BluetoothNotificationRunnable1 + DtmfNotification; + + typedef BluetoothNotificationRunnable1 + NRECNotification; + + typedef BluetoothNotificationRunnable1 + CallHoldNotification; + + typedef BluetoothNotificationRunnable0 + CnumNotification; + + typedef BluetoothNotificationRunnable0 + CindNotification; + + typedef BluetoothNotificationRunnable0 + CopsNotification; + + typedef BluetoothNotificationRunnable0 + ClccNotification; + + typedef BluetoothNotificationRunnable1 + UnknownAtNotification; + + typedef BluetoothNotificationRunnable0 + KeyPressedNotification; + + class AudioStateInitOp; + class ConnectionStateInitOp; + class DialCallInitOp; + class VolumeInitOp; + class UnknownAtInitOp; + + void ConnectionStateNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void AudioStateNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void VoiceRecognitionNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void AnswerCallNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void HangupCallNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void VolumeNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void DialCallNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void DtmfNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void NRECNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CallHoldNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CnumNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CindNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void CopsNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void ClccNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void UnknownAtNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void KeyPressedNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU); + + void HandleNtf(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, + void* aUserData); + + static BluetoothHandsfreeNotificationHandler* sNotificationHandler; +}; + +class BluetoothDaemonHandsfreeInterface MOZ_FINAL + : public BluetoothHandsfreeInterface +{ + class CleanupResultHandler; + class InitResultHandler; + + enum { + MODE_HEADSET = 0x00, + MODE_NARROWBAND_SPEECH = 0x01, + MODE_NARROWBAND_WIDEBAND_SPEECH = 0x02 + }; + +public: + BluetoothDaemonHandsfreeInterface(BluetoothDaemonHandsfreeModule* aModule); + ~BluetoothDaemonHandsfreeInterface(); + + void Init( + BluetoothHandsfreeNotificationHandler* aNotificationHandler, + BluetoothHandsfreeResultHandler* aRes); + void Cleanup(BluetoothHandsfreeResultHandler* aRes); + + /* Connect / Disconnect */ + + void Connect(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void Disconnect(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void ConnectAudio(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void DisconnectAudio(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + + /* Voice Recognition */ + + void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); + void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); + + /* Volume */ + + void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes); + + /* Device status */ + + void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, + int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + + /* Responses */ + + void CopsResponse(const char* aCops, + BluetoothHandsfreeResultHandler* aRes); + void CindResponse(int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + void FormattedAtResponse(const char* aRsp, + BluetoothHandsfreeResultHandler* aRes); + void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes); + void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + + /* Phone State */ + + void PhoneStateChange(int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + +private: + void DispatchError(BluetoothHandsfreeResultHandler* aRes, + BluetoothStatus aStatus); + + BluetoothDaemonHandsfreeModule* mModule; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff --git a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp index b7461991297c..47ddbc5b5882 100644 --- a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp +++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp @@ -45,6 +45,18 @@ Convert(bool aIn, BluetoothScanMode& aOut) return NS_OK; } +nsresult +Convert(int aIn, uint8_t& aOut) +{ + if (NS_WARN_IF(aIn < std::numeric_limits::min()) || + NS_WARN_IF(aIn > std::numeric_limits::max())) { + aOut = 0; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(aIn); + return NS_OK; +} + nsresult Convert(int aIn, int16_t& aOut) { @@ -71,6 +83,20 @@ Convert(uint8_t aIn, bool& aOut) return NS_OK; } +nsresult +Convert(uint8_t aIn, char& aOut) +{ + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, int& aOut) +{ + aOut = static_cast(aIn); + return NS_OK; +} + nsresult Convert(uint8_t aIn, BluetoothAclState& aOut) { @@ -100,6 +126,97 @@ Convert(uint8_t aIn, BluetoothBondState& aOut) return NS_OK; } +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeAudioState& aOut) +{ + static const BluetoothHandsfreeAudioState sAudioState[] = { + CONVERT(0x00, HFP_AUDIO_STATE_DISCONNECTED), + CONVERT(0x01, HFP_AUDIO_STATE_CONNECTING), + CONVERT(0x02, HFP_AUDIO_STATE_CONNECTED), + CONVERT(0x03, HFP_AUDIO_STATE_DISCONNECTING) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAudioState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAudioState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeCallHoldType& aOut) +{ + static const BluetoothHandsfreeCallHoldType sCallHoldType[] = { + CONVERT(0x00, HFP_CALL_HOLD_RELEASEHELD), + CONVERT(0x01, HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD), + CONVERT(0x02, HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD), + CONVERT(0x03, HFP_CALL_HOLD_ADDHELDTOCONF) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallHoldType))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallHoldType[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeConnectionState& aOut) +{ + static const BluetoothHandsfreeConnectionState sConnectionState[] = { + CONVERT(0x00, HFP_CONNECTION_STATE_DISCONNECTED), + CONVERT(0x01, HFP_CONNECTION_STATE_CONNECTING), + CONVERT(0x02, HFP_CONNECTION_STATE_CONNECTED), + CONVERT(0x03, HFP_CONNECTION_STATE_SLC_CONNECTED), + CONVERT(0x04, HFP_CONNECTION_STATE_DISCONNECTING) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sConnectionState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sConnectionState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeNRECState& aOut) +{ + static const BluetoothHandsfreeNRECState sNRECState[] = { + CONVERT(0x00, HFP_NREC_STOPPED), + CONVERT(0x01, HFP_NREC_STARTED) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sNRECState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNRECState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut) +{ + static const BluetoothHandsfreeVoiceRecognitionState sState[] = { + CONVERT(0x00, HFP_VOICE_RECOGNITION_STOPPED), + CONVERT(0x01, HFP_VOICE_RECOGNITION_STOPPED) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sState))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sState[aIn]; + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVolumeType& aOut) +{ + static const BluetoothHandsfreeVolumeType sVolumeType[] = { + CONVERT(0x00, HFP_VOLUME_TYPE_SPEAKER), + CONVERT(0x01, HFP_VOLUME_TYPE_MICROPHONE) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sVolumeType))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sVolumeType[aIn]; + return NS_OK; +} + nsresult Convert(int32_t aIn, BluetoothTypeOfDevice& aOut) { @@ -373,6 +490,147 @@ Convert(const BluetoothAddress& aIn, nsAString& aOut) return NS_OK; } +nsresult +Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut) +{ + static const uint8_t sAtResponse[] = { + CONVERT(HFP_AT_RESPONSE_ERROR, 0x00), + CONVERT(HFP_AT_RESPONSE_OK, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAtResponse))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAtResponse[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallAddressType aIn, uint8_t& aOut) +{ + static const uint8_t sCallAddressType[] = { + CONVERT(HFP_CALL_ADDRESS_TYPE_UNKNOWN, 0x81), + CONVERT(HFP_CALL_ADDRESS_TYPE_INTERNATIONAL, 0x91) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallAddressType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallAddressType[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallDirection aIn, uint8_t& aOut) +{ + static const uint8_t sCallDirection[] = { + CONVERT(HFP_CALL_DIRECTION_OUTGOING, 0x00), + CONVERT(HFP_CALL_DIRECTION_INCOMING, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallDirection))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallDirection[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallState aIn, uint8_t& aOut) +{ + static const uint8_t sCallState[] = { + CONVERT(HFP_CALL_STATE_ACTIVE, 0x00), + CONVERT(HFP_CALL_STATE_HELD, 0x01), + CONVERT(HFP_CALL_STATE_DIALING, 0x02), + CONVERT(HFP_CALL_STATE_ALERTING, 0x03), + CONVERT(HFP_CALL_STATE_INCOMING, 0x04), + CONVERT(HFP_CALL_STATE_WAITING, 0x05), + CONVERT(HFP_CALL_STATE_IDLE, 0x06) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallState))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallState[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallMode aIn, uint8_t& aOut) +{ + static const uint8_t sCallMode[] = { + CONVERT(HFP_CALL_MODE_VOICE, 0x00), + CONVERT(HFP_CALL_MODE_DATA, 0x01), + CONVERT(HFP_CALL_MODE_FAX, 0x02) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallMode))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallMode[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeCallMptyType aIn, uint8_t& aOut) +{ + static const uint8_t sCallMptyType[] = { + CONVERT(HFP_CALL_MPTY_TYPE_SINGLE, 0x00), + CONVERT(HFP_CALL_MPTY_TYPE_MULTI, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallMptyType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallMptyType[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeNetworkState aIn, uint8_t& aOut) +{ + static const uint8_t sNetworkState[] = { + CONVERT(HFP_NETWORK_STATE_NOT_AVAILABLE, 0x00), + CONVERT(HFP_NETWORK_STATE_AVAILABLE, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sNetworkState))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNetworkState[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeServiceType aIn, uint8_t& aOut) +{ + static const uint8_t sServiceType[] = { + CONVERT(HFP_SERVICE_TYPE_HOME, 0x00), + CONVERT(HFP_SERVICE_TYPE_ROAMING, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sServiceType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sServiceType[aIn]; + return NS_OK; +} + +nsresult +Convert(BluetoothHandsfreeVolumeType aIn, uint8_t& aOut) +{ + static const uint8_t sVolumeType[] = { + CONVERT(HFP_VOLUME_TYPE_SPEAKER, 0x00), + CONVERT(HFP_VOLUME_TYPE_MICROPHONE, 0x01) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sVolumeType))) { + aOut = 0x00; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sVolumeType[aIn]; + return NS_OK; +} + nsresult Convert(BluetoothPropertyType aIn, uint8_t& aOut) { @@ -506,6 +764,69 @@ PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU) return PackPDU(aIn.mService, aIn.mOpcode, aIn.mLength, aPDU); } +nsresult +PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + +nsresult +PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackConversion(aIn), aPDU); +} + nsresult PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU) { @@ -591,6 +912,12 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut) return UnpackPDU(aPDU, UnpackConversion(aOut)); } +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut) { @@ -610,6 +937,50 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut) aPDU, UnpackConversion(aOut)); } +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeVoiceRecognitionState& aOut) +{ + return UnpackPDU( + aPDU, + UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut) +{ + return UnpackPDU( + aPDU, UnpackConversion(aOut)); +} + nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut) { @@ -753,4 +1124,64 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut) return UnpackPDU(aPDU, UnpackConversion(aOut)); } +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut) +{ + // We get a pointer to the first character in the PDU, a length + // of 1 ensures we consume the \0 byte. With 'str' pointing to + // the string in the PDU, we can copy the actual bytes. + + const char* str = reinterpret_cast(aPDU.Consume(1)); + if (NS_WARN_IF(!str)) { + return NS_ERROR_ILLEGAL_VALUE; // end of PDU + } + + const char* end = static_cast(memchr(str, '\0', aPDU.GetSize())); + if (NS_WARN_IF(!end)) { + return NS_ERROR_ILLEGAL_VALUE; // no string terminator + } + + ptrdiff_t len = end - str; + + const uint8_t* rest = aPDU.Consume(len); + if (NS_WARN_IF(!rest)) { + // We couldn't consume bytes that should have been there. + return NS_ERROR_ILLEGAL_VALUE; + } + + aOut.Rebind(str, len); + + return NS_OK; +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut) +{ + nsDependentCString cstring; + + nsresult rv = UnpackPDU(aPDU, cstring); + if (NS_FAILED(rv)) { + return NS_ERROR_ILLEGAL_VALUE; + } + + aOut.mString->AssignASCII(cstring.get(), cstring.Length()); + + return NS_OK; +} + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut) +{ + nsDependentCString cstring; + + nsresult rv = UnpackPDU(aPDU, cstring); + if (NS_FAILED(rv)) { + return NS_ERROR_ILLEGAL_VALUE; + } + + *aOut.mString = NS_ConvertUTF8toUTF16(cstring); + + return NS_OK; +} + END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h index 631c46f13859..c6940f79489a 100644 --- a/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h +++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h @@ -83,18 +83,45 @@ Convert(bool aIn, uint8_t& aOut); nsresult Convert(bool aIn, BluetoothScanMode& aOut); +nsresult +Convert(int aIn, uint8_t& aOut); + nsresult Convert(int aIn, int16_t& aOut); nsresult Convert(uint8_t aIn, bool& aOut); +nsresult +Convert(uint8_t aIn, char& aOut); + +nsresult +Convert(uint8_t aIn, int& aOut); + nsresult Convert(uint8_t aIn, BluetoothAclState& aOut); nsresult Convert(uint8_t aIn, BluetoothBondState& aOut); +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeAudioState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeCallHoldType& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeConnectionState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeNRECState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut); + +nsresult +Convert(uint8_t aIn, BluetoothHandsfreeVolumeType& aOut); + nsresult Convert(uint8_t aIn, BluetoothTypeOfDevice& aOut); @@ -137,6 +164,33 @@ Convert(BluetoothAclState aIn, bool& aOut); nsresult Convert(const BluetoothAddress& aIn, nsAString& aOut); +nsresult +Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallAddressType aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallDirection aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallState aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallMode aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeCallMptyType aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeNetworkState aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeServiceType aIn, uint8_t& aOut); + +nsresult +Convert(BluetoothHandsfreeVolumeType aIn, uint8_t& aOut); + nsresult Convert(BluetoothPropertyType aIn, uint8_t& aOut); @@ -192,6 +246,33 @@ PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU); nsresult PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU); +nsresult +PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU); + +nsresult +PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU); + nsresult PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU); @@ -279,6 +360,29 @@ PackPDU(const PackArray& aIn, BluetoothDaemonPDU& aPDU) return aPDU.Write(aIn.mData, aIn.mLength); } +/* |PackCString0| is a helper for packing 0-terminated C string, + * including the \0 character. Pass an instance of this structure + * as the first argument to |PackPDU| to pack a string. + */ +struct PackCString0 +{ + PackCString0(const nsCString& aString) + : mString(aString) + { } + + const nsCString& mString; +}; + +/* This implementation of |PackPDU| packs a 0-terminated C string. + */ +inline nsresult +PackPDU(const PackCString0& aIn, BluetoothDaemonPDU& aPDU) +{ + return PackPDU( + PackArray(reinterpret_cast(aIn.mString.get()), + aIn.mString.Length() + 1), aPDU); +} + template inline nsresult PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU) @@ -352,6 +456,41 @@ PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, return PackPDU(aIn5, aPDU); } +template +inline nsresult +PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7, BluetoothDaemonPDU& aPDU) +{ + nsresult rv = PackPDU(aIn1, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn2, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn3, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn4, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn5, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aIn6, aPDU); + if (NS_FAILED(rv)) { + return rv; + } + return PackPDU(aIn7, aPDU); +} + // // Unpacking // @@ -389,6 +528,9 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, uint32_t& aOut) nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut); +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut); + nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut); @@ -418,6 +560,25 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothDaemonPDUHeader& aOut) nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut); +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, + BluetoothHandsfreeVoiceRecognitionState& aOut); + +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut); + nsresult UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut); @@ -451,6 +612,9 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothUuid& aOut) return aPDU.Read(aOut.mUuid, sizeof(aOut.mUuid)); } +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut); + /* |UnpackConversion| is a helper for convering unpacked values. Pass * an instance of this structure to |UnpackPDU| to read a value from * the PDU in the input type and convert it to the output type. @@ -542,6 +706,44 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, nsTArray& aOut) return NS_OK; } +/* |UnpackCString0| is a helper for unpacking 0-terminated C string, + * including the \0 character. Pass an instance of this structure + * as the first argument to |UnpackPDU| to unpack a string. + */ +struct UnpackCString0 +{ + UnpackCString0(nsCString& aString) + : mString(&aString) + { } + + nsCString* mString; // non-null by construction +}; + +/* This implementation of |UnpackPDU| unpacks a 0-terminated C string. + */ +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut); + +/* |UnpackString0| is a helper for unpacking 0-terminated C string, + * including the \0 character. Pass an instance of this structure + * as the first argument to |UnpackPDU| to unpack a C string and convert + * it to wide-character encoding. + */ +struct UnpackString0 +{ + UnpackString0(nsString& aString) + : mString(&aString) + { } + + nsString* mString; // non-null by construction +}; + +/* This implementation of |UnpackPDU| unpacks a 0-terminated C string + * and converts it to wide-character encoding. + */ +nsresult +UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut); + // // Init operators // diff --git a/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp index 3949f5e4027e..cbb8e35fc2b2 100644 --- a/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp +++ b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp @@ -5,6 +5,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BluetoothDaemonInterface.h" +#include "BluetoothDaemonHandsfreeInterface.h" #include "BluetoothDaemonHelpers.h" #include "BluetoothDaemonSetupInterface.h" #include "BluetoothDaemonSocketInterface.h" @@ -1456,10 +1457,17 @@ class BluetoothDaemonProtocol MOZ_FINAL , public BluetoothDaemonSetupModule , public BluetoothDaemonCoreModule , public BluetoothDaemonSocketModule + , public BluetoothDaemonHandsfreeModule { public: BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection); + nsresult RegisterModule(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE; + + nsresult UnregisterModule(uint8_t aId, + BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE; + // Outgoing PDUs // @@ -1481,6 +1489,8 @@ private: BluetoothDaemonPDU& aPDU, void* aUserData); void HandleSocketSvc(const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, void* aUserData); + void HandleHandsfreeSvc(const BluetoothDaemonPDUHeader& aHeader, + BluetoothDaemonPDU& aPDU, void* aUserData); BluetoothDaemonConnection* mConnection; nsTArray mUserDataQ; @@ -1493,6 +1503,20 @@ BluetoothDaemonProtocol::BluetoothDaemonProtocol( MOZ_ASSERT(mConnection); } +nsresult +BluetoothDaemonProtocol::RegisterModule(uint8_t aId, uint8_t aMode, + BluetoothSetupResultHandler* aRes) +{ + return BluetoothDaemonSetupModule::RegisterModuleCmd(aId, aMode, aRes); +} + +nsresult +BluetoothDaemonProtocol::UnregisterModule(uint8_t aId, + BluetoothSetupResultHandler* aRes) +{ + return BluetoothDaemonSetupModule::UnregisterModuleCmd(aId, aRes); +} + nsresult BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData) { @@ -1527,6 +1551,14 @@ BluetoothDaemonProtocol::HandleSocketSvc( BluetoothDaemonSocketModule::HandleSvc(aHeader, aPDU, aUserData); } +void +BluetoothDaemonProtocol::HandleHandsfreeSvc( + const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU, + void* aUserData) +{ + BluetoothDaemonHandsfreeModule::HandleSvc(aHeader, aPDU, aUserData); +} + void BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) { @@ -1537,7 +1569,11 @@ BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU) INIT_ARRAY_AT(BluetoothDaemonCoreModule::SERVICE_ID, &BluetoothDaemonProtocol::HandleCoreSvc), INIT_ARRAY_AT(BluetoothDaemonSocketModule::SERVICE_ID, - &BluetoothDaemonProtocol::HandleSocketSvc) + &BluetoothDaemonProtocol::HandleSocketSvc), + INIT_ARRAY_AT(0x03, nullptr), // HID host + INIT_ARRAY_AT(0x04, nullptr), // PAN + INIT_ARRAY_AT(BluetoothDaemonHandsfreeModule::SERVICE_ID, + &BluetoothDaemonProtocol::HandleHandsfreeSvc) }; BluetoothDaemonPDUHeader header; @@ -2110,7 +2146,13 @@ BluetoothDaemonInterface::GetBluetoothSocketInterface() BluetoothHandsfreeInterface* BluetoothDaemonInterface::GetBluetoothHandsfreeInterface() { - return nullptr; + if (mHandsfreeInterface) { + return mHandsfreeInterface; + } + + mHandsfreeInterface = new BluetoothDaemonHandsfreeInterface(mProtocol); + + return mHandsfreeInterface; } BluetoothA2dpInterface* diff --git a/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h index 31513fe92baf..0fca73667672 100644 --- a/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h +++ b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h @@ -12,6 +12,7 @@ BEGIN_BLUETOOTH_NAMESPACE class BluetoothDaemonChannel; +class BluetoothDaemonHandsfreeInterface; class BluetoothDaemonProtocol; class BluetoothDaemonSocketInterface; @@ -126,6 +127,7 @@ private: nsTArray > mResultHandlerQ; nsAutoPtr mSocketInterface; + nsAutoPtr mHandsfreeInterface; }; END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.cpp b/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.cpp index 2b736c2cd5ff..c734833400b3 100644 --- a/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.cpp +++ b/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.cpp @@ -76,146 +76,12 @@ static nsTArray > sFetchUuidsRunnableArray; static nsTArray > sBondingRunnableArray; static nsTArray > sUnbondingRunnableArray; -/** - * Classes only used in this file - */ - -class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable -{ -public: - class SetAdapterPropertyResultHandler MOZ_FINAL - : public BluetoothResultHandler - { - public: - void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE - { - BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE"); - } - }; - - NS_IMETHOD - Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - // Bluetooth just enabled, clear profile controllers and runnable arrays. - sControllerArray.Clear(); - sChangeDiscoveryRunnableArray.Clear(); - sSetPropertyRunnableArray.Clear(); - sGetDeviceRunnableArray.Clear(); - sFetchUuidsRunnableArray.Clear(); - sBondingRunnableArray.Clear(); - sUnbondingRunnableArray.Clear(); - - // Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., It should - // be connectable and non-discoverable. - NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE); - sBtInterface->SetAdapterProperty( - BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false), - new SetAdapterPropertyResultHandler()); - - // Trigger BluetoothOppManager to listen - BluetoothOppManager* opp = BluetoothOppManager::Get(); - if (!opp || !opp->Listen()) { - BT_LOGR("Fail to start BluetoothOppManager listening"); - } - - return NS_OK; - } -}; - -/* |ProfileDeinitResultHandler| collects the results of all profile - * result handlers and calls |Proceed| after all results handlers - * have been run. - */ -class ProfileDeinitResultHandler MOZ_FINAL -: public BluetoothProfileResultHandler -{ -public: - ProfileDeinitResultHandler(unsigned char aNumProfiles) - : mNumProfiles(aNumProfiles) - { - MOZ_ASSERT(mNumProfiles); - } - - void Deinit() MOZ_OVERRIDE - { - if (!(--mNumProfiles)) { - Proceed(); - } - } - - void OnError(nsresult aResult) MOZ_OVERRIDE - { - if (!(--mNumProfiles)) { - Proceed(); - } - } - -private: - void Proceed() const - { - sBtInterface->Cleanup(nullptr); - } - - unsigned char mNumProfiles; -}; - -class CleanupTask MOZ_FINAL : public nsRunnable -{ -public: - NS_IMETHOD - Run() - { - static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = { - BluetoothHfpManager::DeinitHfpInterface, - BluetoothA2dpManager::DeinitA2dpInterface, - BluetoothGattManager::DeinitGattInterface - }; - - MOZ_ASSERT(NS_IsMainThread()); - - // Return error if BluetoothService is unavailable - BluetoothService* bs = BluetoothService::Get(); - NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE); - - // Cleanup static adapter properties and notify adapter. - sAdapterBdAddress.Truncate(); - sAdapterBdName.Truncate(); - - InfallibleTArray props; - BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName); - BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress); - if (sAdapterDiscoverable) { - sAdapterDiscoverable = false; - BT_APPEND_NAMED_VALUE(props, "Discoverable", false); - } - if (sAdapterDiscovering) { - sAdapterDiscovering = false; - BT_APPEND_NAMED_VALUE(props, "Discovering", false); - } - - BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"), - NS_LITERAL_STRING(KEY_ADAPTER), props); - bs->DistributeSignal(signal); - - // Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF. - nsRefPtr res = - new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager)); - - for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) { - sDeinitManager[i](res); - } - - return NS_OK; - } -}; - /** * Static callback functions */ -static ControlPlayStatus -PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus) +ControlPlayStatus +BluetoothServiceBluedroid::PlayStatusStringToControlPlayStatus( + const nsAString& aPlayStatus) { ControlPlayStatus playStatus = ControlPlayStatus::PLAYSTATUS_UNKNOWN; if (aPlayStatus.EqualsLiteral("STOPPED")) { @@ -238,8 +104,8 @@ PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus) /** * Static functions */ -static bool -EnsureBluetoothHalLoad() +bool +BluetoothServiceBluedroid::EnsureBluetoothHalLoad() { sBtInterface = BluetoothInterface::GetInstance(); NS_ENSURE_TRUE(sBtInterface, false); @@ -247,7 +113,8 @@ EnsureBluetoothHalLoad() return true; } -class EnableResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::EnableResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE @@ -256,10 +123,7 @@ public: BT_LOGR("BluetoothInterface::Enable failed: %d", aStatus); - nsRefPtr runnable = new BluetoothService::ToggleBtAck(false); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); } }; @@ -267,12 +131,12 @@ public: * result handlers and calls |Proceed| after all results handlers * have been run. */ -class ProfileInitResultHandler MOZ_FINAL -: public BluetoothProfileResultHandler +class BluetoothServiceBluedroid::ProfileInitResultHandler MOZ_FINAL + : public BluetoothProfileResultHandler { public: ProfileInitResultHandler(unsigned char aNumProfiles) - : mNumProfiles(aNumProfiles) + : mNumProfiles(aNumProfiles) { MOZ_ASSERT(mNumProfiles); } @@ -300,7 +164,8 @@ private: unsigned char mNumProfiles; }; -class InitResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::InitResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: void Init() MOZ_OVERRIDE @@ -332,15 +197,12 @@ public: sBtInterface = nullptr; - nsRefPtr runnable = new BluetoothService::ToggleBtAck(false); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); } }; -static nsresult -StartGonkBluetooth() +nsresult +BluetoothServiceBluedroid::StartGonkBluetooth() { MOZ_ASSERT(NS_IsMainThread()); @@ -351,10 +213,7 @@ StartGonkBluetooth() if (bs->IsEnabled()) { // Keep current enable status - nsRefPtr runnable = new BluetoothService::ToggleBtAck(true); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(true); return NS_OK; } @@ -364,7 +223,8 @@ StartGonkBluetooth() return NS_OK; } -class DisableResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::DisableResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE @@ -373,15 +233,12 @@ public: BT_LOGR("BluetoothInterface::Disable failed: %d", aStatus); - nsRefPtr runnable = new BluetoothService::ToggleBtAck(true); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(true); } }; -static nsresult -StopGonkBluetooth() +nsresult +BluetoothServiceBluedroid::StopGonkBluetooth() { MOZ_ASSERT(NS_IsMainThread()); @@ -392,10 +249,7 @@ StopGonkBluetooth() if (!bs->IsEnabled()) { // Keep current enable status - nsRefPtr runnable = new BluetoothService::ToggleBtAck(false); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); return NS_OK; } @@ -404,9 +258,10 @@ StopGonkBluetooth() return NS_OK; } -static void -ReplyStatusError(BluetoothReplyRunnable* aBluetoothReplyRunnable, - BluetoothStatus aStatusCode, const nsAString& aCustomMsg) +void +BluetoothServiceBluedroid::ReplyStatusError( + BluetoothReplyRunnable* aBluetoothReplyRunnable, + BluetoothStatus aStatusCode, const nsAString& aCustomMsg) { MOZ_ASSERT(aBluetoothReplyRunnable, "Reply runnable is nullptr"); @@ -460,12 +315,7 @@ BluetoothServiceBluedroid::StartInternal(BluetoothReplyRunnable* aRunnable) nsresult ret = StartGonkBluetooth(); if (NS_FAILED(ret)) { - nsRefPtr runnable = - new BluetoothService::ToggleBtAck(false); - - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(false); // Reject Promise if(aRunnable) { @@ -492,12 +342,7 @@ BluetoothServiceBluedroid::StopInternal(BluetoothReplyRunnable* aRunnable) nsresult ret = StopGonkBluetooth(); if (NS_FAILED(ret)) { - nsRefPtr runnable = - new BluetoothService::ToggleBtAck(true); - - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - } + BluetoothService::AcknowledgeToggleBt(true); // Reject Promise if(aRunnable) { @@ -554,8 +399,9 @@ BluetoothServiceBluedroid::GetAdaptersInternal( return NS_OK; } -class GetRemoteDevicePropertiesResultHandler MOZ_FINAL -: public BluetoothResultHandler +class BluetoothServiceBluedroid::GetRemoteDevicePropertiesResultHandler + MOZ_FINAL + : public BluetoothResultHandler { public: GetRemoteDevicePropertiesResultHandler(const nsAString& aDeviceAddress) @@ -653,7 +499,8 @@ BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal( return NS_OK; } -class StartDiscoveryResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::StartDiscoveryResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: StartDiscoveryResultHandler(BluetoothReplyRunnable* aRunnable) @@ -685,7 +532,8 @@ BluetoothServiceBluedroid::StartDiscoveryInternal( return NS_OK; } -class CancelDiscoveryResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::CancelDiscoveryResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: CancelDiscoveryResultHandler(BluetoothReplyRunnable* aRunnable) @@ -717,7 +565,8 @@ BluetoothServiceBluedroid::StopDiscoveryInternal( return NS_OK; } -class GetRemoteServicesResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::GetRemoteServicesResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: GetRemoteServicesResultHandler(BluetoothReplyRunnable* aRunnable) @@ -759,7 +608,8 @@ BluetoothServiceBluedroid::FetchUuidsInternal( return NS_OK; } -class SetAdapterPropertyResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::SetAdapterPropertyResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: SetAdapterPropertyResultHandler(BluetoothReplyRunnable* aRunnable) @@ -810,7 +660,8 @@ BluetoothServiceBluedroid::UpdateSdpRecords( return true; } -class CreateBondResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::CreateBondResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: CreateBondResultHandler(BluetoothReplyRunnable* aRunnable) @@ -845,7 +696,8 @@ BluetoothServiceBluedroid::CreatePairedDeviceInternal( return NS_OK; } -class RemoveBondResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::RemoveBondResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: RemoveBondResultHandler(BluetoothReplyRunnable* aRunnable) @@ -880,7 +732,8 @@ BluetoothServiceBluedroid::RemoveDeviceInternal( return NS_OK; } -class PinReplyResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::PinReplyResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: PinReplyResultHandler(BluetoothReplyRunnable* aRunnable) @@ -922,7 +775,8 @@ BluetoothServiceBluedroid::SetPasskeyInternal( return; } -class SspReplyResultHandler MOZ_FINAL : public BluetoothResultHandler +class BluetoothServiceBluedroid::SspReplyResultHandler MOZ_FINAL + : public BluetoothResultHandler { public: SspReplyResultHandler(BluetoothReplyRunnable* aRunnable) @@ -958,8 +812,8 @@ BluetoothServiceBluedroid::SetPairingConfirmationInternal( aConfirm, 0, new SspReplyResultHandler(aRunnable)); } -static void -NextBluetoothProfileController() +void +BluetoothServiceBluedroid::NextBluetoothProfileController() { MOZ_ASSERT(NS_IsMainThread()); @@ -973,10 +827,11 @@ NextBluetoothProfileController() } } -static void -ConnectDisconnect(bool aConnect, const nsAString& aDeviceAddress, - BluetoothReplyRunnable* aRunnable, - uint16_t aServiceUuid, uint32_t aCod = 0) +void +BluetoothServiceBluedroid::ConnectDisconnect( + bool aConnect, const nsAString& aDeviceAddress, + BluetoothReplyRunnable* aRunnable, + uint16_t aServiceUuid, uint32_t aCod) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aRunnable); @@ -1220,6 +1075,54 @@ BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable) // Bluetooth notifications // +/* |ProfileDeinitResultHandler| collects the results of all profile + * result handlers and calls |Proceed| after all results handlers + * have been run. + */ +class BluetoothServiceBluedroid::ProfileDeinitResultHandler MOZ_FINAL + : public BluetoothProfileResultHandler +{ +public: + ProfileDeinitResultHandler(unsigned char aNumProfiles) + : mNumProfiles(aNumProfiles) + { + MOZ_ASSERT(mNumProfiles); + } + + void Deinit() MOZ_OVERRIDE + { + if (!(--mNumProfiles)) { + Proceed(); + } + } + + void OnError(nsresult aResult) MOZ_OVERRIDE + { + if (!(--mNumProfiles)) { + Proceed(); + } + } + +private: + void Proceed() const + { + sBtInterface->Cleanup(nullptr); + } + + unsigned char mNumProfiles; +}; + +class BluetoothServiceBluedroid::SetAdapterPropertyDiscoverableResultHandler + MOZ_FINAL + : public BluetoothResultHandler +{ +public: + void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE + { + BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE"); + } +}; + void BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState) { @@ -1229,23 +1132,70 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState) sAdapterEnabled = aState; - if (!sAdapterEnabled && - NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; + if (!sAdapterEnabled) { + static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = { + BluetoothHfpManager::DeinitHfpInterface, + BluetoothA2dpManager::DeinitA2dpInterface, + BluetoothGattManager::DeinitGattInterface + }; + + // Return error if BluetoothService is unavailable + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE_VOID(bs); + + // Cleanup static adapter properties and notify adapter. + sAdapterBdAddress.Truncate(); + sAdapterBdName.Truncate(); + + InfallibleTArray props; + BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName); + BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress); + if (sAdapterDiscoverable) { + sAdapterDiscoverable = false; + BT_APPEND_NAMED_VALUE(props, "Discoverable", false); + } + if (sAdapterDiscovering) { + sAdapterDiscovering = false; + BT_APPEND_NAMED_VALUE(props, "Discovering", false); + } + + BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"), + NS_LITERAL_STRING(KEY_ADAPTER), props); + bs->DistributeSignal(signal); + + // Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF. + nsRefPtr res = + new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager)); + + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) { + sDeinitManager[i](res); + } } - nsRefPtr runnable = - new BluetoothService::ToggleBtAck(sAdapterEnabled); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; - } + BluetoothService::AcknowledgeToggleBt(sAdapterEnabled); - if (sAdapterEnabled && - NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; + if (sAdapterEnabled) { + // Bluetooth just enabled, clear profile controllers and runnable arrays. + sControllerArray.Clear(); + sChangeDiscoveryRunnableArray.Clear(); + sSetPropertyRunnableArray.Clear(); + sGetDeviceRunnableArray.Clear(); + sFetchUuidsRunnableArray.Clear(); + sBondingRunnableArray.Clear(); + sUnbondingRunnableArray.Clear(); + + // Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., It should + // be connectable and non-discoverable. + NS_ENSURE_TRUE_VOID(sBtInterface); + sBtInterface->SetAdapterProperty( + BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false), + new SetAdapterPropertyDiscoverableResultHandler()); + + // Trigger BluetoothOppManager to listen + BluetoothOppManager* opp = BluetoothOppManager::Get(); + if (!opp || !opp->Listen()) { + BT_LOGR("Fail to start BluetoothOppManager listening"); + } } // Resolve promise if existed diff --git a/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.h b/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.h index 06db64227fea..bd6b86453516 100644 --- a/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.h +++ b/dom/bluetooth2/bluedroid/BluetoothServiceBluedroid.h @@ -16,6 +16,22 @@ BEGIN_BLUETOOTH_NAMESPACE class BluetoothServiceBluedroid : public BluetoothService , public BluetoothNotificationHandler { + class CancelDiscoveryResultHandler; + class CreateBondResultHandler; + class DisableResultHandler; + class EnableResultHandler; + class GetRemoteDevicePropertiesResultHandler; + class GetRemoteServicesResultHandler; + class InitResultHandler; + class PinReplyResultHandler; + class ProfileDeinitResultHandler; + class ProfileInitResultHandler; + class RemoveBondResultHandler; + class SetAdapterPropertyDiscoverableResultHandler; + class SetAdapterPropertyResultHandler; + class SspReplyResultHandler; + class StartDiscoveryResultHandler; + public: BluetoothServiceBluedroid(); ~BluetoothServiceBluedroid(); @@ -193,6 +209,22 @@ public: uint8_t aLen) MOZ_OVERRIDE; virtual void LeTestModeNotification(BluetoothStatus aStatus, uint16_t aNumPackets) MOZ_OVERRIDE; + +protected: + static nsresult StartGonkBluetooth(); + static nsresult StopGonkBluetooth(); + static bool EnsureBluetoothHalLoad(); + + static void ConnectDisconnect(bool aConnect, + const nsAString& aDeviceAddress, + BluetoothReplyRunnable* aRunnable, + uint16_t aServiceUuid, uint32_t aCod = 0); + static void NextBluetoothProfileController(); + static ControlPlayStatus PlayStatusStringToControlPlayStatus( + const nsAString& aPlayStatus); + static void ReplyStatusError(BluetoothReplyRunnable* aReplyRunnable, + BluetoothStatus aStatusCode, + const nsAString& aCustomMsg); }; END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth2/moz.build b/dom/bluetooth2/moz.build index fa7732b68786..f97a1aa96501 100644 --- a/dom/bluetooth2/moz.build +++ b/dom/bluetooth2/moz.build @@ -51,6 +51,7 @@ if CONFIG['MOZ_B2G_BT']: 'bluedroid/BluetoothA2dpHALInterface.cpp', 'bluedroid/BluetoothA2dpManager.cpp', 'bluedroid/BluetoothAvrcpHALInterface.cpp', + 'bluedroid/BluetoothDaemonHandsfreeInterface.cpp', 'bluedroid/BluetoothDaemonHelpers.cpp', 'bluedroid/BluetoothDaemonInterface.cpp', 'bluedroid/BluetoothDaemonSetupInterface.cpp', diff --git a/dom/media/omx/OmxDecoder.cpp b/dom/media/omx/OmxDecoder.cpp index 5fbd3160d0e4..f0fb361c228a 100644 --- a/dom/media/omx/OmxDecoder.cpp +++ b/dom/media/omx/OmxDecoder.cpp @@ -574,12 +574,16 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs, while (findNextBuffer) { options.setSeekTo(aTimeUs, seekMode); findNextBuffer = false; - err = mVideoSource->read(&mVideoBuffer, &options); - { + if (mIsVideoSeeking) { + err = mVideoSource->read(&mVideoBuffer, &options); Mutex::Autolock autoLock(mSeekLock); mIsVideoSeeking = false; PostReleaseVideoBuffer(nullptr, FenceHandle()); } + else { + err = mVideoSource->read(&mVideoBuffer); + } + // If there is no next Keyframe, jump to the previous key frame. if (err == ERROR_END_OF_STREAM && seekMode == MediaSource::ReadOptions::SEEK_NEXT_SYNC) { seekMode = MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC; @@ -593,13 +597,11 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs, ALOG("Unexpected error when seeking to %lld", aTimeUs); break; } + // For some codecs, the length of first decoded frame after seek is 0. + // Need to ignore it and continue to find the next one if (mVideoBuffer->range_length() == 0) { ReleaseVideoBuffer(); findNextBuffer = true; - { - Mutex::Autolock autoLock(mSeekLock); - mIsVideoSeeking = true; - } } } aDoSeek = false; diff --git a/dom/system/gonk/NetworkManager.js b/dom/system/gonk/NetworkManager.js index a499ff7fbf7f..e6dd6171a814 100644 --- a/dom/system/gonk/NetworkManager.js +++ b/dom/system/gonk/NetworkManager.js @@ -997,7 +997,7 @@ NetworkManager.prototype = { } else { let mobile = this.getNetworkInterface( Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); - if (mobile) { + if (mobile && mobile.name) { this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name; } } @@ -1142,7 +1142,7 @@ NetworkManager.prototype = { let mobile = this.getNetworkInterface( Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); // Update the real interface name - if (mobile) { + if (mobile && mobile.name) { this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name; } diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 1dd1dcd4c176..448ff697d72e 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2335,7 +2335,11 @@ bool AsyncPanZoomController::SnapBackIfOverscrolled() { bool AsyncPanZoomController::IsMovingFast() const { ReentrantMonitorAutoEnter lock(mMonitor); - return (GetVelocityVector().Length() > gfxPrefs::APZFlingStopOnTapThreshold()); + if (GetVelocityVector().Length() > gfxPrefs::APZFlingStopOnTapThreshold()) { + APZC_LOG("%p is moving fast\n", this); + return true; + } + return false; } bool AsyncPanZoomController::IsPannable() const { diff --git a/gfx/layers/apz/src/Axis.cpp b/gfx/layers/apz/src/Axis.cpp index d87680ee0cfc..65378e668cbc 100644 --- a/gfx/layers/apz/src/Axis.cpp +++ b/gfx/layers/apz/src/Axis.cpp @@ -83,7 +83,8 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimesta float funcInput = (newVelocity - curveThreshold) / scale; float funcOutput = gVelocityCurveFunction->GetValue(funcInput); float curvedVelocity = (funcOutput * scale) + curveThreshold; - AXIS_LOG("Curving up velocity from %f to %f\n", newVelocity, curvedVelocity); + AXIS_LOG("%p|%s curving up velocity from %f to %f\n", + mAsyncPanZoomController, Name(), newVelocity, curvedVelocity); newVelocity = curvedVelocity; } } @@ -93,6 +94,8 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimesta } } + AXIS_LOG("%p|%s updating velocity to %f with touch\n", + mAsyncPanZoomController, Name(), newVelocity); mVelocity = newVelocity; mPos = aPos; mPosTimeMs = aTimestampMs; @@ -139,6 +142,8 @@ bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement, if (aOverscrollAmountOut != 0.0f) { // No need to have a velocity along this axis anymore; it won't take us // anywhere, so we're just spinning needlessly. + AXIS_LOG("%p|%s has overscrolled, clearing velocity\n", + mAsyncPanZoomController, Name()); mVelocity = 0.0f; displacement -= aOverscrollAmountOut; } @@ -217,6 +222,8 @@ bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) { // Apply dampening. mVelocity *= pow(double(1 - kSpringFriction), aDelta.ToMilliseconds()); + AXIS_LOG("%p|%s sampled overscroll animation, leaving velocity at %f\n", + mAsyncPanZoomController, Name(), mVelocity); // Adjust the amount of overscroll based on the velocity. // Note that we allow for oscillations. mInUnderscroll tracks whether @@ -238,6 +245,8 @@ bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) { fabs(mVelocity) < gfxPrefs::APZOverscrollStopVelocityThreshold()) { // "Jump" to the at-rest state. The jump shouldn't be noticeable as the // velocity and overscroll are already low. + AXIS_LOG("%p|%s oscillation dropped below threshold, going to rest\n", + mAsyncPanZoomController, Name()); mOverscroll = 0; mVelocity = 0; mInUnderscroll = false; @@ -285,12 +294,16 @@ void Axis::EndTouch(uint32_t aTimestampMs) { if (count > 1) { mVelocity /= count; } + AXIS_LOG("%p|%s ending touch, computed velocity %f\n", + mAsyncPanZoomController, Name(), mVelocity); } void Axis::CancelTouch() { // mVelocityQueue is controller-thread only AsyncPanZoomController::AssertOnControllerThread(); + AXIS_LOG("%p|%s cancelling touch, clearing velocity queue\n", + mAsyncPanZoomController, Name()); mVelocity = 0.0f; while (!mVelocityQueue.IsEmpty()) { mVelocityQueue.RemoveElementAt(0); @@ -317,6 +330,8 @@ bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta, } else { mVelocity *= pow(1.0f - aFriction, float(aDelta.ToMilliseconds())); } + AXIS_LOG("%p|%s reduced velocity to %f due to friction\n", + mAsyncPanZoomController, Name(), mVelocity); return true; } @@ -373,6 +388,8 @@ float Axis::GetVelocity() const { } void Axis::SetVelocity(float aVelocity) { + AXIS_LOG("%p|%s direct-setting velocity to %f\n", + mAsyncPanZoomController, Name(), aVelocity); mVelocity = aVelocity; } @@ -441,6 +458,11 @@ ScreenPoint AxisX::MakePoint(ScreenCoord aCoord) const return ScreenPoint(aCoord, 0); } +const char* AxisX::Name() const +{ + return "X"; +} + AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController) : Axis(aAsyncPanZoomController) { @@ -467,5 +489,10 @@ ScreenPoint AxisY::MakePoint(ScreenCoord aCoord) const return ScreenPoint(0, aCoord); } +const char* AxisY::Name() const +{ + return "Y"; +} + } } diff --git a/gfx/layers/apz/src/Axis.h b/gfx/layers/apz/src/Axis.h index 4bc5236457c7..a0b8bf983b41 100644 --- a/gfx/layers/apz/src/Axis.h +++ b/gfx/layers/apz/src/Axis.h @@ -238,6 +238,8 @@ public: virtual ScreenPoint MakePoint(ScreenCoord aCoord) const = 0; + virtual const char* Name() const = 0; + protected: ParentLayerCoord mPos; uint32_t mPosTimeMs; @@ -270,6 +272,7 @@ public: virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE; virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE; + virtual const char* Name() const MOZ_OVERRIDE; }; class AxisY : public Axis { @@ -279,6 +282,7 @@ public: virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE; virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE; + virtual const char* Name() const MOZ_OVERRIDE; }; } diff --git a/gfx/layers/apz/src/InputBlockState.cpp b/gfx/layers/apz/src/InputBlockState.cpp index c8501883102c..d09ab0a01d3d 100644 --- a/gfx/layers/apz/src/InputBlockState.cpp +++ b/gfx/layers/apz/src/InputBlockState.cpp @@ -37,6 +37,7 @@ InputBlockState::SetConfirmedTargetApzc(const nsRefPtr& } mTargetConfirmed = true; + TBS_LOG("%p got confirmed target APZC %p\n", this, mTargetApzc.get()); if (mTargetApzc == aTargetApzc) { // The confirmed target is the same as the tentative one, so we're done. return true; diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index bc53115ded4b..49902647fa4f 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -60,6 +60,7 @@ InputQueue::ReceiveInputEvent(const nsRefPtr& aTarget, // If we're already in a fast fling, then we want the touch event to stop the fling // and to disallow the touch event from being used as part of a fling. block->SetDuringFastMotion(); + INPQ_LOG("block %p tagged as fast-motion\n", block); } block->GetOverscrollHandoffChain()->CancelAnimations(); } @@ -69,6 +70,7 @@ InputQueue::ReceiveInputEvent(const nsRefPtr& aTarget, waitForMainThread |= aTarget->NeedToWaitForContent(); } if (block->IsDuringFastMotion()) { + block->SetConfirmedTargetApzc(aTarget); waitForMainThread = false; } if (waitForMainThread) { diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index c6d01ddaac3d..e513dac3f573 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1805,8 +1805,8 @@ nsLayoutUtils::GetNearestScrollableFrame(nsIFrame* aFrame, uint32_t aFlags) } if (aFlags & SCROLLABLE_ALWAYS_MATCH_ROOT) { nsPresContext* pc = f->PresContext(); - if (pc->IsRootContentDocument() && pc->PresShell()->GetRootScrollFrame() == f) { - return scrollableFrame; + if (pc->IsRootContentDocument() && pc->PresShell()->GetRootFrame() == f) { + return pc->PresShell()->GetRootScrollFrameAsScrollable(); } } } diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index e35633b27f8b..dd30a8eeb003 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -586,7 +586,8 @@ public: SCROLLABLE_ONLY_ASYNC_SCROLLABLE = 0x04, /** * If the SCROLLABLE_ALWAYS_MATCH_ROOT flag is set, then return the - * root scrollable frame for the root content document if we hit it. + * root scrollable frame for the root content document if we don't hit + * anything else. */ SCROLLABLE_ALWAYS_MATCH_ROOT = 0x08, };