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 a07f368f4e
commit 41d806ac30
6 changed files with 169 additions and 64 deletions

View File

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

View File

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

View File

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

View File

@ -76,10 +76,6 @@ public:
bool ExtractBlobHeaders(); bool ExtractBlobHeaders();
void CheckPutFinal(uint32_t aNumRead); 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 // Implement interface BluetoothSocketObserver
void ReceiveSocketData( void ReceiveSocketData(
BluetoothSocket* aSocket, BluetoothSocket* aSocket,
@ -93,6 +89,7 @@ public:
int aChannel) MOZ_OVERRIDE; int aChannel) MOZ_OVERRIDE;
virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE; virtual void OnUpdateSdpRecords(const nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE; virtual void GetAddress(nsAString& aDeviceAddress) MOZ_OVERRIDE;
virtual bool IsConnected() MOZ_OVERRIDE;
private: private:
BluetoothOppManager(); BluetoothOppManager();

View File

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

View File

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