Bug 872907 - Patch 3: Handle Sink property change, r=echou, r=mrbkap

This commit is contained in:
Gina Yeh 2013-06-08 23:25:41 +08:00
Родитель 0d6dda1c7a
Коммит 7acf3408a1
3 изменённых файлов: 139 добавлений и 5 удалений

Просмотреть файл

@ -87,9 +87,9 @@ BluetoothA2dpManagerObserver::Observe(nsISupports* aSubject,
NS_IMPL_ISUPPORTS1(BluetoothA2dpManagerObserver, nsIObserver)
BluetoothA2dpManager::BluetoothA2dpManager()
: mSinkState(SinkState::SINK_DISCONNECTED)
, mConnected(false)
: mConnected(false)
, mPlaying(false)
, mSinkState(SinkState::SINK_DISCONNECTED)
{
}
@ -119,6 +119,26 @@ BluetoothA2dpManager::Cleanup()
sA2dpObserver = nullptr;
}
static SinkState
StatusStringToSinkState(const nsAString& aStatus)
{
SinkState state;
if (aStatus.EqualsLiteral("disconnected")) {
state = SinkState::SINK_DISCONNECTED;
} else if (aStatus.EqualsLiteral("connecting")) {
state = SinkState::SINK_CONNECTING;
} else if (aStatus.EqualsLiteral("connected")) {
state = SinkState::SINK_CONNECTED;
} else if (aStatus.EqualsLiteral("playing")) {
state = SinkState::SINK_PLAYING;
} else if (aStatus.EqualsLiteral("disconnecting")) {
state = SinkState::SINK_DISCONNECTING;
} else {
MOZ_ASSERT(false, "Unknown sink state");
}
return state;
}
//static
BluetoothA2dpManager*
BluetoothA2dpManager::Get()
@ -194,3 +214,67 @@ BluetoothA2dpManager::Disconnect()
NS_ENSURE_TRUE_VOID(bs);
bs->SendSinkMessage(mDeviceAddress, NS_LITERAL_STRING("Disconnect"));
}
void
BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aSignal.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue);
const InfallibleTArray<BluetoothNamedValue>& arr =
aSignal.value().get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(arr.Length() == 1);
const nsString& name = arr[0].name();
const BluetoothValue& value = arr[0].value();
if (name.EqualsLiteral("Connected")) {
// Indicates if a stream is setup to a A2DP sink on the remote device.
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
mConnected = value.get_bool();
} else if (name.EqualsLiteral("Playing")) {
// Indicates if a stream is active to a A2DP sink on the remote device.
MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
mPlaying = value.get_bool();
} else if (name.EqualsLiteral("State")) {
MOZ_ASSERT(value.type() == BluetoothValue::TnsString);
HandleSinkStateChanged(StatusStringToSinkState(value.get_nsString()));
} else {
NS_WARNING("Unknown sink property");
}
}
/* HandleSinkPropertyChanged update sink state in A2dp
*
* Possible values: "disconnected", "connecting", "connected", "playing"
*
* 1. "disconnected" -> "connecting"
* Either an incoming or outgoing connection attempt ongoing
* 2. "connecting" -> "disconnected"
* Connection attempt failed
* 3. "connecting" -> "connected"
* Successfully connected
* 4. "connected" -> "playing"
* Audio stream active
* 5. "playing" -> "connected"
* Audio stream suspended
* 6. "connected" -> "disconnected"
* "playing" -> "disconnected"
* Disconnected from the remote device
* 7. "disconnecting" -> "disconnected"
* Disconnected from local
*/
void
BluetoothA2dpManager::HandleSinkStateChanged(SinkState aState)
{
MOZ_ASSERT_IF(aState == SinkState::SINK_CONNECTED,
mSinkState == SinkState::SINK_CONNECTING ||
mSinkState == SinkState::SINK_PLAYING);
MOZ_ASSERT_IF(aState == SinkState::SINK_PLAYING,
mSinkState == SinkState::SINK_CONNECTED);
if (aState == SinkState::SINK_DISCONNECTED) {
mDeviceAddress.Truncate();
}
mSinkState = aState;
}

Просмотреть файл

@ -39,6 +39,8 @@ private:
bool Init();
void Cleanup();
void HandleSinkStateChanged(SinkState aState);
bool mConnected;
bool mPlaying;
nsString mDeviceAddress;

Просмотреть файл

@ -18,6 +18,7 @@
#include "base/basictypes.h"
#include "BluetoothDBusService.h"
#include "BluetoothA2dpManager.h"
#include "BluetoothHfpManager.h"
#include "BluetoothOppManager.h"
#include "BluetoothReplyRunnable.h"
@ -116,6 +117,12 @@ static Properties sManagerProperties[] = {
{"Adapters", DBUS_TYPE_ARRAY},
};
static Properties sSinkProperties[] = {
{"State", DBUS_TYPE_STRING},
{"Connected", DBUS_TYPE_BOOLEAN},
{"Playing", DBUS_TYPE_BOOLEAN}
};
static const char* sBluetoothDBusIfaces[] =
{
DBUS_MANAGER_IFACE,
@ -349,6 +356,35 @@ private:
BluetoothSignal mSignal;
};
class SinkPropertyChangedHandler : public nsRunnable
{
public:
SinkPropertyChangedHandler(const BluetoothSignal& aSignal)
: mSignal(aSignal)
{
}
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mSignal.name().EqualsLiteral("PropertyChanged"));
MOZ_ASSERT(mSignal.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue);
// Replace object path with device address
nsString address = GetAddressFromObjectPath(mSignal.path());
mSignal.path() = address;
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE(a2dp, NS_ERROR_FAILURE);
a2dp->HandleSinkPropertyChanged(mSignal);
return NS_OK;
}
private:
BluetoothSignal mSignal;
};
static bool
IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
{
@ -1531,6 +1567,13 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
errorStr,
sManagerProperties,
ArrayLength(sManagerProperties));
} else if (dbus_message_is_signal(aMsg, DBUS_SINK_IFACE,
"PropertyChanged")) {
ParsePropertyChange(aMsg,
v,
errorStr,
sSinkProperties,
ArrayLength(sSinkProperties));
} else {
nsAutoCString signalStr;
signalStr += dbus_message_get_member(aMsg);
@ -1545,9 +1588,14 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
}
BluetoothSignal signal(signalName, signalPath, v);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
nsRefPtr<nsRunnable> task;
if (signalInterface.EqualsLiteral(DBUS_SINK_IFACE)) {
task = new SinkPropertyChangedHandler(signal);
} else {
task = new DistributeBluetoothSignalTask(signal);
}
if (NS_FAILED(NS_DispatchToMainThread(task))) {
NS_WARNING("Failed to dispatch to main thread!");
}