Bug 842948 - Patch 2: Handle control signal "PropertyChanged" and add IsConnected() in BluetoothProfileManagerBase, r=echou

This commit is contained in:
Gina Yeh 2013-07-29 17:32:34 +08:00
parent d368c340e4
commit e9527b054f
6 changed files with 169 additions and 64 deletions

View File

@ -45,10 +45,9 @@ BluetoothA2dpManager::Observe(nsISupports* aSubject,
}
BluetoothA2dpManager::BluetoothA2dpManager()
: mConnected(false)
, mPlaying(false)
, mSinkState(SinkState::SINK_DISCONNECTED)
{
ResetA2dp();
ResetAvrcp();
}
bool
@ -75,20 +74,34 @@ BluetoothA2dpManager::~BluetoothA2dpManager()
}
}
static SinkState
void
BluetoothA2dpManager::ResetA2dp()
{
mA2dpConnected = false;
mPlaying = false;
mSinkState = SinkState::SINK_DISCONNECTED;
}
void
BluetoothA2dpManager::ResetAvrcp()
{
mAvrcpConnected = false;
}
static BluetoothA2dpManager::SinkState
StatusStringToSinkState(const nsAString& aStatus)
{
SinkState state;
BluetoothA2dpManager::SinkState state;
if (aStatus.EqualsLiteral("disconnected")) {
state = SinkState::SINK_DISCONNECTED;
state = BluetoothA2dpManager::SinkState::SINK_DISCONNECTED;
} else if (aStatus.EqualsLiteral("connecting")) {
state = SinkState::SINK_CONNECTING;
state = BluetoothA2dpManager::SinkState::SINK_CONNECTING;
} else if (aStatus.EqualsLiteral("connected")) {
state = SinkState::SINK_CONNECTED;
state = BluetoothA2dpManager::SinkState::SINK_CONNECTED;
} else if (aStatus.EqualsLiteral("playing")) {
state = SinkState::SINK_PLAYING;
state = BluetoothA2dpManager::SinkState::SINK_PLAYING;
} else if (aStatus.EqualsLiteral("disconnecting")) {
state = SinkState::SINK_DISCONNECTING;
state = BluetoothA2dpManager::SinkState::SINK_DISCONNECTING;
} else {
MOZ_ASSERT(false, "Unknown sink state");
}
@ -140,7 +153,7 @@ BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress)
return false;
}
if (mConnected) {
if (mA2dpConnected) {
NS_WARNING("BluetoothA2dpManager is connected");
return false;
}
@ -158,7 +171,7 @@ BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress)
void
BluetoothA2dpManager::Disconnect()
{
if (!mConnected) {
if (!mA2dpConnected) {
NS_WARNING("BluetoothA2dpManager has been disconnected");
return;
}
@ -185,7 +198,7 @@ BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
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();
mA2dpConnected = value.get_bool();
NotifyStatusChanged();
NotifyAudioManager();
} else if (name.EqualsLiteral("Playing")) {
@ -244,7 +257,7 @@ BluetoothA2dpManager::NotifyStatusChanged()
NS_NAMED_LITERAL_STRING(type, BLUETOOTH_A2DP_STATUS_CHANGED_ID);
InfallibleTArray<BluetoothNamedValue> parameters;
BluetoothValue v = mConnected;
BluetoothValue v = mA2dpConnected;
parameters.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("connected"), v));
@ -268,7 +281,7 @@ BluetoothA2dpManager::NotifyAudioManager()
NS_ENSURE_TRUE_VOID(obs);
nsAutoString data;
data.AppendInt(mConnected);
data.AppendInt(mA2dpConnected);
if (NS_FAILED(obs->NotifyObservers(this,
BLUETOOTH_A2DP_STATUS_CHANGED_ID,
@ -295,5 +308,26 @@ BluetoothA2dpManager::GetAddress(nsAString& aDeviceAddress)
aDeviceAddress = mDeviceAddress;
}
bool
BluetoothA2dpManager::IsConnected()
{
return mA2dpConnected;
}
void
BluetoothA2dpManager::SetAvrcpConnected(bool aConnected)
{
mAvrcpConnected = aConnected;
if (!aConnected) {
ResetAvrcp();
}
}
bool
BluetoothA2dpManager::IsAvrcpConnected()
{
return mAvrcpConnected;
}
NS_IMPL_ISUPPORTS1(BluetoothA2dpManager, nsIObserver)

View File

@ -12,17 +12,7 @@
BEGIN_BLUETOOTH_NAMESPACE
enum SinkState {
SINK_DISCONNECTED = 1,
SINK_CONNECTING,
SINK_CONNECTED,
SINK_PLAYING,
SINK_DISCONNECTING
};
class BluetoothA2dpManagerObserver;
class BluetoothValue;
class BluetoothSocket;
class BluetoothA2dpManager : public BluetoothProfileManagerBase
{
@ -30,24 +20,39 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
enum SinkState {
SINK_DISCONNECTED = 1,
SINK_CONNECTING,
SINK_CONNECTED,
SINK_PLAYING,
SINK_DISCONNECTING
};
static BluetoothA2dpManager* Get();
~BluetoothA2dpManager();
void ResetA2dp();
void ResetAvrcp();
bool Connect(const nsAString& aDeviceAddress);
void Disconnect();
// Member functions inherited from parent class BluetoothProfileManagerBase
virtual void OnGetServiceChannel(const nsAString& aDeviceAddress,
const nsAString& aServiceUuid,
int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual bool IsConnected() MOZ_OVERRIDE;
// A2DP member functions
bool Connect(const nsAString& aDeviceAddress);
void Disconnect();
void HandleSinkPropertyChanged(const BluetoothSignal& aSignal);
// AVRCP member functions
void SetAvrcpConnected(bool aConnected);
bool IsAvrcpConnected();
private:
BluetoothA2dpManager();
bool Init();
void Cleanup();
void HandleSinkStateChanged(SinkState aState);
void HandleShutdown();
@ -55,10 +60,15 @@ private:
void NotifyStatusChanged();
void NotifyAudioManager();
bool mConnected;
bool mPlaying;
nsString mDeviceAddress;
// A2DP data member
bool mA2dpConnected;
bool mPlaying;
SinkState mSinkState;
// AVRCP data member
bool mAvrcpConnected;
};
END_BLUETOOTH_NAMESPACE

View File

@ -341,7 +341,7 @@ void
BluetoothOppManager::StartSendingNextFile()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsTransferring());
MOZ_ASSERT(!IsConnected());
MOZ_ASSERT(mBlobs.Length() > mCurrentBlobIndex + 1);
mIsServer = false;
@ -1104,7 +1104,7 @@ BluetoothOppManager::CheckPutFinal(uint32_t aNumRead)
}
bool
BluetoothOppManager::IsTransferring()
BluetoothOppManager::IsConnected()
{
return (mConnected && !mSendTransferCompleteFlag);
}

View File

@ -76,10 +76,6 @@ public:
bool ExtractBlobHeaders();
void CheckPutFinal(uint32_t aNumRead);
// Return true if there is an ongoing file-transfer session, please see
// Bug 827267 for more information.
bool IsTransferring();
// Implement interface BluetoothSocketObserver
void ReceiveSocketData(
BluetoothSocket* aSocket,
@ -93,6 +89,7 @@ public:
int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual bool IsConnected() MOZ_OVERRIDE;
private:
BluetoothOppManager();

View File

@ -30,6 +30,7 @@ public:
int aChannel) = 0;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) = 0;
virtual void GetAddress(nsAString& aDeviceAddress) = 0;
virtual bool IsConnected() = 0;
};
END_BLUETOOTH_NAMESPACE

View File

@ -73,6 +73,7 @@ USING_BLUETOOTH_NAMESPACE
#define ERR_A2DP_IS_DISCONNECTED "A2dpIsDisconnected"
#define ERR_AVRCP_IS_DISCONNECTED "AvrcpIsDisconnected"
#define ERR_UNKNOWN_PROFILE "UnknownProfileError"
typedef struct {
const char* name;
@ -216,6 +217,38 @@ private:
BluetoothSignal mSignal;
};
class ControlPropertyChangedHandler : public nsRunnable
{
public:
ControlPropertyChangedHandler(const BluetoothSignal& aSignal)
: mSignal(aSignal)
{
}
nsresult Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (mSignal.value().type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
BT_WARNING("Wrong value type for ControlPropertyChangedHandler");
return NS_ERROR_FAILURE;
}
InfallibleTArray<BluetoothNamedValue>& arr =
mSignal.value().get_ArrayOfBluetoothNamedValue();
MOZ_ASSERT(arr[0].name().EqualsLiteral("Connected"));
MOZ_ASSERT(arr[0].value().type() == BluetoothValue::Tbool);
bool connected = arr[0].value().get_bool();
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE(a2dp, NS_ERROR_FAILURE);
a2dp->SetAvrcpConnected(connected);
return NS_OK;
}
private:
BluetoothSignal mSignal;
};
class SinkPropertyChangedHandler : public nsRunnable
{
public:
@ -229,7 +262,8 @@ public:
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mSignal.name().EqualsLiteral("PropertyChanged"));
MOZ_ASSERT(mSignal.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue);
MOZ_ASSERT(mSignal.value().type() ==
BluetoothValue::TArrayOfBluetoothNamedValue);
// Replace object path with device address
nsString address = GetAddressFromObjectPath(mSignal.path());
@ -409,6 +443,11 @@ public:
return NS_ERROR_FAILURE;
}
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE(a2dp, NS_ERROR_FAILURE);
a2dp->ResetA2dp();
a2dp->ResetAvrcp();
return NS_OK;
}
};
@ -1450,6 +1489,12 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
errorStr,
sSinkProperties,
ArrayLength(sSinkProperties));
} else if (dbus_message_is_signal(aMsg, DBUS_CTL_IFACE, "PropertyChanged")) {
ParsePropertyChange(aMsg,
v,
errorStr,
sControlProperties,
ArrayLength(sControlProperties));
} else {
errorStr = NS_ConvertUTF8toUTF16(dbus_message_get_member(aMsg));
errorStr.AppendLiteral(" Signal not handled!");
@ -1464,6 +1509,8 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
nsRefPtr<nsRunnable> task;
if (signalInterface.EqualsLiteral(DBUS_SINK_IFACE)) {
task = new SinkPropertyChangedHandler(signal);
} else if (signalInterface.EqualsLiteral(DBUS_CTL_IFACE)) {
task = new ControlPropertyChangedHandler(signal);
} else {
task = new DistributeBluetoothSignalTask(signal);
}
@ -1908,37 +1955,30 @@ BluetoothDBusService::GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
}
nsTArray<nsString> deviceAddresses;
BluetoothProfileManagerBase* profile;
if (aProfileId == BluetoothServiceClass::HANDSFREE ||
aProfileId == BluetoothServiceClass::HEADSET) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
if (hfp->IsConnected()) {
nsString address;
hfp->GetAddress(address);
deviceAddresses.AppendElement(address);
}
profile = BluetoothHfpManager::Get();
} else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
BluetoothOppManager* opp = BluetoothOppManager::Get();
if (opp->IsTransferring()) {
nsString address;
opp->GetAddress(address);
deviceAddresses.AppendElement(address);
}
profile = BluetoothOppManager::Get();
} else {
errorStr.AssignLiteral("Unknown profile");
DispatchBluetoothReply(aRunnable, values, errorStr);
DispatchBluetoothReply(aRunnable, values,
NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
return NS_OK;
}
if (profile->IsConnected()) {
nsString address;
profile->GetAddress(address);
deviceAddresses.AppendElement(address);
}
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
nsRefPtr<nsRunnable> func(
new BluetoothArrayOfDevicePropertiesRunnable(deviceAddresses,
runnable,
GetConnectedDevicesFilter));
if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
NS_WARNING("Cannot dispatch task!");
return NS_ERROR_FAILURE;
}
mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL);
runnable.forget();
return NS_OK;
@ -2391,7 +2431,7 @@ BluetoothDBusService::Connect(const nsAString& aDeviceAddress,
opp->Connect(aDeviceAddress, aRunnable);
} else {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING("UnknownProfileError"));
NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
}
}
@ -2409,7 +2449,7 @@ BluetoothDBusService::Disconnect(const uint16_t aProfileId,
BluetoothOppManager* opp = BluetoothOppManager::Get();
opp->Disconnect();
} else {
NS_WARNING("Unknown profile");
BT_WARNING(ERR_UNKNOWN_PROFILE);
return;
}
@ -2424,16 +2464,19 @@ BluetoothDBusService::IsConnected(const uint16_t aProfileId)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothProfileManagerBase* profile;
if (aProfileId == BluetoothServiceClass::HANDSFREE ||
aProfileId == BluetoothServiceClass::HEADSET) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
return (hfp->IsConnected());
profile = BluetoothHfpManager::Get();
} else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) {
BluetoothOppManager* opp = BluetoothOppManager::Get();
return opp->IsTransferring();
profile = BluetoothOppManager::Get();
} else {
NS_WARNING(ERR_UNKNOWN_PROFILE);
return false;
}
return false;
NS_ENSURE_TRUE(profile, false);
return profile->IsConnected();
}
class ConnectBluetoothSocketRunnable : public nsRunnable
@ -2829,6 +2872,16 @@ BluetoothDBusService::SendMetaData(const nsAString& aTitle,
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE_VOID(a2dp);
if (!a2dp->IsConnected()) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_A2DP_IS_DISCONNECTED));
return;
} else if (!a2dp->IsAvrcpConnected()) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_AVRCP_IS_DISCONNECTED));
return;
}
nsAutoString address;
a2dp->GetAddress(address);
nsString objectPath =
@ -2916,6 +2969,16 @@ BluetoothDBusService::SendPlayStatus(uint32_t aDuration,
BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
NS_ENSURE_TRUE_VOID(a2dp);
if (!a2dp->IsConnected()) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_A2DP_IS_DISCONNECTED));
return;
} else if (!a2dp->IsAvrcpConnected()) {
DispatchBluetoothReply(aRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_AVRCP_IS_DISCONNECTED));
return;
}
nsAutoString address;
a2dp->GetAddress(address);
nsString objectPath =