зеркало из https://github.com/mozilla/gecko-dev.git
Bug 881174 - part2 - cdma 3way call RIL impl. r=vicamo
This commit is contained in:
Родитель
06a3eb5083
Коммит
9f41a650ba
|
@ -2152,10 +2152,6 @@ RadioInterface.prototype = {
|
||||||
message.callIndex,
|
message.callIndex,
|
||||||
message.notification);
|
message.notification);
|
||||||
break;
|
break;
|
||||||
case "conferenceError":
|
|
||||||
gTelephonyProvider.notifyConferenceError(message.errorName,
|
|
||||||
message.errorMsg);
|
|
||||||
break;
|
|
||||||
case "datacallerror":
|
case "datacallerror":
|
||||||
connHandler.handleDataCallError(message);
|
connHandler.handleDataCallError(message);
|
||||||
break;
|
break;
|
||||||
|
@ -4179,9 +4175,13 @@ RadioInterface.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
sendWorkerMessage: function(rilMessageType, message, callback) {
|
sendWorkerMessage: function(rilMessageType, message, callback) {
|
||||||
|
if (callback) {
|
||||||
this.workerMessenger.send(rilMessageType, message, function(response) {
|
this.workerMessenger.send(rilMessageType, message, function(response) {
|
||||||
return callback.handleResponse(response);
|
return callback.handleResponse(response);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.workerMessenger.send(rilMessageType, message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ this.REQUEST_HANGUP = 12;
|
||||||
this.REQUEST_HANGUP_WAITING_OR_BACKGROUND = 13;
|
this.REQUEST_HANGUP_WAITING_OR_BACKGROUND = 13;
|
||||||
this.REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND = 14;
|
this.REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND = 14;
|
||||||
this.REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE = 15;
|
this.REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE = 15;
|
||||||
this.REQUEST_SWITCH_HOLDING_AND_ACTIVE = 15;
|
|
||||||
this.REQUEST_CONFERENCE = 16;
|
this.REQUEST_CONFERENCE = 16;
|
||||||
this.REQUEST_UDUB = 17;
|
this.REQUEST_UDUB = 17;
|
||||||
this.REQUEST_LAST_CALL_FAIL_CAUSE = 18;
|
this.REQUEST_LAST_CALL_FAIL_CAUSE = 18;
|
||||||
|
|
|
@ -1466,14 +1466,19 @@ RilObject.prototype = {
|
||||||
this.exitEmergencyCbMode();
|
this.exitEmergencyCbMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._isCdma && Object.keys(this.currentCalls).length == 1) {
|
||||||
|
// Make a Cdma 3way call.
|
||||||
|
options.featureStr = options.number;
|
||||||
|
this.sendCdmaFlashCommand(options);
|
||||||
|
} else {
|
||||||
options.request = REQUEST_DIAL;
|
options.request = REQUEST_DIAL;
|
||||||
this.sendDialRequest(options);
|
this.sendDialRequest(options);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
dialEmergencyNumber: function(options, onerror) {
|
dialEmergencyNumber: function(options, onerror) {
|
||||||
options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
|
options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
|
||||||
REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
|
REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
|
||||||
|
|
||||||
if (this.radioState == GECKO_RADIOSTATE_OFF) {
|
if (this.radioState == GECKO_RADIOSTATE_OFF) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
this.context.debug("Automatically enable radio for an emergency call.");
|
this.context.debug("Automatically enable radio for an emergency call.");
|
||||||
|
@ -1488,7 +1493,13 @@ RilObject.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._isCdma && Object.keys(this.currentCalls).length == 1) {
|
||||||
|
// Make a Cdma 3way call.
|
||||||
|
options.featureStr = options.number;
|
||||||
|
this.sendCdmaFlashCommand(options);
|
||||||
|
} else {
|
||||||
this.sendDialRequest(options);
|
this.sendDialRequest(options);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
sendDialRequest: function(options) {
|
sendDialRequest: function(options) {
|
||||||
|
@ -1503,6 +1514,15 @@ RilObject.prototype = {
|
||||||
Buf.sendParcel();
|
Buf.sendParcel();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
sendCdmaFlashCommand: function(options) {
|
||||||
|
let Buf = this.context.Buf;
|
||||||
|
options.isCdma = true;
|
||||||
|
options.request = REQUEST_CDMA_FLASH;
|
||||||
|
Buf.newParcel(options.request, options);
|
||||||
|
Buf.writeString(options.featureStr);
|
||||||
|
Buf.sendParcel();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hang up all calls
|
* Hang up all calls
|
||||||
*/
|
*/
|
||||||
|
@ -1618,22 +1638,37 @@ RilObject.prototype = {
|
||||||
|
|
||||||
holdCall: function(options) {
|
holdCall: function(options) {
|
||||||
let call = this.currentCalls[options.callIndex];
|
let call = this.currentCalls[options.callIndex];
|
||||||
if (call && call.state == CALL_STATE_ACTIVE) {
|
if (!call) {
|
||||||
|
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
|
||||||
|
options.success = false;
|
||||||
|
this.sendChromeMessage(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let Buf = this.context.Buf;
|
let Buf = this.context.Buf;
|
||||||
if (this._isCdma) {
|
if (this._isCdma) {
|
||||||
Buf.newParcel(REQUEST_CDMA_FLASH);
|
options.featureStr = "";
|
||||||
Buf.writeString("");
|
this.sendCdmaFlashCommand(options);
|
||||||
Buf.sendParcel();
|
} else if (call.state == CALL_STATE_ACTIVE) {
|
||||||
} else {
|
Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, options);
|
||||||
Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
resumeCall: function(options) {
|
resumeCall: function(options) {
|
||||||
let call = this.currentCalls[options.callIndex];
|
let call = this.currentCalls[options.callIndex];
|
||||||
if (call && call.state == CALL_STATE_HOLDING) {
|
if (!call) {
|
||||||
this.context.Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
|
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
|
||||||
|
options.success = false;
|
||||||
|
this.sendChromeMessage(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Buf = this.context.Buf;
|
||||||
|
if (this._isCdma) {
|
||||||
|
options.featureStr = "";
|
||||||
|
this.sendCdmaFlashCommand(options);
|
||||||
|
} else if (call.state == CALL_STATE_HOLDING) {
|
||||||
|
Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, options);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1641,24 +1676,52 @@ RilObject.prototype = {
|
||||||
_hasConferenceRequest: false,
|
_hasConferenceRequest: false,
|
||||||
|
|
||||||
conferenceCall: function(options) {
|
conferenceCall: function(options) {
|
||||||
|
let Buf = this.context.Buf;
|
||||||
|
if (this._isCdma) {
|
||||||
|
options.featureStr = "";
|
||||||
|
this.sendCdmaFlashCommand(options);
|
||||||
|
} else {
|
||||||
this._hasConferenceRequest = true;
|
this._hasConferenceRequest = true;
|
||||||
this.context.Buf.simpleRequest(REQUEST_CONFERENCE, options);
|
Buf.simpleRequest(REQUEST_CONFERENCE, options);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
separateCall: function(options) {
|
separateCall: function(options) {
|
||||||
|
let call = this.currentCalls[options.callIndex];
|
||||||
|
if (!call) {
|
||||||
|
options.errorName = "removeError";
|
||||||
|
options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
|
||||||
|
options.success = false;
|
||||||
|
this.sendChromeMessage(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let Buf = this.context.Buf;
|
let Buf = this.context.Buf;
|
||||||
|
if (this._isCdma) {
|
||||||
|
options.featureStr = "";
|
||||||
|
this.sendCdmaFlashCommand(options);
|
||||||
|
} else {
|
||||||
Buf.newParcel(REQUEST_SEPARATE_CONNECTION, options);
|
Buf.newParcel(REQUEST_SEPARATE_CONNECTION, options);
|
||||||
Buf.writeInt32(1);
|
Buf.writeInt32(1);
|
||||||
Buf.writeInt32(options.callIndex);
|
Buf.writeInt32(options.callIndex);
|
||||||
Buf.sendParcel();
|
Buf.sendParcel();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
holdConference: function() {
|
holdConference: function() {
|
||||||
this.context.Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
|
if (this._isCdma) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.context.Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE);
|
||||||
},
|
},
|
||||||
|
|
||||||
resumeConference: function() {
|
resumeConference: function() {
|
||||||
this.context.Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
|
if (this._isCdma) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.context.Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5292,31 +5355,27 @@ RilObject.prototype[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function REQU
|
||||||
this.getCurrentCalls();
|
this.getCurrentCalls();
|
||||||
};
|
};
|
||||||
RilObject.prototype[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
|
RilObject.prototype[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
|
||||||
if (options.rilRequestError) {
|
options.success = (options.rilRequestError === 0);
|
||||||
return;
|
if (!options.success) {
|
||||||
}
|
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||||
|
|
||||||
this.getCurrentCalls();
|
|
||||||
};
|
|
||||||
RilObject.prototype[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_HOLDING_AND_ACTIVE(length, options) {
|
|
||||||
if (options.rilRequestError) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX Normally we should get a UNSOLICITED_RESPONSE_CALL_STATE_CHANGED parcel
|
|
||||||
// notifying us of call state changes, but sometimes we don't (have no idea why).
|
|
||||||
// this.getCurrentCalls() helps update the call state actively.
|
|
||||||
this.getCurrentCalls();
|
|
||||||
};
|
|
||||||
RilObject.prototype[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
|
|
||||||
if (options.rilRequestError) {
|
|
||||||
this._hasConferenceRequest = false;
|
|
||||||
options = {rilMessageType: "conferenceError",
|
|
||||||
errorName: "addError",
|
|
||||||
errorMsg: RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]};
|
|
||||||
this.sendChromeMessage(options);
|
this.sendChromeMessage(options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.sendChromeMessage(options);
|
||||||
|
this.getCurrentCalls();
|
||||||
|
};
|
||||||
|
RilObject.prototype[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
|
||||||
|
options.success = (options.rilRequestError === 0);
|
||||||
|
if (!options.success) {
|
||||||
|
this._hasConferenceRequest = false;
|
||||||
|
options.errorName = "addError";
|
||||||
|
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||||
|
this.sendChromeMessage(options);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sendChromeMessage(options);
|
||||||
};
|
};
|
||||||
RilObject.prototype[REQUEST_UDUB] = null;
|
RilObject.prototype[REQUEST_UDUB] = null;
|
||||||
RilObject.prototype[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
|
RilObject.prototype[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
|
||||||
|
@ -5903,13 +5962,15 @@ RilObject.prototype[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSIO
|
||||||
if (DEBUG) this.context.debug("Baseband version: " + this.basebandVersion);
|
if (DEBUG) this.context.debug("Baseband version: " + this.basebandVersion);
|
||||||
};
|
};
|
||||||
RilObject.prototype[REQUEST_SEPARATE_CONNECTION] = function REQUEST_SEPARATE_CONNECTION(length, options) {
|
RilObject.prototype[REQUEST_SEPARATE_CONNECTION] = function REQUEST_SEPARATE_CONNECTION(length, options) {
|
||||||
if (options.rilRequestError) {
|
options.success = (options.rilRequestError === 0);
|
||||||
options = {rilMessageType: "conferenceError",
|
if (!options.success) {
|
||||||
errorName: "removeError",
|
options.errorName = "removeError";
|
||||||
errorMsg: RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]};
|
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||||
this.sendChromeMessage(options);
|
this.sendChromeMessage(options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.sendChromeMessage(options);
|
||||||
};
|
};
|
||||||
RilObject.prototype[REQUEST_SET_MUTE] = null;
|
RilObject.prototype[REQUEST_SET_MUTE] = null;
|
||||||
RilObject.prototype[REQUEST_GET_MUTE] = null;
|
RilObject.prototype[REQUEST_GET_MUTE] = null;
|
||||||
|
@ -6125,7 +6186,19 @@ RilObject.prototype[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = function
|
||||||
options.enabled = enabled[0] ? true : false;
|
options.enabled = enabled[0] ? true : false;
|
||||||
this.sendChromeMessage(options);
|
this.sendChromeMessage(options);
|
||||||
};
|
};
|
||||||
RilObject.prototype[REQUEST_CDMA_FLASH] = null;
|
RilObject.prototype[REQUEST_CDMA_FLASH] = function REQUEST_CDMA_FLASH(length, options) {
|
||||||
|
options.success = (options.rilRequestError === 0);
|
||||||
|
if (!options.success) {
|
||||||
|
if (options.rilMessageType === "conferenceCall") {
|
||||||
|
options.errorName = "addError";
|
||||||
|
} else if (options.rilMessageType === "separateCall") {
|
||||||
|
options.errorName = "removeError";
|
||||||
|
}
|
||||||
|
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sendChromeMessage(options);
|
||||||
|
};
|
||||||
RilObject.prototype[REQUEST_CDMA_BURST_DTMF] = null;
|
RilObject.prototype[REQUEST_CDMA_BURST_DTMF] = null;
|
||||||
RilObject.prototype[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
|
RilObject.prototype[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
|
||||||
RilObject.prototype[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {
|
RilObject.prototype[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {
|
||||||
|
|
|
@ -32,6 +32,9 @@ const nsITelephonyProvider = Ci.nsITelephonyProvider;
|
||||||
|
|
||||||
const CALL_WAKELOCK_TIMEOUT = 5000;
|
const CALL_WAKELOCK_TIMEOUT = 5000;
|
||||||
|
|
||||||
|
// Index of the CDMA second call which isn't held in RIL but only in TelephoyProvider.
|
||||||
|
const CDMA_SECOND_CALL_INDEX = 2;
|
||||||
|
|
||||||
let DEBUG;
|
let DEBUG;
|
||||||
function debug(s) {
|
function debug(s) {
|
||||||
dump("TelephonyProvider: " + s + "\n");
|
dump("TelephonyProvider: " + s + "\n");
|
||||||
|
@ -112,6 +115,7 @@ ConferenceCall.prototype = {
|
||||||
function TelephonyProvider() {
|
function TelephonyProvider() {
|
||||||
this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
|
this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
|
||||||
this._listeners = [];
|
this._listeners = [];
|
||||||
|
this._currentCalls = {};
|
||||||
this._updateDebugFlag();
|
this._updateDebugFlag();
|
||||||
this.defaultServiceId = this._getDefaultServiceId();
|
this.defaultServiceId = this._getDefaultServiceId();
|
||||||
|
|
||||||
|
@ -119,6 +123,10 @@ function TelephonyProvider() {
|
||||||
Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
|
Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
|
||||||
|
|
||||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
|
|
||||||
|
for (let i = 0; i < this._numClients; ++i) {
|
||||||
|
this._enumerateCallsForClient(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TelephonyProvider.prototype = {
|
TelephonyProvider.prototype = {
|
||||||
classID: GONK_TELEPHONYPROVIDER_CID,
|
classID: GONK_TELEPHONYPROVIDER_CID,
|
||||||
|
@ -340,6 +348,29 @@ TelephonyProvider.prototype = {
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_currentCalls: null,
|
||||||
|
_enumerateCallsForClient: function(aClientId) {
|
||||||
|
if (DEBUG) debug("Enumeration of calls for client " + aClientId);
|
||||||
|
|
||||||
|
this._getClient(aClientId).sendWorkerMessage("enumerateCalls", null,
|
||||||
|
(function(response) {
|
||||||
|
if (!this._currentCalls[aClientId]) {
|
||||||
|
this._currentCalls[aClientId] = {};
|
||||||
|
}
|
||||||
|
for (let call of response.calls) {
|
||||||
|
call.clientId = aClientId;
|
||||||
|
call.state = this._convertRILCallState(call.state);
|
||||||
|
call.isActive = this._matchActiveSingleCall(call);
|
||||||
|
call.isSwitchable = true;
|
||||||
|
call.isMergeable = true;
|
||||||
|
|
||||||
|
this._currentCalls[aClientId][call.callIndex] = call;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}).bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nsITelephonyProvider interface.
|
* nsITelephonyProvider interface.
|
||||||
*/
|
*/
|
||||||
|
@ -363,41 +394,24 @@ TelephonyProvider.prototype = {
|
||||||
this._listeners.splice(index, 1);
|
this._listeners.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
_enumerateCallsForClient: function(aClientId, aListener) {
|
|
||||||
if (DEBUG) debug("Enumeration of calls for client " + aClientId);
|
|
||||||
|
|
||||||
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._matchActiveSingleCall(call);
|
|
||||||
|
|
||||||
aListener.enumerateCallState(call.clientId, call.callIndex,
|
|
||||||
call.state, call.number,
|
|
||||||
call.isActive, call.isOutgoing,
|
|
||||||
call.isEmergency, call.isConference);
|
|
||||||
}
|
|
||||||
deferred.resolve();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}).bind(this));
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
},
|
|
||||||
|
|
||||||
enumerateCalls: function(aListener) {
|
enumerateCalls: function(aListener) {
|
||||||
if (DEBUG) debug("Requesting enumeration of calls for callback");
|
if (DEBUG) debug("Requesting enumeration of calls for callback");
|
||||||
|
|
||||||
let promise = Promise.resolve();
|
for (let cid = 0; cid < this._numClients; ++cid) {
|
||||||
for (let i = 0; i < this._numClients; ++i) {
|
let calls = this._currentCalls[cid];
|
||||||
promise = promise.then(this._enumerateCallsForClient.bind(this, i, aListener));
|
if (!calls) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (let i = 0, indexes = Object.keys(calls); i < indexes.length; ++i) {
|
||||||
|
let call = calls[indexes[i]];
|
||||||
|
aListener.enumerateCallState(call.clientId, call.callIndex,
|
||||||
|
call.state, call.number,
|
||||||
|
call.isActive, call.isOutgoing,
|
||||||
|
call.isEmergency, call.isConference,
|
||||||
|
call.isSwitchable, call.isMergeable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
promise.then(function() {
|
|
||||||
aListener.enumerateCallStateComplete();
|
aListener.enumerateCallStateComplete();
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isDialing: false,
|
isDialing: false,
|
||||||
|
@ -425,23 +439,70 @@ TelephonyProvider.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCdmaDialSuccess() {
|
||||||
|
let indexes = Object.keys(this._currentCalls[aClientId]);
|
||||||
|
if (indexes.length != 1 ) {
|
||||||
|
aTelephonyCallback.notifyDialSuccess();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RIL doesn't hold the 2nd call. We create one by ourselves.
|
||||||
|
let childCall = {
|
||||||
|
callIndex: CDMA_SECOND_CALL_INDEX,
|
||||||
|
state: RIL.CALL_STATE_DIALING,
|
||||||
|
number: aNumber,
|
||||||
|
isOutgoing: true,
|
||||||
|
isEmergency: false,
|
||||||
|
isConference: false,
|
||||||
|
isSwitchable: false,
|
||||||
|
isMergeable: true,
|
||||||
|
parentId: indexes[0]
|
||||||
|
};
|
||||||
|
aTelephonyCallback.notifyDialSuccess();
|
||||||
|
|
||||||
|
// Manual update call state according to the request response.
|
||||||
|
this.notifyCallStateChanged(aClientId, childCall);
|
||||||
|
|
||||||
|
childCall.state = RIL.CALL_STATE_ACTIVE;
|
||||||
|
this.notifyCallStateChanged(aClientId, childCall);
|
||||||
|
|
||||||
|
let parentCall = this._currentCalls[aClientId][childCall.parentId];
|
||||||
|
parentCall.childId = CDMA_SECOND_CALL_INDEX;
|
||||||
|
parentCall.state = RIL.CALL_STATE_HOLDING;
|
||||||
|
parentCall.isSwitchable = false;
|
||||||
|
parentCall.isMergeable = true;
|
||||||
|
this.notifyCallStateChanged(aClientId, parentCall);
|
||||||
|
};
|
||||||
|
|
||||||
this.isDialing = true;
|
this.isDialing = true;
|
||||||
this._getClient(aClientId).sendWorkerMessage("dial", {
|
this._getClient(aClientId).sendWorkerMessage("dial", {
|
||||||
number: aNumber,
|
number: aNumber,
|
||||||
isDialEmergency: aIsEmergency
|
isDialEmergency: aIsEmergency
|
||||||
}, (function(response) {
|
}, (function(response) {
|
||||||
this.isDialing = false;
|
this.isDialing = false;
|
||||||
if (response.success) {
|
if (!response.success) {
|
||||||
aTelephonyCallback.notifyDialSuccess();
|
|
||||||
} else {
|
|
||||||
aTelephonyCallback.notifyDialError(response.errorMsg);
|
aTelephonyCallback.notifyDialError(response.errorMsg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.isCdma) {
|
||||||
|
onCdmaDialSuccess.call(this);
|
||||||
|
} else {
|
||||||
|
aTelephonyCallback.notifyDialSuccess();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
hangUp: function(aClientId, aCallIndex) {
|
hangUp: function(aClientId, aCallIndex) {
|
||||||
|
let parentId = this._currentCalls[aClientId][aCallIndex].parentId;
|
||||||
|
if (parentId) {
|
||||||
|
// Should release both, child and parent, together. Since RIL holds only
|
||||||
|
// the parent call, we send 'parentId' to RIL.
|
||||||
|
this.hangUp(aClientId, parentId);
|
||||||
|
} else {
|
||||||
this._getClient(aClientId).sendWorkerMessage("hangUp", { callIndex: aCallIndex });
|
this._getClient(aClientId).sendWorkerMessage("hangUp", { callIndex: aCallIndex });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
startTone: function(aClientId, aDtmfChar) {
|
startTone: function(aClientId, aDtmfChar) {
|
||||||
|
@ -461,19 +522,187 @@ TelephonyProvider.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
holdCall: function(aClientId, aCallIndex) {
|
holdCall: function(aClientId, aCallIndex) {
|
||||||
this._getClient(aClientId).sendWorkerMessage("holdCall", { callIndex: aCallIndex });
|
let call = this._currentCalls[aClientId][aCallIndex];
|
||||||
|
if (!call || !call.isSwitchable) {
|
||||||
|
// TODO: Bug 975949 - [B2G] Telephony should throw exceptions when some
|
||||||
|
// operations aren't allowed instead of simply ignoring them.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parentId = this._currentCalls[aClientId][aCallIndex].parentId;
|
||||||
|
if (parentId) {
|
||||||
|
this.resumeCall(aClientId, parentId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCdmaHoldCallSuccess() {
|
||||||
|
let call = this._currentCalls[aClientId][aCallIndex];
|
||||||
|
if (!call) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
call.state = RIL.CALL_STATE_HOLDING;
|
||||||
|
this.notifyCallStateChanged(aClientId, call);
|
||||||
|
|
||||||
|
if (!call.childId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let childCall = this._currentCalls[aClientId][call.childId];
|
||||||
|
childCall.state = RIL.CALL_STATE_ACTIVE;
|
||||||
|
this.notifyCallStateChanged(aClientId, childCall);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getClient(aClientId).sendWorkerMessage("holdCall", {
|
||||||
|
callIndex: aCallIndex
|
||||||
|
},(function(response) {
|
||||||
|
if (!response.success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.isCdma) {
|
||||||
|
onCdmaHoldCallSuccess.call(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
resumeCall: function(aClientId, aCallIndex) {
|
resumeCall: function(aClientId, aCallIndex) {
|
||||||
this._getClient(aClientId).sendWorkerMessage("resumeCall", { callIndex: aCallIndex });
|
let call = this._currentCalls[aClientId][aCallIndex];
|
||||||
|
if (!call || !call.isSwitchable) {
|
||||||
|
// TODO: Bug 975949 - [B2G] Telephony should throw exceptions when some
|
||||||
|
// operations aren't allowed instead of simply ignoring them.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parentId = this._currentCalls[aClientId][aCallIndex].parentId;
|
||||||
|
if (parentId) {
|
||||||
|
this.holdCall(aClientId, parentId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCdmaResumeCallSuccess() {
|
||||||
|
let call = this._currentCalls[aClientId][aCallIndex];
|
||||||
|
if (!call) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
call.state = RIL.CALL_STATE_ACTIVE;
|
||||||
|
this.notifyCallStateChanged(aClientId, call);
|
||||||
|
|
||||||
|
let childId = call.childId;
|
||||||
|
if (!childId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let childCall = this._currentCalls[aClientId][childId];
|
||||||
|
childCall.state = RIL.CALL_STATE_HOLDING;
|
||||||
|
this.notifyCallStateChanged(aClientId, childCall);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getClient(aClientId).sendWorkerMessage("resumeCall", {
|
||||||
|
callIndex: aCallIndex
|
||||||
|
},(function(response) {
|
||||||
|
if (!response.success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.isCdma) {
|
||||||
|
onCdmaResumeCallSuccess.call(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
conferenceCall: function(aClientId) {
|
conferenceCall: function(aClientId) {
|
||||||
this._getClient(aClientId).sendWorkerMessage("conferenceCall");
|
let indexes = Object.keys(this._currentCalls[aClientId]);
|
||||||
|
if (indexes.length < 2) {
|
||||||
|
// TODO: Bug 975949 - [B2G] Telephony should throw exceptions when some
|
||||||
|
// operations aren't allowed instead of simply ignoring them.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < indexes.length; ++i) {
|
||||||
|
let call = this._currentCalls[aClientId][indexes[i]];
|
||||||
|
if (!call.isMergeable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCdmaConferenceCallSuccess() {
|
||||||
|
let indexes = Object.keys(this._currentCalls[aClientId]);
|
||||||
|
if (indexes.length < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < indexes.length; ++i) {
|
||||||
|
let call = this._currentCalls[aClientId][indexes[i]];
|
||||||
|
call.state = RIL.CALL_STATE_ACTIVE;
|
||||||
|
call.isConference = true;
|
||||||
|
this.notifyCallStateChanged(aClientId, call);
|
||||||
|
}
|
||||||
|
this.notifyConferenceCallStateChanged(RIL.CALL_STATE_ACTIVE);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getClient(aClientId).sendWorkerMessage("conferenceCall", null,
|
||||||
|
(function(response) {
|
||||||
|
if (!response.success) {
|
||||||
|
this._notifyAllListeners("notifyConferenceError", [response.errorName,
|
||||||
|
response.errorMsg]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.isCdma) {
|
||||||
|
onCdmaConferenceCallSuccess.call(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
separateCall: function(aClientId, aCallIndex) {
|
separateCall: function(aClientId, aCallIndex) {
|
||||||
this._getClient(aClientId).sendWorkerMessage("separateCall", { callIndex: aCallIndex });
|
let call = this._currentCalls[aClientId][aCallIndex];
|
||||||
|
if (!call || !call.isConference) {
|
||||||
|
// TODO: Bug 975949 - [B2G] Telephony should throw exceptions when some
|
||||||
|
// operations aren't allowed instead of simply ignoring them.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parentId = call.parentId;
|
||||||
|
if (parentId) {
|
||||||
|
this.separateCall(aClientId, parentId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCdmaSeparateCallSuccess() {
|
||||||
|
// See 3gpp2, S.R0006-522-A v1.0. Table 4, XID 6S.
|
||||||
|
let call = this._currentCalls[aClientId][aCallIndex];
|
||||||
|
if (!call || !call.isConference) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let childId = call.childId;
|
||||||
|
if (!childId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let childCall = this._currentCalls[aClientId][childId];
|
||||||
|
this.notifyCallDisconnected(aClientId, childCall);
|
||||||
|
};
|
||||||
|
|
||||||
|
this._getClient(aClientId).sendWorkerMessage("separateCall", {
|
||||||
|
callIndex: aCallIndex
|
||||||
|
}, (function(response) {
|
||||||
|
if (!response.success) {
|
||||||
|
this._notifyAllListeners("notifyConferenceError", [response.errorName,
|
||||||
|
response.errorMsg]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.isCdma) {
|
||||||
|
onCdmaSeparateCallSuccess.call(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
holdConference: function(aClientId) {
|
holdConference: function(aClientId) {
|
||||||
|
@ -540,6 +769,31 @@ TelephonyProvider.prototype = {
|
||||||
aCall.clientId = aClientId;
|
aCall.clientId = aClientId;
|
||||||
this._updateCallAudioState(aCall, null);
|
this._updateCallAudioState(aCall, null);
|
||||||
|
|
||||||
|
let manualConfStateChange = false;
|
||||||
|
let childId = this._currentCalls[aClientId][aCall.callIndex].childId;
|
||||||
|
if (childId) {
|
||||||
|
// Child cannot live without parent.
|
||||||
|
let childCall = this._currentCalls[aClientId][childId];
|
||||||
|
this.notifyCallDisconnected(aClientId, childCall);
|
||||||
|
} else {
|
||||||
|
let parentId = this._currentCalls[aClientId][aCall.callIndex].parentId;
|
||||||
|
if (parentId) {
|
||||||
|
let parentCall = this._currentCalls[aClientId][parentId];
|
||||||
|
// The child is going to be released.
|
||||||
|
delete parentCall.childId;
|
||||||
|
if (parentCall.isConference) {
|
||||||
|
// As the child is going to be gone, the parent should be moved out
|
||||||
|
// of conference accordingly.
|
||||||
|
manualConfStateChange = true;
|
||||||
|
parentCall.isConference = false;
|
||||||
|
parentCall.isSwitchable = true;
|
||||||
|
parentCall.isMergeable = true;
|
||||||
|
aCall.isConference = false;
|
||||||
|
this.notifyCallStateChanged(aClientId, parentCall, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!aCall.failCause ||
|
if (!aCall.failCause ||
|
||||||
aCall.failCause === RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) {
|
aCall.failCause === RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) {
|
||||||
this._notifyAllListeners("callStateChanged", [aClientId,
|
this._notifyAllListeners("callStateChanged", [aClientId,
|
||||||
|
@ -549,11 +803,17 @@ TelephonyProvider.prototype = {
|
||||||
aCall.isActive,
|
aCall.isActive,
|
||||||
aCall.isOutgoing,
|
aCall.isOutgoing,
|
||||||
aCall.isEmergency,
|
aCall.isEmergency,
|
||||||
aCall.isConference]);
|
aCall.isConference,
|
||||||
return;
|
aCall.isSwitchable,
|
||||||
}
|
aCall.isMergeable]);
|
||||||
|
} else {
|
||||||
this.notifyCallError(aClientId, aCall.callIndex, aCall.failCause);
|
this.notifyCallError(aClientId, aCall.callIndex, aCall.failCause);
|
||||||
|
}
|
||||||
|
delete this._currentCalls[aClientId][aCall.callIndex];
|
||||||
|
|
||||||
|
if (manualConfStateChange) {
|
||||||
|
this.notifyConferenceCallStateChanged(RIL.CALL_STATE_UNKNOWN);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -581,10 +841,13 @@ TelephonyProvider.prototype = {
|
||||||
* Handle call state changes by updating our current state and the audio
|
* Handle call state changes by updating our current state and the audio
|
||||||
* system.
|
* system.
|
||||||
*/
|
*/
|
||||||
notifyCallStateChanged: function(aClientId, aCall) {
|
notifyCallStateChanged: function(aClientId, aCall, aSkipStateConversion) {
|
||||||
if (DEBUG) debug("handleCallStateChange: " + JSON.stringify(aCall));
|
if (DEBUG) debug("handleCallStateChange: " + JSON.stringify(aCall));
|
||||||
|
|
||||||
|
if (!aSkipStateConversion) {
|
||||||
aCall.state = this._convertRILCallState(aCall.state);
|
aCall.state = this._convertRILCallState(aCall.state);
|
||||||
|
}
|
||||||
|
|
||||||
if (aCall.state == nsITelephonyProvider.CALL_STATE_DIALING) {
|
if (aCall.state == nsITelephonyProvider.CALL_STATE_DIALING) {
|
||||||
gSystemMessenger.broadcastMessage("telephony-new-call", {});
|
gSystemMessenger.broadcastMessage("telephony-new-call", {});
|
||||||
}
|
}
|
||||||
|
@ -592,14 +855,35 @@ TelephonyProvider.prototype = {
|
||||||
aCall.clientId = aClientId;
|
aCall.clientId = aClientId;
|
||||||
this._updateCallAudioState(aCall, null);
|
this._updateCallAudioState(aCall, null);
|
||||||
|
|
||||||
|
let call = this._currentCalls[aClientId][aCall.callIndex];
|
||||||
|
if (call) {
|
||||||
|
call.state = aCall.state;
|
||||||
|
call.isConference = aCall.isConference;
|
||||||
|
call.isEmergency = aCall.isEmergency;
|
||||||
|
call.isActive = aCall.isActive;
|
||||||
|
call.isSwitchable = aCall.isSwitchable != null ?
|
||||||
|
aCall.isSwitchable : call.isSwitchable;
|
||||||
|
call.isMergeable = aCall.isMergeable != null ?
|
||||||
|
aCall.isMergeable : call.isMergeable;
|
||||||
|
} else {
|
||||||
|
call = aCall;
|
||||||
|
call.isSwitchable = aCall.isSwitchable != null ?
|
||||||
|
aCall.isSwitchable : true;
|
||||||
|
call.isMergeable = aCall.isMergeable != null ?
|
||||||
|
aCall.isMergeable : true;
|
||||||
|
this._currentCalls[aClientId][aCall.callIndex] = call;
|
||||||
|
}
|
||||||
|
|
||||||
this._notifyAllListeners("callStateChanged", [aClientId,
|
this._notifyAllListeners("callStateChanged", [aClientId,
|
||||||
aCall.callIndex,
|
call.callIndex,
|
||||||
aCall.state,
|
call.state,
|
||||||
aCall.number,
|
call.number,
|
||||||
aCall.isActive,
|
call.isActive,
|
||||||
aCall.isOutgoing,
|
call.isOutgoing,
|
||||||
aCall.isEmergency,
|
call.isEmergency,
|
||||||
aCall.isConference]);
|
call.isConference,
|
||||||
|
call.isSwitchable,
|
||||||
|
call.isMergeable]);
|
||||||
},
|
},
|
||||||
|
|
||||||
notifyCdmaCallWaiting: function(aClientId, aNumber) {
|
notifyCdmaCallWaiting: function(aClientId, aNumber) {
|
||||||
|
@ -607,6 +891,12 @@ TelephonyProvider.prototype = {
|
||||||
// the sleep mode when the RIL handles the incoming call.
|
// the sleep mode when the RIL handles the incoming call.
|
||||||
this._acquireCallRingWakeLock();
|
this._acquireCallRingWakeLock();
|
||||||
|
|
||||||
|
let call = this._currentCalls[aClientId][CDMA_SECOND_CALL_INDEX];
|
||||||
|
if (call) {
|
||||||
|
// TODO: Bug 977503 - B2G RIL: [CDMA] update callNumber when a waiting
|
||||||
|
// call comes after a 3way call.
|
||||||
|
this.notifyCallDisconnected(aClientId, call);
|
||||||
|
}
|
||||||
this._notifyAllListeners("notifyCdmaCallWaiting", [aClientId, aNumber]);
|
this._notifyAllListeners("notifyCdmaCallWaiting", [aClientId, aNumber]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -624,12 +914,6 @@ TelephonyProvider.prototype = {
|
||||||
this._notifyAllListeners("conferenceCallStateChanged", [aState]);
|
this._notifyAllListeners("conferenceCallStateChanged", [aState]);
|
||||||
},
|
},
|
||||||
|
|
||||||
notifyConferenceError: function(aName, aMessage) {
|
|
||||||
if (DEBUG) debug("handleConferenceError: " + aName + "." +
|
|
||||||
" Error details: " + aMessage);
|
|
||||||
this._notifyAllListeners("notifyConferenceError", [aName, aMessage]);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nsIObserver interface.
|
* nsIObserver interface.
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче