Bumping manifests a=b2g-bump
[gecko.git] / dom / bluetooth / BluetoothHidManager.cpp
blob3f08e09b148f27329f0ccc3f45afd6f6727448b6
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "BluetoothHidManager.h"
11 #include "BluetoothCommon.h"
12 #include "BluetoothService.h"
13 #include "BluetoothUtils.h"
15 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
16 #include "mozilla/Services.h"
17 #include "mozilla/StaticPtr.h"
18 #include "nsIObserverService.h"
19 #include "MainThreadUtils.h"
21 using namespace mozilla;
22 USING_BLUETOOTH_NAMESPACE
24 namespace {
25 StaticRefPtr<BluetoothHidManager> sBluetoothHidManager;
26 bool sInShutdown = false;
27 } // anonymous namespace
29 NS_IMETHODIMP
30 BluetoothHidManager::Observe(nsISupports* aSubject,
31 const char* aTopic,
32 const char16_t* aData)
34 MOZ_ASSERT(sBluetoothHidManager);
36 if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
37 HandleShutdown();
38 return NS_OK;
41 MOZ_ASSERT(false, "BluetoothHidManager got unexpected topic!");
42 return NS_ERROR_UNEXPECTED;
45 BluetoothHidManager::BluetoothHidManager()
47 Reset();
50 void
51 BluetoothHidManager::Reset()
53 mConnected = false;
54 mController = nullptr;
57 bool
58 BluetoothHidManager::Init()
60 MOZ_ASSERT(NS_IsMainThread());
62 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
63 NS_ENSURE_TRUE(obs, false);
64 if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
65 BT_WARNING("Failed to add shutdown observer!");
66 return false;
69 return true;
72 BluetoothHidManager::~BluetoothHidManager()
74 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
75 NS_ENSURE_TRUE_VOID(obs);
76 if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
77 BT_WARNING("Failed to remove shutdown observer!");
81 //static
82 BluetoothHidManager*
83 BluetoothHidManager::Get()
85 MOZ_ASSERT(NS_IsMainThread());
87 // If we already exist, exit early
88 if (sBluetoothHidManager) {
89 return sBluetoothHidManager;
92 // If we're in shutdown, don't create a new instance
93 NS_ENSURE_FALSE(sInShutdown, nullptr);
95 // Create a new instance, register, and return
96 BluetoothHidManager* manager = new BluetoothHidManager();
97 NS_ENSURE_TRUE(manager->Init(), nullptr);
99 sBluetoothHidManager = manager;
100 return sBluetoothHidManager;
103 void
104 BluetoothHidManager::HandleShutdown()
106 MOZ_ASSERT(NS_IsMainThread());
107 sInShutdown = true;
108 Disconnect(nullptr);
109 sBluetoothHidManager = nullptr;
112 void
113 BluetoothHidManager::Connect(const nsAString& aDeviceAddress,
114 BluetoothProfileController* aController)
116 MOZ_ASSERT(NS_IsMainThread());
117 MOZ_ASSERT(!aDeviceAddress.IsEmpty());
118 MOZ_ASSERT(aController && !mController);
120 BluetoothService* bs = BluetoothService::Get();
121 if (!bs || sInShutdown) {
122 aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
123 return;
126 if (mConnected) {
127 aController->NotifyCompletion(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
128 return;
131 mDeviceAddress = aDeviceAddress;
132 mController = aController;
134 if (NS_FAILED(bs->SendInputMessage(aDeviceAddress,
135 NS_LITERAL_STRING("Connect")))) {
136 aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
137 return;
141 void
142 BluetoothHidManager::Disconnect(BluetoothProfileController* aController)
144 MOZ_ASSERT(NS_IsMainThread());
146 BluetoothService* bs = BluetoothService::Get();
147 if (!bs) {
148 if (aController) {
149 aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
151 return;
154 if (!mConnected) {
155 if (aController) {
156 aController->NotifyCompletion(NS_LITERAL_STRING(ERR_ALREADY_DISCONNECTED));
158 return;
161 MOZ_ASSERT(!mDeviceAddress.IsEmpty());
162 MOZ_ASSERT(!mController);
164 mController = aController;
166 if (NS_FAILED(bs->SendInputMessage(mDeviceAddress,
167 NS_LITERAL_STRING("Disconnect")))) {
168 aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
169 return;
173 void
174 BluetoothHidManager::OnConnect(const nsAString& aErrorStr)
176 MOZ_ASSERT(NS_IsMainThread());
179 * On the one hand, notify the controller that we've done for outbound
180 * connections. On the other hand, we do nothing for inbound connections.
182 NS_ENSURE_TRUE_VOID(mController);
184 nsRefPtr<BluetoothProfileController> controller = mController.forget();
185 controller->NotifyCompletion(aErrorStr);
188 void
189 BluetoothHidManager::OnDisconnect(const nsAString& aErrorStr)
191 MOZ_ASSERT(NS_IsMainThread());
194 * On the one hand, notify the controller that we've done for outbound
195 * connections. On the other hand, we do nothing for inbound connections.
197 NS_ENSURE_TRUE_VOID(mController);
199 nsRefPtr<BluetoothProfileController> controller = mController.forget();
200 controller->NotifyCompletion(aErrorStr);
203 bool
204 BluetoothHidManager::IsConnected()
206 return mConnected;
209 void
210 BluetoothHidManager::HandleInputPropertyChanged(const BluetoothSignal& aSignal)
212 MOZ_ASSERT(NS_IsMainThread());
213 MOZ_ASSERT(aSignal.value().type() == BluetoothValue::TArrayOfBluetoothNamedValue);
215 const InfallibleTArray<BluetoothNamedValue>& arr =
216 aSignal.value().get_ArrayOfBluetoothNamedValue();
217 MOZ_ASSERT(arr.Length() == 1);
219 const nsString& name = arr[0].name();
220 const BluetoothValue& value = arr[0].value();
222 if (name.EqualsLiteral("Connected")) {
223 MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
224 MOZ_ASSERT(mConnected != value.get_bool());
226 mConnected = value.get_bool();
227 NotifyStatusChanged();
228 if (mConnected) {
229 OnConnect(EmptyString());
230 } else {
231 OnDisconnect(EmptyString());
236 void
237 BluetoothHidManager::NotifyStatusChanged()
239 MOZ_ASSERT(NS_IsMainThread());
241 NS_NAMED_LITERAL_STRING(type, BLUETOOTH_HID_STATUS_CHANGED_ID);
242 InfallibleTArray<BluetoothNamedValue> parameters;
244 BT_APPEND_NAMED_VALUE(parameters, "connected", mConnected);
245 BT_APPEND_NAMED_VALUE(parameters, "address", mDeviceAddress);
247 BT_ENSURE_TRUE_VOID_BROADCAST_SYSMSG(type, parameters);
250 void
251 BluetoothHidManager::OnGetServiceChannel(const nsAString& aDeviceAddress,
252 const nsAString& aServiceUuid,
253 int aChannel)
255 // Do nothing here as bluez acquires service channel and connects for us
258 void
259 BluetoothHidManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
261 // Do nothing here as bluez acquires service channel and connects for us
264 void
265 BluetoothHidManager::GetAddress(nsAString& aDeviceAddress)
267 aDeviceAddress = mDeviceAddress;
270 NS_IMPL_ISUPPORTS(BluetoothHidManager, nsIObserver)