merge b2g-i to m-c

This commit is contained in:
Carsten "Tomcat" Book 2014-04-14 15:43:56 +02:00
commit a49b0d1b1d
30 changed files with 1417 additions and 1406 deletions

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="55bcc2d7e44dc805c24b57d1e783fc26e8a2ee86"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52c909ccead537f8f9dbf634f3e6639078a8b0bd">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="55bcc2d7e44dc805c24b57d1e783fc26e8a2ee86"/>

View File

@ -18,7 +18,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "a71af1a665a6596324db3487ba73a1d83bf695f2",
"revision": "baa54fb0f2c415a4521259d7fa2f14db32f608a7",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3abbd2d0a60f1a1618db93f8b1957cae6de379c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e046133c79d13d2ad26814547a163ec1732d36e7"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>

View File

@ -205,7 +205,22 @@ ClassToIcon(uint32_t aClass, nsAString& aRetIcon)
}
break;
}
if (aRetIcon.IsEmpty()) {
if (HAS_AUDIO(aClass)) {
/**
* Property 'Icon' may be missed due to CoD of major class is TOY(0x08).
* But we need to assign Icon as audio-card if service class is 'Audio'.
* This is for PTS test case TC_AG_COD_BV_02_I. As HFP specification
* defines that service class is 'Audio' can be considered as HFP HF.
*/
aRetIcon.AssignLiteral("audio-card");
} else {
BT_LOGR("No icon to match class: %x", aClass);
}
}
}
static ControlPlayStatus
PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus)
{

View File

@ -643,19 +643,17 @@ void BluetoothHfpManager::ProcessDialCall(char *aNumber)
void
BluetoothHfpManager::ProcessAtCnum()
{
NS_ENSURE_TRUE_VOID(!mMsisdn.IsEmpty());
NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
if (!mMsisdn.IsEmpty()) {
nsAutoCString message("+CNUM: ,\"");
message.Append(NS_ConvertUTF16toUTF8(mMsisdn).get());
message.AppendLiteral("\",");
message.AppendInt(BTHF_CALL_ADDRTYPE_UNKNOWN);
message.AppendLiteral(",,4");
nsAutoCString message("+CNUM: ,\"");
message.Append(NS_ConvertUTF16toUTF8(mMsisdn).get());
message.AppendLiteral("\",");
message.AppendInt(BTHF_CALL_ADDRTYPE_UNKNOWN);
message.AppendLiteral(",,4");
SendLine(message.get());
}
NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
sBluetoothHfpInterface->formatted_at_response(message.get()));
NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
sBluetoothHfpInterface->at_response(BTHF_AT_RESPONSE_OK, 0));
SendResponse(BTHF_AT_RESPONSE_OK);
}
void

File diff suppressed because it is too large Load Diff

View File

@ -42,10 +42,17 @@ disabled = Bug 821927
disabled = Bug 821958
[test_outgoing_emergency_in_airplane_mode.js]
[test_emergency_label.js]
[test_conference.js]
[test_dsds_default_service_id.js]
[test_call_mute.js]
[test_dsds_normal_call.js]
[test_dsds_connection_conflict.js]
[test_audiomanager_phonestate.js]
[test_outgoing_answer_radio_off.js]
[test_conference_two_calls.js]
[test_conference_add_error.js]
[test_conference_remove_error.js]
[test_conference_two_hangup_one.js]
[test_conference_two_hold_resume.js]
[test_conference_two_remove_one.js]
[test_conference_three_hangup_one.js]
[test_conference_three_remove_one.js]

View File

@ -14,160 +14,6 @@ const PHONE_STATE_RINGTONE = 1;
const PHONE_STATE_IN_CALL = 2;
const PHONE_STATE_IN_COMMUNICATION = 3;
let conference;
function checkTelephonyActiveAndCalls(active, calls) {
is(telephony.active, active, "telephony.active");
is(telephony.calls.length, calls.length, "telephony.calls");
for (let i = 0; i < calls.length; ++i) {
is(telephony.calls[i], calls[i]);
}
}
function checkConferenceStateAndCalls(state, calls) {
is(conference.state, state, "conference.state");
is(conference.calls.length, calls.length, "conference.calls");
for (let i = 0; i < calls.length; i++) {
is(conference.calls[i], calls[i]);
}
}
function checkInitialState() {
log("Verify initial state.");
ok(telephony.calls, 'telephony.call');
checkTelephonyActiveAndCalls(null, []);
ok(conference.calls, 'conference.calls');
checkConferenceStateAndCalls('', []);
}
function checkEventCallState(event, call, state) {
is(call, event.call, "event.call");
is(call.state, state, "call state");
}
function dial(number) {
log("Make an outgoing call: " + number);
let deferred = Promise.defer();
telephony.dial(number).then(call => {
ok(call);
is(call.number, number);
is(call.state, "dialing");
call.onalerting = function onalerting(event) {
call.onalerting = null;
log("Received 'onalerting' call event.");
checkEventCallState(event, call, "alerting");
deferred.resolve(call);
};
});
return deferred.promise;
}
function answer(call) {
log("Answering the incoming call.");
let deferred = Promise.defer();
call.onconnecting = function onconnectingIn(event) {
log("Received 'connecting' call event for incoming call.");
call.onconnecting = null;
checkEventCallState(event, call, "connecting");
};
call.onconnected = function onconnectedIn(event) {
log("Received 'connected' call event for incoming call.");
call.onconnected = null;
checkEventCallState(event, call, "connected");
ok(!call.onconnecting);
deferred.resolve(call);
};
call.answer();
return deferred.promise;
}
function remoteDial(number) {
log("Simulating an incoming call.");
let deferred = Promise.defer();
telephony.onincoming = function onincoming(event) {
log("Received 'incoming' call event.");
telephony.onimcoming = null;
let call = event.call;
ok(call);
is(call.number, number);
is(call.state, "incoming");
deferred.resolve(call);
};
emulator.run("gsm call " + number);
return deferred.promise;
}
function remoteAnswer(call) {
log("Remote answering the call.");
let deferred = Promise.defer();
call.onconnected = function onconnected(event) {
log("Received 'connected' call event.");
call.onconnected = null;
checkEventCallState(event, call, "connected");
deferred.resolve(call);
};
emulator.run("gsm accept " + call.number);
return deferred.promise;
}
function remoteHangUp(call) {
log("Remote hanging up the call.");
let deferred = Promise.defer();
call.ondisconnected = function ondisconnected(event) {
log("Received 'disconnected' call event.");
call.ondisconnected = null;
checkEventCallState(event, call, "disconnected");
deferred.resolve(call);
};
emulator.run("gsm cancel " + call.number);
return deferred.promise;
}
function remoteHangUpCalls(calls) {
let promise = Promise.resolve();
for (let call of calls) {
promise = promise.then(remoteHangUp.bind(null, call));
}
return promise;
}
// The length of callsToAdd should be 2.
function addCallsToConference(callsToAdd) {
log("Add " + callsToAdd.length + " calls into conference.");
let deferred = Promise.defer();
conference.onconnected = function() {
deferred.resolve();
};
conference.add(callsToAdd[0], callsToAdd[1]);
return deferred.promise;
}
let audioManager;
function checkStates(speakerEnabled, phoneState) {
if (!audioManager) {
@ -203,59 +49,55 @@ function check(phoneStateOrig, phoneStateEnabled, phoneStateDisabled) {
// Start the test
startTest(function() {
conference = telephony.conferenceGroup;
ok(conference);
let outNumber = "5555550101";
let inNumber = "5555550201";
let outCall;
let inCall;
Promise.resolve()
.then(checkInitialState)
.then(() => check(PHONE_STATE_CURRENT, PHONE_STATE_NORMAL, PHONE_STATE_NORMAL))
// Dial in
.then(() => remoteDial(inNumber))
.then(() => gRemoteDial(inNumber))
.then(call => { inCall = call; })
// TODO - Bug 948860: should this be {RINGTONE, RINGTONE, RINGTONE}?
// From current UX spec, there is no chance that an user may enable speaker
// during alerting, so basically this 'set speaker enable' action can't
// happen in B2G.
.then(() => check(PHONE_STATE_RINGTONE, PHONE_STATE_NORMAL, PHONE_STATE_NORMAL))
.then(() => answer(inCall))
.then(() => gAnswer(inCall))
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
// Hang up all
.then(() => remoteHangUp(inCall))
.then(() => gRemoteHangUp(inCall))
.then(() => check(PHONE_STATE_NORMAL, PHONE_STATE_NORMAL))
// Dial out
.then(() => dial(outNumber))
.then(() => gDial(outNumber))
.then(call => { outCall = call; })
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
.then(() => remoteAnswer(outCall))
.then(() => gRemoteAnswer(outCall))
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
// Hang up all
.then(() => remoteHangUp(outCall))
.then(() => gRemoteHangUp(outCall))
.then(() => check(PHONE_STATE_NORMAL, PHONE_STATE_NORMAL))
// Dial out
.then(() => dial(outNumber))
.then(() => gDial(outNumber))
.then(call => { outCall = call; })
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
.then(() => remoteAnswer(outCall))
.then(() => gRemoteAnswer(outCall))
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
// Dial out and dial in
.then(() => remoteDial(inNumber))
.then(() => gRemoteDial(inNumber))
.then(call => { inCall = call; })
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
.then(() => answer(inCall))
.then(() => gAnswer(inCall))
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
// Conference
.then(() => addCallsToConference([outCall, inCall]))
.then(() => gAddCallsToConference([outCall, inCall]))
.then(() => check(PHONE_STATE_IN_CALL, PHONE_STATE_IN_CALL))
// Hang up all
.then(() => remoteHangUpCalls([outCall, inCall]))
.then(() => gRemoteHangUpCalls([outCall, inCall]))
.then(() => check(PHONE_STATE_NORMAL, PHONE_STATE_NORMAL))
// End

View File

@ -1,967 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
let conference;
/**
* The functions are created to provide the string format of the emulator call
* list results.
*
* Usage:
* let outInfo = outCallStrPool('911');
* outInfo.ringing == "outbound to 911 : ringing"
* outInfo.active == "outbound to 911 : active"
*/
function callStrPool(prefix, number) {
let padding = " : ";
let numberInfo = prefix + number + padding.substr(number.length);
let info = {};
let states = ['ringing', 'incoming', 'active', 'held'];
for (let state of states) {
info[state] = numberInfo + state;
}
return info;
}
function outCallStrPool(number) {
return callStrPool("outbound to ", number);
}
function inCallStrPool(number) {
return callStrPool("inbound from ", number);
}
function checkInitialState() {
log("Verify initial state.");
ok(telephony.calls, 'telephony.call');
checkTelephonyActiveAndCalls(null, []);
ok(conference.calls, 'conference.calls');
checkConferenceStateAndCalls('', []);
}
function checkEventCallState(event, call, state) {
is(call, event.call, "event.call");
is(call.state, state, "call state");
}
function checkTelephonyActiveAndCalls(active, calls) {
is(telephony.active, active, "telephony.active");
is(telephony.calls.length, calls.length, "telephony.calls");
for (let i = 0; i < calls.length; ++i) {
is(telephony.calls[i], calls[i]);
}
}
function checkConferenceStateAndCalls(state, calls) {
is(conference.state, state, "conference.state");
is(conference.calls.length, calls.length, "conference.calls");
for (let i = 0; i < calls.length; i++) {
is(conference.calls[i], calls[i]);
}
}
function checkState(active, calls, conferenceState, conferenceCalls) {
checkTelephonyActiveAndCalls(active, calls);
checkConferenceStateAndCalls(conferenceState, conferenceCalls);
}
function checkEmulatorCallList(expectedCallList) {
let deferred = Promise.defer();
emulator.run("gsm list", function(result) {
log("Call list is now: " + result);
for (let i = 0; i < expectedCallList.length; ++i) {
is(result[i], expectedCallList[i], "emulator calllist");
}
is(result[expectedCallList.length], "OK", "emulator calllist");
deferred.resolve();
});
return deferred.promise;
}
// Promise.
function checkAll(active, calls, conferenceState, conferenceCalls, callList) {
checkState(active, calls, conferenceState, conferenceCalls);
return checkEmulatorCallList(callList);
}
// Make sure there's no pending event before we jump to the next case.
function receivedPending(received, pending, nextAction) {
let index = pending.indexOf(received);
if (index != -1) {
pending.splice(index, 1);
}
if (pending.length === 0) {
nextAction();
}
}
function dial(number) {
log("Make an outgoing call: " + number);
let deferred = Promise.defer();
telephony.dial(number).then(call => {
ok(call);
is(call.number, number);
is(call.state, "dialing");
call.onalerting = function onalerting(event) {
call.onalerting = null;
log("Received 'onalerting' call event.");
checkEventCallState(event, call, "alerting");
deferred.resolve(call);
};
});
return deferred.promise;
}
// Answering an incoming call could trigger conference state change.
function answer(call, conferenceStateChangeCallback) {
log("Answering the incoming call.");
let deferred = Promise.defer();
let done = function() {
deferred.resolve(call);
};
let pending = ["call.onconnected"];
let receive = function(name) {
receivedPending(name, pending, done);
};
// When there's already a connected conference call, answering a new incoming
// call triggers conference state change. We should wait for
// |conference.onstatechange| before checking the state of the conference call.
if (conference.state === "connected") {
pending.push("conference.onstatechange");
check_onstatechange(conference, "conference", "held", function() {
if (typeof conferenceStateChangeCallback === "function") {
conferenceStateChangeCallback();
}
receive("conference.onstatechange");
});
}
call.onconnecting = function onconnectingIn(event) {
log("Received 'connecting' call event for incoming call.");
call.onconnecting = null;
checkEventCallState(event, call, "connecting");
};
call.onconnected = function onconnectedIn(event) {
log("Received 'connected' call event for incoming call.");
call.onconnected = null;
checkEventCallState(event, call, "connected");
ok(!call.onconnecting);
receive("call.onconnected");
};
call.answer();
return deferred.promise;
}
function remoteDial(number) {
log("Simulating an incoming call.");
let deferred = Promise.defer();
telephony.onincoming = function onincoming(event) {
log("Received 'incoming' call event.");
telephony.onincoming = null;
let call = event.call;
ok(call);
is(call.number, number);
is(call.state, "incoming");
deferred.resolve(call);
};
emulator.run("gsm call " + number);
return deferred.promise;
}
function remoteAnswer(call) {
log("Remote answering the call.");
let deferred = Promise.defer();
call.onconnected = function onconnected(event) {
log("Received 'connected' call event.");
call.onconnected = null;
checkEventCallState(event, call, "connected");
deferred.resolve(call);
};
emulator.run("gsm accept " + call.number);
return deferred.promise;
}
function remoteHangUp(call) {
log("Remote hanging up the call.");
let deferred = Promise.defer();
call.ondisconnected = function ondisconnected(event) {
log("Received 'disconnected' call event.");
call.ondisconnected = null;
checkEventCallState(event, call, "disconnected");
deferred.resolve(call);
};
emulator.run("gsm cancel " + call.number);
return deferred.promise;
}
function remoteHangUpCalls(calls) {
let promise = Promise.resolve();
for (let call of calls) {
promise = promise.then(remoteHangUp.bind(null, call));
}
return promise;
}
// container might be telephony or conference.
function check_oncallschanged(container, containerName, expectedCalls,
callback) {
container.oncallschanged = function(event) {
log("Received 'callschanged' event for the " + containerName);
if (event.call) {
let index = expectedCalls.indexOf(event.call);
ok(index != -1);
expectedCalls.splice(index, 1);
if (expectedCalls.length === 0) {
container.oncallschanged = null;
callback();
}
}
};
}
function check_ongroupchange(call, callName, group, callback) {
call.ongroupchange = function(event) {
log("Received 'groupchange' event for the " + callName);
call.ongroupchange = null;
is(call.group, group);
callback();
};
}
function check_onstatechange(call, callName, state, callback) {
call.onstatechange = function(event) {
log("Received 'statechange' event for the " + callName);
call.onstatechange = null;
is(call.state, state);
callback();
};
}
function StateEventChecker(state, previousEvent) {
let event = 'on' + state;
return function(call, callName, callback) {
call[event] = function() {
log("Received '" + state + "' event for the " + callName);
call[event] = null;
if (previousEvent) {
// We always clear the event handler when the event is received.
// Therefore, if the corresponding handler is not existed, the expected
// previous event has been already received.
ok(!call[previousEvent]);
}
is(call.state, state);
callback();
};
};
}
let check_onholding = StateEventChecker('holding', null);
let check_onheld = StateEventChecker('held', 'onholding');
let check_onresuming = StateEventChecker('resuming', null);
let check_onconnected = StateEventChecker('connected', 'onresuming');
// The length of callsToAdd should be 1 or 2.
function addCallsToConference(callsToAdd, connectedCallback) {
log("Add " + callsToAdd.length + " calls into conference.");
let deferred = Promise.defer();
let done = function() {
deferred.resolve();
};
let pending = ["conference.oncallschanged", "conference.onconnected"];
let receive = function(name) {
receivedPending(name, pending, done);
};
for (let call of callsToAdd) {
let callName = "callToAdd (" + call.number + ')';
let ongroupchange = callName + ".ongroupchange";
pending.push(ongroupchange);
check_ongroupchange(call, callName, conference,
receive.bind(null, ongroupchange));
let onstatechange = callName + ".onstatechange";
pending.push(onstatechange);
check_onstatechange(call, callName, 'connected',
receive.bind(null, onstatechange));
}
check_oncallschanged(conference, 'conference', callsToAdd,
receive.bind(null, "conference.oncallschanged"));
check_onconnected(conference, "conference", function() {
ok(!conference.oncallschanged);
if (typeof connectedCallback === 'function') {
connectedCallback();
}
receive("conference.onconnected");
});
// Cannot use apply() through webidl, so just separate the cases to handle.
if (callsToAdd.length == 2) {
conference.add(callsToAdd[0], callsToAdd[1]);
} else {
conference.add(callsToAdd[0]);
}
return deferred.promise;
}
function holdConference(calls, heldCallback) {
log("Holding the conference call.");
let deferred = Promise.defer();
let done = function() {
deferred.resolve();
};
let pending = ["conference.onholding", "conference.onheld"];
let receive = function(name) {
receivedPending(name, pending, done);
};
for (let call of calls) {
let callName = "call (" + call.number + ')';
let onholding = callName + ".onholding";
pending.push(onholding);
check_onholding(call, callName, receive.bind(null, onholding));
let onheld = callName + ".onheld";
pending.push(onheld);
check_onheld(call, callName, receive.bind(null, onheld));
}
check_onholding(conference, "conference",
receive.bind(null, "conference.onholding"));
check_onheld(conference, "conference", function() {
if (typeof heldCallback === 'function') {
heldCallback();
}
receive("conference.onheld");
});
conference.hold();
return deferred.promise;
}
function resumeConference(calls, connectedCallback) {
log("Resuming the held conference call.");
let deferred = Promise.defer();
let done = function() {
deferred.resolve();
};
let pending = ["conference.onresuming", "conference.onconnected"];
let receive = function(name) {
receivedPending(name, pending, done);
};
for (let call of calls) {
let callName = "call (" + call.number + ')';
let onresuming = callName + ".onresuming";
pending.push(onresuming);
check_onresuming(call, callName, receive.bind(null, onresuming));
let onconnected = callName + ".onconnected";
pending.push(onconnected);
check_onconnected(call, callName, receive.bind(null, onconnected));
}
check_onresuming(conference, "conference",
receive.bind(null, "conference.onresuming"));
check_onconnected(conference, "conference", function() {
if (typeof connectedCallback === 'function') {
connectedCallback();
}
receive("conference.onconnected");
});
conference.resume();
return deferred.promise;
}
// The length of autoRemovedCalls should be 0 or 1.
function removeCallInConference(callToRemove, autoRemovedCalls, remainedCalls,
statechangeCallback) {
log("Removing a participant from the conference call.");
is(conference.state, 'connected');
let deferred = Promise.defer();
let done = function() {
deferred.resolve();
};
let pending = ["callToRemove.ongroupchange", "telephony.oncallschanged",
"conference.oncallschanged", "conference.onstatechange"];
let receive = function(name) {
receivedPending(name, pending, done);
};
// Remained call in conference will be held.
for (let call of remainedCalls) {
let callName = "remainedCall (" + call.number + ')';
let onstatechange = callName + ".onstatechange";
pending.push(onstatechange);
check_onstatechange(call, callName, 'held',
receive.bind(null, onstatechange));
}
// When a call is removed from conference with 2 calls, another one will be
// automatically removed from group and be put on hold.
for (let call of autoRemovedCalls) {
let callName = "autoRemovedCall (" + call.number + ')';
let ongroupchange = callName + ".ongroupchange";
pending.push(ongroupchange);
check_ongroupchange(call, callName, null,
receive.bind(null, ongroupchange));
let onstatechange = callName + ".onstatechange";
pending.push(onstatechange);
check_onstatechange(call, callName, 'held',
receive.bind(null, onstatechange));
}
check_ongroupchange(callToRemove, "callToRemove", null, function() {
is(callToRemove.state, 'connected');
receive("callToRemove.ongroupchange");
});
check_oncallschanged(telephony, 'telephony',
autoRemovedCalls.concat(callToRemove),
receive.bind(null, "telephony.oncallschanged"));
check_oncallschanged(conference, 'conference',
autoRemovedCalls.concat(callToRemove), function() {
is(conference.calls.length, remainedCalls.length);
receive("conference.oncallschanged");
});
check_onstatechange(conference, 'conference',
(remainedCalls.length ? 'held' : ''), function() {
ok(!conference.oncallschanged);
if (typeof statechangeCallback === 'function') {
statechangeCallback();
}
receive("conference.onstatechange");
});
conference.remove(callToRemove);
return deferred.promise;
}
// The length of autoRemovedCalls should be 0 or 1.
function hangUpCallInConference(callToHangUp, autoRemovedCalls, remainedCalls,
statechangeCallback) {
log("Release one call in conference.");
let deferred = Promise.defer();
let done = function() {
deferred.resolve();
};
let pending = ["conference.oncallschanged", "remoteHangUp"];
let receive = function(name) {
receivedPending(name, pending, done);
};
// When a call is hang up from conference with 2 calls, another one will be
// automatically removed from group.
for (let call of autoRemovedCalls) {
let callName = "autoRemovedCall (" + call.number + ')';
let ongroupchange = callName + ".ongroupchange";
pending.push(ongroupchange);
check_ongroupchange(call, callName, null,
receive.bind(null, ongroupchange));
}
if (autoRemovedCalls.length) {
pending.push("telephony.oncallschanged");
check_oncallschanged(telephony, 'telephony',
autoRemovedCalls,
receive.bind(null, "telephony.oncallschanged"));
}
check_oncallschanged(conference, 'conference',
autoRemovedCalls.concat(callToHangUp), function() {
is(conference.calls.length, remainedCalls.length);
receive("conference.oncallschanged");
});
if (remainedCalls.length === 0) {
pending.push("conference.onstatechange");
check_onstatechange(conference, 'conference', '', function() {
ok(!conference.oncallschanged);
if (typeof statechangeCallback === 'function') {
statechangeCallback();
}
receive("conference.onstatechange");
});
}
remoteHangUp(callToHangUp)
.then(receive.bind(null, "remoteHangUp"));
return deferred.promise;
}
function handleConferenceRemoveError(callToRemove) {
log('Handle conference remove error.');
let deferred = Promise.defer();
conference.onerror = function(evt) {
log('Receiving a conference error event.');
is(evt.name, 'removeError', 'conference removeError');
deferred.resolve();
}
conference.remove(callToRemove);
return deferred.promise;
}
function handleConferenceAddError(callToAdd) {
log('Handle conference add error.');
let deferred = Promise.defer();
conference.onerror = function(evt) {
log('Receiving a conference error event.');
is(evt.name, 'addError', 'conference addError');
deferred.resolve();
}
conference.add(callToAdd);
return deferred.promise;
}
/**
* Setup a conference with an outgoing call and an incoming call.
*
* @return Promise<[outCall, inCall]>
*/
function setupConferenceTwoCalls(outNumber, inNumber) {
log('Create conference with two calls.');
let outCall;
let inCall;
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
return Promise.resolve()
.then(checkInitialState)
.then(() => dial(outNumber))
.then(call => { outCall = call; })
.then(() => checkAll(outCall, [outCall], '', [], [outInfo.ringing]))
.then(() => remoteAnswer(outCall))
.then(() => checkAll(outCall, [outCall], '', [], [outInfo.active]))
.then(() => remoteDial(inNumber))
.then(call => { inCall = call; })
.then(() => checkAll(outCall, [outCall, inCall], '', [],
[outInfo.active, inInfo.incoming]))
.then(() => answer(inCall))
.then(() => checkAll(inCall, [outCall, inCall], '', [],
[outInfo.held, inInfo.active]))
.then(() => addCallsToConference([outCall, inCall], function() {
checkState(conference, [], 'connected', [outCall, inCall]);
}))
.then(() => checkAll(conference, [], 'connected', [outCall, inCall],
[outInfo.active, inInfo.active]))
.then(() => {
return [outCall, inCall];
});
}
/**
* Setup a conference with an outgoing call and two incoming calls.
*
* @return Promise<[outCall, inCall, inCall2]>
*/
function setupConferenceThreeCalls(outNumber, inNumber, inNumber2) {
log('Create conference with three calls.');
let outCall;
let inCall;
let inCall2;
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
let inInfo2 = inCallStrPool(inNumber2);
return Promise.resolve()
.then(() => setupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
outCall = calls[0];
inCall = calls[1];
})
.then(() => remoteDial(inNumber2))
.then(call => { inCall2 = call; })
.then(() => checkAll(conference, [inCall2], 'connected', [outCall, inCall],
[outInfo.active, inInfo.active, inInfo2.incoming]))
.then(() => answer(inCall2, function() {
checkState(inCall2, [inCall2], 'held', [outCall, inCall]);
}))
.then(() => checkAll(inCall2, [inCall2], 'held', [outCall, inCall],
[outInfo.held, inInfo.held, inInfo2.active]))
.then(() => addCallsToConference([inCall2], function() {
checkState(conference, [], 'connected', [outCall, inCall, inCall2]);
}))
.then(() => checkAll(conference, [],
'connected', [outCall, inCall, inCall2],
[outInfo.active, inInfo.active, inInfo2.active]))
.then(() => {
return [outCall, inCall, inCall2];
});
}
/**
* Setup a conference with an outgoing call and four incoming calls.
*
* @return Promise<[outCall, inCall, inCall2, inCall3, inCall4]>
*/
function setupConferenceFiveCalls(outNumber, inNumber, inNumber2, inNumber3,
inNumber4) {
log('Create conference with five calls.');
let outCall;
let inCall;
let inCall2;
let inCall3;
let inCall4;
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
let inInfo2 = inCallStrPool(inNumber2);
let inInfo3 = inCallStrPool(inNumber3);
let inInfo4 = inCallStrPool(inNumber4);
return Promise.resolve()
.then(() => setupConferenceThreeCalls(outNumber, inNumber, inNumber2))
.then(calls => {
[outCall, inCall, inCall2] = calls;
})
.then(() => remoteDial(inNumber3))
.then(call => {inCall3 = call;})
.then(() => checkAll(conference, [inCall3], 'connected',
[outCall, inCall, inCall2],
[outInfo.active, inInfo.active, inInfo2.active,
inInfo3.incoming]))
.then(() => answer(inCall3, function() {
checkState(inCall3, [inCall3], 'held', [outCall, inCall, inCall2]);
}))
.then(() => checkAll(inCall3, [inCall3], 'held',
[outCall, inCall, inCall2],
[outInfo.held, inInfo.held, inInfo2.held,
inInfo3.active]))
.then(() => addCallsToConference([inCall3], function() {
checkState(conference, [], 'connected', [outCall, inCall, inCall2, inCall3]);
}))
.then(() => checkAll(conference, [], 'connected',
[outCall, inCall, inCall2, inCall3],
[outInfo.active, inInfo.active, inInfo2.active,
inInfo3.active]))
.then(() => remoteDial(inNumber4))
.then(call => {inCall4 = call;})
.then(() => checkAll(conference, [inCall4], 'connected',
[outCall, inCall, inCall2, inCall3],
[outInfo.active, inInfo.active, inInfo2.active,
inInfo3.active, inInfo4.incoming]))
.then(() => answer(inCall4, function() {
checkState(inCall4, [inCall4], 'held', [outCall, inCall, inCall2, inCall3]);
}))
.then(() => checkAll(inCall4, [inCall4], 'held',
[outCall, inCall, inCall2, inCall3],
[outInfo.held, inInfo.held, inInfo2.held,
inInfo3.held, inInfo4.active]))
.then(() => addCallsToConference([inCall4], function() {
checkState(conference, [], 'connected', [outCall, inCall, inCall2,
inCall3, inCall4]);
}))
.then(() => checkAll(conference, [], 'connected',
[outCall, inCall, inCall2, inCall3, inCall4],
[outInfo.active, inInfo.active, inInfo2.active,
inInfo3.active, inInfo4.active]))
.then(() => {
return [outCall, inCall, inCall2, inCall3, inCall4];
});
}
function testConferenceTwoCalls() {
log('= testConferenceTwoCalls =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
return Promise.resolve()
.then(() => setupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => remoteHangUpCalls([outCall, inCall]));
}
function testConferenceHoldAndResume() {
log('= testConferenceHoldAndResume =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
return Promise.resolve()
.then(() => setupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => holdConference([outCall, inCall], function() {
checkState(null, [], 'held', [outCall, inCall]);
}))
.then(() => checkAll(null, [], 'held', [outCall, inCall],
[outInfo.held, inInfo.held]))
.then(() => resumeConference([outCall, inCall], function() {
checkState(conference, [], 'connected', [outCall, inCall]);
}))
.then(() => checkAll(conference, [], 'connected', [outCall, inCall],
[outInfo.active, inInfo.active]))
.then(() => remoteHangUpCalls([outCall, inCall]));
}
function testConferenceThreeAndRemoveOne() {
log('= testConferenceThreeAndRemoveOne =');
let outCall;
let inCall;
let inCall2;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
let inInfo2 = inCallStrPool(inNumber2);
return Promise.resolve()
.then(() => setupConferenceThreeCalls(outNumber, inNumber, inNumber2))
.then(calls => {
[outCall, inCall, inCall2] = calls;
})
.then(() => removeCallInConference(outCall, [], [inCall, inCall2],
function() {
checkState(outCall, [outCall], 'held', [inCall, inCall2]);
}))
.then(() => checkAll(outCall, [outCall], 'held', [inCall, inCall2],
[outInfo.active, inInfo.held, inInfo2.held]))
.then(() => remoteHangUpCalls([outCall, inCall, inCall2]));
}
function testConferenceThreeAndHangupOne() {
log('= testConferenceThreeAndHangupOne =');
let outCall;
let inCall;
let inCall2;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let inInfo = inCallStrPool(inNumber);
let inInfo2 = inCallStrPool(inNumber2);
return Promise.resolve()
.then(() => setupConferenceThreeCalls(outNumber, inNumber, inNumber2))
.then(calls => {
[outCall, inCall, inCall2] = calls;
})
.then(() => hangUpCallInConference(outCall, [], [inCall, inCall2]))
.then(() => checkAll(conference, [], 'connected', [inCall, inCall2],
[inInfo.active, inInfo2.active]))
.then(() => remoteHangUpCalls([inCall, inCall2]));
}
function testConferenceTwoAndRemoveOne() {
log('= testConferenceTwoAndRemoveOne =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
return Promise.resolve()
.then(() => setupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => removeCallInConference(outCall, [inCall], [], function() {
checkState(outCall, [outCall, inCall], '', []);
}))
.then(() => checkAll(outCall, [outCall, inCall], '', [],
[outInfo.active, inInfo.held]))
.then(() => remoteHangUpCalls([outCall, inCall]));
}
function testConferenceTwoAndHangupOne() {
log('= testConferenceTwoAndHangupOne =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inInfo = inCallStrPool(inNumber);
return Promise.resolve()
.then(() => setupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => hangUpCallInConference(outCall, [inCall], [], function() {
checkState(inCall, [inCall], '', []);
}))
.then(() => checkAll(inCall, [inCall], '', [], [inInfo.active]))
.then(() => remoteHangUpCalls([inCall]));
}
function testConferenceRemoveError() {
log('= testConferenceRemoveError =');
let outCall;
let inCall;
let inCall2;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
let inInfo2 = inCallStrPool(inNumber2);
return Promise.resolve()
.then(() => setupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => remoteDial(inNumber2))
.then(call => {inCall2 = call;})
.then(() => checkAll(conference, [inCall2], 'connected', [outCall, inCall],
[outInfo.active, inInfo.active, inInfo2.incoming]))
.then(() => answer(inCall2, function() {
checkState(inCall2, [inCall2], 'held', [outCall, inCall]);
}))
.then(() => checkAll(inCall2, [inCall2], 'held', [outCall, inCall],
[outInfo.held, inInfo.held, inInfo2.active]))
.then(() => resumeConference([outCall, inCall], function() {
checkState(conference, [inCall2], 'connected', [outCall, inCall]);
}))
// Not allowed to remove a call when there are one connected and one held
// calls.
.then(() => handleConferenceRemoveError(outCall))
.then(() => remoteHangUpCalls([outCall, inCall, inCall2]));
}
function testConferenceAddError() {
log('= testConferenceAddError =');
let outCall, inCall, inCall2, inCall3, inCall4, inCall5;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let inNumber3 = "5555550203";
let inNumber4 = "5555550204";
let inNumber5 = "5555550205";
let outInfo = outCallStrPool(outNumber);
let inInfo = inCallStrPool(inNumber);
let inInfo2 = inCallStrPool(inNumber2);
let inInfo3 = inCallStrPool(inNumber3);
let inInfo4 = inCallStrPool(inNumber4);
let inInfo5 = inCallStrPool(inNumber5);
return Promise.resolve()
.then(() => setupConferenceFiveCalls(outNumber, inNumber, inNumber2,
inNumber3, inNumber4))
.then(calls => {
[outCall, inCall, inCall2, inCall3, inCall4] = calls;
})
.then(() => remoteDial(inNumber5))
.then(call => {inCall5 = call;})
.then(() => answer(inCall5, function() {
checkState(inCall5, [inCall5], 'held',
[outCall, inCall, inCall2, inCall3, inCall4]);
}))
.then(() => checkAll(inCall5, [inCall5], 'held',
[outCall, inCall, inCall2, inCall3, inCall4],
[outInfo.held, inInfo.held, inInfo2.held,
inInfo3.held, inInfo4.held, inInfo5.active]))
// Maximum number of conference participants is 5.
.then(() => handleConferenceAddError(inCall5))
.then(() => remoteHangUpCalls([outCall, inCall, inCall2, inCall3, inCall4,
inCall5]));
}
// Start the test
startTest(function() {
conference = telephony.conferenceGroup;
ok(conference);
testConferenceTwoCalls()
.then(testConferenceHoldAndResume)
.then(testConferenceThreeAndRemoveOne)
.then(testConferenceThreeAndHangupOne)
.then(testConferenceTwoAndRemoveOne)
.then(testConferenceTwoAndHangupOne)
.then(testConferenceRemoveError)
.then(testConferenceAddError)
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,71 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function handleConferenceAddError(callToAdd) {
log('Handle conference add error.');
let deferred = Promise.defer();
conference.onerror = function(evt) {
log('Receiving a conference error event.');
conference.onerror = null;
is(evt.name, 'addError', 'conference addError');
deferred.resolve();
}
conference.add(callToAdd);
return deferred.promise;
}
function testConferenceAddError() {
log('= testConferenceAddError =');
let outCall, inCall, inCall2, inCall3, inCall4, inCall5;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let inNumber3 = "5555550203";
let inNumber4 = "5555550204";
let inNumber5 = "5555550205";
let outInfo = gOutCallStrPool(outNumber);
let inInfo = gInCallStrPool(inNumber);
let inInfo2 = gInCallStrPool(inNumber2);
let inInfo3 = gInCallStrPool(inNumber3);
let inInfo4 = gInCallStrPool(inNumber4);
let inInfo5 = gInCallStrPool(inNumber5);
return Promise.resolve()
.then(() => gSetupConferenceFiveCalls(outNumber, inNumber, inNumber2,
inNumber3, inNumber4))
.then(calls => {
[outCall, inCall, inCall2, inCall3, inCall4] = calls;
})
.then(() => gRemoteDial(inNumber5))
.then(call => {inCall5 = call;})
.then(() => gAnswer(inCall5, function() {
gCheckState(inCall5, [inCall5], 'held',
[outCall, inCall, inCall2, inCall3, inCall4]);
}))
.then(() => gCheckAll(inCall5, [inCall5], 'held',
[outCall, inCall, inCall2, inCall3, inCall4],
[outInfo.held, inInfo.held, inInfo2.held,
inInfo3.held, inInfo4.held, inInfo5.active]))
// Maximum number of conference participants is 5.
.then(() => handleConferenceAddError(inCall5))
.then(() => gRemoteHangUpCalls([outCall, inCall, inCall2, inCall3, inCall4,
inCall5]));
}
// Start the test
startTest(function() {
testConferenceAddError()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,68 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function handleConferenceRemoveError(callToRemove) {
log('Handle conference remove error.');
let deferred = Promise.defer();
conference.onerror = function(evt) {
log('Receiving a conference error event.');
conference.onerror = null;
is(evt.name, 'removeError', 'conference removeError');
deferred.resolve();
}
conference.remove(callToRemove);
return deferred.promise;
}
function testConferenceRemoveError() {
log('= testConferenceRemoveError =');
let outCall;
let inCall;
let inCall2;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let outInfo = gOutCallStrPool(outNumber);
let inInfo = gInCallStrPool(inNumber);
let inInfo2 = gInCallStrPool(inNumber2);
return Promise.resolve()
.then(() => gSetupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => gRemoteDial(inNumber2))
.then(call => {inCall2 = call;})
.then(() => gCheckAll(conference, [inCall2], 'connected', [outCall, inCall],
[outInfo.active, inInfo.active, inInfo2.incoming]))
.then(() => gAnswer(inCall2, function() {
gCheckState(inCall2, [inCall2], 'held', [outCall, inCall]);
}))
.then(() => gCheckAll(inCall2, [inCall2], 'held', [outCall, inCall],
[outInfo.held, inInfo.held, inInfo2.active]))
.then(() => gResumeConference([outCall, inCall], function() {
gCheckState(conference, [inCall2], 'connected', [outCall, inCall]);
}))
// Not allowed to remove a call when there are one connected and one held
// calls.
.then(() => handleConferenceRemoveError(outCall))
.then(() => gRemoteHangUpCalls([outCall, inCall, inCall2]));
}
// Start the test
startTest(function() {
testConferenceRemoveError()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,37 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function testConferenceThreeAndHangupOne() {
log('= testConferenceThreeAndHangupOne =');
let outCall;
let inCall;
let inCall2;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let inInfo = gInCallStrPool(inNumber);
let inInfo2 = gInCallStrPool(inNumber2);
return Promise.resolve()
.then(() => gSetupConferenceThreeCalls(outNumber, inNumber, inNumber2))
.then(calls => {
[outCall, inCall, inCall2] = calls;
})
.then(() => gHangUpCallInConference(outCall, [], [inCall, inCall2]))
.then(() => gCheckAll(conference, [], 'connected', [inCall, inCall2],
[inInfo.active, inInfo2.active]))
.then(() => gRemoteHangUpCalls([inCall, inCall2]));
}
// Start the test
startTest(function() {
testConferenceThreeAndHangupOne()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,41 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function testConferenceThreeAndRemoveOne() {
log('= testConferenceThreeAndRemoveOne =');
let outCall;
let inCall;
let inCall2;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inNumber2 = "5555550202";
let outInfo = gOutCallStrPool(outNumber);
let inInfo = gInCallStrPool(inNumber);
let inInfo2 = gInCallStrPool(inNumber2);
return Promise.resolve()
.then(() => gSetupConferenceThreeCalls(outNumber, inNumber, inNumber2))
.then(calls => {
[outCall, inCall, inCall2] = calls;
})
.then(() => gRemoveCallInConference(outCall, [], [inCall, inCall2],
function() {
gCheckState(outCall, [outCall], 'held', [inCall, inCall2]);
}))
.then(() => gCheckAll(outCall, [outCall], 'held', [inCall, inCall2],
[outInfo.active, inInfo.held, inInfo2.held]))
.then(() => gRemoteHangUpCalls([outCall, inCall, inCall2]));
}
// Start the test
startTest(function() {
testConferenceThreeAndRemoveOne()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,30 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function testConferenceTwoCalls() {
log('= testConferenceTwoCalls =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
return Promise.resolve()
.then(() => gSetupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => gRemoteHangUpCalls([outCall, inCall]));
}
// Start the test
startTest(function() {
testConferenceTwoCalls()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,35 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function testConferenceTwoAndHangupOne() {
log('= testConferenceTwoAndHangupOne =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
let inInfo = gInCallStrPool(inNumber);
return Promise.resolve()
.then(() => gSetupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => gHangUpCallInConference(outCall, [inCall], [], function() {
gCheckState(inCall, [inCall], '', []);
}))
.then(() => gCheckAll(inCall, [inCall], '', [], [inInfo.active]))
.then(() => gRemoteHangUpCalls([inCall]));
}
// Start the test
startTest(function() {
testConferenceTwoAndHangupOne()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,42 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function testConferenceHoldAndResume() {
log('= testConferenceHoldAndResume =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
let outInfo = gOutCallStrPool(outNumber);
let inInfo = gInCallStrPool(inNumber);
return Promise.resolve()
.then(() => gSetupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => gHoldConference([outCall, inCall], function() {
gCheckState(null, [], 'held', [outCall, inCall]);
}))
.then(() => gCheckAll(null, [], 'held', [outCall, inCall],
[outInfo.held, inInfo.held]))
.then(() => gResumeConference([outCall, inCall], function() {
gCheckState(conference, [], 'connected', [outCall, inCall]);
}))
.then(() => gCheckAll(conference, [], 'connected', [outCall, inCall],
[outInfo.active, inInfo.active]))
.then(() => gRemoteHangUpCalls([outCall, inCall]));
}
// Start the test
startTest(function() {
testConferenceHoldAndResume()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -0,0 +1,37 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function testConferenceTwoAndRemoveOne() {
log('= testConferenceTwoAndRemoveOne =');
let outCall;
let inCall;
let outNumber = "5555550101";
let inNumber = "5555550201";
let outInfo = gOutCallStrPool(outNumber);
let inInfo = gInCallStrPool(inNumber);
return Promise.resolve()
.then(() => gSetupConferenceTwoCalls(outNumber, inNumber))
.then(calls => {
[outCall, inCall] = calls;
})
.then(() => gRemoveCallInConference(outCall, [inCall], [], function() {
gCheckState(outCall, [outCall, inCall], '', []);
}))
.then(() => gCheckAll(outCall, [outCall, inCall], '', [],
[outInfo.active, inInfo.held]))
.then(() => gRemoteHangUpCalls([outCall, inCall]));
}
// Start the test
startTest(function() {
testConferenceTwoAndRemoveOne()
.then(null, error => {
ok(false, 'promise rejects during test.');
})
.then(finish);
});

View File

@ -4,36 +4,6 @@
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
function remoteAnswer(call) {
log("Remote answering the call.");
let deferred = Promise.defer();
call.onconnected = function onconnected(event) {
log("Received 'connected' call event.");
call.onconnected = null;
deferred.resolve(call);
};
emulator.run("gsm accept " + call.number);
return deferred.promise;
}
function remoteHangUp(call) {
log("Remote hanging up the call.");
let deferred = Promise.defer();
call.ondisconnected = function ondisconnected(event) {
log("Received 'disconnected' call event.");
call.ondisconnected = null;
deferred.resolve(call);
};
emulator.run("gsm cancel " + call.number);
return deferred.promise;
}
function muxModem(id) {
let deferred = Promise.defer();
@ -59,7 +29,7 @@ function testNewCallWhenOtherConnectionInUse(firstServiceId, secondServiceId) {
outCall = call;
is(outCall.serviceId, firstServiceId);
})
.then(() => remoteAnswer(outCall))
.then(() => gRemoteAnswer(outCall))
.then(() => {
return telephony.dial("0912345001", secondServiceId);
})
@ -69,7 +39,7 @@ function testNewCallWhenOtherConnectionInUse(firstServiceId, secondServiceId) {
}, cause => {
is(cause, "OtherConnectionInUse");
})
.then(() => remoteHangUp(outCall));
.then(() => gRemoteHangUp(outCall));
}
startDSDSTest(function() {

View File

@ -4,170 +4,6 @@
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = 'head.js';
/**
* The functions are created to provide the string format of the emulator call
* list results.
*
* Usage:
* let outInfo = OutCallStrPool("911");
* outInfo.ringing == "outbound to 911 : ringing"
* outInfo.active == "outbound to 911 : active"
*/
function CallStrPool(prefix, number) {
let padding = " : ";
let numberInfo = prefix + number + padding.substr(number.length);
let info = {};
let states = ["ringing", "incoming", "active", "held"];
for (let state of states) {
info[state] = numberInfo + state;
}
return info;
}
function OutCallStrPool(number) {
return CallStrPool("outbound to ", number);
}
function InCallStrPool(number) {
return CallStrPool("inbound from ", number);
}
function checkEventCallState(event, call, state) {
is(call, event.call, "event.call");
is(call.state, state, "call state");
}
function checkTelephonyActiveAndCalls(active, calls) {
is(telephony.active, active, "telephony.active");
is(telephony.calls.length, calls.length, "telephony.calls");
for (let i = 0; i < calls.length; ++i) {
is(telephony.calls[i], calls[i]);
}
}
function checkEmulatorCallList(expectedCallList) {
let deferred = Promise.defer();
emulator.run("gsm list", function(result) {
log("Call list is now: " + result);
for (let i = 0; i < expectedCallList.length; ++i) {
is(result[i], expectedCallList[i], "emulator calllist");
}
is(result[expectedCallList.length], "OK", "emulator calllist");
deferred.resolve();
});
return deferred.promise;
}
// Promise.
function checkAll(active, calls, callList) {
checkTelephonyActiveAndCalls(active, calls);
return checkEmulatorCallList(callList);
}
function dial(number, serviceId) {
serviceId = typeof serviceId !== "undefined" ? serviceId : 0;
log("Make an outgoing call: " + number + ", serviceId: " + serviceId);
let deferred = Promise.defer();
telephony.dial(number).then(call => {
ok(call);
is(call.number, number);
is(call.state, "dialing");
call.onalerting = function onalerting(event) {
call.onalerting = null;
log("Received 'onalerting' call event.");
is(call.serviceId, serviceId);
checkEventCallState(event, call, "alerting");
deferred.resolve(call);
};
});
return deferred.promise;
}
function remoteDial(number) {
log("Simulating an incoming call.");
let deferred = Promise.defer();
telephony.onincoming = function onincoming(event) {
log("Received 'incoming' call event.");
telephony.onincoming = null;
let call = event.call;
ok(call);
is(call.number, number);
is(call.state, "incoming");
deferred.resolve(call);
};
emulator.run("gsm call " + number);
return deferred.promise;
}
function answer(call) {
log("Answering the incoming call.");
let deferred = Promise.defer();
call.onconnecting = function onconnectingIn(event) {
log("Received 'connecting' call event for incoming call.");
call.onconnecting = null;
checkEventCallState(event, call, "connecting");
};
call.onconnected = function onconnectedIn(event) {
log("Received 'connected' call event for incoming call.");
call.onconnected = null;
checkEventCallState(event, call, "connected");
ok(!call.onconnecting);
deferred.resolve(call);
};
call.answer();
return deferred.promise;
}
function remoteAnswer(call) {
log("Remote answering the call.");
let deferred = Promise.defer();
call.onconnected = function onconnected(event) {
log("Received 'connected' call event.");
call.onconnected = null;
checkEventCallState(event, call, "connected");
deferred.resolve(call);
};
emulator.run("gsm accept " + call.number);
return deferred.promise;
}
function remoteHangUp(call) {
log("Remote hanging up the call.");
let deferred = Promise.defer();
call.ondisconnected = function ondisconnected(event) {
log("Received 'disconnected' call event.");
call.ondisconnected = null;
checkEventCallState(event, call, "disconnected");
deferred.resolve(call);
};
emulator.run("gsm cancel " + call.number);
return deferred.promise;
}
function muxModem(id) {
let deferred = Promise.defer();
@ -180,36 +16,36 @@ function muxModem(id) {
function testOutgoingCallForServiceId(number, serviceId) {
let outCall;
let outInfo = OutCallStrPool(number);
let outInfo = gOutCallStrPool(number);
return Promise.resolve()
.then(() => dial(number, serviceId))
.then(() => gDial(number, serviceId))
.then(call => {
outCall = call;
is(outCall.serviceId, serviceId);
})
.then(() => checkAll(outCall, [outCall], [outInfo.ringing]))
.then(() => remoteAnswer(outCall))
.then(() => checkAll(outCall, [outCall], [outInfo.active]))
.then(() => remoteHangUp(outCall))
.then(() => checkAll(null, [], []));
.then(() => gCheckAll(outCall, [outCall], '', [], [outInfo.ringing]))
.then(() => gRemoteAnswer(outCall))
.then(() => gCheckAll(outCall, [outCall], '', [], [outInfo.active]))
.then(() => gRemoteHangUp(outCall))
.then(() => gCheckAll(null, [], '', [], []));
}
function testIncomingCallForServiceId(number, serviceId) {
let inCall;
let inInfo = InCallStrPool(number);
let inInfo = gInCallStrPool(number);
return Promise.resolve()
.then(() => remoteDial(number))
.then(() => gRemoteDial(number))
.then(call => {
inCall = call;
is(inCall.serviceId, serviceId);
})
.then(() => checkAll(null, [inCall], [inInfo.incoming]))
.then(() => answer(inCall))
.then(() => checkAll(inCall, [inCall], [inInfo.active]))
.then(() => remoteHangUp(inCall))
.then(() => checkAll(null, [], []));
.then(() => gCheckAll(null, [inCall], '', [], [inInfo.incoming]))
.then(() => gAnswer(inCall))
.then(() => gCheckAll(inCall, [inCall], '', [], [inInfo.active]))
.then(() => gRemoteHangUp(inCall))
.then(() => gCheckAll(null, [], '', [], []));
}
function testOutgoingCall() {

View File

@ -8,16 +8,6 @@ let connection;
let number = "112";
let outgoing;
function receivedPending(received, pending, nextAction) {
let index = pending.indexOf(received);
if (index != -1) {
pending.splice(index, 1);
}
if (pending.length === 0) {
nextAction();
}
}
function setRadioEnabled(enabled, callback) {
let request = connection.setRadioEnabled(enabled);
let desiredRadioState = enabled ? 'enabled' : 'disabled';
@ -30,12 +20,12 @@ function setRadioEnabled(enabled, callback) {
log("Received 'radiostatechange' event, radioState: " + state);
if (state == desiredRadioState) {
receivedPending('onradiostatechange', pending, done);
gReceivedPending('onradiostatechange', pending, done);
}
};
request.onsuccess = function onsuccess() {
receivedPending('onsuccess', pending, done);
gReceivedPending('onsuccess', pending, done);
};
request.onerror = function onerror() {

View File

@ -6,16 +6,6 @@ MARIONETTE_HEAD_JS = 'head.js';
let connection;
function receivedPending(received, pending, nextAction) {
let index = pending.indexOf(received);
if (index != -1) {
pending.splice(index, 1);
}
if (pending.length === 0) {
nextAction();
}
}
function setRadioEnabled(enabled, callback) {
let request = connection.setRadioEnabled(enabled);
let desiredRadioState = enabled ? 'enabled' : 'disabled';
@ -28,12 +18,12 @@ function setRadioEnabled(enabled, callback) {
log("Received 'radiostatechange' event, radioState: " + state);
if (state == desiredRadioState) {
receivedPending('onradiostatechange', pending, done);
gReceivedPending('onradiostatechange', pending, done);
}
};
request.onsuccess = function onsuccess() {
receivedPending('onsuccess', pending, done);
gReceivedPending('onsuccess', pending, done);
};
request.onerror = function onerror() {