/* -*- 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 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 FactoryCreate() { nsRefPtr 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& 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 bool SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow, 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; bool IsEnabled() const { return mEnabled; } bool IsToggling() const; void RemoveObserverFromTable(const nsAString& key); void DispatchToCommandThread(nsRunnable* aRunnable); 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(); /** * Due to the fact that some operations require multiple calls, a * CommandThread is created that can run blocking, platform-specific calls * where either no asynchronous equivilent exists, or else where multiple * asynchronous calls would require excessive runnable bouncing between main * thread and IO thread. * * For instance, when we retrieve an Adapter object, we would like it to come * with all of its properties filled in and registered as an agent, which * requires a minimum of 3 calls to platform specific code on some platforms. * */ nsCOMPtr mBluetoothCommandThread; typedef nsClassHashtable BluetoothSignalObserverTable; BluetoothSignalObserverTable mBluetoothSignalObserverTable; bool mEnabled; }; END_BLUETOOTH_NAMESPACE #endif