Bug 944262 - Part 1: [B2G] On conference call,we can't switch the speaker between off and on. r=vicamo, a=1.3+
authorHsin-Yi Tsai <htsai@mozilla.com>
Fri, 06 Dec 2013 16:02:28 +0800
changeset 175977 0e98e973fad6094823aecdd2c3b3977e08218e4d
parent 175976 9625ee0234de2c0cd5acdd4a4ff660fdbcfc266f
child 175978 995f9a8971a5cbadf6f4f72ae461b09f2ce247dc
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvicamo, 1
bugs944262
milestone28.0a2
Bug 944262 - Part 1: [B2G] On conference call,we can't switch the speaker between off and on. r=vicamo, a=1.3+
dom/telephony/gonk/TelephonyProvider.js
--- a/dom/telephony/gonk/TelephonyProvider.js
+++ b/dom/telephony/gonk/TelephonyProvider.js
@@ -78,16 +78,42 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "nsISystemMessagesInternal");
 
 XPCOMUtils.defineLazyGetter(this, "gPhoneNumberUtils", function () {
   let ns = {};
   Cu.import("resource://gre/modules/PhoneNumberUtils.jsm", ns);
   return ns.PhoneNumberUtils;
 });
 
+function SingleCall(options){
+  this.clientId = options.clientId;
+  this.callIndex = options.callIndex;
+  this.state = options.state;
+  this.number = options.number;
+  this.isOutgoing = options.isOutgoing;
+  this.isEmergency = options.isEmergency;
+  this.isConference = options.isConference;
+}
+SingleCall.prototype = {
+  clientId: null,
+  callIndex: null,
+  state: null,
+  number: null,
+  isOutgoing: false,
+  isEmergency: false,
+  isConference: false
+};
+
+function ConferenceCall(state){
+  this.state = state;
+}
+ConferenceCall.prototype = {
+  state: null
+};
+
 function TelephonyProvider() {
   this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
   this._listeners = [];
   this._updateDebugFlag();
   this.defaultServiceId = this._getDefaultServiceId();
 
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
   Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
@@ -157,65 +183,73 @@ TelephonyProvider.prototype = {
       try {
         handler.apply(listener, aArgs);
       } catch (e) {
         debug("listener for " + aMethodName + " threw an exception: " + e);
       }
     }
   },
 
-  _matchActiveCall: function _matchActiveCall(aCall) {
-    if (this._activeCall &&
-        this._activeCall.callIndex == aCall.callIndex &&
-        this._activeCall.clientId == aCall.clientId) {
-      return true;
-    }
-
-    return false;
+  _matchActiveSingleCall: function _matchActiveSingleCall(aCall) {
+    return this._activeCall &&
+           this._activeCall instanceof SingleCall &&
+           this._activeCall.clientId === aCall.clientId &&
+           this._activeCall.callIndex === aCall.callIndex;
   },
 
   /**
    * Track the active call and update the audio system as its state changes.
    */
   _activeCall: null,
   _updateCallAudioState: function _updateCallAudioState(aCall,
                                                         aConferenceState) {
     if (aConferenceState === nsITelephonyProvider.CALL_STATE_CONNECTED) {
+      this._activeCall = new ConferenceCall(aConferenceState);
       gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
       if (this.speakerEnabled) {
         gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
                                      nsIAudioManager.FORCE_SPEAKER);
       }
+      if (DEBUG) {
+        debug("Active call, put audio system into PHONE_STATE_IN_CALL: " +
+              gAudioManager.phoneState);
+      }
       return;
     }
+
     if (aConferenceState === nsITelephonyProvider.CALL_STATE_UNKNOWN ||
         aConferenceState === nsITelephonyProvider.CALL_STATE_HELD) {
-      if (!this._activeCall) {
+      if (this._activeCall instanceof ConferenceCall) {
+        this._activeCall = null;
         gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
+        if (DEBUG) {
+          debug("No active call, put audio system into PHONE_STATE_NORMAL: " +
+                gAudioManager.phoneState);
+        }
       }
       return;
     }
 
     if (!aCall) {
       return;
     }
 
     if (aCall.isConference) {
-      if (this._matchActiveCall(aCall)) {
+      if (this._matchActiveSingleCall(aCall)) {
         this._activeCall = null;
       }
       return;
     }
 
     switch (aCall.state) {
       case nsITelephonyProvider.CALL_STATE_DIALING: // Fall through...
       case nsITelephonyProvider.CALL_STATE_ALERTING:
       case nsITelephonyProvider.CALL_STATE_CONNECTED:
         aCall.isActive = true;
-        this._activeCall = aCall;
+        this._activeCall = new SingleCall(aCall);
         gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
         if (this.speakerEnabled) {
           gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
                                        nsIAudioManager.FORCE_SPEAKER);
         }
         if (DEBUG) {
           debug("Active call, put audio system into PHONE_STATE_IN_CALL: " +
                 gAudioManager.phoneState);
@@ -233,17 +267,17 @@ TelephonyProvider.prototype = {
                   gAudioManager.phoneState);
           }
         }
         break;
 
       case nsITelephonyProvider.CALL_STATE_HELD: // Fall through...
       case nsITelephonyProvider.CALL_STATE_DISCONNECTED:
         aCall.isActive = false;
-        if (this._matchActiveCall(aCall)) {
+        if (this._matchActiveSingleCall(aCall)) {
           // Previously active call is not active now.
           this._activeCall = null;
         }
 
         if (!this._activeCall) {
           // No active call. Disable the audio.
           gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
           if (DEBUG) {
@@ -350,17 +384,17 @@ TelephonyProvider.prototype = {
 
     let deferred = Promise.defer();
 
     this._getClient(aClientId).sendWorkerMessage("enumerateCalls", null,
                                                  (function(response) {
       for (let call of response.calls) {
         call.clientId = aClientId;
         call.state = this._convertRILCallState(call.state);
-        call.isActive = this._matchActiveCall(call);
+        call.isActive = this._matchActiveSingleCall(call);
 
         aListener.enumerateCallState(call.clientId, call.callIndex,
                                      call.state, call.number,
                                      call.isActive, call.isOutgoing,
                                      call.isEmergency, call.isConference);
       }
       deferred.resolve();
 
@@ -489,16 +523,17 @@ TelephonyProvider.prototype = {
       new Date().getTime() - aCall.started : 0;
     let data = {
       number: aCall.number,
       duration: duration,
       direction: aCall.isOutgoing ? "outgoing" : "incoming"
     };
     gSystemMessenger.broadcastMessage("telephony-call-ended", data);
 
+    aCall.clientId = aClientId;
     this._updateCallAudioState(aCall, null);
 
     if (!aCall.failCause ||
         aCall.failCause === RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) {
       this._notifyAllListeners("callStateChanged", [aClientId,
                                                     aCall.callIndex,
                                                     aCall.state,
                                                     aCall.number,
@@ -540,16 +575,17 @@ TelephonyProvider.prototype = {
   notifyCallStateChanged: function notifyCallStateChanged(aClientId, aCall) {
     if (DEBUG) debug("handleCallStateChange: " + JSON.stringify(aCall));
 
     aCall.state = this._convertRILCallState(aCall.state);
     if (aCall.state == nsITelephonyProvider.CALL_STATE_DIALING) {
       gSystemMessenger.broadcastMessage("telephony-new-call", {});
     }
 
+    aCall.clientId = aClientId;
     this._updateCallAudioState(aCall, null);
 
     this._notifyAllListeners("callStateChanged", [aClientId,
                                                   aCall.callIndex,
                                                   aCall.state,
                                                   aCall.number,
                                                   aCall.isActive,
                                                   aCall.isOutgoing,