Bug 1077190 - Part 1: Correct the logic of audio state setting. r=hsinyi
authorSzu-Yu Chen [:aknow] <szchen@mozilla.com>
Thu, 16 Oct 2014 23:40:00 +0200
changeset 211148 057b2dc0590ea8cc3e7b5aaea850ef23e4bf56aa
parent 211147 23c96e4cfc35463938ee276e3bafae28e62ac016
child 211149 515d83408ae7d37b6c264742796804ef0fd65d14
push id50654
push usercbook@mozilla.com
push dateMon, 20 Oct 2014 13:15:00 +0000
treeherdermozilla-inbound@ae49e79844e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsinyi
bugs1077190
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1077190 - Part 1: Correct the logic of audio state setting. r=hsinyi
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/ril_consts.js
dom/system/gonk/ril_worker.js
dom/telephony/gonk/TelephonyService.js
dom/telephony/nsIGonkTelephonyService.idl
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1967,16 +1967,19 @@ RadioInterface.prototype = {
         break;
     }
     return null;
   },
 
   handleUnsolicitedWorkerMessage: function(message) {
     let connHandler = gDataConnectionManager.getConnectionHandler(this.clientId);
     switch (message.rilMessageType) {
+      case "audioStateChanged":
+        gTelephonyService.notifyAudioStateChanged(this.clientId, message.state);
+        break;
       case "callRing":
         gTelephonyService.notifyCallRing();
         break;
       case "callStateChange":
         gTelephonyService.notifyCallStateChanged(this.clientId, message.call);
         break;
       case "callDisconnected":
         gTelephonyService.notifyCallDisconnected(this.clientId, message.call);
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -465,16 +465,21 @@ this.NETWORK_CREG_TECH_LTE = 14;
 this.NETWORK_CREG_TECH_HSPAP = 15;
 this.NETWORK_CREG_TECH_GSM = 16;
 
 this.CELL_INFO_TYPE_GSM = 1;
 this.CELL_INFO_TYPE_CDMA = 2;
 this.CELL_INFO_TYPE_LTE = 3;
 this.CELL_INFO_TYPE_WCDMA = 4;
 
+// Order matters.
+this.AUDIO_STATE_NO_CALL  = 0;
+this.AUDIO_STATE_INCOMING = 1;
+this.AUDIO_STATE_IN_CALL  = 2;
+
 this.CALL_STATE_UNKNOWN = -1;
 this.CALL_STATE_ACTIVE = 0;
 this.CALL_STATE_HOLDING = 1;
 this.CALL_STATE_DIALING = 2;
 this.CALL_STATE_ALERTING = 3;
 this.CALL_STATE_INCOMING = 4;
 this.CALL_STATE_WAITING = 5;
 
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3988,16 +3988,36 @@ RilObject.prototype = {
     }
 
     if (clearConferenceRequest) {
       this._hasConferenceRequest = false;
     }
     if (conferenceChanged) {
       this._ensureConference();
     }
+
+    // Update audio state.
+    let message = {rilMessageType: "audioStateChanged",
+                   state: this._detectAudioState()};
+    this.sendChromeMessage(message);
+  },
+
+  _detectAudioState: function() {
+    let callNum = Object.keys(this.currentCalls).length;
+    if (!callNum) {
+      return AUDIO_STATE_NO_CALL;
+    }
+
+    let firstIndex = Object.keys(this.currentCalls)[0];
+    if (callNum == 1 &&
+        this.currentCalls[firstIndex].state == CALL_STATE_INCOMING) {
+      return AUDIO_STATE_INCOMING;
+    }
+
+    return AUDIO_STATE_IN_CALL;
   },
 
   _addNewVoiceCall: function(newCall) {
     // Format international numbers appropriately.
     if (newCall.number && newCall.toa == TOA_INTERNATIONAL &&
         newCall.number[0] != "+") {
       newCall.number = "+" + newCall.number;
     }
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -38,19 +38,16 @@ const CALL_WAKELOCK_TIMEOUT = 5000;
 
 // Index of the CDMA second call which isn't held in RIL but only in TelephoyService.
 const CDMA_SECOND_CALL_INDEX = 2;
 
 const DIAL_ERROR_INVALID_STATE_ERROR = "InvalidStateError";
 const DIAL_ERROR_OTHER_CONNECTION_IN_USE = "OtherConnectionInUse";
 const DIAL_ERROR_BAD_NUMBER = RIL.GECKO_CALL_ERROR_BAD_NUMBER;
 
-const AUDIO_STATE_NO_CALL  = 0;
-const AUDIO_STATE_INCOMING = 1;
-const AUDIO_STATE_IN_CALL  = 2;
 const AUDIO_STATE_NAME = [
   "PHONE_STATE_NORMAL",
   "PHONE_STATE_RINGTONE",
   "PHONE_STATE_IN_CALL"
 ];
 
 const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
 
@@ -151,16 +148,17 @@ function TelephonyService() {
   this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
   this._listeners = [];
 
   this._mmiRegExp = null;
 
   this._isDialing = false;
   this._cachedDialRequest = null;
   this._currentCalls = {};
+  this._audioStates = {};
 
   this._cdmaCallWaitingNumber = null;
 
   // _isActiveCall[clientId][callIndex] shows the active status of the call.
   this._isActiveCall = {};
   this._numActiveCall = 0;
 
   this._updateDebugFlag();
@@ -169,16 +167,17 @@ function TelephonyService() {
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
   Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   for (let i = 0; i < this._numClients; ++i) {
     this._enumerateCallsForClient(i);
     this._isActiveCall[i] = {};
+    this._audioStates[i] = RIL.AUDIO_STATE_NO_CALL;
   }
 }
 TelephonyService.prototype = {
   classID: GONK_TELEPHONYSERVICE_CID,
   classInfo: XPCOMUtils.generateCI({classID: GONK_TELEPHONYSERVICE_CID,
                                     contractID: GONK_TELEPHONYSERVICE_CONTRACTID,
                                     classDescription: "TelephonyService",
                                     interfaces: [Ci.nsITelephonyService,
@@ -272,49 +271,40 @@ TelephonyService.prototype = {
     // Update active count and info.
     let oldActive = this._isActiveCall[aCall.clientId][aCall.callIndex];
     if (!oldActive && active) {
       this._numActiveCall++;
     } else if (oldActive && !active) {
       this._numActiveCall--;
     }
     this._isActiveCall[aCall.clientId][aCall.callIndex] = active;
-
-    if (incoming && !this._numActiveCall) {
-      // Change the phone state into RINGTONE only when there's no active call.
-      this._updateCallAudioState(AUDIO_STATE_INCOMING);
-    } else if (this._numActiveCall) {
-      this._updateCallAudioState(AUDIO_STATE_IN_CALL);
-    } else {
-      this._updateCallAudioState(AUDIO_STATE_NO_CALL);
-    }
   },
 
-  _updateCallAudioState: function(aAudioState) {
+  _updateAudioState: function(aAudioState) {
     switch (aAudioState) {
-      case AUDIO_STATE_NO_CALL:
+      case RIL.AUDIO_STATE_NO_CALL:
         gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
         break;
 
-      case AUDIO_STATE_INCOMING:
+      case RIL.AUDIO_STATE_INCOMING:
         gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
         break;
 
-      case AUDIO_STATE_IN_CALL:
+      case RIL.AUDIO_STATE_IN_CALL:
         gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
         if (this.speakerEnabled) {
           gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
                                        nsIAudioManager.FORCE_SPEAKER);
         }
         break;
     }
 
     if (DEBUG) {
       debug("Put audio system into " + AUDIO_STATE_NAME[aAudioState] + ": " +
-            gAudioManager.phoneState);
+            aAudioState + ", result is: " + gAudioManager.phoneState);
     }
   },
 
   _convertRILCallState: function(aState) {
     switch (aState) {
       case RIL.CALL_STATE_UNKNOWN:
         return nsITelephonyService.CALL_STATE_UNKNOWN;
       case RIL.CALL_STATE_ACTIVE:
@@ -1092,16 +1082,27 @@ TelephonyService.prototype = {
                            nsIAudioManager.FORCE_NONE;
     gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
   },
 
   /**
    * nsIGonkTelephonyService interface.
    */
 
+  notifyAudioStateChanged: function(aClientId, aState) {
+    this._audioStates[aClientId] = aState;
+
+    let audioState = aState;
+    for (let i = 0; i < this._numClients; ++i) {
+      audioState = Math.max(audioState, this._audioStates[i]);
+    }
+
+    this._updateAudioState(audioState);
+  },
+
   /**
    * Handle call disconnects by updating our current state and the audio system.
    */
   notifyCallDisconnected: function(aClientId, aCall) {
     if (DEBUG) debug("handleCallDisconnected: " + JSON.stringify(aCall));
 
     aCall.clientId = aClientId;
     aCall.state = nsITelephonyService.CALL_STATE_DISCONNECTED;
--- a/dom/telephony/nsIGonkTelephonyService.idl
+++ b/dom/telephony/nsIGonkTelephonyService.idl
@@ -5,19 +5,21 @@
 
 #include "nsITelephonyService.idl"
 
 %{C++
 #define GONK_TELEPHONY_SERVICE_CONTRACTID \
         "@mozilla.org/telephony/gonktelephonyservice;1"
 %}
 
-[scriptable, uuid(79eec3c3-2dfc-4bbf-b106-af5457651ae0)]
+[scriptable, uuid(068d7bf2-1773-48ef-95f8-bd835115fed7)]
 interface nsIGonkTelephonyService : nsITelephonyService
 {
+  void notifyAudioStateChanged(in unsigned long clientId, in short state);
+
   void notifyCallDisconnected(in unsigned long clientId, in jsval call);
 
   void notifyCallRing();
 
   void notifyCallStateChanged(in unsigned long clientId, in jsval call,
                               [optional] in boolean skipStateConversion);
 
   void notifyCdmaCallWaiting(in unsigned long clientId, in jsval waitingCall);