merge b2g-inbound to mozilla-central a=merge

--HG--
extra : amend_source : ad8bcefd86ba5855cbe5b98b7211a09d2a14e5b2
This commit is contained in:
Carsten "Tomcat" Book 2014-06-05 14:37:37 +02:00
commit 4cdea9d7c7
42 changed files with 551 additions and 327 deletions

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "7f0af1e164a39efb732c0c341c2a8e51f681d913",
"revision": "c3d40600c0090c5ca6ca4427f3a870ff443a109d",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -24,6 +24,9 @@
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#define ERR_INVALID_ADAPTER_STATE "InvalidAdapterStateError"
#define ERR_CHANGE_ADAPTER_STATE "ChangeAdapterStateError"
using namespace mozilla;
using namespace mozilla::dom;
@ -121,6 +124,7 @@ public:
BluetoothReplyRunnable::ReleaseMembers();
mAdapterPtr = nullptr;
}
private:
nsRefPtr<BluetoothAdapter> mAdapterPtr;
};
@ -156,6 +160,38 @@ public:
}
};
class EnableDisableAdapterTask : public BluetoothReplyRunnable
{
public:
EnableDisableAdapterTask(Promise* aPromise)
: BluetoothReplyRunnable(nullptr)
, mPromise(aPromise)
{ }
bool
ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
{
/*
* It is supposed to be Promise<void> according to BluetoothAdapter.webidl,
* but we have to pass "true" since it is mandatory to pass an
* argument while calling MaybeResolve.
*/
mPromise->MaybeResolve(true);
aValue.setUndefined();
return true;
}
void
ReleaseMembers()
{
BluetoothReplyRunnable::ReleaseMembers();
mPromise = nullptr;
}
private:
nsRefPtr<Promise> mPromise;
};
static int kCreatePairedDeviceTimeout = 50000; // unit: msec
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
@ -164,12 +200,13 @@ BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
, BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
, mJsUuids(nullptr)
, mJsDeviceAddresses(nullptr)
// TODO: Change to Disabled after Bug 1006309 landed
, mState(BluetoothAdapterState::Enabled)
, mDiscoverable(false)
, mDiscovering(false)
, mPairable(false)
, mPowered(false)
, mIsRooted(false)
, mState(BluetoothAdapterState::Disabled)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(IsDOMBinding());
@ -231,7 +268,11 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
{
const nsString& name = aValue.name();
const BluetoothValue& value = aValue.value();
if (name.EqualsLiteral("Name")) {
if (name.EqualsLiteral("State")) {
bool isEnabled = value.get_bool();
mState = isEnabled ? BluetoothAdapterState::Enabled
: BluetoothAdapterState::Disabled;
} else if (name.EqualsLiteral("Name")) {
mName = value.get_nsString();
} else if (name.EqualsLiteral("Address")) {
mAddress = value.get_nsString();
@ -669,19 +710,55 @@ BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
return request.forget();
}
/*
* TODO: Implement Enable/Disable functions
*/
already_AddRefed<Promise>
BluetoothAdapter::EnableDisable(bool aEnable)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
NS_ENSURE_TRUE(global, nullptr);
nsRefPtr<Promise> promise = new Promise(global);
// Make sure BluetoothService is available before modifying adapter state
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
promise->MaybeReject(ERR_CHANGE_ADAPTER_STATE);
return promise.forget();
}
if (aEnable) {
if (mState != BluetoothAdapterState::Disabled) {
promise->MaybeReject(ERR_INVALID_ADAPTER_STATE);
return promise.forget();
}
mState = BluetoothAdapterState::Enabling;
} else {
if (mState != BluetoothAdapterState::Enabled) {
promise->MaybeReject(ERR_INVALID_ADAPTER_STATE);
return promise.forget();
}
mState = BluetoothAdapterState::Disabling;
}
// TODO: Fire attr changed event for this state change
nsRefPtr<BluetoothReplyRunnable> result = new EnableDisableAdapterTask(promise);
if(NS_FAILED(bs->EnableDisable(aEnable, result))) {
promise->MaybeReject(ERR_CHANGE_ADAPTER_STATE);
}
return promise.forget();
}
already_AddRefed<Promise>
BluetoothAdapter::Enable()
{
return nullptr;
return EnableDisable(true);
}
already_AddRefed<Promise>
BluetoothAdapter::Disable()
{
return nullptr;
return EnableDisable(false);
}
already_AddRefed<DOMRequest>

View File

@ -122,10 +122,9 @@ public:
SetAuthorization(const nsAString& aDeviceAddress, bool aAllow,
ErrorResult& aRv);
already_AddRefed<Promise>
Enable();
already_AddRefed<Promise>
Disable();
already_AddRefed<Promise> EnableDisable(bool aEnable);
already_AddRefed<Promise> Enable();
already_AddRefed<Promise> Disable();
already_AddRefed<DOMRequest>
Connect(BluetoothDevice& aDevice,

View File

@ -163,14 +163,8 @@ BluetoothService::ToggleBtAck::Run()
sBluetoothService->SetEnabled(mEnabled);
sToggleInProgress = false;
nsAutoString signalName;
signalName = mEnabled ? NS_LITERAL_STRING("Enabled")
: NS_LITERAL_STRING("Disabled");
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true);
sBluetoothService->DistributeSignal(signal);
// Event 'AdapterAdded' has to be fired after firing 'Enabled'
sBluetoothService->TryFiringAdapterAdded();
sBluetoothService->FireAdapterStateChanged(mEnabled);
return NS_OK;
}
@ -220,19 +214,6 @@ BluetoothService::~BluetoothService()
Cleanup();
}
PLDHashOperator
RemoveObserversExceptBluetoothManager
(const nsAString& key,
nsAutoPtr<BluetoothSignalObserverList>& value,
void* arg)
{
if (!key.EqualsLiteral(KEY_MANAGER)) {
return PL_DHASH_REMOVE;
}
return PL_DHASH_NEXT;
}
// static
BluetoothService*
BluetoothService::Create()
@ -384,7 +365,8 @@ BluetoothService::DistributeSignal(const BluetoothSignal& aSignal)
}
nsresult
BluetoothService::StartBluetooth(bool aIsStartup)
BluetoothService::StartBluetooth(bool aIsStartup,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
@ -405,7 +387,7 @@ BluetoothService::StartBluetooth(bool aIsStartup)
*/
if (aIsStartup || !sBluetoothService->IsEnabled()) {
// Switch Bluetooth on
if (NS_FAILED(sBluetoothService->StartInternal())) {
if (NS_FAILED(sBluetoothService->StartInternal(aRunnable))) {
BT_WARNING("Bluetooth service failed to start!");
}
} else {
@ -420,7 +402,8 @@ BluetoothService::StartBluetooth(bool aIsStartup)
}
nsresult
BluetoothService::StopBluetooth(bool aIsStartup)
BluetoothService::StopBluetooth(bool aIsStartup,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
@ -466,7 +449,7 @@ BluetoothService::StopBluetooth(bool aIsStartup)
*/
if (aIsStartup || sBluetoothService->IsEnabled()) {
// Switch Bluetooth off
if (NS_FAILED(sBluetoothService->StopInternal())) {
if (NS_FAILED(sBluetoothService->StopInternal(aRunnable))) {
BT_WARNING("Bluetooth service failed to stop!");
}
} else {
@ -481,13 +464,15 @@ BluetoothService::StopBluetooth(bool aIsStartup)
}
nsresult
BluetoothService::StartStopBluetooth(bool aStart, bool aIsStartup)
BluetoothService::StartStopBluetooth(bool aStart,
bool aIsStartup,
BluetoothReplyRunnable* aRunnable)
{
nsresult rv;
if (aStart) {
rv = StartBluetooth(aIsStartup);
rv = StartBluetooth(aIsStartup, aRunnable);
} else {
rv = StopBluetooth(aIsStartup);
rv = StopBluetooth(aIsStartup, aRunnable);
}
return rv;
}
@ -504,17 +489,6 @@ BluetoothService::SetEnabled(bool aEnabled)
unused << childActors[index]->SendEnabled(aEnabled);
}
if (!aEnabled) {
/**
* Remove all handlers except BluetoothManager when turning off bluetooth
* since it is possible that the event 'onAdapterAdded' would be fired after
* BluetoothManagers of child process are registered. Please see Bug 827759
* for more details.
*/
mBluetoothSignalObserverTable.Enumerate(
RemoveObserversExceptBluetoothManager, nullptr);
}
/**
* mEnabled: real status of bluetooth
* aEnabled: expected status of bluetooth
@ -553,7 +527,7 @@ nsresult
BluetoothService::HandleStartupSettingsCheck(bool aEnable)
{
MOZ_ASSERT(NS_IsMainThread());
return StartStopBluetooth(aEnable, true);
return StartStopBluetooth(aEnable, true, nullptr);
}
nsresult
@ -610,37 +584,6 @@ BluetoothService::HandleSettingsChanged(const nsAString& aData)
}
SWITCH_BT_DEBUG(value.toBoolean());
return NS_OK;
}
// Second, check if the string is BLUETOOTH_ENABLED_SETTING
if (!JS_StringEqualsAscii(cx, key.toString(), BLUETOOTH_ENABLED_SETTING, &match)) {
MOZ_ASSERT(!JS_IsExceptionPending(cx));
return NS_ERROR_OUT_OF_MEMORY;
}
if (match) {
JS::Rooted<JS::Value> value(cx);
if (!JS_GetProperty(cx, obj, "value", &value)) {
MOZ_ASSERT(!JS_IsExceptionPending(cx));
return NS_ERROR_OUT_OF_MEMORY;
}
if (!value.isBoolean()) {
MOZ_ASSERT(false, "Expecting a boolean for 'bluetooth.enabled'!");
return NS_ERROR_UNEXPECTED;
}
if (sToggleInProgress || value.toBoolean() == IsEnabled()) {
// Nothing to do here.
return NS_OK;
}
sToggleInProgress = true;
nsresult rv = StartStopBluetooth(value.toBoolean(), false);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@ -704,7 +647,7 @@ BluetoothService::HandleShutdown()
}
}
if (IsEnabled() && NS_FAILED(StopBluetooth(false))) {
if (IsEnabled() && NS_FAILED(StopBluetooth(false, nullptr))) {
MOZ_ASSERT(false, "Failed to deliver stop message!");
}
@ -785,6 +728,38 @@ BluetoothService::AdapterAddedReceived()
mAdapterAddedReceived = true;
}
/**
* Enable/Disable the local adapter.
*
* There is only one adapter on the mobile in current use cases.
* In addition, bluedroid couldn't enable/disable a single adapter.
* So currently we will turn on/off BT to enable/disable the adapter.
*
* TODO: To support enable/disable single adapter in the future,
* we will need to implement EnableDisableInternal for different stacks.
*/
nsresult
BluetoothService::EnableDisable(bool aEnable,
BluetoothReplyRunnable* aRunnable)
{
sToggleInProgress = true;
return StartStopBluetooth(aEnable, false, aRunnable);
}
void
BluetoothService::FireAdapterStateChanged(bool aEnable)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> props;
BT_APPEND_NAMED_VALUE(props, "State", aEnable);
BluetoothValue value(props);
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), value);
DistributeSignal(signal);
}
void
BluetoothService::Notify(const BluetoothSignal& aData)
{

View File

@ -315,6 +315,28 @@ public:
void TryFiringAdapterAdded();
void AdapterAddedReceived();
void FireAdapterStateChanged(bool aEnable);
nsresult EnableDisable(bool aEnable,
BluetoothReplyRunnable* aRunnable);
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StartInternal(BluetoothReplyRunnable* aRunnable) = 0;
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StopInternal(BluetoothReplyRunnable* aRunnable) = 0;
protected:
BluetoothService() : mEnabled(false)
, mAdapterAddedReceived(false)
@ -330,31 +352,15 @@ protected:
Cleanup();
nsresult
StartBluetooth(bool aIsStartup);
StartBluetooth(bool aIsStartup, BluetoothReplyRunnable* aRunnable);
nsresult
StopBluetooth(bool aIsStartup);
StopBluetooth(bool aIsStartup, BluetoothReplyRunnable* aRunnable);
nsresult
StartStopBluetooth(bool aStart, bool aIsStartup);
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StartInternal() = 0;
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StopInternal() = 0;
StartStopBluetooth(bool aStart,
bool aIsStartup,
BluetoothReplyRunnable* aRunnable);
/**
* Called when XPCOM first creates this service.

View File

@ -33,34 +33,47 @@
#include "mozilla/StaticPtr.h"
#include "mozilla/unused.h"
#define ENSURE_BLUETOOTH_IS_READY(runnable, result) \
do { \
if (!sBtInterface || !IsEnabled()) { \
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth is not ready"); \
DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \
return result; \
} \
} while(0)
using namespace mozilla;
using namespace mozilla::ipc;
USING_BLUETOOTH_NAMESPACE
/**
* Static variables
*/
static bluetooth_device_t* sBtDevice;
static const bt_interface_t* sBtInterface;
static bool sAdapterDiscoverable = false;
static bool sIsBtEnabled = false;
// TODO: Non thread-safe static variables
static nsString sAdapterBdAddress;
static nsString sAdapterBdName;
static uint32_t sAdapterDiscoverableTimeout;
static InfallibleTArray<nsString> sAdapterBondedAddressArray;
static InfallibleTArray<BluetoothNamedValue> sRemoteDevicesPack;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeAdapterStateRunnableArray;
// Static variables below should only be used on *main thread*
static const bt_interface_t* sBtInterface;
static nsTArray<nsRefPtr<BluetoothProfileController> > sControllerArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
static nsTArray<int> sRequestedDeviceCountArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
// Static variables below should only be used on *callback thread*
// Atomic static variables
static Atomic<bool> sAdapterDiscoverable(false);
static Atomic<uint32_t> sAdapterDiscoverableTimeout(0);
/**
* Classes only used in this file
*/
class DistributeBluetoothSignalTask : public nsRunnable {
class DistributeBluetoothSignalTask MOZ_FINAL : public nsRunnable
{
public:
DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
mSignal(aSignal)
@ -84,12 +97,9 @@ private:
BluetoothSignal mSignal;
};
class SetupAfterEnabledTask : public nsRunnable
class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable
{
public:
SetupAfterEnabledTask()
{ }
NS_IMETHOD
Run()
{
@ -135,17 +145,37 @@ public:
}
};
class CleanupTask : public nsRunnable
class CleanupTask MOZ_FINAL : public nsRunnable
{
public:
CleanupTask()
{ }
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
/*
* Cleanup static adapter properties and notify adapter to clean them
*
* TODO: clean up and notify Discovering also
*/
sAdapterBdAddress.Truncate();
sAdapterBdName.Truncate();
sAdapterDiscoverable = false;
InfallibleTArray<BluetoothNamedValue> props;
BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName);
BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress);
BT_APPEND_NAMED_VALUE(props, "Discoverable",
BluetoothValue(sAdapterDiscoverable));
BluetoothValue value(props);
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), value);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
bs->DistributeSignal(signal);
// Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF.
BluetoothHfpManager::DeinitHfpInterface();
BluetoothA2dpManager::DeinitA2dpInterface();
@ -270,45 +300,69 @@ PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus)
return playStatus;
}
static bool
IsReady()
{
if (!sBtInterface || !sIsBtEnabled) {
BT_LOGR("Warning! Bluetooth Service is not ready");
return false;
}
return true;
}
/**
* Bluedroid HAL callback functions
*
* Several callbacks are dispatched to main thread to avoid racing issues.
*/
static void
AdapterStateChangeCallback(bt_state_t aStatus)
{
MOZ_ASSERT(!NS_IsMainThread());
BT_LOGR("BT_STATE %d", aStatus);
BT_LOGR("BT_STATE: %d", aStatus);
sIsBtEnabled = (aStatus == BT_STATE_ON);
bool isBtEnabled = (aStatus == BT_STATE_ON);
if (!sIsBtEnabled && NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
if (!isBtEnabled &&
NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(sIsBtEnabled);
new BluetoothService::ToggleBtAck(isBtEnabled);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
if (sIsBtEnabled &&
if (isBtEnabled &&
NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
// Resolve promise if existed
if(!sChangeAdapterStateRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sChangeAdapterStateRunnableArray[0],
BluetoothValue(true),
EmptyString());
sChangeAdapterStateRunnableArray.RemoveElementAt(0);
}
}
class AdapterPropertiesCallbackTask MOZ_FINAL : public nsRunnable
{
public:
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (!sSetPropertyRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sSetPropertyRunnableArray[0],
BluetoothValue(true), EmptyString());
sSetPropertyRunnableArray.RemoveElementAt(0);
}
return NS_OK;
}
};
/**
* AdapterPropertiesCallback will be called after enable() but before
* AdapterStateChangeCallback sIsBtEnabled get updated. At that moment, both
* AdapterStateChangeCallback is called. At that moment, both
* BluetoothManager/BluetoothAdapter does not register observer yet.
*/
static void
@ -385,14 +439,64 @@ AdapterPropertiesCallback(bt_status_t aStatus, int aNumProperties,
BT_WARNING("Failed to dispatch to main thread!");
}
// bluedroid BTU task was stored in the task queue, see GKI_send_msg
if (!sSetPropertyRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sSetPropertyRunnableArray[0], BluetoothValue(true),
EmptyString());
sSetPropertyRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new AdapterPropertiesCallbackTask());
}
class RemoteDevicePropertiesCallbackTask : public nsRunnable
{
const InfallibleTArray<BluetoothNamedValue> mProps;
nsString mRemoteDeviceBdAddress;
public:
RemoteDevicePropertiesCallbackTask(
const InfallibleTArray<BluetoothNamedValue>& aProps,
const nsAString& aRemoteDeviceBdAddress)
: mProps(aProps)
, mRemoteDeviceBdAddress(aRemoteDeviceBdAddress)
{ }
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (sRequestedDeviceCountArray.IsEmpty()) {
// This is possible because the callback would be called after turning
// Bluetooth on.
return NS_OK;
}
// Update to registered BluetoothDevice objects
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
mRemoteDeviceBdAddress, mProps);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
BT_WARNING("Failed to dispatch to main thread!");
return NS_OK;
}
static InfallibleTArray<BluetoothNamedValue> sRemoteDevicesPack;
// Use address as the index
sRemoteDevicesPack.AppendElement(
BluetoothNamedValue(mRemoteDeviceBdAddress, mProps));
if (--sRequestedDeviceCountArray[0] == 0) {
if (!sGetDeviceRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sGetDeviceRunnableArray[0],
sRemoteDevicesPack, EmptyString());
sGetDeviceRunnableArray.RemoveElementAt(0);
}
sRequestedDeviceCountArray.RemoveElementAt(0);
sRemoteDevicesPack.Clear();
}
return NS_OK;
}
};
/**
* RemoteDevicePropertiesCallback will be called, as the following conditions:
* 1. When BT is turning on, bluedroid automatically execute this callback
@ -404,13 +508,6 @@ RemoteDevicePropertiesCallback(bt_status_t aStatus, bt_bdaddr_t *aBdAddress,
{
MOZ_ASSERT(!NS_IsMainThread());
if (sRequestedDeviceCountArray.IsEmpty()) {
MOZ_ASSERT(sGetDeviceRunnableArray.IsEmpty());
return;
}
sRequestedDeviceCountArray[0]--;
InfallibleTArray<BluetoothNamedValue> props;
nsString remoteDeviceBdAddress;
@ -435,36 +532,9 @@ RemoteDevicePropertiesCallback(bt_status_t aStatus, bt_bdaddr_t *aBdAddress,
}
}
// Update to registered BluetoothDevice objects
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
remoteDeviceBdAddress, props);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
BT_WARNING("Failed to dispatch to main thread!");
}
// Use address as the index
sRemoteDevicesPack.AppendElement(
BluetoothNamedValue(remoteDeviceBdAddress, props));
if (sRequestedDeviceCountArray[0] == 0) {
MOZ_ASSERT(!sGetDeviceRunnableArray.IsEmpty());
if (sGetDeviceRunnableArray.IsEmpty()) {
BT_LOGR("No runnable to return");
return;
}
DispatchBluetoothReply(sGetDeviceRunnableArray[0],
sRemoteDevicesPack, EmptyString());
// After firing it, clean up cache
sRemoteDevicesPack.Clear();
sRequestedDeviceCountArray.RemoveElementAt(0);
sGetDeviceRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(
new RemoteDevicePropertiesCallbackTask(props, remoteDeviceBdAddress));
}
static void
@ -511,18 +581,33 @@ DeviceFoundCallback(int aNumProperties, bt_property_t *aProperties)
}
}
class DiscoveryStateChangedCallbackTask MOZ_FINAL : public nsRunnable
{
public:
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
BluetoothValue values(true);
DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
values, EmptyString());
sChangeDiscoveryRunnableArray.RemoveElementAt(0);
}
return NS_OK;
}
};
static void
DiscoveryStateChangedCallback(bt_discovery_state_t aState)
{
MOZ_ASSERT(!NS_IsMainThread());
if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
BluetoothValue values(true);
DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
values, EmptyString());
sChangeDiscoveryRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new DiscoveryStateChangedCallbackTask());
}
static void
@ -581,26 +666,75 @@ SspRequestCallback(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
}
}
class BondStateChangedCallbackTask : public nsRunnable
{
nsString mRemoteDeviceBdAddress;
bool mBonded;
public:
BondStateChangedCallbackTask(const nsAString& aRemoteDeviceBdAddress,
bool aBonded)
: mRemoteDeviceBdAddress(aRemoteDeviceBdAddress)
, mBonded(aBonded)
{ }
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (mBonded && !sBondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sBondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sBondingRunnableArray.RemoveElementAt(0);
} else if (!mBonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sUnbondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sUnbondingRunnableArray.RemoveElementAt(0);
}
// Update bonding status to gaia
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "address", mRemoteDeviceBdAddress);
BT_APPEND_NAMED_VALUE(propertiesArray, "status", mBonded);
BluetoothSignal signal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
return NS_OK;
}
};
static void
BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
bt_bond_state_t aState)
{
MOZ_ASSERT(!NS_IsMainThread());
nsAutoString remoteAddress;
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
if (aState == BT_BOND_STATE_BONDING) {
// No need to handle bonding state
return;
}
nsAutoString remoteBdAddress;
BdAddressTypeToString(aRemoteBdAddress, remoteBdAddress);
if (aState == BT_BOND_STATE_BONDED &&
sAdapterBondedAddressArray.Contains(remoteBdAddress)) {
// See bug 940271 for more details about this case.
return;
}
// We don't need to handle bonding state
NS_ENSURE_TRUE_VOID(aState != BT_BOND_STATE_BONDING);
NS_ENSURE_FALSE_VOID(aState == BT_BOND_STATE_BONDED &&
sAdapterBondedAddressArray.Contains(remoteAddress));
bool bonded;
if (aState == BT_BOND_STATE_NONE) {
bonded = false;
sAdapterBondedAddressArray.RemoveElement(remoteAddress);
sAdapterBondedAddressArray.RemoveElement(remoteBdAddress);
} else if (aState == BT_BOND_STATE_BONDED) {
bonded = true;
sAdapterBondedAddressArray.AppendElement(remoteAddress);
sAdapterBondedAddressArray.AppendElement(remoteBdAddress);
}
// Update bonded address list to BluetoothAdapter
@ -614,27 +748,9 @@ BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
BluetoothValue(propertiesChangeArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
// Update bonding status to gaia
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
BT_APPEND_NAMED_VALUE(propertiesArray, "status", bonded);
BluetoothSignal newSignal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(newSignal));
if (bonded && !sBondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sBondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sBondingRunnableArray.RemoveElementAt(0);
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sUnbondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sUnbondingRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(
new BondStateChangedCallbackTask(remoteBdAddress, bonded));
}
static void
@ -673,15 +789,17 @@ EnsureBluetoothHalLoad()
{
hw_module_t* module;
hw_device_t* device;
int err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err != 0) {
BT_LOGR("Error: %s", strerror(err));
return false;
}
module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
sBtDevice = (bluetooth_device_t *)device;
NS_ENSURE_TRUE(sBtDevice, false);
sBtInterface = sBtDevice->get_bluetooth_interface();
bluetooth_device_t* btDevice = (bluetooth_device_t *)device;
NS_ENSURE_TRUE(btDevice, false);
sBtInterface = btDevice->get_bluetooth_interface();
NS_ENSURE_TRUE(sBtInterface, false);
return true;
@ -709,12 +827,16 @@ static nsresult
StartStopGonkBluetooth(bool aShouldEnable)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
if (sIsBtEnabled == aShouldEnable) {
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
if (bs->IsEnabled() == aShouldEnable) {
// Keep current enable status
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(sIsBtEnabled);
new BluetoothService::ToggleBtAck(aShouldEnable);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
@ -772,10 +894,15 @@ BluetoothServiceBluedroid::~BluetoothServiceBluedroid()
}
nsresult
BluetoothServiceBluedroid::StartInternal()
BluetoothServiceBluedroid::StartInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
// aRunnable will be a nullptr while startup
if(aRunnable) {
sChangeAdapterStateRunnableArray.AppendElement(aRunnable);
}
nsresult ret = StartStopGonkBluetooth(true);
if (NS_FAILED(ret)) {
nsRefPtr<nsRunnable> runnable =
@ -790,10 +917,15 @@ BluetoothServiceBluedroid::StartInternal()
}
nsresult
BluetoothServiceBluedroid::StopInternal()
BluetoothServiceBluedroid::StopInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
// aRunnable will be a nullptr during starup and shutdown
if(aRunnable) {
sChangeAdapterStateRunnableArray.AppendElement(aRunnable);
}
nsresult ret = StartStopGonkBluetooth(false);
if (NS_FAILED(ret)) {
nsRefPtr<nsRunnable> runnable =
@ -828,6 +960,11 @@ BluetoothServiceBluedroid::GetAdaptersInternal(
uint32_t numAdapters = 1; // Bluedroid supports single adapter only
for (uint32_t i = 0; i < numAdapters; i++) {
// Since Atomic<*> is not acceptable for BT_APPEND_NAMED_VALUE(),
// create another variable to store data.
bool discoverable = sAdapterDiscoverable;
uint32_t discoverableTimeout = sAdapterDiscoverableTimeout;
BluetoothValue properties = InfallibleTArray<BluetoothNamedValue>();
// TODO: Revise here based on new BluetoothAdapter interface
@ -836,9 +973,9 @@ BluetoothServiceBluedroid::GetAdaptersInternal(
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"Name", sAdapterBdName);
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"Discoverable", sAdapterDiscoverable);
"Discoverable", discoverable);
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"DiscoverableTimeout", sAdapterDiscoverableTimeout);
"DiscoverableTimeout", discoverableTimeout);
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"Devices", sAdapterBondedAddressArray);
@ -856,11 +993,7 @@ BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
BluetoothProfileManagerBase* profile =
BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid);
@ -910,11 +1043,7 @@ BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
int requestedDeviceCount = aDeviceAddress.Length();
if (requestedDeviceCount == 0) {
@ -947,12 +1076,8 @@ BluetoothServiceBluedroid::StartDiscoveryInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
return NS_OK;
}
int ret = sBtInterface->start_discovery();
if (ret != BT_STATUS_SUCCESS) {
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StartDiscovery"));
@ -970,11 +1095,7 @@ BluetoothServiceBluedroid::StopDiscoveryInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
int ret = sBtInterface->cancel_discovery();
if (ret != BT_STATUS_SUCCESS) {
@ -994,12 +1115,7 @@ BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
const nsString propName = aValue.name();
bt_property_t prop;
@ -1072,11 +1188,7 @@ BluetoothServiceBluedroid::CreatePairedDeviceInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);
@ -1097,11 +1209,7 @@ BluetoothServiceBluedroid::RemoveDeviceInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);
@ -1124,11 +1232,7 @@ BluetoothServiceBluedroid::SetPinCodeInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return false;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);
@ -1161,11 +1265,7 @@ BluetoothServiceBluedroid::SetPairingConfirmationInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return false;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);

View File

@ -22,8 +22,8 @@ public:
BluetoothServiceBluedroid();
~BluetoothServiceBluedroid();
virtual nsresult StartInternal();
virtual nsresult StopInternal();
virtual nsresult StartInternal(BluetoothReplyRunnable* aRunnable);
virtual nsresult StopInternal(BluetoothReplyRunnable* aRunnable);
virtual nsresult
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable);

View File

@ -2097,8 +2097,10 @@ public:
};
nsresult
BluetoothDBusService::StartInternal()
BluetoothDBusService::StartInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(!aRunnable);
nsRefPtr<nsRunnable> runnable = new StartBluetoothRunnable();
nsresult rv = DispatchToBtThread(runnable);
if (NS_FAILED(rv)) {
@ -2225,8 +2227,10 @@ public:
};
nsresult
BluetoothDBusService::StopInternal()
BluetoothDBusService::StopInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(!aRunnable);
nsRefPtr<nsRunnable> runnable = new StopBluetoothRunnable();
nsresult rv = DispatchToBtThread(runnable);
if (NS_FAILED(rv)) {

View File

@ -47,9 +47,9 @@ public:
bool IsReady();
virtual nsresult StartInternal() MOZ_OVERRIDE;
virtual nsresult StartInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult StopInternal() MOZ_OVERRIDE;
virtual nsresult StopInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;

View File

@ -192,6 +192,10 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
switch (aRequest.type()) {
case Request::TGetAdaptersRequest:
return actor->DoRequest(aRequest.get_GetAdaptersRequest());
case Request::TStartBluetoothRequest:
return actor->DoRequest(aRequest.get_StartBluetoothRequest());
case Request::TStopBluetoothRequest:
return actor->DoRequest(aRequest.get_StopBluetoothRequest());
case Request::TSetPropertyRequest:
return actor->DoRequest(aRequest.get_SetPropertyRequest());
case Request::TStartDiscoveryRequest:
@ -321,6 +325,30 @@ BluetoothRequestParent::DoRequest(const GetAdaptersRequest& aRequest)
return true;
}
bool
BluetoothRequestParent::DoRequest(const StartBluetoothRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStartBluetoothRequest);
nsresult rv = mService->StartInternal(mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const StopBluetoothRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStopBluetoothRequest);
nsresult rv = mService->StopInternal(mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const SetPropertyRequest& aRequest)
{

View File

@ -128,6 +128,12 @@ protected:
bool
DoRequest(const GetAdaptersRequest& aRequest);
bool
DoRequest(const StartBluetoothRequest& aRequest);
bool
DoRequest(const StopBluetoothRequest& aRequest);
bool
DoRequest(const SetPropertyRequest& aRequest);

View File

@ -103,6 +103,20 @@ BluetoothServiceChildProcess::GetAdaptersInternal(
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StartInternal(BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StartBluetoothRequest());
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StopInternal(BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StopBluetoothRequest());
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::GetConnectedDevicePropertiesInternal(
uint16_t aServiceUuid,
@ -377,18 +391,6 @@ BluetoothServiceChildProcess::HandleShutdown()
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StartInternal()
{
MOZ_CRASH("This should never be called!");
}
nsresult
BluetoothServiceChildProcess::StopInternal()
{
MOZ_CRASH("This should never be called!");
}
bool
BluetoothServiceChildProcess::IsConnected(uint16_t aServiceUuid)
{

View File

@ -46,6 +46,12 @@ public:
virtual nsresult
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
StartInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
StopInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable)
@ -199,14 +205,6 @@ protected:
HandleShutdown() MOZ_OVERRIDE;
private:
// This method should never be called.
virtual nsresult
StartInternal() MOZ_OVERRIDE;
// This method should never be called.
virtual nsresult
StopInternal() MOZ_OVERRIDE;
bool
IsSignalRegistered(const nsAString& aNodeName) {
return !!mBluetoothSignalObserverTable.Get(aNodeName);

View File

@ -25,6 +25,14 @@ namespace bluetooth {
struct GetAdaptersRequest
{ };
struct StartBluetoothRequest
{
};
struct StopBluetoothRequest
{
};
struct SetPropertyRequest
{
BluetoothObjectType type;
@ -166,6 +174,8 @@ struct SendPlayStatusRequest
union Request
{
GetAdaptersRequest;
StartBluetoothRequest;
StopBluetoothRequest;
SetPropertyRequest;
GetPropertyRequest;
StartDiscoveryRequest;

View File

@ -2,6 +2,7 @@
* 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 "domstubs.idl"
#include "nsISupports.idl"
interface nsIDOMMozCellBroadcastEtwsInfo;
@ -10,7 +11,7 @@ interface nsIDOMMozCellBroadcastEtwsInfo;
* MozCellBroadcastMessage encapsulates Cell Broadcast short message service
* (CBS) messages.
*/
[scriptable, uuid(6abe65de-6729-41f7-906a-3f3a2dbe30ae)]
[scriptable, uuid(701e74a9-5fc4-4e2d-a324-9b7693395159)]
interface nsIDOMMozCellBroadcastMessage : nsISupports
{
/**
@ -53,7 +54,7 @@ interface nsIDOMMozCellBroadcastMessage : nsISupports
/**
* System time stamp at receival.
*/
readonly attribute jsval timestamp; // jsval is for Date.
readonly attribute DOMTimeStamp timestamp;
/**
* Additional ETWS-specific info.

View File

@ -196,7 +196,7 @@ function testReceiving_ETWS_Timestamp() {
doTestHelper(pdu, testReceiving_ETWS_WarningType, function(message) {
// Cell Broadcast messages do not contain a timestamp field (however, ETWS
// does). We only check the timestamp doesn't go too far (60 seconds) here.
let msMessage = message.timestamp.getTime();
let msMessage = message.timestamp;
let msNow = Date.now();
ok(Math.abs(msMessage - msNow) < (1000 * 60), "message.timestamp");
});

View File

@ -361,7 +361,7 @@ function testReceiving_GSM_Timestamp() {
doTestHelper(pdu, testReceiving_GSM_WarningType, function(message) {
// Cell Broadcast messages do not contain a timestamp field (however, ETWS
// does). We only check the timestamp doesn't go too far (60 seconds) here.
let msMessage = message.timestamp.getTime();
let msMessage = message.timestamp;
let msNow = Date.now();
ok(Math.abs(msMessage - msNow) < (1000 * 60), "message.timestamp");
});

View File

@ -7,5 +7,3 @@
DIRS += ['interfaces', 'src']
TEST_DIRS += ['tests']
if CONFIG['ENABLE_TESTS']:
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']

View File

@ -4,5 +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/.
MOCHITEST_MANIFESTS += ['mochitest.ini']
MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini']
if CONFIG['ENABLE_TESTS']:
XPCSHELL_TESTS_MANIFESTS += ['xpcshell/xpcshell.ini']

View File

@ -1,9 +1,6 @@
[DEFAULT]
head = header_helpers.js
tail =
support-files =
test_sms_basics.html
test_smsfilter.html
[test_smsservice_createsmsmessage.js]
[test_wsp_pdu_helper.js]

View File

@ -312,7 +312,7 @@ function CellBroadcastMessage(pdu) {
this.language = pdu.language;
this.body = pdu.fullBody;
this.messageClass = pdu.messageClass;
this.timestamp = new Date(pdu.timestamp);
this.timestamp = pdu.timestamp;
if (pdu.etws != null) {
this.etws = new CellBroadcastEtwsInfo(pdu.etws);

View File

@ -12791,9 +12791,17 @@ SimRecordHelperObject.prototype = {
let ICCUtilsHelper = this.context.ICCUtilsHelper;
let RIL = this.context.RIL;
// TS 31.102, clause 4.2.18 EFAD
let mncLength = 0;
if (ad && ad[3]) {
mncLength = ad[3] & 0x0f;
if (mncLength != 0x02 && mncLength != 0x03) {
mncLength = 0;
}
}
// The 4th byte of the response is the length of MNC.
let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi,
ad && ad[3]);
mncLength);
if (mccMnc) {
RIL.iccInfo.mcc = mccMnc.mcc;
RIL.iccInfo.mnc = mccMnc.mnc;
@ -14130,6 +14138,7 @@ ICCUtilsHelperObject.prototype = {
* The imsi of icc.
* @param mncLength [optional]
* The length of mnc.
* Zero indicates we haven't got a valid mnc length.
*
* @return An object contains the parsing result of mcc and mnc.
* Or null if any error occurred.

View File

@ -2504,7 +2504,7 @@ add_test(function test_reading_ad_and_parsing_mcc_mnc() {
io.loadTransparentEF = function fakeLoadTransparentEF(options) {
let ad = [0x00, 0x00, 0x00];
if (mncLengthInEf) {
if (typeof mncLengthInEf === 'number') {
ad.push(mncLengthInEf);
}
@ -2531,9 +2531,20 @@ add_test(function test_reading_ad_and_parsing_mcc_mnc() {
}
do_test(undefined, "466923202422409", "466", "92" );
do_test(0x00, "466923202422409", "466", "92" );
do_test(0x01, "466923202422409", "466", "92" );
do_test(0x02, "466923202422409", "466", "92" );
do_test(0x03, "466923202422409", "466", "923");
do_test(0x04, "466923202422409", "466", "92" );
do_test(0xff, "466923202422409", "466", "92" );
do_test(undefined, "310260542718417", "310", "260");
do_test(0x00, "310260542718417", "310", "260");
do_test(0x01, "310260542718417", "310", "260");
do_test(0x02, "310260542718417", "310", "26" );
do_test(0x03, "310260542718417", "310", "260");
do_test(0x04, "310260542718417", "310", "260");
do_test(0xff, "310260542718417", "310", "260");
run_next_test();
});

View File

@ -12,7 +12,7 @@
[include:dom/activities/tests/unit/xpcshell.ini]
[include:dom/apps/tests/unit/xpcshell.ini]
[include:dom/encoding/test/unit/xpcshell.ini]
[include:dom/mobilemessage/tests/xpcshell.ini]
[include:dom/mobilemessage/tests/xpcshell/xpcshell.ini]
[include:dom/network/tests/unit/xpcshell.ini]
[include:dom/payment/tests/unit/xpcshell.ini]
[include:dom/permission/tests/unit/xpcshell.ini]

View File

@ -3,7 +3,7 @@
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
[include:dom/apps/tests/unit/xpcshell.ini]
[include:dom/mobilemessage/tests/xpcshell.ini]
[include:dom/mobilemessage/tests/xpcshell/xpcshell.ini]
[include:dom/network/tests/unit_stats/xpcshell.ini]
[include:dom/system/gonk/tests/xpcshell.ini]
[include:dom/wappush/tests/xpcshell.ini]