1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/bluetooth/BluetoothRilListener.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,425 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "BluetoothRilListener.h" 1.11 + 1.12 +#include "BluetoothHfpManager.h" 1.13 +#include "nsIDOMMobileConnection.h" 1.14 +#include "nsIRadioInterfaceLayer.h" 1.15 +#include "nsRadioInterfaceLayer.h" 1.16 +#include "nsServiceManagerUtils.h" 1.17 +#include "nsString.h" 1.18 + 1.19 +USING_BLUETOOTH_NAMESPACE 1.20 + 1.21 +/** 1.22 + * IccListener 1.23 + */ 1.24 +NS_IMPL_ISUPPORTS(IccListener, nsIIccListener) 1.25 + 1.26 +NS_IMETHODIMP 1.27 +IccListener::NotifyIccInfoChanged() 1.28 +{ 1.29 + // mOwner would be set to nullptr only in the dtor of BluetoothRilListener 1.30 + NS_ENSURE_TRUE(mOwner, NS_ERROR_FAILURE); 1.31 + 1.32 + BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); 1.33 + NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); 1.34 + 1.35 + hfp->HandleIccInfoChanged(mOwner->mClientId); 1.36 + 1.37 + return NS_OK; 1.38 +} 1.39 + 1.40 +NS_IMETHODIMP 1.41 +IccListener::NotifyStkCommand(const nsAString & aMessage) 1.42 +{ 1.43 + return NS_OK; 1.44 +} 1.45 + 1.46 +NS_IMETHODIMP 1.47 +IccListener::NotifyStkSessionEnd() 1.48 +{ 1.49 + return NS_OK; 1.50 +} 1.51 + 1.52 +NS_IMETHODIMP 1.53 +IccListener::NotifyCardStateChanged() 1.54 +{ 1.55 + return NS_OK; 1.56 +} 1.57 + 1.58 +bool 1.59 +IccListener::Listen(bool aStart) 1.60 +{ 1.61 + NS_ENSURE_TRUE(mOwner, false); 1.62 + 1.63 + nsCOMPtr<nsIIccProvider> provider = 1.64 + do_GetService(NS_RILCONTENTHELPER_CONTRACTID); 1.65 + NS_ENSURE_TRUE(provider, false); 1.66 + 1.67 + nsresult rv; 1.68 + if (aStart) { 1.69 + rv = provider->RegisterIccMsg(mOwner->mClientId, this); 1.70 + } else { 1.71 + rv = provider->UnregisterIccMsg(mOwner->mClientId, this); 1.72 + } 1.73 + 1.74 + return NS_SUCCEEDED(rv); 1.75 +} 1.76 + 1.77 +void 1.78 +IccListener::SetOwner(BluetoothRilListener *aOwner) 1.79 +{ 1.80 + mOwner = aOwner; 1.81 +} 1.82 + 1.83 +/** 1.84 + * MobileConnectionListener 1.85 + */ 1.86 +NS_IMPL_ISUPPORTS(MobileConnectionListener, nsIMobileConnectionListener) 1.87 + 1.88 +NS_IMETHODIMP 1.89 +MobileConnectionListener::NotifyVoiceChanged() 1.90 +{ 1.91 + BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); 1.92 + NS_ENSURE_TRUE(hfp, NS_OK); 1.93 + 1.94 + hfp->HandleVoiceConnectionChanged(mClientId); 1.95 + 1.96 + return NS_OK; 1.97 +} 1.98 + 1.99 +NS_IMETHODIMP 1.100 +MobileConnectionListener::NotifyDataChanged() 1.101 +{ 1.102 + return NS_OK; 1.103 +} 1.104 + 1.105 +NS_IMETHODIMP 1.106 +MobileConnectionListener::NotifyUssdReceived(const nsAString & message, 1.107 + bool sessionEnded) 1.108 +{ 1.109 + return NS_OK; 1.110 +} 1.111 + 1.112 +NS_IMETHODIMP 1.113 +MobileConnectionListener::NotifyDataError(const nsAString & message) 1.114 +{ 1.115 + return NS_OK; 1.116 +} 1.117 + 1.118 +NS_IMETHODIMP 1.119 +MobileConnectionListener::NotifyCFStateChange(bool success, 1.120 + uint16_t action, 1.121 + uint16_t reason, 1.122 + const nsAString& number, 1.123 + uint16_t timeSeconds, 1.124 + uint16_t serviceClass) 1.125 +{ 1.126 + return NS_OK; 1.127 +} 1.128 + 1.129 +NS_IMETHODIMP 1.130 +MobileConnectionListener::NotifyEmergencyCbModeChanged(bool active, 1.131 + uint32_t timeoutMs) 1.132 +{ 1.133 + return NS_OK; 1.134 +} 1.135 + 1.136 +NS_IMETHODIMP 1.137 +MobileConnectionListener::NotifyOtaStatusChanged(const nsAString & status) 1.138 +{ 1.139 + return NS_OK; 1.140 +} 1.141 + 1.142 +NS_IMETHODIMP 1.143 +MobileConnectionListener::NotifyIccChanged() 1.144 +{ 1.145 + return NS_OK; 1.146 +} 1.147 + 1.148 +NS_IMETHODIMP 1.149 +MobileConnectionListener::NotifyRadioStateChanged() 1.150 +{ 1.151 + return NS_OK; 1.152 +} 1.153 + 1.154 +bool 1.155 +MobileConnectionListener::Listen(bool aStart) 1.156 +{ 1.157 + nsCOMPtr<nsIMobileConnectionProvider> provider = 1.158 + do_GetService(NS_RILCONTENTHELPER_CONTRACTID); 1.159 + NS_ENSURE_TRUE(provider, false); 1.160 + 1.161 + nsresult rv; 1.162 + if (aStart) { 1.163 + rv = provider->RegisterMobileConnectionMsg(mClientId, this); 1.164 + } else { 1.165 + rv = provider->UnregisterMobileConnectionMsg(mClientId, this); 1.166 + } 1.167 + 1.168 + return NS_SUCCEEDED(rv); 1.169 +} 1.170 + 1.171 +/** 1.172 + * TelephonyListener Implementation 1.173 + */ 1.174 +NS_IMPL_ISUPPORTS(TelephonyListener, nsITelephonyListener) 1.175 + 1.176 +NS_IMETHODIMP 1.177 +TelephonyListener::CallStateChanged(uint32_t aServiceId, 1.178 + uint32_t aCallIndex, 1.179 + uint16_t aCallState, 1.180 + const nsAString& aNumber, 1.181 + bool aIsActive, 1.182 + bool aIsOutgoing, 1.183 + bool aIsEmergency, 1.184 + bool aIsConference, 1.185 + bool aIsSwitchable, 1.186 + bool aIsMergeable) 1.187 +{ 1.188 + BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); 1.189 + NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); 1.190 + 1.191 + hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber, 1.192 + aIsOutgoing, aIsConference, true); 1.193 + return NS_OK; 1.194 +} 1.195 + 1.196 +NS_IMETHODIMP 1.197 +TelephonyListener::EnumerateCallState(uint32_t aServiceId, 1.198 + uint32_t aCallIndex, 1.199 + uint16_t aCallState, 1.200 + const nsAString_internal& aNumber, 1.201 + bool aIsActive, 1.202 + bool aIsOutgoing, 1.203 + bool aIsEmergency, 1.204 + bool aIsConference, 1.205 + bool aIsSwitchable, 1.206 + bool aIsMergeable) 1.207 +{ 1.208 + BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); 1.209 + NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); 1.210 + 1.211 + hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber, 1.212 + aIsOutgoing, aIsConference, false); 1.213 + return NS_OK; 1.214 +} 1.215 + 1.216 +NS_IMETHODIMP 1.217 +TelephonyListener::NotifyError(uint32_t aServiceId, 1.218 + int32_t aCallIndex, 1.219 + const nsAString& aError) 1.220 +{ 1.221 + BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); 1.222 + NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); 1.223 + 1.224 + if (aCallIndex > 0) { 1.225 + // In order to not miss any related call state transition. 1.226 + // It's possible that 3G network signal lost for unknown reason. 1.227 + // If a call is released abnormally, NotifyError() will be called, 1.228 + // instead of CallStateChanged(). We need to reset the call array state 1.229 + // via setting CALL_STATE_DISCONNECTED 1.230 + hfp->HandleCallStateChanged(aCallIndex, 1.231 + nsITelephonyProvider::CALL_STATE_DISCONNECTED, 1.232 + aError, EmptyString(), false, false, true); 1.233 + BT_WARNING("Reset the call state due to call transition ends abnormally"); 1.234 + } 1.235 + 1.236 + BT_WARNING(NS_ConvertUTF16toUTF8(aError).get()); 1.237 + return NS_OK; 1.238 +} 1.239 + 1.240 +NS_IMETHODIMP 1.241 +TelephonyListener::ConferenceCallStateChanged(uint16_t aCallState) 1.242 +{ 1.243 + return NS_OK; 1.244 +} 1.245 + 1.246 +NS_IMETHODIMP 1.247 +TelephonyListener::EnumerateCallStateComplete() 1.248 +{ 1.249 + return NS_OK; 1.250 +} 1.251 + 1.252 +NS_IMETHODIMP 1.253 +TelephonyListener::SupplementaryServiceNotification(uint32_t aServiceId, 1.254 + int32_t aCallIndex, 1.255 + uint16_t aNotification) 1.256 +{ 1.257 + return NS_OK; 1.258 +} 1.259 + 1.260 +NS_IMETHODIMP 1.261 +TelephonyListener::NotifyConferenceError(const nsAString& aName, 1.262 + const nsAString& aMessage) 1.263 +{ 1.264 + BT_WARNING(NS_ConvertUTF16toUTF8(aName).get()); 1.265 + BT_WARNING(NS_ConvertUTF16toUTF8(aMessage).get()); 1.266 + 1.267 + return NS_OK; 1.268 +} 1.269 + 1.270 +NS_IMETHODIMP 1.271 +TelephonyListener::NotifyCdmaCallWaiting(uint32_t aServiceId, 1.272 + const nsAString& aNumber) 1.273 +{ 1.274 + BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); 1.275 + NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE); 1.276 + 1.277 + hfp->UpdateSecondNumber(aNumber); 1.278 + 1.279 + return NS_OK; 1.280 +} 1.281 + 1.282 +bool 1.283 +TelephonyListener::Listen(bool aStart) 1.284 +{ 1.285 + nsCOMPtr<nsITelephonyProvider> provider = 1.286 + do_GetService(TELEPHONY_PROVIDER_CONTRACTID); 1.287 + NS_ENSURE_TRUE(provider, false); 1.288 + 1.289 + nsresult rv; 1.290 + if (aStart) { 1.291 + rv = provider->RegisterListener(this); 1.292 + } else { 1.293 + rv = provider->UnregisterListener(this); 1.294 + } 1.295 + 1.296 + return NS_SUCCEEDED(rv); 1.297 +} 1.298 + 1.299 +/** 1.300 + * BluetoothRilListener 1.301 + */ 1.302 +BluetoothRilListener::BluetoothRilListener() 1.303 +{ 1.304 + // Query number of total clients (sim slots) 1.305 + uint32_t numOfClients; 1.306 + nsCOMPtr<nsIRadioInterfaceLayer> radioInterfaceLayer = 1.307 + do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID); 1.308 + NS_ENSURE_TRUE_VOID(radioInterfaceLayer); 1.309 + 1.310 + radioInterfaceLayer->GetNumRadioInterfaces(&numOfClients); 1.311 + 1.312 + // Init MobileConnectionListener array and IccInfoListener 1.313 + for (uint32_t i = 0; i < numOfClients; i++) { 1.314 + mMobileConnListeners.AppendElement(new MobileConnectionListener(i)); 1.315 + } 1.316 + 1.317 + mTelephonyListener = new TelephonyListener(); 1.318 + mIccListener = new IccListener(); 1.319 + mIccListener->SetOwner(this); 1.320 + 1.321 + // Probe for available client 1.322 + SelectClient(); 1.323 +} 1.324 + 1.325 +BluetoothRilListener::~BluetoothRilListener() 1.326 +{ 1.327 + mIccListener->SetOwner(nullptr); 1.328 +} 1.329 + 1.330 +bool 1.331 +BluetoothRilListener::Listen(bool aStart) 1.332 +{ 1.333 + NS_ENSURE_TRUE(ListenMobileConnAndIccInfo(aStart), false); 1.334 + NS_ENSURE_TRUE(mTelephonyListener->Listen(aStart), false); 1.335 + 1.336 + return true; 1.337 +} 1.338 + 1.339 +void 1.340 +BluetoothRilListener::SelectClient() 1.341 +{ 1.342 + // Reset mClientId 1.343 + mClientId = mMobileConnListeners.Length(); 1.344 + 1.345 + nsCOMPtr<nsIMobileConnectionProvider> connection = 1.346 + do_GetService(NS_RILCONTENTHELPER_CONTRACTID); 1.347 + NS_ENSURE_TRUE_VOID(connection); 1.348 + 1.349 + for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) { 1.350 + nsCOMPtr<nsIDOMMozMobileConnectionInfo> voiceInfo; 1.351 + connection->GetVoiceConnectionInfo(i, getter_AddRefs(voiceInfo)); 1.352 + if (!voiceInfo) { 1.353 + BT_WARNING("%s: Failed to get voice connection info", __FUNCTION__); 1.354 + continue; 1.355 + } 1.356 + 1.357 + nsString regState; 1.358 + voiceInfo->GetState(regState); 1.359 + if (regState.EqualsLiteral("registered")) { 1.360 + // Found available client 1.361 + mClientId = i; 1.362 + return; 1.363 + } 1.364 + } 1.365 +} 1.366 + 1.367 +void 1.368 +BluetoothRilListener::ServiceChanged(uint32_t aClientId, bool aRegistered) 1.369 +{ 1.370 + // Stop listening 1.371 + ListenMobileConnAndIccInfo(false); 1.372 + 1.373 + /** 1.374 + * aRegistered: 1.375 + * - TRUE: service becomes registered. We were listening to all clients 1.376 + * and one of them becomes available. Select it to listen. 1.377 + * - FALSE: service becomes un-registered. The client we were listening 1.378 + * becomes unavailable. Select another registered one to listen. 1.379 + */ 1.380 + if (aRegistered) { 1.381 + mClientId = aClientId; 1.382 + } else { 1.383 + SelectClient(); 1.384 + } 1.385 + 1.386 + // Restart listening 1.387 + ListenMobileConnAndIccInfo(true); 1.388 + 1.389 + BT_LOGR("%d client %d. new mClientId %d", aRegistered, aClientId, 1.390 + (mClientId < mMobileConnListeners.Length()) ? mClientId : -1); 1.391 +} 1.392 + 1.393 +void 1.394 +BluetoothRilListener::EnumerateCalls() 1.395 +{ 1.396 + nsCOMPtr<nsITelephonyProvider> provider = 1.397 + do_GetService(TELEPHONY_PROVIDER_CONTRACTID); 1.398 + NS_ENSURE_TRUE_VOID(provider); 1.399 + 1.400 + nsCOMPtr<nsITelephonyListener> listener( 1.401 + do_QueryObject(mTelephonyListener)); 1.402 + 1.403 + provider->EnumerateCalls(listener); 1.404 +} 1.405 + 1.406 +bool 1.407 +BluetoothRilListener::ListenMobileConnAndIccInfo(bool aStart) 1.408 +{ 1.409 + /** 1.410 + * mClientId < number of total clients: 1.411 + * The client with mClientId is available. Start/Stop listening 1.412 + * mobile connection and icc info of this client only. 1.413 + * 1.414 + * mClientId >= number of total clients: 1.415 + * All clients are unavailable. Start/Stop listening mobile 1.416 + * connections of all clients. 1.417 + */ 1.418 + if (mClientId < mMobileConnListeners.Length()) { 1.419 + NS_ENSURE_TRUE(mMobileConnListeners[mClientId]->Listen(aStart), false); 1.420 + NS_ENSURE_TRUE(mIccListener->Listen(aStart), false); 1.421 + } else { 1.422 + for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) { 1.423 + NS_ENSURE_TRUE(mMobileConnListeners[i]->Listen(aStart), false); 1.424 + } 1.425 + } 1.426 + 1.427 + return true; 1.428 +}