dom/bluetooth/BluetoothRilListener.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:112fc54d5144
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/. */
6
7 #include "BluetoothRilListener.h"
8
9 #include "BluetoothHfpManager.h"
10 #include "nsIDOMMobileConnection.h"
11 #include "nsIRadioInterfaceLayer.h"
12 #include "nsRadioInterfaceLayer.h"
13 #include "nsServiceManagerUtils.h"
14 #include "nsString.h"
15
16 USING_BLUETOOTH_NAMESPACE
17
18 /**
19 * IccListener
20 */
21 NS_IMPL_ISUPPORTS(IccListener, nsIIccListener)
22
23 NS_IMETHODIMP
24 IccListener::NotifyIccInfoChanged()
25 {
26 // mOwner would be set to nullptr only in the dtor of BluetoothRilListener
27 NS_ENSURE_TRUE(mOwner, NS_ERROR_FAILURE);
28
29 BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
30 NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
31
32 hfp->HandleIccInfoChanged(mOwner->mClientId);
33
34 return NS_OK;
35 }
36
37 NS_IMETHODIMP
38 IccListener::NotifyStkCommand(const nsAString & aMessage)
39 {
40 return NS_OK;
41 }
42
43 NS_IMETHODIMP
44 IccListener::NotifyStkSessionEnd()
45 {
46 return NS_OK;
47 }
48
49 NS_IMETHODIMP
50 IccListener::NotifyCardStateChanged()
51 {
52 return NS_OK;
53 }
54
55 bool
56 IccListener::Listen(bool aStart)
57 {
58 NS_ENSURE_TRUE(mOwner, false);
59
60 nsCOMPtr<nsIIccProvider> provider =
61 do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
62 NS_ENSURE_TRUE(provider, false);
63
64 nsresult rv;
65 if (aStart) {
66 rv = provider->RegisterIccMsg(mOwner->mClientId, this);
67 } else {
68 rv = provider->UnregisterIccMsg(mOwner->mClientId, this);
69 }
70
71 return NS_SUCCEEDED(rv);
72 }
73
74 void
75 IccListener::SetOwner(BluetoothRilListener *aOwner)
76 {
77 mOwner = aOwner;
78 }
79
80 /**
81 * MobileConnectionListener
82 */
83 NS_IMPL_ISUPPORTS(MobileConnectionListener, nsIMobileConnectionListener)
84
85 NS_IMETHODIMP
86 MobileConnectionListener::NotifyVoiceChanged()
87 {
88 BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
89 NS_ENSURE_TRUE(hfp, NS_OK);
90
91 hfp->HandleVoiceConnectionChanged(mClientId);
92
93 return NS_OK;
94 }
95
96 NS_IMETHODIMP
97 MobileConnectionListener::NotifyDataChanged()
98 {
99 return NS_OK;
100 }
101
102 NS_IMETHODIMP
103 MobileConnectionListener::NotifyUssdReceived(const nsAString & message,
104 bool sessionEnded)
105 {
106 return NS_OK;
107 }
108
109 NS_IMETHODIMP
110 MobileConnectionListener::NotifyDataError(const nsAString & message)
111 {
112 return NS_OK;
113 }
114
115 NS_IMETHODIMP
116 MobileConnectionListener::NotifyCFStateChange(bool success,
117 uint16_t action,
118 uint16_t reason,
119 const nsAString& number,
120 uint16_t timeSeconds,
121 uint16_t serviceClass)
122 {
123 return NS_OK;
124 }
125
126 NS_IMETHODIMP
127 MobileConnectionListener::NotifyEmergencyCbModeChanged(bool active,
128 uint32_t timeoutMs)
129 {
130 return NS_OK;
131 }
132
133 NS_IMETHODIMP
134 MobileConnectionListener::NotifyOtaStatusChanged(const nsAString & status)
135 {
136 return NS_OK;
137 }
138
139 NS_IMETHODIMP
140 MobileConnectionListener::NotifyIccChanged()
141 {
142 return NS_OK;
143 }
144
145 NS_IMETHODIMP
146 MobileConnectionListener::NotifyRadioStateChanged()
147 {
148 return NS_OK;
149 }
150
151 bool
152 MobileConnectionListener::Listen(bool aStart)
153 {
154 nsCOMPtr<nsIMobileConnectionProvider> provider =
155 do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
156 NS_ENSURE_TRUE(provider, false);
157
158 nsresult rv;
159 if (aStart) {
160 rv = provider->RegisterMobileConnectionMsg(mClientId, this);
161 } else {
162 rv = provider->UnregisterMobileConnectionMsg(mClientId, this);
163 }
164
165 return NS_SUCCEEDED(rv);
166 }
167
168 /**
169 * TelephonyListener Implementation
170 */
171 NS_IMPL_ISUPPORTS(TelephonyListener, nsITelephonyListener)
172
173 NS_IMETHODIMP
174 TelephonyListener::CallStateChanged(uint32_t aServiceId,
175 uint32_t aCallIndex,
176 uint16_t aCallState,
177 const nsAString& aNumber,
178 bool aIsActive,
179 bool aIsOutgoing,
180 bool aIsEmergency,
181 bool aIsConference,
182 bool aIsSwitchable,
183 bool aIsMergeable)
184 {
185 BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
186 NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
187
188 hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber,
189 aIsOutgoing, aIsConference, true);
190 return NS_OK;
191 }
192
193 NS_IMETHODIMP
194 TelephonyListener::EnumerateCallState(uint32_t aServiceId,
195 uint32_t aCallIndex,
196 uint16_t aCallState,
197 const nsAString_internal& aNumber,
198 bool aIsActive,
199 bool aIsOutgoing,
200 bool aIsEmergency,
201 bool aIsConference,
202 bool aIsSwitchable,
203 bool aIsMergeable)
204 {
205 BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
206 NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
207
208 hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber,
209 aIsOutgoing, aIsConference, false);
210 return NS_OK;
211 }
212
213 NS_IMETHODIMP
214 TelephonyListener::NotifyError(uint32_t aServiceId,
215 int32_t aCallIndex,
216 const nsAString& aError)
217 {
218 BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
219 NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
220
221 if (aCallIndex > 0) {
222 // In order to not miss any related call state transition.
223 // It's possible that 3G network signal lost for unknown reason.
224 // If a call is released abnormally, NotifyError() will be called,
225 // instead of CallStateChanged(). We need to reset the call array state
226 // via setting CALL_STATE_DISCONNECTED
227 hfp->HandleCallStateChanged(aCallIndex,
228 nsITelephonyProvider::CALL_STATE_DISCONNECTED,
229 aError, EmptyString(), false, false, true);
230 BT_WARNING("Reset the call state due to call transition ends abnormally");
231 }
232
233 BT_WARNING(NS_ConvertUTF16toUTF8(aError).get());
234 return NS_OK;
235 }
236
237 NS_IMETHODIMP
238 TelephonyListener::ConferenceCallStateChanged(uint16_t aCallState)
239 {
240 return NS_OK;
241 }
242
243 NS_IMETHODIMP
244 TelephonyListener::EnumerateCallStateComplete()
245 {
246 return NS_OK;
247 }
248
249 NS_IMETHODIMP
250 TelephonyListener::SupplementaryServiceNotification(uint32_t aServiceId,
251 int32_t aCallIndex,
252 uint16_t aNotification)
253 {
254 return NS_OK;
255 }
256
257 NS_IMETHODIMP
258 TelephonyListener::NotifyConferenceError(const nsAString& aName,
259 const nsAString& aMessage)
260 {
261 BT_WARNING(NS_ConvertUTF16toUTF8(aName).get());
262 BT_WARNING(NS_ConvertUTF16toUTF8(aMessage).get());
263
264 return NS_OK;
265 }
266
267 NS_IMETHODIMP
268 TelephonyListener::NotifyCdmaCallWaiting(uint32_t aServiceId,
269 const nsAString& aNumber)
270 {
271 BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
272 NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
273
274 hfp->UpdateSecondNumber(aNumber);
275
276 return NS_OK;
277 }
278
279 bool
280 TelephonyListener::Listen(bool aStart)
281 {
282 nsCOMPtr<nsITelephonyProvider> provider =
283 do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
284 NS_ENSURE_TRUE(provider, false);
285
286 nsresult rv;
287 if (aStart) {
288 rv = provider->RegisterListener(this);
289 } else {
290 rv = provider->UnregisterListener(this);
291 }
292
293 return NS_SUCCEEDED(rv);
294 }
295
296 /**
297 * BluetoothRilListener
298 */
299 BluetoothRilListener::BluetoothRilListener()
300 {
301 // Query number of total clients (sim slots)
302 uint32_t numOfClients;
303 nsCOMPtr<nsIRadioInterfaceLayer> radioInterfaceLayer =
304 do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID);
305 NS_ENSURE_TRUE_VOID(radioInterfaceLayer);
306
307 radioInterfaceLayer->GetNumRadioInterfaces(&numOfClients);
308
309 // Init MobileConnectionListener array and IccInfoListener
310 for (uint32_t i = 0; i < numOfClients; i++) {
311 mMobileConnListeners.AppendElement(new MobileConnectionListener(i));
312 }
313
314 mTelephonyListener = new TelephonyListener();
315 mIccListener = new IccListener();
316 mIccListener->SetOwner(this);
317
318 // Probe for available client
319 SelectClient();
320 }
321
322 BluetoothRilListener::~BluetoothRilListener()
323 {
324 mIccListener->SetOwner(nullptr);
325 }
326
327 bool
328 BluetoothRilListener::Listen(bool aStart)
329 {
330 NS_ENSURE_TRUE(ListenMobileConnAndIccInfo(aStart), false);
331 NS_ENSURE_TRUE(mTelephonyListener->Listen(aStart), false);
332
333 return true;
334 }
335
336 void
337 BluetoothRilListener::SelectClient()
338 {
339 // Reset mClientId
340 mClientId = mMobileConnListeners.Length();
341
342 nsCOMPtr<nsIMobileConnectionProvider> connection =
343 do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
344 NS_ENSURE_TRUE_VOID(connection);
345
346 for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) {
347 nsCOMPtr<nsIDOMMozMobileConnectionInfo> voiceInfo;
348 connection->GetVoiceConnectionInfo(i, getter_AddRefs(voiceInfo));
349 if (!voiceInfo) {
350 BT_WARNING("%s: Failed to get voice connection info", __FUNCTION__);
351 continue;
352 }
353
354 nsString regState;
355 voiceInfo->GetState(regState);
356 if (regState.EqualsLiteral("registered")) {
357 // Found available client
358 mClientId = i;
359 return;
360 }
361 }
362 }
363
364 void
365 BluetoothRilListener::ServiceChanged(uint32_t aClientId, bool aRegistered)
366 {
367 // Stop listening
368 ListenMobileConnAndIccInfo(false);
369
370 /**
371 * aRegistered:
372 * - TRUE: service becomes registered. We were listening to all clients
373 * and one of them becomes available. Select it to listen.
374 * - FALSE: service becomes un-registered. The client we were listening
375 * becomes unavailable. Select another registered one to listen.
376 */
377 if (aRegistered) {
378 mClientId = aClientId;
379 } else {
380 SelectClient();
381 }
382
383 // Restart listening
384 ListenMobileConnAndIccInfo(true);
385
386 BT_LOGR("%d client %d. new mClientId %d", aRegistered, aClientId,
387 (mClientId < mMobileConnListeners.Length()) ? mClientId : -1);
388 }
389
390 void
391 BluetoothRilListener::EnumerateCalls()
392 {
393 nsCOMPtr<nsITelephonyProvider> provider =
394 do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
395 NS_ENSURE_TRUE_VOID(provider);
396
397 nsCOMPtr<nsITelephonyListener> listener(
398 do_QueryObject(mTelephonyListener));
399
400 provider->EnumerateCalls(listener);
401 }
402
403 bool
404 BluetoothRilListener::ListenMobileConnAndIccInfo(bool aStart)
405 {
406 /**
407 * mClientId < number of total clients:
408 * The client with mClientId is available. Start/Stop listening
409 * mobile connection and icc info of this client only.
410 *
411 * mClientId >= number of total clients:
412 * All clients are unavailable. Start/Stop listening mobile
413 * connections of all clients.
414 */
415 if (mClientId < mMobileConnListeners.Length()) {
416 NS_ENSURE_TRUE(mMobileConnListeners[mClientId]->Listen(aStart), false);
417 NS_ENSURE_TRUE(mIccListener->Listen(aStart), false);
418 } else {
419 for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) {
420 NS_ENSURE_TRUE(mMobileConnListeners[i]->Listen(aStart), false);
421 }
422 }
423
424 return true;
425 }

mercurial