mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset f6b637a621ac (bug 864485)
This commit is contained in:
parent
6d23474f4f
commit
73afdd110d
@ -471,8 +471,6 @@
|
||||
@BINPATH@/components/NetworkStatsManager.manifest
|
||||
@BINPATH@/components/NetworkInterfaceListService.manifest
|
||||
@BINPATH@/components/NetworkInterfaceListService.js
|
||||
@BINPATH@/components/TelephonyProvider.manifest
|
||||
@BINPATH@/components/TelephonyProvider.js
|
||||
#endif
|
||||
#ifdef MOZ_ENABLE_DBUS
|
||||
@BINPATH@/components/@DLL_PREFIX@dbusservice@DLL_SUFFIX@
|
||||
|
@ -71,13 +71,17 @@ const RIL_IPC_MSG_NAMES = [
|
||||
"RIL:IccInfoChanged",
|
||||
"RIL:VoiceInfoChanged",
|
||||
"RIL:DataInfoChanged",
|
||||
"RIL:EnumerateCalls",
|
||||
"RIL:GetAvailableNetworks",
|
||||
"RIL:NetworkSelectionModeChanged",
|
||||
"RIL:SelectNetwork",
|
||||
"RIL:SelectNetworkAuto",
|
||||
"RIL:CallStateChanged",
|
||||
"RIL:EmergencyCbModeChanged",
|
||||
"RIL:VoicemailNotification",
|
||||
"RIL:VoicemailInfoChanged",
|
||||
"RIL:CallError",
|
||||
"RIL:SuppSvcNotification",
|
||||
"RIL:CardLockResult",
|
||||
"RIL:CardLockRetryCount",
|
||||
"RIL:USSDReceived",
|
||||
@ -104,9 +108,11 @@ const RIL_IPC_MSG_NAMES = [
|
||||
"RIL:UpdateIccContact",
|
||||
"RIL:SetRoamingPreference",
|
||||
"RIL:GetRoamingPreference",
|
||||
"RIL:CdmaCallWaiting",
|
||||
"RIL:ExitEmergencyCbMode",
|
||||
"RIL:SetVoicePrivacyMode",
|
||||
"RIL:GetVoicePrivacyMode",
|
||||
"RIL:ConferenceCallStateChanged",
|
||||
"RIL:OtaStatusChanged"
|
||||
];
|
||||
|
||||
@ -114,6 +120,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsISyncMessageSender");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
function MobileIccCardLockResult(options) {
|
||||
this.lockType = options.lockType;
|
||||
this.enabled = options.enabled;
|
||||
@ -439,6 +449,7 @@ RILContentHelper.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionProvider,
|
||||
Ci.nsICellBroadcastProvider,
|
||||
Ci.nsIVoicemailProvider,
|
||||
Ci.nsITelephonyProvider,
|
||||
Ci.nsIIccProvider,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
@ -448,6 +459,7 @@ RILContentHelper.prototype = {
|
||||
interfaces: [Ci.nsIMobileConnectionProvider,
|
||||
Ci.nsICellBroadcastProvider,
|
||||
Ci.nsIVoicemailProvider,
|
||||
Ci.nsITelephonyProvider,
|
||||
Ci.nsIIccProvider]}),
|
||||
|
||||
// An utility function to copy objects.
|
||||
@ -1269,9 +1281,11 @@ RILContentHelper.prototype = {
|
||||
},
|
||||
|
||||
_mobileConnectionListeners: null,
|
||||
_telephonyListeners: null,
|
||||
_cellBroadcastListeners: null,
|
||||
_voicemailListeners: null,
|
||||
_iccListeners: null,
|
||||
_enumerateTelephonyCallbacks: null,
|
||||
|
||||
voicemailStatus: null,
|
||||
|
||||
@ -1333,6 +1347,24 @@ RILContentHelper.prototype = {
|
||||
this.unregisterListener("_mobileConnectionListeners", listener);
|
||||
},
|
||||
|
||||
registerTelephonyMsg: function registerTelephonyMsg(listener) {
|
||||
debug("Registering for telephony-related messages");
|
||||
this.registerListener("_telephonyListeners", listener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterTelephonyMsg");
|
||||
},
|
||||
|
||||
unregisterTelephonyMsg: function unregisteTelephonyMsg(listener) {
|
||||
this.unregisterListener("_telephonyListeners", listener);
|
||||
|
||||
// We also need to make sure the listener is removed from
|
||||
// _enumerateTelephonyCallbacks.
|
||||
let index = this._enumerateTelephonyCallbacks.indexOf(listener);
|
||||
if (index != -1) {
|
||||
this._enumerateTelephonyCallbacks.splice(index, 1);
|
||||
if (DEBUG) debug("Unregistered enumerateTelephony callback: " + listener);
|
||||
}
|
||||
},
|
||||
|
||||
registerVoicemailMsg: function registerVoicemailMsg(listener) {
|
||||
debug("Registering for voicemail-related messages");
|
||||
this.registerListener("_voicemailListeners", listener);
|
||||
@ -1363,6 +1395,135 @@ RILContentHelper.prototype = {
|
||||
this.unregisterListener("_iccListeners", listener);
|
||||
},
|
||||
|
||||
enumerateCalls: function enumerateCalls(callback) {
|
||||
debug("Requesting enumeration of calls for callback: " + callback);
|
||||
// We need 'requestId' to meet the 'RILContentHelper <--> RadioInterfaceLayer'
|
||||
// protocol.
|
||||
let requestId = this._getRandomId();
|
||||
cpmm.sendAsyncMessage("RIL:EnumerateCalls", {
|
||||
clientId: 0,
|
||||
data: {
|
||||
requestId: requestId
|
||||
}
|
||||
});
|
||||
if (!this._enumerateTelephonyCallbacks) {
|
||||
this._enumerateTelephonyCallbacks = [];
|
||||
}
|
||||
this._enumerateTelephonyCallbacks.push(callback);
|
||||
},
|
||||
|
||||
startTone: function startTone(dtmfChar) {
|
||||
debug("Sending Tone for " + dtmfChar);
|
||||
cpmm.sendAsyncMessage("RIL:StartTone", {
|
||||
clientId: 0,
|
||||
data: dtmfChar
|
||||
});
|
||||
},
|
||||
|
||||
stopTone: function stopTone() {
|
||||
debug("Stopping Tone");
|
||||
cpmm.sendAsyncMessage("RIL:StopTone", {clientId: 0});
|
||||
},
|
||||
|
||||
dial: function dial(number) {
|
||||
debug("Dialing " + number);
|
||||
cpmm.sendAsyncMessage("RIL:Dial", {
|
||||
clientId: 0,
|
||||
data: number
|
||||
});
|
||||
},
|
||||
|
||||
dialEmergency: function dialEmergency(number) {
|
||||
debug("Dialing emergency " + number);
|
||||
cpmm.sendAsyncMessage("RIL:DialEmergency", {
|
||||
clientId: 0,
|
||||
data: number
|
||||
});
|
||||
},
|
||||
|
||||
hangUp: function hangUp(callIndex) {
|
||||
debug("Hanging up call no. " + callIndex);
|
||||
cpmm.sendAsyncMessage("RIL:HangUp", {
|
||||
clientId: 0,
|
||||
data: callIndex
|
||||
});
|
||||
},
|
||||
|
||||
answerCall: function answerCall(callIndex) {
|
||||
cpmm.sendAsyncMessage("RIL:AnswerCall", {
|
||||
clientId: 0,
|
||||
data: callIndex
|
||||
});
|
||||
},
|
||||
|
||||
rejectCall: function rejectCall(callIndex) {
|
||||
cpmm.sendAsyncMessage("RIL:RejectCall", {
|
||||
clientId: 0,
|
||||
data: callIndex
|
||||
});
|
||||
},
|
||||
|
||||
holdCall: function holdCall(callIndex) {
|
||||
cpmm.sendAsyncMessage("RIL:HoldCall", {
|
||||
clientId: 0,
|
||||
data: callIndex
|
||||
});
|
||||
},
|
||||
|
||||
resumeCall: function resumeCall(callIndex) {
|
||||
cpmm.sendAsyncMessage("RIL:ResumeCall", {
|
||||
clientId: 0,
|
||||
data: callIndex
|
||||
});
|
||||
},
|
||||
|
||||
conferenceCall: function conferenceCall() {
|
||||
cpmm.sendAsyncMessage("RIL:ConferenceCall", {
|
||||
clientId: 0
|
||||
});
|
||||
},
|
||||
|
||||
separateCall: function separateCall(callIndex) {
|
||||
cpmm.sendAsyncMessage("RIL:SeparateCall", {
|
||||
clientId: 0,
|
||||
data: callIndex
|
||||
});
|
||||
},
|
||||
|
||||
holdConference: function holdConference() {
|
||||
cpmm.sendAsyncMessage("RIL:HoldConference", {
|
||||
clientId: 0
|
||||
});
|
||||
},
|
||||
|
||||
resumeConference: function resumeConference() {
|
||||
cpmm.sendAsyncMessage("RIL:ResumeConference", {
|
||||
clientId: 0
|
||||
});
|
||||
},
|
||||
|
||||
get microphoneMuted() {
|
||||
return cpmm.sendSyncMessage("RIL:GetMicrophoneMuted", {clientId: 0})[0];
|
||||
},
|
||||
|
||||
set microphoneMuted(value) {
|
||||
cpmm.sendAsyncMessage("RIL:SetMicrophoneMuted", {
|
||||
clientId: 0,
|
||||
data: value
|
||||
});
|
||||
},
|
||||
|
||||
get speakerEnabled() {
|
||||
return cpmm.sendSyncMessage("RIL:GetSpeakerEnabled", {clientId: 0})[0];
|
||||
},
|
||||
|
||||
set speakerEnabled(value) {
|
||||
cpmm.sendAsyncMessage("RIL:SetSpeakerEnabled", {
|
||||
clientId: 0,
|
||||
data: value
|
||||
});
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
@ -1459,6 +1620,9 @@ RILContentHelper.prototype = {
|
||||
"notifyOtaStatusChanged",
|
||||
[msg.json.data]);
|
||||
break;
|
||||
case "RIL:EnumerateCalls":
|
||||
this.handleEnumerateCalls(msg.json.calls);
|
||||
break;
|
||||
case "RIL:GetAvailableNetworks":
|
||||
this.handleGetAvailableNetworks(msg.json);
|
||||
break;
|
||||
@ -1473,6 +1637,35 @@ RILContentHelper.prototype = {
|
||||
this.handleSelectNetwork(msg.json,
|
||||
RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
|
||||
break;
|
||||
case "RIL:CallStateChanged": {
|
||||
let data = msg.json.data;
|
||||
this._deliverEvent("_telephonyListeners",
|
||||
"callStateChanged",
|
||||
[data.callIndex, data.state,
|
||||
data.number, data.isActive,
|
||||
data.isOutgoing, data.isEmergency,
|
||||
data.isConference]);
|
||||
break;
|
||||
}
|
||||
case "RIL:ConferenceCallStateChanged": {
|
||||
let data = msg.json.data;
|
||||
this._deliverEvent("_telephonyListeners",
|
||||
"conferenceCallStateChanged",
|
||||
[data]);
|
||||
break;
|
||||
}
|
||||
case "RIL:CallError": {
|
||||
let data = msg.json.data;
|
||||
this._deliverEvent("_telephonyListeners",
|
||||
"notifyError",
|
||||
[data.callIndex, data.errorMsg]);
|
||||
break;
|
||||
}
|
||||
case "RIL:SuppSvcNotification":
|
||||
this._deliverEvent("_telephonyListeners",
|
||||
"supplementaryServiceNotification",
|
||||
[msg.json.callIndex, msg.json.notification]);
|
||||
break;
|
||||
case "RIL:VoicemailNotification":
|
||||
this.handleVoicemailNotification(msg.json.data);
|
||||
break;
|
||||
@ -1593,6 +1786,11 @@ RILContentHelper.prototype = {
|
||||
this.handleSimpleRequest(msg.json.requestId, msg.json.errorMsg,
|
||||
msg.json.mode);
|
||||
break;
|
||||
case "RIL:CdmaCallWaiting":
|
||||
this._deliverEvent("_telephonyListeners",
|
||||
"notifyCdmaCallWaiting",
|
||||
[msg.json.data]);
|
||||
break;
|
||||
case "RIL:ExitEmergencyCbMode":
|
||||
this.handleExitEmergencyCbMode(msg.json);
|
||||
break;
|
||||
@ -1612,6 +1810,35 @@ RILContentHelper.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
handleEnumerateCalls: function handleEnumerateCalls(calls) {
|
||||
debug("handleEnumerateCalls: " + JSON.stringify(calls));
|
||||
let callback = this._enumerateTelephonyCallbacks.shift();
|
||||
if (!calls.length) {
|
||||
callback.enumerateCallStateComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i in calls) {
|
||||
let call = calls[i];
|
||||
let keepGoing;
|
||||
try {
|
||||
keepGoing =
|
||||
callback.enumerateCallState(call.callIndex, call.state, call.number,
|
||||
call.isActive, call.isOutgoing,
|
||||
call.isEmergency, call.isConference);
|
||||
} catch (e) {
|
||||
debug("callback handler for 'enumerateCallState' threw an " +
|
||||
" exception: " + e);
|
||||
keepGoing = true;
|
||||
}
|
||||
if (!keepGoing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
callback.enumerateCallStateComplete();
|
||||
},
|
||||
|
||||
handleSimpleRequest: function handleSimpleRequest(requestId, errorMsg, result) {
|
||||
if (errorMsg) {
|
||||
this.fireRequestError(requestId, errorMsg);
|
||||
@ -1824,6 +2051,10 @@ RILContentHelper.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_getRandomId: function _getRandomId() {
|
||||
return gUUIDGenerator.generateUUID().toString();
|
||||
},
|
||||
|
||||
_deliverEvent: function _deliverEvent(listenerType, name, args) {
|
||||
let thisListeners = this[listenerType];
|
||||
if (!thisListeners) {
|
||||
|
@ -46,6 +46,9 @@ const RADIOINTERFACE_CID =
|
||||
const RILNETWORKINTERFACE_CID =
|
||||
Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
|
||||
|
||||
const nsIAudioManager = Ci.nsIAudioManager;
|
||||
const nsITelephonyProvider = Ci.nsITelephonyProvider;
|
||||
|
||||
const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
|
||||
const kSmsReceivedObserverTopic = "sms-received";
|
||||
const kSilentSmsReceivedObserverTopic = "silent-sms-received";
|
||||
@ -70,7 +73,30 @@ const DOM_MOBILE_MESSAGE_DELIVERY_SENDING = "sending";
|
||||
const DOM_MOBILE_MESSAGE_DELIVERY_SENT = "sent";
|
||||
const DOM_MOBILE_MESSAGE_DELIVERY_ERROR = "error";
|
||||
|
||||
const RADIO_POWER_OFF_TIMEOUT = 30000;
|
||||
const CALL_WAKELOCK_TIMEOUT = 5000;
|
||||
const RADIO_POWER_OFF_TIMEOUT = 30000;
|
||||
|
||||
const RIL_IPC_TELEPHONY_MSG_NAMES = [
|
||||
"RIL:EnumerateCalls",
|
||||
"RIL:GetMicrophoneMuted",
|
||||
"RIL:SetMicrophoneMuted",
|
||||
"RIL:GetSpeakerEnabled",
|
||||
"RIL:SetSpeakerEnabled",
|
||||
"RIL:StartTone",
|
||||
"RIL:StopTone",
|
||||
"RIL:Dial",
|
||||
"RIL:DialEmergency",
|
||||
"RIL:HangUp",
|
||||
"RIL:AnswerCall",
|
||||
"RIL:RejectCall",
|
||||
"RIL:HoldCall",
|
||||
"RIL:ResumeCall",
|
||||
"RIL:RegisterTelephonyMsg",
|
||||
"RIL:ConferenceCall",
|
||||
"RIL:SeparateCall",
|
||||
"RIL:HoldConference",
|
||||
"RIL:ResumeConference"
|
||||
];
|
||||
|
||||
const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [
|
||||
"RIL:GetRilContext",
|
||||
@ -162,10 +188,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "gSystemWorkerManager",
|
||||
"@mozilla.org/telephony/system-worker-manager;1",
|
||||
"nsISystemWorkerManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyProvider",
|
||||
"@mozilla.org/telephony/telephonyprovider;1",
|
||||
"nsIGonkTelephonyProvider");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "WAP", function () {
|
||||
let wap = {};
|
||||
Cu.import("resource://gre/modules/WapPushManager.js", wap);
|
||||
@ -178,6 +200,64 @@ XPCOMUtils.defineLazyGetter(this, "PhoneNumberUtils", function () {
|
||||
return ns.PhoneNumberUtils;
|
||||
});
|
||||
|
||||
function convertRILCallState(state) {
|
||||
switch (state) {
|
||||
case RIL.CALL_STATE_ACTIVE:
|
||||
return nsITelephonyProvider.CALL_STATE_CONNECTED;
|
||||
case RIL.CALL_STATE_HOLDING:
|
||||
return nsITelephonyProvider.CALL_STATE_HELD;
|
||||
case RIL.CALL_STATE_DIALING:
|
||||
return nsITelephonyProvider.CALL_STATE_DIALING;
|
||||
case RIL.CALL_STATE_ALERTING:
|
||||
return nsITelephonyProvider.CALL_STATE_ALERTING;
|
||||
case RIL.CALL_STATE_INCOMING:
|
||||
case RIL.CALL_STATE_WAITING:
|
||||
return nsITelephonyProvider.CALL_STATE_INCOMING;
|
||||
default:
|
||||
throw new Error("Unknown rilCallState: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
function convertRILSuppSvcNotification(notification) {
|
||||
switch (notification) {
|
||||
case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD:
|
||||
return nsITelephonyProvider.NOTIFICATION_REMOTE_HELD;
|
||||
case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED:
|
||||
return nsITelephonyProvider.NOTIFICATION_REMOTE_RESUMED;
|
||||
default:
|
||||
throw new Error("Unknown rilSuppSvcNotification: " + notification);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake nsIAudioManager implementation so that we can run the telephony
|
||||
* code in a non-Gonk build.
|
||||
*/
|
||||
let FakeAudioManager = {
|
||||
microphoneMuted: false,
|
||||
masterVolume: 1.0,
|
||||
masterMuted: false,
|
||||
phoneState: nsIAudioManager.PHONE_STATE_CURRENT,
|
||||
_forceForUse: {},
|
||||
setForceForUse: function setForceForUse(usage, force) {
|
||||
this._forceForUse[usage] = force;
|
||||
},
|
||||
getForceForUse: function setForceForUse(usage) {
|
||||
return this._forceForUse[usage] || nsIAudioManager.FORCE_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
|
||||
try {
|
||||
return Cc["@mozilla.org/telephony/audiomanager;1"]
|
||||
.getService(nsIAudioManager);
|
||||
} catch (ex) {
|
||||
//TODO on the phone this should not fall back as silently.
|
||||
if (DEBUG) debug("Using fake audio manager.");
|
||||
return FakeAudioManager;
|
||||
}
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
|
||||
@ -210,6 +290,9 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
|
||||
_registerMessageListeners: function _registerMessageListeners() {
|
||||
ppmm.addMessageListener("child-process-shutdown", this);
|
||||
for (let msgname of RIL_IPC_TELEPHONY_MSG_NAMES) {
|
||||
ppmm.addMessageListener(msgname, this);
|
||||
}
|
||||
for (let msgname of RIL_IPC_MOBILECONNECTION_MSG_NAMES) {
|
||||
ppmm.addMessageListener(msgname, this);
|
||||
}
|
||||
@ -226,6 +309,9 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
|
||||
_unregisterMessageListeners: function _unregisterMessageListeners() {
|
||||
ppmm.removeMessageListener("child-process-shutdown", this);
|
||||
for (let msgname of RIL_IPC_TELEPHONY_MSG_NAMES) {
|
||||
ppmm.removeMessageListener(msgname, this);
|
||||
}
|
||||
for (let msgname of RIL_IPC_MOBILECONNECTION_MSG_NAMES) {
|
||||
ppmm.removeMessageListener(msgname, this);
|
||||
}
|
||||
@ -344,7 +430,15 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
return;
|
||||
}
|
||||
|
||||
if (RIL_IPC_MOBILECONNECTION_MSG_NAMES.indexOf(msg.name) != -1) {
|
||||
if (RIL_IPC_TELEPHONY_MSG_NAMES.indexOf(msg.name) != -1) {
|
||||
if (!msg.target.assertPermission("telephony")) {
|
||||
if (DEBUG) {
|
||||
debug("Telephony message " + msg.name +
|
||||
" from a content process with no 'telephony' privileges.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else if (RIL_IPC_MOBILECONNECTION_MSG_NAMES.indexOf(msg.name) != -1) {
|
||||
if (!msg.target.assertPermission("mobileconnection")) {
|
||||
if (DEBUG) {
|
||||
debug("MobileConnection message " + msg.name +
|
||||
@ -382,6 +476,9 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
}
|
||||
|
||||
switch (msg.name) {
|
||||
case "RIL:RegisterTelephonyMsg":
|
||||
this._registerMessageTarget("telephony", msg.target);
|
||||
return;
|
||||
case "RIL:RegisterMobileConnectionMsg":
|
||||
this._registerMessageTarget("mobileconnection", msg.target);
|
||||
return;
|
||||
@ -422,6 +519,13 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
}
|
||||
},
|
||||
|
||||
sendTelephonyMessage: function sendTelephonyMessage(message, clientId, data) {
|
||||
this._sendTargetMessage("telephony", message, {
|
||||
clientId: clientId,
|
||||
data: data
|
||||
});
|
||||
},
|
||||
|
||||
sendMobileConnectionMessage: function sendMobileConnectionMessage(message, clientId, data) {
|
||||
this._sendTargetMessage("mobileconnection", message, {
|
||||
clientId: clientId,
|
||||
@ -790,6 +894,61 @@ RadioInterface.prototype = {
|
||||
case "RIL:GetRilContext":
|
||||
// This message is sync.
|
||||
return this.rilContext;
|
||||
case "RIL:EnumerateCalls":
|
||||
this.enumerateCalls(msg.target, msg.json.data);
|
||||
break;
|
||||
case "RIL:GetMicrophoneMuted":
|
||||
// This message is sync.
|
||||
return this.microphoneMuted;
|
||||
case "RIL:SetMicrophoneMuted":
|
||||
this.microphoneMuted = msg.json.data;
|
||||
break;
|
||||
case "RIL:GetSpeakerEnabled":
|
||||
// This message is sync.
|
||||
return this.speakerEnabled;
|
||||
case "RIL:SetSpeakerEnabled":
|
||||
this.speakerEnabled = msg.json.data;
|
||||
break;
|
||||
case "RIL:StartTone":
|
||||
this.workerMessenger.send("startTone", { dtmfChar: msg.json.data });
|
||||
break;
|
||||
case "RIL:StopTone":
|
||||
this.workerMessenger.send("stopTone");
|
||||
break;
|
||||
case "RIL:Dial":
|
||||
this.dial(msg.json.data);
|
||||
break;
|
||||
case "RIL:DialEmergency":
|
||||
this.dialEmergency(msg.json.data);
|
||||
break;
|
||||
case "RIL:HangUp":
|
||||
this.workerMessenger.send("hangUp", { callIndex: msg.json.data });
|
||||
break;
|
||||
case "RIL:AnswerCall":
|
||||
this.workerMessenger.send("answerCall", { callIndex: msg.json.data });
|
||||
break;
|
||||
case "RIL:RejectCall":
|
||||
this.workerMessenger.send("rejectCall", { callIndex: msg.json.data });
|
||||
break;
|
||||
case "RIL:HoldCall":
|
||||
this.workerMessenger.send("holdCall", { callIndex: msg.json.data });
|
||||
break;
|
||||
case "RIL:ResumeCall":
|
||||
this.workerMessenger.send("resumeCall", { callIndex: msg.json.data });
|
||||
break;
|
||||
case "RIL:ConferenceCall":
|
||||
this.workerMessenger.send("conferenceCall");
|
||||
break;
|
||||
case "RIL:SeparateCall":
|
||||
this.workerMessenger.send("separateCall",
|
||||
{ callIndex: msg.json.data });
|
||||
break;
|
||||
case "RIL:HoldConference":
|
||||
this.workerMessenger.send("holdConference");
|
||||
break;
|
||||
case "RIL:ResumeConference":
|
||||
this.workerMessenger.send("resumeConference");
|
||||
break;
|
||||
case "RIL:GetAvailableNetworks":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "getAvailableNetworks");
|
||||
break;
|
||||
@ -899,26 +1058,28 @@ RadioInterface.prototype = {
|
||||
handleUnsolicitedWorkerMessage: function handleUnsolicitedWorkerMessage(message) {
|
||||
switch (message.rilMessageType) {
|
||||
case "callRing":
|
||||
gTelephonyProvider.notifyCallRing();
|
||||
this.handleCallRing();
|
||||
break;
|
||||
case "callStateChange":
|
||||
gTelephonyProvider.notifyCallStateChanged(message.call);
|
||||
// This one will handle its own notifications.
|
||||
this.handleCallStateChange(message.call);
|
||||
break;
|
||||
case "callDisconnected":
|
||||
gTelephonyProvider.notifyCallDisconnected(message.call);
|
||||
// This one will handle its own notifications.
|
||||
this.handleCallDisconnected(message.call);
|
||||
break;
|
||||
case "conferenceCallStateChanged":
|
||||
gTelephonyProvider.notifyConferenceCallStateChanged(message.state);
|
||||
this.handleConferenceCallStateChanged(message.state);
|
||||
break;
|
||||
case "cdmaCallWaiting":
|
||||
gTelephonyProvider.notifyCdmaCallWaiting(message.number);
|
||||
gMessageManager.sendTelephonyMessage("RIL:CdmaCallWaiting",
|
||||
this.clientId, message.number);
|
||||
break;
|
||||
case "callError":
|
||||
gTelephonyProvider.notifyCallError(message.callIndex, message.errorMsg);
|
||||
this.handleCallError(message);
|
||||
break;
|
||||
case "suppSvcNotification":
|
||||
gTelephonyProvider.notifySupplementaryService(message.callIndex,
|
||||
message.notification);
|
||||
this.handleSuppSvcNotification(message);
|
||||
break;
|
||||
case "emergencyCbModeChange":
|
||||
this.handleEmergencyCbModeChange(message);
|
||||
@ -1566,6 +1727,165 @@ RadioInterface.prototype = {
|
||||
this.setupDataCallByType("default");
|
||||
},
|
||||
|
||||
/**
|
||||
* Track the active call and update the audio system as its state changes.
|
||||
*/
|
||||
_activeCall: null,
|
||||
updateCallAudioState: function updateCallAudioState(options) {
|
||||
if (options.conferenceState === nsITelephonyProvider.CALL_STATE_CONNECTED) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
if (this.speakerEnabled) {
|
||||
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
|
||||
nsIAudioManager.FORCE_SPEAKER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (options.conferenceState === nsITelephonyProvider.CALL_STATE_UNKNOWN ||
|
||||
options.conferenceState === nsITelephonyProvider.CALL_STATE_HELD) {
|
||||
if (!this._activeCall) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options.call) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.call.isConference) {
|
||||
if (this._activeCall && this._activeCall.callIndex == options.call.callIndex) {
|
||||
this._activeCall = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let call = options.call;
|
||||
switch (call.state) {
|
||||
case nsITelephonyProvider.CALL_STATE_DIALING: // Fall through...
|
||||
case nsITelephonyProvider.CALL_STATE_ALERTING:
|
||||
case nsITelephonyProvider.CALL_STATE_CONNECTED:
|
||||
call.isActive = true;
|
||||
this._activeCall = call;
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
if (this.speakerEnabled) {
|
||||
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
|
||||
nsIAudioManager.FORCE_SPEAKER);
|
||||
}
|
||||
if (DEBUG) {
|
||||
this.debug("Active call, put audio system into PHONE_STATE_IN_CALL: "
|
||||
+ gAudioManager.phoneState);
|
||||
}
|
||||
break;
|
||||
case nsITelephonyProvider.CALL_STATE_INCOMING:
|
||||
call.isActive = false;
|
||||
if (!this._activeCall) {
|
||||
// We can change the phone state into RINGTONE only when there's
|
||||
// no active call.
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
|
||||
if (DEBUG) {
|
||||
this.debug("Incoming call, put audio system into " +
|
||||
"PHONE_STATE_RINGTONE: " + gAudioManager.phoneState);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nsITelephonyProvider.CALL_STATE_HELD: // Fall through...
|
||||
case nsITelephonyProvider.CALL_STATE_DISCONNECTED:
|
||||
call.isActive = false;
|
||||
if (this._activeCall &&
|
||||
this._activeCall.callIndex == call.callIndex) {
|
||||
// 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) {
|
||||
this.debug("No active call, put audio system into " +
|
||||
"PHONE_STATE_NORMAL: " + gAudioManager.phoneState);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_callRingWakeLock: null,
|
||||
_callRingWakeLockTimer: null,
|
||||
_cancelCallRingWakeLockTimer: function _cancelCallRingWakeLockTimer() {
|
||||
if (this._callRingWakeLockTimer) {
|
||||
this._callRingWakeLockTimer.cancel();
|
||||
}
|
||||
if (this._callRingWakeLock) {
|
||||
this._callRingWakeLock.unlock();
|
||||
this._callRingWakeLock = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle an incoming call.
|
||||
*
|
||||
* Not much is known about this call at this point, but it's enough
|
||||
* to start bringing up the Phone app already.
|
||||
*/
|
||||
handleCallRing: function handleCallRing() {
|
||||
if (!this._callRingWakeLock) {
|
||||
this._callRingWakeLock = gPowerManagerService.newWakeLock("cpu");
|
||||
}
|
||||
if (!this._callRingWakeLockTimer) {
|
||||
this._callRingWakeLockTimer =
|
||||
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
}
|
||||
this._callRingWakeLockTimer
|
||||
.initWithCallback(this._cancelCallRingWakeLockTimer.bind(this),
|
||||
CALL_WAKELOCK_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
|
||||
gSystemMessenger.broadcastMessage("telephony-new-call", {});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call state changes by updating our current state and the audio
|
||||
* system.
|
||||
*/
|
||||
handleCallStateChange: function handleCallStateChange(call) {
|
||||
if (DEBUG) this.debug("handleCallStateChange: " + JSON.stringify(call));
|
||||
call.state = convertRILCallState(call.state);
|
||||
|
||||
if (call.state == nsITelephonyProvider.CALL_STATE_DIALING) {
|
||||
gSystemMessenger.broadcastMessage("telephony-new-call", {});
|
||||
}
|
||||
this.updateCallAudioState({call: call});
|
||||
gMessageManager.sendTelephonyMessage("RIL:CallStateChanged",
|
||||
this.clientId, call);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call disconnects by updating our current state and the audio system.
|
||||
*/
|
||||
handleCallDisconnected: function handleCallDisconnected(call) {
|
||||
if (DEBUG) this.debug("handleCallDisconnected: " + JSON.stringify(call));
|
||||
call.state = nsITelephonyProvider.CALL_STATE_DISCONNECTED;
|
||||
let duration = ("started" in call && typeof call.started == "number") ?
|
||||
new Date().getTime() - call.started : 0;
|
||||
let data = {
|
||||
number: call.number,
|
||||
duration: duration,
|
||||
direction: call.isOutgoing ? "outgoing" : "incoming"
|
||||
};
|
||||
gSystemMessenger.broadcastMessage("telephony-call-ended", data);
|
||||
this.updateCallAudioState({call: call});
|
||||
gMessageManager.sendTelephonyMessage("RIL:CallStateChanged",
|
||||
this.clientId, call);
|
||||
},
|
||||
|
||||
handleConferenceCallStateChanged: function handleConferenceCallStateChanged(state) {
|
||||
debug("handleConferenceCallStateChanged: " + state);
|
||||
state = state != null ? convertRILCallState(state) :
|
||||
nsITelephonyProvider.CALL_STATE_UNKNOWN;
|
||||
this.updateCallAudioState({conferenceState: state});
|
||||
gMessageManager.sendTelephonyMessage("RIL:ConferenceCallStateChanged",
|
||||
this.clientId, state);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update network selection mode
|
||||
*/
|
||||
@ -1585,6 +1905,23 @@ RadioInterface.prototype = {
|
||||
this.clientId, message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call error.
|
||||
*/
|
||||
handleCallError: function handleCallError(message) {
|
||||
gMessageManager.sendTelephonyMessage("RIL:CallError",
|
||||
this.clientId, message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle supplementary service notification.
|
||||
*/
|
||||
handleSuppSvcNotification: function handleSuppSvcNotification(message) {
|
||||
message.notification = convertRILSuppSvcNotification(message.notification);
|
||||
gMessageManager.sendTelephonyMessage("RIL:SuppSvcNotification",
|
||||
this.clientId, message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle WDP port push PDU. Constructor WDP bearer information and deliver
|
||||
* to WapPushManager.
|
||||
@ -1972,6 +2309,8 @@ RadioInterface.prototype = {
|
||||
}
|
||||
break;
|
||||
case "xpcom-shutdown":
|
||||
// Cancel the timer for the call-ring wake lock.
|
||||
this._cancelCallRingWakeLockTimer();
|
||||
// Shutdown all RIL network interfaces
|
||||
for each (let apnSetting in this.apnSettings.byAPN) {
|
||||
if (apnSetting.iface) {
|
||||
@ -2121,6 +2460,56 @@ RadioInterface.prototype = {
|
||||
|
||||
// Handle phone functions of nsIRILContentHelper
|
||||
|
||||
enumerateCalls: function enumerateCalls(target, message) {
|
||||
if (DEBUG) this.debug("Requesting enumeration of calls for callback");
|
||||
this.workerMessenger.send("enumerateCalls", message, (function(response) {
|
||||
for (let call of response.calls) {
|
||||
call.state = convertRILCallState(call.state);
|
||||
call.isActive = this._activeCall ?
|
||||
call.callIndex == this._activeCall.callIndex : false;
|
||||
}
|
||||
target.sendAsyncMessage("RIL:EnumerateCalls", response);
|
||||
return false;
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
_validateNumber: function _validateNumber(number) {
|
||||
// note: isPlainPhoneNumber also accepts USSD and SS numbers
|
||||
if (PhoneNumberUtils.isPlainPhoneNumber(number)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.handleCallError({
|
||||
callIndex: -1,
|
||||
errorMsg: RIL.RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[RIL.CALL_FAIL_UNOBTAINABLE_NUMBER]
|
||||
});
|
||||
if (DEBUG) {
|
||||
this.debug("Number '" + number + "' doesn't seem to be a viable number." +
|
||||
" Drop.");
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
dial: function dial(number) {
|
||||
if (DEBUG) this.debug("Dialing " + number);
|
||||
number = PhoneNumberUtils.normalize(number);
|
||||
if (this._validateNumber(number)) {
|
||||
this.workerMessenger.send("dial", { number: number,
|
||||
isDialEmergency: false });
|
||||
}
|
||||
},
|
||||
|
||||
dialEmergency: function dialEmergency(number) {
|
||||
if (DEBUG) this.debug("Dialing emergency " + number);
|
||||
// we don't try to be too clever here, as the phone is probably in the
|
||||
// locked state. Let's just check if it's a number without normalizing
|
||||
if (this._validateNumber(number)) {
|
||||
this.workerMessenger.send("dial", { number: number,
|
||||
isDialEmergency: true });
|
||||
}
|
||||
},
|
||||
|
||||
_sendCfStateChanged: function _sendCfStateChanged(message) {
|
||||
gMessageManager.sendMobileConnectionMessage("RIL:CfStateChanged",
|
||||
this.clientId, message);
|
||||
@ -2175,6 +2564,37 @@ RadioInterface.prototype = {
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
get microphoneMuted() {
|
||||
return gAudioManager.microphoneMuted;
|
||||
},
|
||||
set microphoneMuted(value) {
|
||||
if (value == this.microphoneMuted) {
|
||||
return;
|
||||
}
|
||||
gAudioManager.microphoneMuted = value;
|
||||
|
||||
if (!this._activeCall) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
}
|
||||
},
|
||||
|
||||
get speakerEnabled() {
|
||||
return (gAudioManager.getForceForUse(nsIAudioManager.USE_COMMUNICATION) ==
|
||||
nsIAudioManager.FORCE_SPEAKER);
|
||||
},
|
||||
set speakerEnabled(value) {
|
||||
if (value == this.speakerEnabled) {
|
||||
return;
|
||||
}
|
||||
let force = value ? nsIAudioManager.FORCE_SPEAKER :
|
||||
nsIAudioManager.FORCE_NONE;
|
||||
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
|
||||
|
||||
if (!this._activeCall) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* List of tuples of national language identifier pairs.
|
||||
*
|
||||
@ -2942,13 +3362,6 @@ RadioInterface.prototype = {
|
||||
this.workerMessenger.send("deactivateDataCall", { cid: cid,
|
||||
reason: reason });
|
||||
},
|
||||
|
||||
sendWorkerMessage: function sendWorkerMessage(rilMessageType, message,
|
||||
callback) {
|
||||
this.workerMessenger.send(rilMessageType, message, function (response) {
|
||||
return callback.handleResponse(response);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function RILNetworkInterface(radioInterface, apnSetting) {
|
||||
|
@ -78,13 +78,7 @@ interface nsIRilContext : nsISupports
|
||||
readonly attribute nsIDOMMozMobileConnectionInfo data;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(3bc96351-53b0-47a1-a888-c74c64b60f25)]
|
||||
interface nsIRilSendWorkerMessageCallback : nsISupports
|
||||
{
|
||||
boolean handleResponse(in jsval response);
|
||||
};
|
||||
|
||||
[scriptable, uuid(61a8ca67-6113-4cd0-b443-e045f09863ed)]
|
||||
[scriptable, uuid(a50d65aa-00da-11e3-b954-7bfb233d98fc)]
|
||||
interface nsIRadioInterface : nsISupports
|
||||
{
|
||||
readonly attribute nsIRilContext rilContext;
|
||||
@ -111,10 +105,6 @@ interface nsIRadioInterface : nsISupports
|
||||
in DOMString message,
|
||||
in boolean silent,
|
||||
in nsIMobileMessageCallback request);
|
||||
|
||||
void sendWorkerMessage(in DOMString type,
|
||||
[optional] in jsval message,
|
||||
[optional] in nsIRilSendWorkerMessageCallback callback);
|
||||
};
|
||||
|
||||
[scriptable, uuid(44b03951-1444-4c03-bd37-0bcb3a01b56f)]
|
||||
|
@ -4,9 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/telephony/TelephonyFactory.h"
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsIGonkTelephonyProvider.h"
|
||||
#endif
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "TelephonyIPCProvider.h"
|
||||
@ -20,10 +17,6 @@ TelephonyFactory::CreateTelephonyProvider()
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
provider = new TelephonyIPCProvider();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
} else {
|
||||
provider = do_CreateInstance(GONK_TELEPHONY_PROVIDER_CONTRACTID);
|
||||
#endif
|
||||
}
|
||||
|
||||
return provider.forget();
|
||||
|
@ -1,525 +0,0 @@
|
||||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var RIL = {};
|
||||
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
||||
|
||||
const GONK_TELEPHONYPROVIDER_CONTRACTID =
|
||||
"@mozilla.org/telephony/gonktelephonyprovider;1";
|
||||
const GONK_TELEPHONYPROVIDER_CID =
|
||||
Components.ID("{67d26434-d063-4d28-9f48-5b3189788155}");
|
||||
|
||||
const kPrefenceChangedObserverTopic = "nsPref:changed";
|
||||
const kXpcomShutdownObserverTopic = "xpcom-shutdown";
|
||||
|
||||
const nsIAudioManager = Ci.nsIAudioManager;
|
||||
const nsITelephonyProvider = Ci.nsITelephonyProvider;
|
||||
|
||||
const CALL_WAKELOCK_TIMEOUT = 5000;
|
||||
|
||||
let DEBUG;
|
||||
function debug(s) {
|
||||
dump("TelephonyProvider: " + s + "\n");
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
|
||||
try {
|
||||
return Cc["@mozilla.org/telephony/audiomanager;1"]
|
||||
.getService(nsIAudioManager);
|
||||
} catch (ex) {
|
||||
//TODO on the phone this should not fall back as silently.
|
||||
|
||||
// Fake nsIAudioManager implementation so that we can run the telephony
|
||||
// code in a non-Gonk build.
|
||||
if (DEBUG) debug("Using fake audio manager.");
|
||||
return {
|
||||
microphoneMuted: false,
|
||||
masterVolume: 1.0,
|
||||
masterMuted: false,
|
||||
phoneState: nsIAudioManager.PHONE_STATE_CURRENT,
|
||||
_forceForUse: {},
|
||||
|
||||
setForceForUse: function setForceForUse(usage, force) {
|
||||
this._forceForUse[usage] = force;
|
||||
},
|
||||
|
||||
getForceForUse: function setForceForUse(usage) {
|
||||
return this._forceForUse[usage] || nsIAudioManager.FORCE_NONE;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gPowerManagerService",
|
||||
"@mozilla.org/power/powermanagerservice;1",
|
||||
"nsIPowerManagerService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gRadioInterface", function () {
|
||||
let ril = Cc["@mozilla.org/ril;1"].getService(Ci["nsIRadioInterfaceLayer"]);
|
||||
// TODO: Bug 854326 - B2G Multi-SIM: support multiple SIM cards for SMS/MMS
|
||||
return ril.getRadioInterface(0);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gPhoneNumberUtils", function () {
|
||||
let ns = {};
|
||||
Cu.import("resource://gre/modules/PhoneNumberUtils.jsm", ns);
|
||||
return ns.PhoneNumberUtils;
|
||||
});
|
||||
|
||||
function TelephonyProvider() {
|
||||
this._listeners = [];
|
||||
|
||||
this._updateDebugFlag();
|
||||
|
||||
Services.obs.addObserver(this, kPrefenceChangedObserverTopic, false);
|
||||
Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
|
||||
}
|
||||
TelephonyProvider.prototype = {
|
||||
classID: GONK_TELEPHONYPROVIDER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: GONK_TELEPHONYPROVIDER_CID,
|
||||
contractID: GONK_TELEPHONYPROVIDER_CONTRACTID,
|
||||
classDescription: "TelephonyProvider",
|
||||
interfaces: [Ci.nsITelephonyProvider,
|
||||
Ci.nsIGonkTelephonyProvider],
|
||||
flags: Ci.nsIClassInfo.SINGLETON}),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyProvider,
|
||||
Ci.nsIGonkTelephonyProvider,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
_callRingWakeLock: null,
|
||||
_callRingWakeLockTimer: null,
|
||||
_cancelCallRingWakeLockTimer: function _cancelCallRingWakeLockTimer() {
|
||||
if (this._callRingWakeLockTimer) {
|
||||
this._callRingWakeLockTimer.cancel();
|
||||
}
|
||||
if (this._callRingWakeLock) {
|
||||
this._callRingWakeLock.unlock();
|
||||
this._callRingWakeLock = null;
|
||||
}
|
||||
},
|
||||
|
||||
// An array of nsITelephonyListener instances.
|
||||
_listeners: null,
|
||||
_notifyAllListeners: function _notifyAllListeners(aMethodName, aArgs) {
|
||||
let listeners = this._listeners.slice();
|
||||
for (let listener of listeners) {
|
||||
if (this._listeners.indexOf(listener) == -1) {
|
||||
// Listener has been unregistered in previous run.
|
||||
continue;
|
||||
}
|
||||
|
||||
let handler = listener[aMethodName];
|
||||
try {
|
||||
handler.apply(listener, aArgs);
|
||||
} catch (e) {
|
||||
debug("listener for " + aMethodName + " threw an exception: " + e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
|
||||
if (this.speakerEnabled) {
|
||||
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
|
||||
nsIAudioManager.FORCE_SPEAKER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (aConferenceState === nsITelephonyProvider.CALL_STATE_UNKNOWN ||
|
||||
aConferenceState === nsITelephonyProvider.CALL_STATE_HELD) {
|
||||
if (!this._activeCall) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aCall) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aCall.isConference) {
|
||||
if (this._activeCall && this._activeCall.callIndex == aCall.callIndex) {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case nsITelephonyProvider.CALL_STATE_INCOMING:
|
||||
aCall.isActive = false;
|
||||
if (!this._activeCall) {
|
||||
// We can change the phone state into RINGTONE only when there's
|
||||
// no active call.
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
|
||||
if (DEBUG) {
|
||||
debug("Incoming call, put audio system into PHONE_STATE_RINGTONE: " +
|
||||
gAudioManager.phoneState);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nsITelephonyProvider.CALL_STATE_HELD: // Fall through...
|
||||
case nsITelephonyProvider.CALL_STATE_DISCONNECTED:
|
||||
aCall.isActive = false;
|
||||
if (this._activeCall &&
|
||||
this._activeCall.callIndex == aCall.callIndex) {
|
||||
// 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) {
|
||||
debug("No active call, put audio system into PHONE_STATE_NORMAL: " +
|
||||
gAudioManager.phoneState);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_convertRILCallState: function _convertRILCallState(aState) {
|
||||
switch (aState) {
|
||||
case RIL.CALL_STATE_ACTIVE:
|
||||
return nsITelephonyProvider.CALL_STATE_CONNECTED;
|
||||
case RIL.CALL_STATE_HOLDING:
|
||||
return nsITelephonyProvider.CALL_STATE_HELD;
|
||||
case RIL.CALL_STATE_DIALING:
|
||||
return nsITelephonyProvider.CALL_STATE_DIALING;
|
||||
case RIL.CALL_STATE_ALERTING:
|
||||
return nsITelephonyProvider.CALL_STATE_ALERTING;
|
||||
case RIL.CALL_STATE_INCOMING:
|
||||
case RIL.CALL_STATE_WAITING:
|
||||
return nsITelephonyProvider.CALL_STATE_INCOMING;
|
||||
default:
|
||||
throw new Error("Unknown rilCallState: " + aState);
|
||||
}
|
||||
},
|
||||
|
||||
_convertRILSuppSvcNotification: function _convertRILSuppSvcNotification(aNotification) {
|
||||
switch (aNotification) {
|
||||
case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD:
|
||||
return nsITelephonyProvider.NOTIFICATION_REMOTE_HELD;
|
||||
case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED:
|
||||
return nsITelephonyProvider.NOTIFICATION_REMOTE_RESUMED;
|
||||
default:
|
||||
throw new Error("Unknown rilSuppSvcNotification: " + aNotification);
|
||||
}
|
||||
},
|
||||
|
||||
_validateNumber: function _validateNumber(aNumber) {
|
||||
// note: isPlainPhoneNumber also accepts USSD and SS numbers
|
||||
if (gPhoneNumberUtils.isPlainPhoneNumber(aNumber)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let errorMsg = RIL.RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[RIL.CALL_FAIL_UNOBTAINABLE_NUMBER];
|
||||
let currentThread = Services.tm.currentThread;
|
||||
currentThread.dispatch(this.notifyCallError.bind(this, -1, errorMsg),
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
if (DEBUG) {
|
||||
debug("Number '" + aNumber + "' doesn't seem to be a viable number. Drop.");
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_updateDebugFlag: function _updateDebugFlag() {
|
||||
try {
|
||||
DEBUG = RIL.DEBUG_RIL ||
|
||||
Services.prefs.getBoolPref("ril.debugging.enabled");
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsITelephonyProvider interface.
|
||||
*/
|
||||
|
||||
registerListener: function(aListener) {
|
||||
if (this._listeners.indexOf(aListener) >= 0) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
this._listeners.push(aListener);
|
||||
},
|
||||
|
||||
unregisterListener: function(aListener) {
|
||||
let index = this._listeners.indexOf(aListener);
|
||||
if (index < 0) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
this._listeners.splice(index, 1);
|
||||
},
|
||||
|
||||
enumerateCalls: function(aListener) {
|
||||
if (DEBUG) debug("Requesting enumeration of calls for callback");
|
||||
gRadioInterface.sendWorkerMessage("enumerateCalls", null,
|
||||
(function(response) {
|
||||
for (let call of response.calls) {
|
||||
call.state = this._convertRILCallState(call.state);
|
||||
call.isActive = this._activeCall ?
|
||||
(call.callIndex == this._activeCall.callIndex) : false;
|
||||
|
||||
aListener.enumerateCallState(call.callIndex, call.state, call.number,
|
||||
call.isActive, call.isOutgoing,
|
||||
call.isEmergency, call.isConference);
|
||||
}
|
||||
aListener.enumerateCallStateComplete();
|
||||
|
||||
return false;
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
dial: function(aNumber, aIsEmergency) {
|
||||
if (DEBUG) debug("Dialing " + (aIsEmergency ? "emergency " : "") + aNumber);
|
||||
// we don't try to be too clever here, as the phone is probably in the
|
||||
// locked state. Let's just check if it's a number without normalizing
|
||||
if (!aIsEmergency) {
|
||||
aNumber = gPhoneNumberUtils.normalize(aNumber);
|
||||
}
|
||||
if (this._validateNumber(aNumber)) {
|
||||
gRadioInterface.sendWorkerMessage("dial", { number: aNumber,
|
||||
isDialEmergency: aIsEmergency });
|
||||
}
|
||||
},
|
||||
|
||||
hangUp: function(aCallIndex) {
|
||||
gRadioInterface.sendWorkerMessage("hangUp", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
startTone: function(aDtmfChar) {
|
||||
gRadioInterface.sendWorkerMessage("startTone", { dtmfChar: aDtmfChar });
|
||||
},
|
||||
|
||||
stopTone: function() {
|
||||
gRadioInterface.sendWorkerMessage("stopTone");
|
||||
},
|
||||
|
||||
answerCall: function(aCallIndex) {
|
||||
gRadioInterface.sendWorkerMessage("answerCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
rejectCall: function(aCallIndex) {
|
||||
gRadioInterface.sendWorkerMessage("rejectCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
holdCall: function(aCallIndex) {
|
||||
gRadioInterface.sendWorkerMessage("holdCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
resumeCall: function(aCallIndex) {
|
||||
gRadioInterface.sendWorkerMessage("resumeCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
conferenceCall: function conferenceCall() {
|
||||
gRadioInterface.sendWorkerMessage("conferenceCall");
|
||||
},
|
||||
|
||||
separateCall: function separateCall(aCallIndex) {
|
||||
gRadioInterface.sendWorkerMessage("separateCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
holdConference: function holdConference() {
|
||||
gRadioInterface.sendWorkerMessage("holdConference");
|
||||
},
|
||||
|
||||
resumeConference: function resumeConference() {
|
||||
gRadioInterface.sendWorkerMessage("resumeConference");
|
||||
},
|
||||
|
||||
get microphoneMuted() {
|
||||
return gAudioManager.microphoneMuted;
|
||||
},
|
||||
|
||||
set microphoneMuted(aMuted) {
|
||||
if (aMuted == this.microphoneMuted) {
|
||||
return;
|
||||
}
|
||||
gAudioManager.microphoneMuted = aMuted;
|
||||
|
||||
if (!this._activeCall) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
}
|
||||
},
|
||||
|
||||
get speakerEnabled() {
|
||||
let force = gAudioManager.getForceForUse(nsIAudioManager.USE_COMMUNICATION);
|
||||
return (force == nsIAudioManager.FORCE_SPEAKER);
|
||||
},
|
||||
|
||||
set speakerEnabled(aEnabled) {
|
||||
if (aEnabled == this.speakerEnabled) {
|
||||
return;
|
||||
}
|
||||
let force = aEnabled ? nsIAudioManager.FORCE_SPEAKER :
|
||||
nsIAudioManager.FORCE_NONE;
|
||||
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
|
||||
|
||||
if (!this._activeCall) {
|
||||
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIGonkTelephonyProvider interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle call disconnects by updating our current state and the audio system.
|
||||
*/
|
||||
notifyCallDisconnected: function notifyCallDisconnected(aCall) {
|
||||
if (DEBUG) debug("handleCallDisconnected: " + JSON.stringify(aCall));
|
||||
|
||||
aCall.state = nsITelephonyProvider.CALL_STATE_DISCONNECTED;
|
||||
let duration = ("started" in aCall && typeof aCall.started == "number") ?
|
||||
new Date().getTime() - aCall.started : 0;
|
||||
let data = {
|
||||
number: aCall.number,
|
||||
duration: duration,
|
||||
direction: aCall.isOutgoing ? "outgoing" : "incoming"
|
||||
};
|
||||
gSystemMessenger.broadcastMessage("telephony-call-ended", data);
|
||||
|
||||
this._updateCallAudioState(aCall, null);
|
||||
|
||||
this._notifyAllListeners("callStateChanged", [aCall.callIndex,
|
||||
aCall.state,
|
||||
aCall.number,
|
||||
aCall.isActive,
|
||||
aCall.isOutgoing,
|
||||
aCall.isEmergency,
|
||||
aCall.isConference]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call error.
|
||||
*/
|
||||
notifyCallError: function notifyCallError(aCallIndex, aErrorMsg) {
|
||||
this._notifyAllListeners("notifyError", [aCallIndex, aErrorMsg]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle an incoming call.
|
||||
*
|
||||
* Not much is known about this call at this point, but it's enough
|
||||
* to start bringing up the Phone app already.
|
||||
*/
|
||||
notifyCallRing: function notifyCallRing() {
|
||||
if (!this._callRingWakeLock) {
|
||||
this._callRingWakeLock = gPowerManagerService.newWakeLock("cpu");
|
||||
}
|
||||
if (!this._callRingWakeLockTimer) {
|
||||
this._callRingWakeLockTimer =
|
||||
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
}
|
||||
this._callRingWakeLockTimer
|
||||
.initWithCallback(this._cancelCallRingWakeLockTimer.bind(this),
|
||||
CALL_WAKELOCK_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
|
||||
gSystemMessenger.broadcastMessage("telephony-new-call", {});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle call state changes by updating our current state and the audio
|
||||
* system.
|
||||
*/
|
||||
notifyCallStateChanged: function notifyCallStateChanged(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", {});
|
||||
}
|
||||
|
||||
this._updateCallAudioState(aCall, null);
|
||||
|
||||
this._notifyAllListeners("callStateChanged", [aCall.callIndex,
|
||||
aCall.state,
|
||||
aCall.number,
|
||||
aCall.isActive,
|
||||
aCall.isOutgoing,
|
||||
aCall.isEmergency,
|
||||
aCall.isConference]);
|
||||
},
|
||||
|
||||
notifyCdmaCallWaiting: function notifyCdmaCallWaiting(aNumber) {
|
||||
this._notifyAllListeners("notifyCdmaCallWaiting", [aNumber]);
|
||||
},
|
||||
|
||||
notifySupplementaryService: function notifySupplementaryService(aCallIndex,
|
||||
aNotification) {
|
||||
let notification = this._convertRILSuppSvcNotification(aNotification);
|
||||
this._notifyAllListeners("supplementaryServiceNotification",
|
||||
[aCallIndex, notification]);
|
||||
},
|
||||
|
||||
notifyConferenceCallStateChanged: function notifyConferenceCallStateChanged(aState) {
|
||||
if (DEBUG) debug("handleConferenceCallStateChanged: " + aState);
|
||||
aState = aState != null ? convertRILCallState(aState) :
|
||||
nsITelephonyProvider.CALL_STATE_UNKNOWN;
|
||||
this._updateCallAudioState(null, aState);
|
||||
|
||||
this._notifyAllListeners("conferenceCallStateChanged", [aState]);
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIObserver interface.
|
||||
*/
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case kPrefenceChangedObserverTopic:
|
||||
if (aData === "ril.debugging.enabled") {
|
||||
this._updateDebugFlag();
|
||||
}
|
||||
break;
|
||||
|
||||
case kXpcomShutdownObserverTopic:
|
||||
// Cancel the timer for the call-ring wake lock.
|
||||
this._cancelCallRingWakeLockTimer();
|
||||
|
||||
Services.obs.removeObserver(this, kPrefenceChangedObserverTopic);
|
||||
Services.obs.removeObserver(this, kXpcomShutdownObserverTopic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyProvider]);
|
@ -1,2 +0,0 @@
|
||||
component {67d26434-d063-4d28-9f48-5b3189788155} TelephonyProvider.js
|
||||
contract @mozilla.org/telephony/gonktelephonyprovider;1 {67d26434-d063-4d28-9f48-5b3189788155}
|
@ -42,15 +42,6 @@ IPDL_SOURCES += [
|
||||
'ipc/TelephonyTypes.ipdlh'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
XPIDL_SOURCES += [
|
||||
'nsIGonkTelephonyProvider.idl',
|
||||
]
|
||||
EXTRA_COMPONENTS += [
|
||||
'gonk/TelephonyProvider.js',
|
||||
'gonk/TelephonyProvider.manifest',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
LIBXUL_LIBRARY = True
|
||||
|
@ -1,31 +0,0 @@
|
||||
/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsITelephonyProvider.idl"
|
||||
|
||||
%{C++
|
||||
#define GONK_TELEPHONY_PROVIDER_CONTRACTID \
|
||||
"@mozilla.org/telephony/gonktelephonyprovider;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(0d106c7e-ba47-48ee-ba48-c92002d401b6)]
|
||||
interface nsIGonkTelephonyProvider : nsITelephonyProvider
|
||||
{
|
||||
void notifyCallDisconnected(in jsval call);
|
||||
|
||||
void notifyCallError(in long callIndex,
|
||||
in AString error);
|
||||
|
||||
void notifyCallRing();
|
||||
|
||||
void notifyCallStateChanged(in jsval call);
|
||||
|
||||
void notifyCdmaCallWaiting(in AString number);
|
||||
|
||||
void notifySupplementaryService(in long callIndex,
|
||||
in AString notification);
|
||||
|
||||
void notifyConferenceCallStateChanged(in unsigned short state);
|
||||
};
|
Loading…
Reference in New Issue
Block a user