2011-12-05 11:58:27 +04:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Telephony.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
2012-01-20 00:53:32 +04:00
|
|
|
* the Mozilla Foundation.
|
2011-12-05 11:58:27 +04:00
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Ben Turner <bent.mozilla@gmail.com> (Original Author)
|
|
|
|
* Philipp von Weitershausen <philipp@weitershausen.de>
|
2012-01-20 00:53:32 +04:00
|
|
|
* Sinker Li <thinker@codemud.net>
|
2011-12-05 11:58:27 +04:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
"use strict";
|
|
|
|
|
2011-12-05 11:58:27 +04:00
|
|
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
2011-12-24 09:02:52 +04:00
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
2011-12-05 11:58:27 +04:00
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
var RIL = {};
|
|
|
|
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
|
|
|
|
2012-02-02 22:41:07 +04:00
|
|
|
const DEBUG = false; // set to true to see debug messages
|
2011-12-05 11:58:27 +04:00
|
|
|
|
2012-01-20 00:53:32 +04:00
|
|
|
const RADIOINTERFACELAYER_CID =
|
2012-01-10 03:18:23 +04:00
|
|
|
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
|
2012-01-18 05:34:09 +04:00
|
|
|
const DATACALLINFO_CID =
|
|
|
|
Components.ID("{ef474cd9-94f7-4c05-a31b-29b9de8a10d2}");
|
2011-12-05 11:58:27 +04:00
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
const nsIAudioManager = Ci.nsIAudioManager;
|
2012-01-20 00:53:32 +04:00
|
|
|
const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
|
2011-12-12 22:22:26 +04:00
|
|
|
|
2011-12-24 09:02:52 +04:00
|
|
|
const kSmsReceivedObserverTopic = "sms-received";
|
|
|
|
const DOM_SMS_DELIVERY_RECEIVED = "received";
|
2012-02-20 03:44:29 +04:00
|
|
|
const DOM_SMS_DELIVERY_SENT = "sent";
|
2011-12-24 09:02:52 +04:00
|
|
|
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
|
|
|
|
"@mozilla.org/sms/smsservice;1",
|
|
|
|
"nsISmsService");
|
2011-12-12 22:22:26 +04:00
|
|
|
|
2012-02-20 03:44:29 +04:00
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, "gSmsRequestManager",
|
|
|
|
"@mozilla.org/sms/smsrequestmanager;1",
|
|
|
|
"nsISmsRequestManager");
|
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
function convertRILCallState(state) {
|
|
|
|
switch (state) {
|
|
|
|
case RIL.CALL_STATE_ACTIVE:
|
2012-01-20 00:53:32 +04:00
|
|
|
return nsIRadioInterfaceLayer.CALL_STATE_CONNECTED;
|
2012-01-10 02:28:47 +04:00
|
|
|
case RIL.CALL_STATE_HOLDING:
|
2012-01-20 00:53:32 +04:00
|
|
|
return nsIRadioInterfaceLayer.CALL_STATE_HELD;
|
2012-01-10 02:28:47 +04:00
|
|
|
case RIL.CALL_STATE_DIALING:
|
2012-01-20 00:53:32 +04:00
|
|
|
return nsIRadioInterfaceLayer.CALL_STATE_DIALING;
|
2012-01-10 02:28:47 +04:00
|
|
|
case RIL.CALL_STATE_ALERTING:
|
2012-01-20 00:53:32 +04:00
|
|
|
return nsIRadioInterfaceLayer.CALL_STATE_RINGING;
|
2012-01-10 02:28:47 +04:00
|
|
|
case RIL.CALL_STATE_INCOMING:
|
2012-01-20 00:53:32 +04:00
|
|
|
return nsIRadioInterfaceLayer.CALL_STATE_INCOMING;
|
2012-01-10 02:28:47 +04:00
|
|
|
case RIL.CALL_STATE_WAITING:
|
2012-01-20 00:53:32 +04:00
|
|
|
return nsIRadioInterfaceLayer.CALL_STATE_HELD; // XXX This may not be right...
|
2012-01-10 02:28:47 +04:00
|
|
|
default:
|
|
|
|
throw new Error("Unknown rilCallState: " + state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-12 22:22:26 +04:00
|
|
|
/**
|
|
|
|
* 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,
|
2012-01-10 02:28:47 +04:00
|
|
|
phoneState: nsIAudioManager.PHONE_STATE_CURRENT,
|
2011-12-12 22:22:26 +04:00
|
|
|
_forceForUse: {},
|
|
|
|
setForceForUse: function setForceForUse(usage, force) {
|
|
|
|
this._forceForUse[usage] = force;
|
|
|
|
},
|
|
|
|
getForceForUse: function setForceForUse(usage) {
|
2012-01-10 02:28:47 +04:00
|
|
|
return this._forceForUse[usage] || nsIAudioManager.FORCE_NONE;
|
2011-12-12 22:22:26 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
|
|
|
|
try {
|
|
|
|
return Cc["@mozilla.org/telephony/audiomanager;1"]
|
2012-01-10 02:28:47 +04:00
|
|
|
.getService(nsIAudioManager);
|
2011-12-12 22:22:26 +04:00
|
|
|
} catch (ex) {
|
|
|
|
//TODO on the phone this should not fall back as silently.
|
|
|
|
debug("Using fake audio manager.");
|
|
|
|
return FakeAudioManager;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2011-12-05 11:58:27 +04:00
|
|
|
|
2012-01-18 05:34:09 +04:00
|
|
|
function DataCallInfo(state, cid, apn) {
|
|
|
|
this.callState = state;
|
|
|
|
this.cid = cid;
|
|
|
|
this.apn = apn;
|
|
|
|
}
|
|
|
|
DataCallInfo.protoptype = {
|
|
|
|
classID: DATACALLINFO_CID,
|
|
|
|
classInfo: XPCOMUtils.generateCI({classID: DATACALLINFO_CID,
|
|
|
|
classDescription: "DataCallInfo",
|
|
|
|
interfaces: [Ci.nsIDataCallInfo]}),
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallInfo]),
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-01-20 00:53:32 +04:00
|
|
|
function RadioInterfaceLayer() {
|
2011-12-05 11:58:27 +04:00
|
|
|
this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
|
|
|
|
this.worker.onerror = this.onerror.bind(this);
|
|
|
|
this.worker.onmessage = this.onmessage.bind(this);
|
2012-01-10 02:28:47 +04:00
|
|
|
debug("Starting Worker\n");
|
2011-12-07 10:57:19 +04:00
|
|
|
this.currentState = {
|
|
|
|
signalStrength: null,
|
|
|
|
operator: null,
|
|
|
|
radioState: null,
|
2012-01-10 02:28:47 +04:00
|
|
|
cardState: null
|
2011-12-07 10:57:19 +04:00
|
|
|
};
|
2011-12-05 11:58:27 +04:00
|
|
|
}
|
2012-01-20 00:53:32 +04:00
|
|
|
RadioInterfaceLayer.prototype = {
|
2011-12-05 11:58:27 +04:00
|
|
|
|
2012-01-20 00:53:32 +04:00
|
|
|
classID: RADIOINTERFACELAYER_CID,
|
|
|
|
classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
|
|
|
|
classDescription: "RadioInterfaceLayer",
|
2012-01-10 03:18:23 +04:00
|
|
|
interfaces: [Ci.nsIWorkerHolder,
|
2012-01-20 00:53:32 +04:00
|
|
|
Ci.nsIRadioInterfaceLayer]}),
|
2011-12-05 11:58:27 +04:00
|
|
|
|
2012-01-10 03:18:23 +04:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWorkerHolder,
|
2012-01-20 00:53:32 +04:00
|
|
|
Ci.nsIRadioInterfaceLayer]),
|
2011-12-05 11:58:27 +04:00
|
|
|
|
|
|
|
onerror: function onerror(event) {
|
|
|
|
debug("Got an error: " + event.filename + ":" +
|
|
|
|
event.lineno + ": " + event.message + "\n");
|
2012-01-10 02:28:47 +04:00
|
|
|
event.preventDefault();
|
2011-12-05 11:58:27 +04:00
|
|
|
},
|
|
|
|
|
2011-12-12 22:22:26 +04:00
|
|
|
/**
|
|
|
|
* Process the incoming message from the RIL worker:
|
|
|
|
* (1) Update the current state. This way any component that hasn't
|
|
|
|
* been listening for callbacks can easily catch up by looking at
|
|
|
|
* this.currentState.
|
|
|
|
* (2) Update state in related systems such as the audio.
|
|
|
|
* (3) Multiplex the message to telephone callbacks.
|
|
|
|
*/
|
2011-12-05 11:58:27 +04:00
|
|
|
onmessage: function onmessage(event) {
|
|
|
|
let message = event.data;
|
|
|
|
debug("Received message: " + JSON.stringify(message));
|
|
|
|
switch (message.type) {
|
2012-01-10 02:28:47 +04:00
|
|
|
case "callStateChange":
|
|
|
|
// This one will handle its own notifications.
|
|
|
|
this.handleCallStateChange(message.call);
|
|
|
|
break;
|
|
|
|
case "callDisconnected":
|
|
|
|
// This one will handle its own notifications.
|
|
|
|
this.handleCallDisconnected(message.call);
|
|
|
|
break;
|
|
|
|
case "enumerateCalls":
|
|
|
|
// This one will handle its own notifications.
|
|
|
|
this.handleEnumerateCalls(message.calls);
|
|
|
|
break;
|
2012-02-10 23:27:23 +04:00
|
|
|
case "registrationstatechange":
|
|
|
|
this.currentState.registrationState = message.registrationState;
|
|
|
|
break;
|
|
|
|
case "gprsregistrationstatechange":
|
|
|
|
this.currentState.gprsRegistrationState = message.gprsRegistrationState;
|
|
|
|
break;
|
2011-12-05 11:58:27 +04:00
|
|
|
case "signalstrengthchange":
|
2011-12-07 10:57:19 +04:00
|
|
|
this.currentState.signalStrength = message.signalStrength;
|
2011-12-05 11:58:27 +04:00
|
|
|
break;
|
|
|
|
case "operatorchange":
|
2011-12-07 10:57:19 +04:00
|
|
|
this.currentState.operator = message.operator;
|
2011-12-05 11:58:27 +04:00
|
|
|
break;
|
2011-12-07 10:57:19 +04:00
|
|
|
case "radiostatechange":
|
|
|
|
this.currentState.radioState = message.radioState;
|
2011-12-05 11:58:27 +04:00
|
|
|
break;
|
|
|
|
case "cardstatechange":
|
2011-12-07 10:57:19 +04:00
|
|
|
this.currentState.cardState = message.cardState;
|
2011-12-05 11:58:27 +04:00
|
|
|
break;
|
2011-12-24 09:02:52 +04:00
|
|
|
case "sms-received":
|
|
|
|
this.handleSmsReceived(message);
|
2011-12-07 10:57:19 +04:00
|
|
|
return;
|
2012-02-20 03:44:29 +04:00
|
|
|
case "sms-sent":
|
|
|
|
this.handleSmsSent(message);
|
|
|
|
return;
|
2012-01-18 05:34:09 +04:00
|
|
|
case "datacallstatechange":
|
2012-02-10 23:27:38 +04:00
|
|
|
this.handleDataCallState(message.datacall);
|
2012-01-18 05:34:09 +04:00
|
|
|
break;
|
|
|
|
case "datacalllist":
|
|
|
|
this.handleDataCallList(message);
|
|
|
|
break;
|
2012-01-10 02:28:47 +04:00
|
|
|
default:
|
|
|
|
throw new Error("Don't know about this message type: " + message.type);
|
2011-12-05 11:58:27 +04:00
|
|
|
}
|
2012-01-10 02:28:47 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Track the active call and update the audio system as its state changes.
|
|
|
|
*
|
|
|
|
* XXX Needs some more work to support hold/resume.
|
|
|
|
*/
|
|
|
|
_activeCall: null,
|
2012-01-12 04:20:16 +04:00
|
|
|
updateCallAudioState: function updateCallAudioState() {
|
|
|
|
if (!this._activeCall) {
|
2012-01-10 02:28:47 +04:00
|
|
|
// Disable audio.
|
|
|
|
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
|
2012-01-12 04:20:16 +04:00
|
|
|
debug("No active call, put audio system into PHONE_STATE_NORMAL.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (this._activeCall.state) {
|
2012-01-20 00:53:32 +04:00
|
|
|
case nsIRadioInterfaceLayer.CALL_STATE_INCOMING:
|
2012-01-12 04:20:16 +04:00
|
|
|
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_RINGTONE;
|
|
|
|
debug("Incoming call, put audio system into PHONE_STATE_RINGTONE.");
|
|
|
|
break;
|
2012-01-20 00:53:32 +04:00
|
|
|
case nsIRadioInterfaceLayer.CALL_STATE_DIALING: // Fall through...
|
|
|
|
case nsIRadioInterfaceLayer.CALL_STATE_CONNECTED:
|
2012-01-12 04:20:16 +04:00
|
|
|
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
|
|
|
|
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
|
|
|
|
nsIAudioManager.FORCE_NONE);
|
|
|
|
debug("Active call, put audio system into PHONE_STATE_IN_CALL.");
|
|
|
|
break;
|
2012-01-10 02:28:47 +04:00
|
|
|
}
|
2011-12-05 11:58:27 +04:00
|
|
|
},
|
|
|
|
|
2011-12-12 22:22:26 +04:00
|
|
|
/**
|
2012-01-10 02:28:47 +04:00
|
|
|
* Handle call state changes by updating our current state and the audio
|
|
|
|
* system.
|
2011-12-12 22:22:26 +04:00
|
|
|
*/
|
2012-01-10 02:28:47 +04:00
|
|
|
handleCallStateChange: function handleCallStateChange(call) {
|
|
|
|
debug("handleCallStateChange: " + JSON.stringify(call));
|
|
|
|
call.state = convertRILCallState(call.state);
|
2012-02-02 23:12:32 +04:00
|
|
|
if (call.state == nsIRadioInterfaceLayer.CALL_STATE_DIALING ||
|
|
|
|
call.state == nsIRadioInterfaceLayer.CALL_STATE_RINGING ||
|
|
|
|
call.state == nsIRadioInterfaceLayer.CALL_STATE_CONNECTED) {
|
2012-01-10 02:28:47 +04:00
|
|
|
// This is now the active call.
|
2012-01-12 04:20:16 +04:00
|
|
|
this._activeCall = call;
|
2012-01-10 02:28:47 +04:00
|
|
|
}
|
2012-01-12 04:20:16 +04:00
|
|
|
this.updateCallAudioState();
|
2012-01-10 02:28:47 +04:00
|
|
|
this._deliverCallback("callStateChanged",
|
|
|
|
[call.callIndex, call.state, call.number]);
|
|
|
|
},
|
2011-12-12 22:22:26 +04:00
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
/**
|
|
|
|
* Handle call disconnects by updating our current state and the audio system.
|
|
|
|
*/
|
2012-01-12 04:20:16 +04:00
|
|
|
handleCallDisconnected: function handleCallDisconnected(call) {
|
2012-01-10 02:28:47 +04:00
|
|
|
debug("handleCallDisconnected: " + JSON.stringify(call));
|
2012-01-25 01:25:21 +04:00
|
|
|
if (this._activeCall && this._activeCall.callIndex == call.callIndex) {
|
2012-01-12 04:20:16 +04:00
|
|
|
this._activeCall = null;
|
2011-12-12 22:22:26 +04:00
|
|
|
}
|
2012-01-12 04:20:16 +04:00
|
|
|
this.updateCallAudioState();
|
2012-01-10 02:28:47 +04:00
|
|
|
this._deliverCallback("callStateChanged",
|
2012-01-20 00:53:32 +04:00
|
|
|
[call.callIndex,
|
|
|
|
nsIRadioInterfaceLayer.CALL_STATE_DISCONNECTED,
|
2012-01-10 02:28:47 +04:00
|
|
|
call.number]);
|
|
|
|
},
|
2011-12-12 22:22:26 +04:00
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
/**
|
|
|
|
* Handle calls delivered in response to a 'enumerateCalls' request.
|
|
|
|
*/
|
|
|
|
handleEnumerateCalls: function handleEnumerateCalls(calls) {
|
|
|
|
debug("handleEnumerateCalls: " + JSON.stringify(calls));
|
|
|
|
let callback = this._enumerationCallbacks.shift();
|
2012-01-12 04:20:16 +04:00
|
|
|
let activeCallIndex = this._activeCall ? this._activeCall.callIndex : -1;
|
2012-01-10 02:28:47 +04:00
|
|
|
for (let i in calls) {
|
|
|
|
let call = calls[i];
|
|
|
|
let state = convertRILCallState(call.state);
|
|
|
|
let keepGoing;
|
|
|
|
try {
|
|
|
|
keepGoing =
|
|
|
|
callback.enumerateCallState(call.callIndex, state, call.number,
|
|
|
|
call.callIndex == activeCallIndex);
|
|
|
|
} catch (e) {
|
|
|
|
debug("callback handler for 'enumerateCallState' threw an " +
|
|
|
|
" exception: " + e);
|
|
|
|
keepGoing = true;
|
|
|
|
}
|
|
|
|
if (!keepGoing) {
|
2011-12-12 22:22:26 +04:00
|
|
|
break;
|
2012-01-10 02:28:47 +04:00
|
|
|
}
|
2011-12-12 22:22:26 +04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2011-12-24 09:02:52 +04:00
|
|
|
handleSmsReceived: function handleSmsReceived(message) {
|
|
|
|
//TODO: put the sms into a database, assign it a proper id, yada yada
|
|
|
|
let sms = gSmsService.createSmsMessage(-1,
|
|
|
|
DOM_SMS_DELIVERY_RECEIVED,
|
|
|
|
message.sender || null,
|
|
|
|
message.receiver || null,
|
|
|
|
message.body || null,
|
|
|
|
message.timestamp);
|
|
|
|
Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
|
|
|
|
},
|
|
|
|
|
2012-02-20 03:44:29 +04:00
|
|
|
handleSmsSent: function handleSmsSent(message) {
|
2012-02-20 18:57:38 +04:00
|
|
|
let sms = gSmsService.createSmsMessage(-1,
|
|
|
|
DOM_SMS_DELIVERY_SENT,
|
|
|
|
null,
|
|
|
|
message.number,
|
|
|
|
message.body,
|
|
|
|
Date.now());
|
2012-02-20 03:44:29 +04:00
|
|
|
//TODO At this point we should save the sms into the DB (bug 712809)
|
2012-02-20 18:57:38 +04:00
|
|
|
//TODO handle errors (bug 727319)
|
|
|
|
gSmsRequestManager.notifySmsSent(message.requestId, sms);
|
2012-02-20 03:44:29 +04:00
|
|
|
},
|
|
|
|
|
2012-01-18 05:34:09 +04:00
|
|
|
/**
|
|
|
|
* Handle data call state changes.
|
|
|
|
*/
|
2012-02-10 23:27:38 +04:00
|
|
|
handleDataCallState: function handleDataCallState(datacall) {
|
2012-01-18 05:34:09 +04:00
|
|
|
this._deliverDataCallCallback("dataCallStateChanged",
|
2012-02-10 23:27:38 +04:00
|
|
|
[datacall.cid, datacall.ifname, datacall.state]);
|
2012-01-18 05:34:09 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle data call list.
|
|
|
|
*/
|
|
|
|
handleDataCallList: function handleDataCallList(message) {
|
|
|
|
let datacalls = [];
|
|
|
|
for each (let datacall in message.datacalls) {
|
|
|
|
datacalls.push(new DataCallInfo(datacall.state,
|
|
|
|
datacall.cid,
|
|
|
|
datacall.apn));
|
|
|
|
}
|
|
|
|
this._deliverDataCallCallback("receiveDataCallList",
|
|
|
|
[datacalls, datacalls.length]);
|
|
|
|
},
|
|
|
|
|
2011-12-06 12:47:35 +04:00
|
|
|
// nsIRadioWorker
|
2011-12-05 11:58:27 +04:00
|
|
|
|
|
|
|
worker: null,
|
|
|
|
|
2012-01-20 00:53:32 +04:00
|
|
|
// nsIRadioInterfaceLayer
|
2011-12-05 11:58:27 +04:00
|
|
|
|
2011-12-07 10:57:19 +04:00
|
|
|
currentState: null,
|
2011-12-05 11:58:27 +04:00
|
|
|
|
|
|
|
dial: function dial(number) {
|
|
|
|
debug("Dialing " + number);
|
|
|
|
this.worker.postMessage({type: "dial", number: number});
|
|
|
|
},
|
|
|
|
|
2011-12-07 10:57:19 +04:00
|
|
|
hangUp: function hangUp(callIndex) {
|
|
|
|
debug("Hanging up call no. " + callIndex);
|
|
|
|
this.worker.postMessage({type: "hangUp", callIndex: callIndex});
|
|
|
|
},
|
2012-01-18 05:34:09 +04:00
|
|
|
|
2011-12-17 01:47:32 +04:00
|
|
|
startTone: function startTone(dtmfChar) {
|
|
|
|
debug("Sending Tone for " + dtmfChar);
|
|
|
|
this.worker.postMessage({type: "startTone", dtmfChar: dtmfChar});
|
|
|
|
},
|
|
|
|
|
|
|
|
stopTone: function stopTone() {
|
|
|
|
debug("Stopping Tone");
|
|
|
|
this.worker.postMessage({type: "stopTone"});
|
|
|
|
},
|
2011-12-07 10:57:19 +04:00
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
answerCall: function answerCall(callIndex) {
|
|
|
|
this.worker.postMessage({type: "answerCall", callIndex: callIndex});
|
2011-12-07 10:57:19 +04:00
|
|
|
},
|
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
rejectCall: function rejectCall(callIndex) {
|
|
|
|
this.worker.postMessage({type: "rejectCall", callIndex: callIndex});
|
2011-12-07 10:57:19 +04:00
|
|
|
},
|
|
|
|
|
2011-12-12 22:30:43 +04:00
|
|
|
get microphoneMuted() {
|
|
|
|
return gAudioManager.microphoneMuted;
|
|
|
|
},
|
|
|
|
set microphoneMuted(value) {
|
|
|
|
if (value == this.microphoneMuted) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
gAudioManager.phoneState = value ?
|
2012-01-10 02:28:47 +04:00
|
|
|
nsIAudioManager.PHONE_STATE_IN_COMMUNICATION :
|
|
|
|
nsIAudioManager.PHONE_STATE_IN_CALL; //XXX why is this needed?
|
2011-12-12 22:30:43 +04:00
|
|
|
gAudioManager.microphoneMuted = value;
|
|
|
|
},
|
|
|
|
|
|
|
|
get speakerEnabled() {
|
2012-01-10 02:28:47 +04:00
|
|
|
return (gAudioManager.getForceForUse(nsIAudioManager.USE_COMMUNICATION) ==
|
|
|
|
nsIAudioManager.FORCE_SPEAKER);
|
2011-12-12 22:30:43 +04:00
|
|
|
},
|
|
|
|
set speakerEnabled(value) {
|
|
|
|
if (value == this.speakerEnabled) {
|
|
|
|
return;
|
|
|
|
}
|
2012-01-10 02:28:47 +04:00
|
|
|
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL; // XXX why is this needed?
|
|
|
|
let force = value ? nsIAudioManager.FORCE_SPEAKER :
|
|
|
|
nsIAudioManager.FORCE_NONE;
|
2012-02-10 23:27:23 +04:00
|
|
|
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
|
2011-12-12 22:30:43 +04:00
|
|
|
},
|
|
|
|
|
2011-12-24 09:02:52 +04:00
|
|
|
getNumberOfMessagesForText: function getNumberOfMessagesForText(text) {
|
|
|
|
//TODO: this assumes 7bit encoding, which is incorrect. Need to look
|
|
|
|
// for characters not supported by 7bit alphabets and then calculate
|
|
|
|
// length in UCS2 encoding.
|
|
|
|
return Math.ceil(text.length / 160);
|
|
|
|
},
|
|
|
|
|
2012-02-20 03:44:29 +04:00
|
|
|
sendSMS: function sendSMS(number, message, requestId, processId) {
|
2011-12-24 09:02:52 +04:00
|
|
|
this.worker.postMessage({type: "sendSMS",
|
|
|
|
number: number,
|
2012-02-20 03:44:29 +04:00
|
|
|
body: message,
|
|
|
|
requestId: requestId,
|
|
|
|
processId: processId});
|
2011-12-24 09:02:52 +04:00
|
|
|
},
|
|
|
|
|
2011-12-05 11:58:27 +04:00
|
|
|
_callbacks: null,
|
2012-01-10 02:28:47 +04:00
|
|
|
_enumerationCallbacks: null,
|
2011-12-05 11:58:27 +04:00
|
|
|
|
|
|
|
registerCallback: function registerCallback(callback) {
|
2012-01-10 02:28:47 +04:00
|
|
|
if (this._callbacks) {
|
|
|
|
if (this._callbacks.indexOf(callback) != -1) {
|
|
|
|
throw new Error("Already registered this callback!");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this._callbacks = [];
|
|
|
|
}
|
2011-12-05 11:58:27 +04:00
|
|
|
this._callbacks.push(callback);
|
2012-01-12 04:20:08 +04:00
|
|
|
debug("Registered callback: " + callback);
|
2011-12-05 11:58:27 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
unregisterCallback: function unregisterCallback(callback) {
|
2012-01-12 04:20:08 +04:00
|
|
|
if (!this._callbacks) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let index = this._callbacks.indexOf(callback);
|
|
|
|
if (index != -1) {
|
2012-01-10 02:28:47 +04:00
|
|
|
this._callbacks.splice(index, 1);
|
2012-01-12 04:20:08 +04:00
|
|
|
debug("Unregistered callback: " + callback);
|
2012-01-10 02:28:47 +04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
enumerateCalls: function enumerateCalls(callback) {
|
|
|
|
debug("Requesting enumeration of calls for callback: " + callback);
|
|
|
|
this.worker.postMessage({type: "enumerateCalls"});
|
|
|
|
if (!this._enumerationCallbacks) {
|
|
|
|
this._enumerationCallbacks = [];
|
2011-12-05 11:58:27 +04:00
|
|
|
}
|
2012-01-10 02:28:47 +04:00
|
|
|
this._enumerationCallbacks.push(callback);
|
2011-12-05 11:58:27 +04:00
|
|
|
},
|
|
|
|
|
2012-01-10 02:28:47 +04:00
|
|
|
_deliverCallback: function _deliverCallback(name, args) {
|
|
|
|
// We need to worry about callback registration state mutations during the
|
|
|
|
// callback firing. The behaviour we want is to *not* call any callbacks
|
|
|
|
// that are added during the firing and to *not* call any callbacks that are
|
|
|
|
// removed during the firing. To address this, we make a copy of the
|
|
|
|
// callback list before dispatching and then double-check that each callback
|
|
|
|
// is still registered before calling it.
|
|
|
|
if (!this._callbacks) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let callbacks = this._callbacks.slice();
|
|
|
|
for each (let callback in callbacks) {
|
|
|
|
if (this._callbacks.indexOf(callback) == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let handler = callback[name];
|
|
|
|
if (typeof handler != "function") {
|
|
|
|
throw new Error("No handler for " + name);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
handler.apply(callback, args);
|
|
|
|
} catch (e) {
|
|
|
|
debug("callback handler for " + name + " threw an exception: " + e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2012-01-18 05:34:09 +04:00
|
|
|
|
|
|
|
registerDataCallCallback: function registerDataCallCallback(callback) {
|
|
|
|
if (this._datacall_callbacks) {
|
|
|
|
if (this._datacall_callbacks.indexOf(callback) != -1) {
|
|
|
|
throw new Error("Already registered this callback!");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this._datacall_callbacks = [];
|
|
|
|
}
|
|
|
|
this._datacall_callbacks.push(callback);
|
|
|
|
debug("Registering callback: " + callback);
|
|
|
|
},
|
|
|
|
|
|
|
|
unregisterDataCallCallback: function unregisterDataCallCallback(callback) {
|
|
|
|
if (!this._datacall_callbacks) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let index = this._datacall_callbacks.indexOf(callback);
|
|
|
|
if (index != -1) {
|
|
|
|
this._datacall_callbacks.splice(index, 1);
|
|
|
|
debug("Unregistering callback: " + callback);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_deliverDataCallCallback: function _deliverDataCallCallback(name, args) {
|
|
|
|
// We need to worry about callback registration state mutations during the
|
|
|
|
// callback firing. The behaviour we want is to *not* call any callbacks
|
|
|
|
// that are added during the firing and to *not* call any callbacks that are
|
|
|
|
// removed during the firing. To address this, we make a copy of the
|
|
|
|
// callback list before dispatching and then double-check that each callback
|
|
|
|
// is still registered before calling it.
|
|
|
|
if (!this._datacall_callbacks) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let callbacks = this._datacall_callbacks.slice();
|
|
|
|
for each (let callback in callbacks) {
|
|
|
|
if (this._datacall_callbacks.indexOf(callback) == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let handler = callback[name];
|
|
|
|
if (typeof handler != "function") {
|
|
|
|
throw new Error("No handler for " + name);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
handler.apply(callback, args);
|
|
|
|
} catch (e) {
|
|
|
|
debug("callback handler for " + name + " threw an exception: " + e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-02-10 23:27:38 +04:00
|
|
|
setupDataCall: function setupDataCall(radioTech, apn, user, passwd, chappap, pdptype) {
|
2012-01-18 05:34:09 +04:00
|
|
|
this.worker.postMessage({type: "setupDataCall",
|
|
|
|
radioTech: radioTech,
|
|
|
|
apn: apn,
|
|
|
|
user: user,
|
|
|
|
passwd: passwd,
|
|
|
|
chappap: chappap,
|
|
|
|
pdptype: pdptype});
|
|
|
|
},
|
|
|
|
|
2012-02-10 23:27:38 +04:00
|
|
|
deactivateDataCall: function deactivateDataCall(cid, reason) {
|
2012-01-18 05:34:09 +04:00
|
|
|
this.worker.postMessage({type: "deactivateDataCall",
|
|
|
|
cid: cid,
|
|
|
|
reason: reason});
|
|
|
|
},
|
|
|
|
|
|
|
|
getDataCallList: function getDataCallList() {
|
|
|
|
this.worker.postMessage({type: "getDataCallList"});
|
|
|
|
},
|
|
|
|
|
2011-12-05 11:58:27 +04:00
|
|
|
};
|
|
|
|
|
2012-01-20 00:53:32 +04:00
|
|
|
const NSGetFactory = XPCOMUtils.generateNSGetFactory([RadioInterfaceLayer]);
|
2011-12-05 11:58:27 +04:00
|
|
|
|
|
|
|
let debug;
|
|
|
|
if (DEBUG) {
|
|
|
|
debug = function (s) {
|
2012-01-20 00:53:32 +04:00
|
|
|
dump("-*- RadioInterfaceLayer: " + s + "\n");
|
2011-12-05 11:58:27 +04:00
|
|
|
};
|
|
|
|
} else {
|
|
|
|
debug = function (s) {};
|
|
|
|
}
|