mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
1d16ad0801
Starting and stopping Bluetooth support can block the executing thread for an indefinite amount of time. In most cases these operations are only performed when Gecko starts and stops, so we don't want to keep a separate Bluetooth command thread for this. This patch replaces the Bluetooth command thread by a LazyIdleThread, which only consumes resources while it executes actual code. After a timeout period, the LazyIdleThread cleans up its internal state. The timeout is currently 3 seconds, which has been choosen arbitrarily. Thanks to bent for helping with the details of LazyIdleThread.
407 lines
11 KiB
C++
407 lines
11 KiB
C++
/* -*- 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_bluetootheventservice_h__
|
|
#define mozilla_dom_bluetooth_bluetootheventservice_h__
|
|
|
|
#include "BluetoothCommon.h"
|
|
#include "BluetoothProfileManagerBase.h"
|
|
#include "mozilla/dom/ipc/Blob.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsClassHashtable.h"
|
|
#include "nsIObserver.h"
|
|
#include "nsIThread.h"
|
|
#include "nsTObserverArray.h"
|
|
|
|
namespace mozilla {
|
|
namespace ipc {
|
|
class UnixSocketConsumer;
|
|
}
|
|
}
|
|
|
|
BEGIN_BLUETOOTH_NAMESPACE
|
|
|
|
class BluetoothManager;
|
|
class BluetoothNamedValue;
|
|
class BluetoothReplyRunnable;
|
|
class BluetoothSignal;
|
|
|
|
typedef mozilla::ObserverList<BluetoothSignal> BluetoothSignalObserverList;
|
|
|
|
class BluetoothService : public nsIObserver
|
|
, public BluetoothSignalObserver
|
|
{
|
|
class ToggleBtAck;
|
|
friend class ToggleBtAck;
|
|
|
|
class ToggleBtTask;
|
|
friend class ToggleBtTask;
|
|
|
|
class StartupTask;
|
|
friend class StartupTask;
|
|
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
/**
|
|
* Add a message handler object from message distribution observer.
|
|
* Must be called from the main thread.
|
|
*
|
|
* @param aNodeName Node name of the object
|
|
* @param aMsgHandler Weak pointer to the object
|
|
*/
|
|
virtual void
|
|
RegisterBluetoothSignalHandler(const nsAString& aNodeName,
|
|
BluetoothSignalObserver* aMsgHandler);
|
|
|
|
/**
|
|
* Remove a message handler object from message distribution observer.
|
|
* Must be called from the main thread.
|
|
*
|
|
* @param aNodeName Node name of the object
|
|
* @param aMsgHandler Weak pointer to the object
|
|
*/
|
|
virtual void
|
|
UnregisterBluetoothSignalHandler(const nsAString& aNodeName,
|
|
BluetoothSignalObserver* aMsgHandler);
|
|
|
|
/**
|
|
* Remove a message handlers for the given observer.
|
|
* Must be called from the main thread.
|
|
*
|
|
* @param aMsgHandler Weak pointer to the object
|
|
*/
|
|
void
|
|
UnregisterAllSignalHandlers(BluetoothSignalObserver* aMsgHandler);
|
|
|
|
/**
|
|
* Distribute a signal to the observer list
|
|
*
|
|
* @param aSignal Signal object to distribute
|
|
*
|
|
* @return NS_OK if signal distributed, NS_ERROR_FAILURE on error
|
|
*/
|
|
void
|
|
DistributeSignal(const BluetoothSignal& aEvent);
|
|
|
|
/**
|
|
* Called when get a Bluetooth Signal from BluetoothDBusService
|
|
*
|
|
*/
|
|
void
|
|
Notify(const BluetoothSignal& aParam);
|
|
|
|
/**
|
|
* Returns the BluetoothService singleton. Only to be called from main thread.
|
|
*
|
|
* @param aService Pointer to return singleton into.
|
|
*
|
|
* @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise (if service
|
|
* has not yet been started, for instance)
|
|
*/
|
|
static BluetoothService*
|
|
Get();
|
|
|
|
static already_AddRefed<BluetoothService>
|
|
FactoryCreate()
|
|
{
|
|
nsRefPtr<BluetoothService> service = Get();
|
|
return service.forget();
|
|
}
|
|
|
|
/**
|
|
* Returns the path of the default adapter, implemented via a platform
|
|
* specific method.
|
|
*
|
|
* @return Default adapter path/name on success, NULL otherwise
|
|
*/
|
|
virtual nsresult
|
|
GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
/**
|
|
* Returns the properties of paired devices, implemented via a platform
|
|
* specific method.
|
|
*
|
|
* @return NS_OK on success, NS_ERROR_FAILURE otherwise
|
|
*/
|
|
virtual nsresult
|
|
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
/**
|
|
* Returns the properties of connected devices regarding to specific profile,
|
|
* implemented via a platform specific methood.
|
|
*
|
|
* @return NS_OK on success, NS_ERROR_FAILURE otherwise
|
|
*/
|
|
virtual nsresult
|
|
GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
/**
|
|
* Stop device discovery (platform specific implementation)
|
|
*
|
|
* @return NS_OK if discovery stopped correctly, false otherwise
|
|
*/
|
|
virtual nsresult
|
|
StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
/**
|
|
* Start device discovery (platform specific implementation)
|
|
*
|
|
* @return NS_OK if discovery stopped correctly, false otherwise
|
|
*/
|
|
virtual nsresult
|
|
StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
/**
|
|
* Set a property for the specified object
|
|
*
|
|
* @param aPropName Name of the property
|
|
* @param aValue Boolean value
|
|
* @param aRunnable Runnable to run on async reply
|
|
*
|
|
* @return NS_OK if property is set correctly, NS_ERROR_FAILURE otherwise
|
|
*/
|
|
virtual nsresult
|
|
SetProperty(BluetoothObjectType aType,
|
|
const BluetoothNamedValue& aValue,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
/**
|
|
* Get the path of a device
|
|
*
|
|
* @param aAdapterPath Path to the Adapter that's communicating with the device
|
|
* @param aDeviceAddress Device address (XX:XX:XX:XX:XX:XX format)
|
|
* @param aDevicePath Return value of path
|
|
*
|
|
* @return True if path set correctly, false otherwise
|
|
*/
|
|
virtual bool
|
|
GetDevicePath(const nsAString& aAdapterPath,
|
|
const nsAString& aDeviceAddress,
|
|
nsAString& aDevicePath) = 0;
|
|
|
|
virtual nsresult
|
|
CreatePairedDeviceInternal(const nsAString& aAddress,
|
|
int aTimeout,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual nsresult
|
|
RemoveDeviceInternal(const nsAString& aObjectPath,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual nsresult
|
|
GetScoSocket(const nsAString& aObjectPath,
|
|
bool aAuth,
|
|
bool aEncrypt,
|
|
mozilla::ipc::UnixSocketConsumer* aConsumer) = 0;
|
|
|
|
/**
|
|
* Get corresponding service channel of specific service on remote device.
|
|
* It's usually the very first step of establishing an outbound connection.
|
|
*
|
|
* @param aObjectPath Object path of remote device
|
|
* @param aServiceUuid UUID of the target service
|
|
* @param aManager Instance which has callback function OnGetServiceChannel()
|
|
*
|
|
* @return NS_OK if the task begins, NS_ERROR_FAILURE otherwise
|
|
*/
|
|
virtual nsresult
|
|
GetServiceChannel(const nsAString& aDeviceAddress,
|
|
const nsAString& aServiceUuid,
|
|
BluetoothProfileManagerBase* aManager) = 0;
|
|
|
|
virtual bool
|
|
UpdateSdpRecords(const nsAString& aDeviceAddress,
|
|
BluetoothProfileManagerBase* aManager) = 0;
|
|
|
|
virtual bool
|
|
SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual bool
|
|
SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual bool
|
|
SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
Connect(const nsAString& aDeviceAddress,
|
|
uint16_t aProfileId,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
Disconnect(uint16_t aProfileId, BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual bool
|
|
IsConnected(uint16_t aProfileId) = 0;
|
|
|
|
virtual void
|
|
SendFile(const nsAString& aDeviceAddress,
|
|
BlobParent* aBlobParent,
|
|
BlobChild* aBlobChild,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
StopSendingFile(const nsAString& aDeviceAddress,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
ConnectSco(BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
DisconnectSco(BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
IsScoConnected(BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
SendMetaData(const nsAString& aTitle,
|
|
const nsAString& aArtist,
|
|
const nsAString& aAlbum,
|
|
int64_t aMediaNumber,
|
|
int64_t aTotalMediaCount,
|
|
int64_t aDuration,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
SendPlayStatus(int64_t aDuration,
|
|
int64_t aPosition,
|
|
const nsAString& aPlayStatus,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
virtual void
|
|
UpdatePlayStatus(uint32_t aDuration,
|
|
uint32_t aPosition,
|
|
ControlPlayStatus aPlayStatus) = 0;
|
|
|
|
virtual nsresult
|
|
SendSinkMessage(const nsAString& aDeviceAddresses,
|
|
const nsAString& aMessage) = 0;
|
|
|
|
virtual nsresult
|
|
SendInputMessage(const nsAString& aDeviceAddresses,
|
|
const nsAString& aMessage,
|
|
BluetoothReplyRunnable* aRunnable) = 0;
|
|
|
|
bool
|
|
IsEnabled() const
|
|
{
|
|
return mEnabled;
|
|
}
|
|
|
|
bool
|
|
IsToggling() const;
|
|
|
|
void
|
|
RemoveObserverFromTable(const nsAString& key);
|
|
|
|
protected:
|
|
BluetoothService()
|
|
: mEnabled(false)
|
|
{
|
|
mBluetoothSignalObserverTable.Init();
|
|
}
|
|
|
|
virtual ~BluetoothService();
|
|
|
|
bool
|
|
Init();
|
|
|
|
void
|
|
Cleanup();
|
|
|
|
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;
|
|
|
|
/**
|
|
* Platform specific startup functions go here. Usually deals with member
|
|
* variables, so not static. Guaranteed to be called outside of main thread.
|
|
*
|
|
* @return true if Bluetooth is enabled, false otherwise
|
|
*/
|
|
virtual bool
|
|
IsEnabledInternal() = 0;
|
|
|
|
/**
|
|
* Called when XPCOM first creates this service.
|
|
*/
|
|
virtual nsresult
|
|
HandleStartup();
|
|
|
|
/**
|
|
* Called when the startup settings check has completed.
|
|
*/
|
|
nsresult
|
|
HandleStartupSettingsCheck(bool aEnable);
|
|
|
|
/**
|
|
* Called when "mozsettings-changed" observer topic fires.
|
|
*/
|
|
nsresult
|
|
HandleSettingsChanged(const nsAString& aData);
|
|
|
|
/**
|
|
* Called when XPCOM is shutting down.
|
|
*/
|
|
virtual nsresult
|
|
HandleShutdown();
|
|
|
|
// Called by ToggleBtAck.
|
|
void
|
|
SetEnabled(bool aEnabled);
|
|
|
|
// Called by Get().
|
|
static BluetoothService*
|
|
Create();
|
|
|
|
typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
|
|
BluetoothSignalObserverTable;
|
|
|
|
BluetoothSignalObserverTable mBluetoothSignalObserverTable;
|
|
|
|
bool mEnabled;
|
|
|
|
private:
|
|
/**
|
|
* Due to the fact that the startup and shutdown of the Bluetooth system
|
|
* can take an indefinite amount of time, a command thread is created
|
|
* that can run blocking calls. The thread is not intended for regular
|
|
* Bluetooth operations though.
|
|
*/
|
|
nsCOMPtr<nsIThread> mBluetoothThread;
|
|
};
|
|
|
|
END_BLUETOOTH_NAMESPACE
|
|
|
|
#endif
|