import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 859764 - Part 5: Changes in Test Cases. r=echen (f1a5cd4fd3)
- Bug 859764 - Part 6: Changes in Payment. r=ferjm, r=smaug (2b47641375)
- Bug 1010756 - Helpful errors for using nsCOMPtr on non-XPCOM types; r=froydnj (6b1521c482)
- leftover (e1a24351e9)
- Bug 1192102 - Remove unused file embedded/android/GeckoSmsManager.java. r=blassey (ac05ae649d)
- var-let (8ddb529f96)
- Bug 1181466 - Fix observe function in SmsService/MmsService. r=btseng (ca93122404)
- Bug 733331 - Part 2: Update enabledGsmTableTuples when MCC changes in SmsService.js and fix segmentChars in SmsSegmentHelper.jsm. r=btseng (24fa23e4be)
- Bug 1173156 - Fix typo and add a Marionette test case. r=btseng (e7199eb55a)
- Bug 1132774 - [B2G][SMS] Enable DEBUG Flag in SmsService if the default value of "ril.debugging.enabled" is true. r=btseng (7300d24fb7)
- Bug 1169160 - [MobileConnection] Support more call barring program: all service, outgoing service and incoming service. r=hsinyi,aknow (872c2cc056)
- Bug 1169225 - [MobileConnectionService] Support setting/getting call waiting on all serviceClass. r=aknow (14c546a9ca)
- Bug 1110619 - Part 1: IDL Interface Changes. r=echen (beae2b4b77)
- Bug 1168064 - B2G RIL: filter out cell info with unknown values. r=echen (11dfc5a7e8)
- Bug 1159591 - Part 2: Move MMI logic from ril_worker to telephonyService (Call Forwarding). r=aknow (b4edb76863)
- Bug 1159591 - Part 3: Move MMI logic from ril_worker to telephonyService (Icc Lock). r=aknow (3faba76808)
- Bug 1138263 - Make TelephonyService.js JSHint friendly. r=hsinyi (454bd4c765)
- Bug 1159591 - Part 4: Move MMI logic from ril_worker to telephonyService (IMEI). r=aknow (57f423ecdd)
- Bug 1159591 - Part 5: Move MMI logic from ril_worker to telephonyService (CLIP). r=aknow (c6611dbcb8)
- Bug 1159591 - Part 6: Move MMI logic from ril_worker to telephonyService (CLIR). r=aknow (8c1fc03edb)
- Bug 1159591 - Part 7: Move MMI logic from ril_worker to telephonyService (Call Barring Password). r=aknow (5d8bcbf177)
- Bug 1159591 - Part 8: Move MMI logic from ril_worker to telephonyService (Call Barring). r=aknow (aa0b89aea1)
- Bug 1159591 - Part 9: Move MMI logic from ril_worker to telephonyService (Call Waiting). r=aknow (1d14d2b864)
- Bug 1159591 - Part 10: Move MMI logic from ril_worker to telephonyService (USSD). r=aknow (c92130b5b2)
- Bug 1159591 - Part 11: Move MMI consts from ril_consts to telephonyService. r=aknow (0e7b3fea9a)
- Bug 1159591 - Part 12: Move radio check for MMI to a common place. r=aknow (dcdc3178ad)
- Bug 1110619 - Part 2: Implementation Changes. r=echen (6d8e78d684)
- Bug 1110619 - Part 3: Bluetooth Changes. r=btian (9787727be0)
- Bug 1147736 - Part 1: Extend TelephonyCallInfo. r=aknow (2a426cc99f)
- Bug 1147736 - Part 2: Bypass NotifyError. r=aknow (6cd6fd6867)
- Bug 1147736 - Part 3: Deprecate NotifyError. r=aknow (e41c719442)
- Bug 1147736 - Part 4: Deprecate NotifyError(Bluetooth). r=btian (9c8f97bb22)
- Bug 1204817 - Delete the child property of a parent call only when the parent call exists. r=btseng (d35dc6b08f)
- Bug 1191205 - Cancel USSD sessions only when needed. r=edgar (01a72dbacb)
- Bug 1200134 - Control USSD Sessions with State-Transitions instead of Boolean. r=echen (a4e55b3d9d)
- Bug 1163511 - Use defineLazyModuleGetter. r=hsinyi (8a97a4912c)
- Bug 991582 - Part 2: Handle the result of RIL request in a consistent way. r=aknow (914ecc2bbb)
- Bug 1164248 - Handling of session/sessionEnded for notifyUssdReceived. r=edgar (a79df75d38)
- Bug 1223662 - Part 1: Check mmiServiceCode with correct constant. r=echen (abeb286050)
- Bug 1174673 - Part 1: Automatically resume the held call. r=hsinyi (280543af7d)
- Bug 1174673 - Part 2: Update test case. r=hsinyi (cfe19f1a52)
- Bug 1185156 - Fix bug in resuming held call. r=hsinyi (b96346d319)
- Bug 1162426 - Part 1: Provide TelephonyUtils. r=hsinyi (62b71e6e83)
- Bug 1162426 - Part 2: Test case. r=hsniyi (13a0b3c6f5)
- Bug 1171807 - Part 1: Add enums for TelephonyCall::State and TelephonyCallGroup::State (WebIDL). r=hsinyi (0b698eecc4)
- Bug 1145551 - DTMF should be sent using the active SIM, the given or the default one (in that order). r=aknow (6157636493)
- Bug 1171807 - Part 2: Move to enums and deprecate TelephonyCall.mCallState and TelephonyCallGroup.mCallState (DOM). r=btseng (5faef22d91)
- Bug 1168515 - do not block incall MMI requests on alerting state. r=aknow (b1f85c5789)
- Bug 1155072 - Part 1: Deprecate nsITelephonyListener.conferenceCallStateChanged (Telephony). r=btseng (e41d1a4bc9)
- Bug 1155072 - Part 2: Deprecate nsITelephonyListener.conferenceCallStateChanged (Bluetooth). r=btian (27e69fa89b)
- Bug 1166936 - JS Warning in TelephonyService.js r=aknow (3559d3ad3d)
- Bug 1191237 - Part 1: Enhance |TelephonyService.js|. r=aknow (86576a6d32)
- Bug 1202902 - Fix the world. (0dc256d67d)
- Bug 1161438 - Part 1 - Exporting contact to SIM should also return updated contact. r=echen (505d7d7f83)
- Bug 1159622 - Split test_icc_contact.js into read contact and add contact. r=echen (fec0c428df)
- Bug 1122376 - Support read SIM contact dialling number exceed 20 digits. r=echen (5d0599e93c)
- Bug 1161438 - Part 2 - marionette testcase. r=echen (1f0d18a479)
- Bug 1114937 - Part 5: Fix Test Case to Remove Contact with Correct Contact Id. r=echen (8d746fdbd2)
- Bug 1194149 - Continue importing contacts when there is no sufficient Type 2 USIM contact fields record. r=echen (e9be40dbf2)
- Bug 962995 - xpcshell tests for write ICC UCS2 characters for 0x81 and 0x82 encoding. r=echen (9500afaa4d)
- Bug 1161438 - Part 3 - xpcshell testcase. r=echen (01f7fb4514)
- Bug 1122376 - Support write SIM contact dialling number exceed 20 digits. r=echen (91133e286d)
- Bug 999300 - Part 1: Removed the Ril v5 legacy support. r=edgar (ded77fcb6f)
- Bug 999300 - Part 2: Update the related testcases. r=edgar (f77a8b96cc)
- Bug 1177146 - [Aries][RIL] Reply from QUERY_AVAILABLE_NETWORKS has extra strings. r=hsinyi (a6816cbbab)
- Bug 1043250 - Part 1: Update ril_worker and xpcshell test. r=btseng (8b9b25b5cf)
- Bug 1185406 - B2G RIL: Read 'pcscf' and expose it in nsIRilNetworkInfo. r=hsinyi (ce707ecb83)
- Bug 1174998 - Part 3: Read data call's MTU from network/apn settings. r=echen (bfa08d8380)
- Bug 1166320 - Make volume service safer to use off main thread. r=dhylands (b3976622ad)
- Bug 1177374 - Call realpath on volume mount points so thatVolumeService::GetVolumeByPath works properly. r=achen (aea97080eb)
- Bug 1195166 - AutoMounter: add ignore command to allow volumes to be ignored. r=alchen (f265d832c8)
- Bug 1196724 - Refactoring of AudioManager r=alwu (e5b896b7ce)
- Bug 1222564 - Save audio volume to database r=alwu (1303d01ae7)
- Bug 1164049 - Fix some mode lines in embedding/. r=smaug (79ddce4871)
This commit is contained in:
2023-01-24 11:52:32 +08:00
parent 795ba7b999
commit 7edec4880a
132 changed files with 5482 additions and 3547 deletions
+2
View File
@@ -538,6 +538,8 @@
@RESPATH@/components/RILSystemMessengerHelper.manifest
@RESPATH@/components/TelephonyAudioService.js
@RESPATH@/components/TelephonyAudioService.manifest
@RESPATH@/components/USSDReceivedWrapper.js
@RESPATH@/components/USSDReceivedWrapper.manifest
#ifndef DISABLE_MOZ_RIL_GEOLOC
@RESPATH@/components/TelephonyService.js
@RESPATH@/components/TelephonyService.manifest
+14 -31
View File
@@ -165,6 +165,12 @@ MobileConnectionListener::NotifyNetworkSelectionModeChanged()
return NS_OK;
}
NS_IMETHODIMP
MobileConnectionListener::NotifyDeviceIdentitiesChanged()
{
return NS_OK;
}
bool
MobileConnectionListener::Listen(bool aStart)
{
@@ -203,16 +209,23 @@ TelephonyListener::HandleCallInfo(nsITelephonyCallInfo* aInfo, bool aSend)
uint32_t callIndex;
uint16_t callState;
nsAutoString number;
nsAutoString disconnectedReason;
bool isOutgoing;
bool isConference;
aInfo->GetCallIndex(&callIndex);
aInfo->GetCallState(&callState);
aInfo->GetNumber(number);
aInfo->GetDisconnectedReason(disconnectedReason);
aInfo->GetIsOutgoing(&isOutgoing);
aInfo->GetIsConference(&isConference);
hfp->HandleCallStateChanged(callIndex, callState, EmptyString(), number,
// The disconnectedReason of a disconnected call must be nonempty no matter
// the call is disconnected for a normal reason or an error.
MOZ_ASSERT((callState != nsITelephonyService::CALL_STATE_DISCONNECTED ||
!disconnectedReason.IsEmpty()),
"disconnectedReason of an disconnected call must be nonempty.");
hfp->HandleCallStateChanged(callIndex, callState, disconnectedReason, number,
isOutgoing, isConference, aSend);
return NS_OK;
}
@@ -233,36 +246,6 @@ TelephonyListener::EnumerateCallState(nsITelephonyCallInfo* aInfo)
return HandleCallInfo(aInfo, false);
}
NS_IMETHODIMP
TelephonyListener::NotifyError(uint32_t aServiceId,
int32_t aCallIndex,
const nsAString& aError)
{
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
if (aCallIndex > 0) {
// In order to not miss any related call state transition.
// It's possible that 3G network signal lost for unknown reason.
// If a call is released abnormally, NotifyError() will be called,
// instead of CallStateChanged(). We need to reset the call array state
// via setting CALL_STATE_DISCONNECTED
hfp->HandleCallStateChanged(aCallIndex,
nsITelephonyService::CALL_STATE_DISCONNECTED,
aError, EmptyString(), false, false, true);
BT_WARNING("Reset the call state due to call transition ends abnormally");
}
BT_WARNING(NS_ConvertUTF16toUTF8(aError).get());
return NS_OK;
}
NS_IMETHODIMP
TelephonyListener::ConferenceCallStateChanged(uint16_t aCallState)
{
return NS_OK;
}
NS_IMETHODIMP
TelephonyListener::EnumerateCallStateComplete()
{
@@ -47,7 +47,7 @@ const CELLBROADCASTETWSINFO_CID =
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
let DEBUG;
var DEBUG;
function debug(s) {
dump("CellBroadcastService: " + s);
}
@@ -156,7 +156,7 @@ CellBroadcastService.prototype = {
.getRadioInterface(clientId).sendWorkerMessage("setCellBroadcastSearchList",
{ searchList: newSearchList },
(function callback(aResponse) {
if (DEBUG && !aResponse.success) {
if (DEBUG && aResponse.errorMsg) {
debug("Failed to set new search list: " + newSearchList +
" to client id: " + clientId);
}
@@ -165,7 +165,7 @@ CellBroadcastService.prototype = {
if (responses.length == numOfRilClients) {
let successCount = 0;
for (let i = 0; i < responses.length; i++) {
if (responses[i].success) {
if (!responses[i].errorMsg) {
successCount++;
}
}
+3 -1
View File
@@ -3,7 +3,9 @@ b2g = true
browser = false
qemu = true
[test_icc_contact.js]
[test_icc_contact_read.js]
[test_icc_contact_add.js]
[test_icc_contact_update.js]
[test_icc_card_lock_get_retry_count.js]
[test_icc_card_lock_change_pin.js]
[test_icc_card_lock_enable_pin.js]
@@ -0,0 +1,97 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 120000;
MARIONETTE_HEAD_JS = "head.js";
var TEST_ADD_DATA = [{
// a contact without email and anr.
name: ["add1"],
tel: [{value: "0912345678"}],
}, {
// a contact over 20 digits.
name: ["add2"],
tel: [{value: "012345678901234567890123456789"}],
}, {
// a contact over 40 digits.
name: ["add3"],
tel: [{value: "01234567890123456789012345678901234567890123456789"}],
}, {
// a contact with email but without anr.
name: ["add4"],
tel: [{value: "01234567890123456789"}],
email:[{value: "test@mozilla.com"}],
}, {
// a contact with anr but without email.
name: ["add5"],
tel: [{value: "01234567890123456789"}, {value: "123456"}, {value: "123"}],
}, {
// a contact with email and anr.
name: ["add6"],
tel: [{value: "01234567890123456789"}, {value: "123456"}, {value: "123"}],
email:[{value: "test@mozilla.com"}],
}];
function testAddContact(aIcc, aType, aMozContact, aPin2) {
log("testAddContact: type=" + aType + ", pin2=" + aPin2);
let contact = new mozContact(aMozContact);
return aIcc.updateContact(aType, contact, aPin2)
.then((aResult) => {
is(aResult.name[0], aMozContact.name[0]);
// Maximum digits of the Dialling Number is 20, and maximum digits of Extension is 20.
is(aResult.tel[0].value, aMozContact.tel[0].value.substring(0, 40));
// We only support SIM in emulator, so we don't have anr and email field.
ok(aResult.tel.length == 1);
ok(!aResult.email);
// Get ICC contact for checking new contact
return aIcc.readContacts(aType)
.then((aResult) => {
let contact = aResult[aResult.length - 1];
is(contact.name[0], aMozContact.name[0]);
// Maximum digits of the Dialling Number is 20, and maximum digits of Extension is 20.
is(contact.tel[0].value, aMozContact.tel[0].value.substring(0, 40));
is(contact.id.substring(0, aIcc.iccInfo.iccid.length), aIcc.iccInfo.iccid);
return contact.id;
})
.then((aContactId) => {
// Clean up contact
return removeContact(aIcc, aContactId, aType, aPin2);
});
}, (aError) => {
if (aType === "fdn" && aPin2 === undefined) {
ok(aError.name === "SimPin2",
"expected error when pin2 is not provided");
} else {
ok(false, "Cannot add " + aType + " contact: " + aError.name);
}
})
}
function removeContact(aIcc, aContactId, aType, aPin2) {
log("removeContact: contactId=" + aContactId +
", type=" + aType + ", pin2=" + aPin2);
let contact = new mozContact({});
contact.id = aContactId;
return aIcc.updateContact(aType, contact, aPin2);
}
// Start tests
startTestCommon(function() {
let icc = getMozIcc();
let promise = Promise.resolve();
for (let i = 0; i < TEST_ADD_DATA.length; i++) {
let test_data = TEST_ADD_DATA[i];
// Test add adn contacts
promise = promise.then(() => testAddContact(icc, "adn", test_data))
// Test add fdn contacts
.then(() => testAddContact(icc, "fdn", test_data, "0000"))
// Test add fdn contacts without passing pin2
.then(() => testAddContact(icc, "fdn", test_data));
}
return promise;
});
@@ -9,58 +9,46 @@ function testReadContacts(aIcc, aType) {
let iccId = aIcc.iccInfo.iccid;
return aIcc.readContacts(aType)
.then((aResult) => {
is(Array.isArray(aResult), true);
is(Array.isArray(aResult), true);
is(aResult.length, 6, "Check contact number.");
// Alpha Id(Encoded with GSM 8 bit): "Mozilla", Dialling Number: 15555218201
is(aResult[0].name[0], "Mozilla");
is(aResult[0].tel[0].value, "15555218201");
is(aResult[0].id, iccId + "1");
// Alpha Id(Encoded with UCS2 0x80: "Saßê\u9ec3", Dialling Number: 15555218202
is(aResult[1].name[0], "Saßê黃");
is(aResult[1].tel[0].value, "15555218202");
is(aResult[1].id, iccId + "2");
// Alpha Id(Encoded with UCS2 0x81): "Fire \u706b", Dialling Number: 15555218203
is(aResult[2].name[0], "Fire 火");
is(aResult[2].tel[0].value, "15555218203");
is(aResult[2].id, iccId + "3");
// Alpha Id(Encoded with UCS2 0x82): "Huang \u9ec3", Dialling Number: 15555218204
is(aResult[3].name[0], "Huang 黃");
is(aResult[3].tel[0].value, "15555218204");
is(aResult[3].id, iccId + "4");
// Alpha Id(Encoded with GSM 8 bit): "Contact001",
// Dialling Number: 9988776655443322110001234567890123456789
is(aResult[4].name[0], "Contact001");
is(aResult[4].tel[0].value, "9988776655443322110001234567890123456789");
is(aResult[4].id, iccId + "5");
// Alpha Id(Encoded with GSM 8 bit): "Contact002",
// Dialling Number: 0123456789012345678999887766554433221100
is(aResult[5].name[0], "Contact002");
is(aResult[5].tel[0].value, "0123456789012345678999887766554433221100");
is(aResult[5].id, iccId + "6");
}, (aError) => {
ok(false, "Cannot get " + aType + " contacts");
});
}
function testAddContact(aIcc, aType, aPin2) {
log("testAddContact: type=" + aType + ", pin2=" + aPin2);
let contact = new mozContact({
name: ["add"],
tel: [{value: "0912345678"}],
email:[]
});
return aIcc.updateContact(aType, contact, aPin2)
.then((aResult) => {
// Get ICC contact for checking new contact
return aIcc.readContacts(aType)
.then((aResult) => {
// There are 4 SIM contacts which are harded in emulator
is(aResult.length, 5);
is(aResult[4].name[0], "add");
is(aResult[4].tel[0].value, "0912345678");
}, (aError) => {
ok(false, "Cannot get " + aType + " contacts: " + aError.name);
})
}, (aError) => {
if (aType === "fdn" && aPin2 === undefined) {
ok(aError.name === "SimPin2",
"expected error when pin2 is not provided");
} else {
ok(false, "Cannot add " + aType + " contact: " + aError.name);
}
});
}
// Start tests
startTestCommon(function() {
@@ -68,14 +56,8 @@ startTestCommon(function() {
// Test read adn contacts
return testReadContacts(icc, "adn")
// Test add adn contacts
.then(() => testAddContact(icc, "adn"))
// Test read fdn contact
.then(() => testReadContacts(icc, "fdn"))
// Test add fdn contacts
.then(() => testAddContact(icc, "fdn", "0000"))
// Test add fdn contacts without passing pin2
.then(() => testAddContact(icc, "fdn"))
// Test read sdn contacts
.then(() => testReadContacts(icc, "sdn"));
});
@@ -0,0 +1,122 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 120000;
MARIONETTE_HEAD_JS = "head.js";
const TEST_UPDATE_DATA = [{
id: 1,
data: {
name: ["Mozilla"],
tel: [{value: "9876543210987654321001234"}]},
expect: {
number: "9876543210987654321001234"}
}, {
id:2,
data: {
name: ["Saßê黃"],
tel: [{value: "98765432109876543210998877665544332211001234"}]},
expect: {
// We don't support extension chain now.
number: "9876543210987654321099887766554433221100"}
}, {
id: 3,
data: {
name: ["Fire 火"],
tel: [{value: ""}]},
expect: {
number: null}
}, {
id: 5,
data: {
name: ["Contact001"],
tel: [{value: "9988776655443322110098765432109876543210"}]},
expect: {
number: "9988776655443322110098765432109876543210"}
}, {
id: 6,
data: {
name: ["Contact002"],
tel: [{value: "+99887766554433221100"}]},
expect: {
number: "+99887766554433221100"}
}];
function testUpdateContact(aIcc, aType, aContactId, aMozContact, aExpect, aPin2) {
log("testUpdateContact: type=" + aType +
", mozContact=" + JSON.stringify(aMozContact) +
", expect=" + aExpect.number + ", pin2=" + aPin2);
let contact = new mozContact(aMozContact);
contact.id = aIcc.iccInfo.iccid + aContactId;
return aIcc.updateContact(aType, contact, aPin2)
.then((aResult) => {
// Get ICC contact for checking expect contact
return aIcc.readContacts(aType)
.then((aResult) => {
let contact = aResult[aContactId - 1];
is(contact.name[0], aMozContact.name[0]);
if (aExpect.number == null) {
is(contact.tel, null);
} else {
is(contact.tel[0].value, aExpect.number);
}
is(contact.id, aIcc.iccInfo.iccid + aContactId);
});
}, (aError) => {
if (aType === "fdn" && aPin2 === undefined) {
ok(aError.name === "SimPin2",
"expected error when pin2 is not provided");
} else {
ok(false, "Cannot update " + aType + " contact: " + aError.name);
}
});
}
function revertContact(aIcc, aContact, aType, aPin2) {
log("revertContact: contact:" + JSON.stringify(aContact) +
", type=" + aType + ", pin2=" + aPin2);
return aIcc.updateContact(aType, aContact, aPin2);
}
// Start tests
startTestCommon(function() {
let icc = getMozIcc();
let adnContacts;
let fdnContacts;
return icc.readContacts("adn")
.then((aResult) => {
adnContacts = aResult;
})
.then(() => icc.readContacts("fdn"))
.then((aResult) => {
fdnContacts = aResult;
})
.then(() => {
let promise = Promise.resolve();
for (let i = 0; i < TEST_UPDATE_DATA.length; i++) {
let test_data = TEST_UPDATE_DATA[i];
let adnContact = adnContacts[test_data.id - 1];
let fdnContact = fdnContacts[test_data.id - 1];
// Test update adn contacts
promise = promise.then(() => testUpdateContact(icc, "adn", test_data.id,
test_data.data, test_data.expect))
// Test update fdn contacts
.then(() => testUpdateContact(icc, "fdn", test_data.id, test_data.data,
test_data.expect))
// Test update fdn contacts without passing pin2
.then(() => testUpdateContact(icc, "fdn", test_data.id, test_data.data,
test_data.expect, "0000"))
.then(() => revertContact(icc, adnContact, "adn"))
.then(() => revertContact(icc, fdnContact, "fdn", "0000"));
}
return promise;
});
});
+11 -2
View File
@@ -299,7 +299,7 @@ bool
MobileConnection::IsValidCallBarringProgram(int32_t aProgram)
{
return aProgram >= nsIMobileConnection::CALL_BARRING_PROGRAM_ALL_OUTGOING &&
aProgram <= nsIMobileConnection::CALL_BARRING_PROGRAM_INCOMING_ROAMING;
aProgram <= nsIMobileConnection::CALL_BARRING_PROGRAM_INCOMING_SERVICE;
}
bool
@@ -875,7 +875,9 @@ MobileConnection::SetCallWaitingOption(bool aEnabled, ErrorResult& aRv)
RefPtr<MobileConnectionCallback> requestCallback =
new MobileConnectionCallback(GetOwner(), request);
nsresult rv = mMobileConnection->SetCallWaiting(aEnabled, requestCallback);
nsresult rv = mMobileConnection->SetCallWaiting(aEnabled,
nsIMobileConnection::ICC_SERVICE_CLASS_VOICE,
requestCallback);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
@@ -1125,6 +1127,13 @@ MobileConnection::NotifyNetworkSelectionModeChanged()
return NS_OK;
}
NS_IMETHODIMP
MobileConnection::NotifyDeviceIdentitiesChanged()
{
// To be supported when bug 1222870 is required in m-c.
return NS_OK;
}
// nsIIccListener
NS_IMETHODIMP
@@ -191,6 +191,14 @@ MobileConnectionCallback::NotifyGetCallBarringSuccess(uint16_t aProgram,
return NotifySuccess(jsResult);
}
NS_IMETHODIMP
MobileConnectionCallback::NotifyGetCallWaitingSuccess(uint16_t aServiceClass)
{
return (aServiceClass & nsIMobileConnection::ICC_SERVICE_CLASS_VOICE)
? NotifySuccess(JS::TrueHandleValue)
: NotifySuccess(JS::FalseHandleValue);
}
NS_IMETHODIMP
MobileConnectionCallback::NotifyGetClirStatusSuccess(uint16_t aN, uint16_t aM)
{
@@ -46,8 +46,7 @@ const NS_DATA_CALL_ERROR_TOPIC_ID = "data-call-error";
const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
const INT32_MAX = 2147483647;
const UNKNOWN_RSSI = 99;
const UNKNOWN_VALUE = Ci.nsICellInfo.UNKNOWN_VALUE;
XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionMessenger",
"@mozilla.org/ril/system-messenger-helper;1",
@@ -77,7 +76,7 @@ XPCOMUtils.defineLazyGetter(this, "gRadioInterfaceLayer", function() {
return ril;
});
let DEBUG = RIL.DEBUG_RIL;
var DEBUG = RIL.DEBUG_RIL;
function debug(s) {
dump("MobileConnectionService: " + s + "\n");
}
@@ -163,7 +162,26 @@ MobileCallForwardingOptions.prototype = {
serviceClass: Ci.nsIMobileConnection.ICC_SERVICE_CLASS_NONE
}
function NeighboringCellInfo() {}
function NeighboringCellInfo(aOptions) {
this.networkType = aOptions.networkType;
this.gsmLocationAreaCode = (aOptions.gsmLocationAreaCode !== undefined &&
aOptions.gsmLocationAreaCode >= 0 &&
aOptions.gsmLocationAreaCode <= 65535) ?
aOptions.gsmLocationAreaCode : UNKNOWN_VALUE;
this.gsmCellId = (aOptions.gsmCellId !== undefined &&
aOptions.gsmCellId >= 0 &&
aOptions.gsmCellId <= 65535) ?
aOptions.gsmCellId : UNKNOWN_VALUE;
this.wcdmaPsc = (aOptions.wcdmaPsc !== undefined && aOptions.wcdmaPsc >= 0 &&
aOptions.wcdmaPsc <= 511) ?
aOptions.wcdmaPsc : UNKNOWN_VALUE;
this.signalStrength = (aOptions.signalStrength !== undefined &&
((aOptions.signalStrength >= 0 &&
aOptions.signalStrength <= 31) ||
(aOptions.signalStrength >= -120 &&
aOptions.signalStrength <= -25))) ?
aOptions.signalStrength : UNKNOWN_VALUE;
}
NeighboringCellInfo.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsINeighboringCellInfo]),
classID: NEIGHBORINGCELLINFO_CID,
@@ -173,16 +191,28 @@ NeighboringCellInfo.prototype = {
interfaces: [Ci.nsINeighboringCellInfo]
}),
isValid: function() {
return !(this.gsmLocationAreaCode == UNKNOWN_VALUE &&
this.gsmCellId == UNKNOWN_VALUE &&
this.wcdmaPsc == UNKNOWN_VALUE &&
this.signalStrength == UNKNOWN_VALUE);
},
// nsINeighboringCellInfo
networkType: null,
gsmLocationAreaCode: -1,
gsmCellId: -1,
wcdmaPsc: -1,
signalStrength: UNKNOWN_RSSI
gsmLocationAreaCode: UNKNOWN_VALUE,
gsmCellId: UNKNOWN_VALUE,
wcdmaPsc: UNKNOWN_VALUE,
signalStrength: UNKNOWN_VALUE
};
function CellInfo() {}
function CellInfo(aOptions) {
this.type = aOptions.type;
this.registered = aOptions.registered;
this.timestampType = aOptions.timestampType;
this.timestamp = aOptions.timestamp;
}
CellInfo.prototype = {
// nsICellInfo
@@ -193,7 +223,28 @@ CellInfo.prototype = {
timestamp: 0
};
function GsmCellInfo() {}
function GsmCellInfo(aOptions) {
CellInfo.call(this, aOptions);
// Cell Identity
this.mcc = (aOptions.mcc !== undefined && aOptions.mcc >= 0 &&
aOptions.mcc <= 999) ? aOptions.mcc : UNKNOWN_VALUE;
this.mnc = (aOptions.mnc !== undefined && aOptions.mnc >= 0 &&
aOptions.mnc <= 999) ? aOptions.mnc : UNKNOWN_VALUE;
this.lac = (aOptions.lac !== undefined && aOptions.lac >= 0 &&
aOptions.lac <= 65535) ? aOptions.lac : UNKNOWN_VALUE;
this.cid = (aOptions.cid !== undefined && aOptions.cid >= 0 &&
aOptions.cid <= 65535) ? aOptions.cid : UNKNOWN_VALUE;
// Signal Strength
this.signalStrength = (aOptions.signalStrength !== undefined &&
aOptions.signalStrength >= 0 &&
aOptions.signalStrength <= 31) ?
aOptions.signalStrength : UNKNOWN_VALUE;
this.bitErrorRate = (aOptions.bitErrorRate !== undefined &&
aOptions.bitErrorRate >= 0 && aOptions.bitErrorRate <= 7)
? aOptions.bitErrorRate : UNKNOWN_VALUE;
}
GsmCellInfo.prototype = {
__proto__: CellInfo.prototype,
QueryInterface: XPCOMUtils.generateQI([Ci.nsICellInfo,
@@ -205,17 +256,47 @@ GsmCellInfo.prototype = {
interfaces: [Ci.nsIGsmCellInfo]
}),
isValid: function() {
return !(this.mcc == UNKNOWN_VALUE && this.mnc == UNKNOWN_VALUE &&
this.lac == UNKNOWN_VALUE && this.cid == UNKNOWN_VALUE &&
this.signalStrength == UNKNOWN_VALUE &&
this.bitErrorRate == UNKNOWN_VALUE);
},
// nsIGsmCellInfo
mcc: INT32_MAX,
mnc: INT32_MAX,
lac: INT32_MAX,
cid: INT32_MAX,
signalStrength: UNKNOWN_RSSI,
bitErrorRate: UNKNOWN_RSSI
mcc: UNKNOWN_VALUE,
mnc: UNKNOWN_VALUE,
lac: UNKNOWN_VALUE,
cid: UNKNOWN_VALUE,
signalStrength: UNKNOWN_VALUE,
bitErrorRate: UNKNOWN_VALUE
};
function WcdmaCellInfo() {}
function WcdmaCellInfo(aOptions) {
CellInfo.call(this, aOptions);
// Cell Identity
this.mcc = (aOptions.mcc !== undefined && aOptions.mcc >= 0 &&
aOptions.mcc <= 999) ? aOptions.mcc : UNKNOWN_VALUE;
this.mnc = (aOptions.mnc !== undefined && aOptions.mnc >= 0 &&
aOptions.mnc <= 999) ? aOptions.mnc : UNKNOWN_VALUE;
this.lac = (aOptions.lac !== undefined && aOptions.lac >= 0 &&
aOptions.lac <= 65535) ? aOptions.lac : UNKNOWN_VALUE;
this.cid = (aOptions.cid !== undefined && aOptions.cid >= 0 &&
aOptions.cid <= 268435455) ? aOptions.cid : UNKNOWN_VALUE;
this.psc = (aOptions.psc !== undefined && aOptions.psc >= 0 &&
aOptions.psc <= 511) ? aOptions.psc : UNKNOWN_VALUE;
// Signal Strength
this.signalStrength = (aOptions.signalStrength !== undefined &&
aOptions.signalStrength >= 0 &&
aOptions.signalStrength <= 31) ?
aOptions.signalStrength : UNKNOWN_VALUE;
this.bitErrorRate = (aOptions.bitErrorRate !== undefined &&
aOptions.bitErrorRate >= 0 && aOptions.bitErrorRate <= 7)
? aOptions.bitErrorRate : UNKNOWN_VALUE;
}
WcdmaCellInfo.prototype = {
__proto__: CellInfo.prototype,
QueryInterface: XPCOMUtils.generateQI([Ci.nsICellInfo,
@@ -227,18 +308,57 @@ WcdmaCellInfo.prototype = {
interfaces: [Ci.nsIWcdmaCellInfo]
}),
isValid: function() {
return !(this.mcc == UNKNOWN_VALUE && this.mnc == UNKNOWN_VALUE &&
this.lac == UNKNOWN_VALUE && this.cid == UNKNOWN_VALUE &&
this.psc == UNKNOWN_VALUE && this.signalStrength == UNKNOWN_VALUE &&
this.bitErrorRate == UNKNOWN_VALUE);
},
// nsIWcdmaCellInfo
mcc: INT32_MAX,
mnc: INT32_MAX,
lac: INT32_MAX,
cid: INT32_MAX,
psc: INT32_MAX,
signalStrength: UNKNOWN_RSSI,
bitErrorRate: UNKNOWN_RSSI
mcc: UNKNOWN_VALUE,
mnc: UNKNOWN_VALUE,
lac: UNKNOWN_VALUE,
cid: UNKNOWN_VALUE,
psc: UNKNOWN_VALUE,
signalStrength: UNKNOWN_VALUE,
bitErrorRate: UNKNOWN_VALUE
};
function LteCellInfo() {}
function LteCellInfo(aOptions) {
CellInfo.call(this, aOptions);
// Cell Identity
this.mcc = (aOptions.mcc !== undefined && aOptions.mcc >= 0 &&
aOptions.mcc <= 999) ? aOptions.mcc : UNKNOWN_VALUE;
this.mnc = (aOptions.mnc !== undefined && aOptions.mnc >= 0 &&
aOptions.mnc <= 999) ? aOptions.mnc : UNKNOWN_VALUE;
this.cid = (aOptions.cid !== undefined && aOptions.cid >= 0 &&
aOptions.cid <= 268435455) ? aOptions.cid : UNKNOWN_VALUE;
this.pcid = (aOptions.pcid !== undefined && aOptions.pcid >= 0 &&
aOptions.pcid <= 503) ? aOptions.pcid : UNKNOWN_VALUE;
this.tac = (aOptions.tac !== undefined && aOptions.tac >= 0 &&
aOptions.tac <= 65535) ? aOptions.tac : UNKNOWN_VALUE;
// Signal Strength
this.signalStrength = (aOptions.signalStrength !== undefined &&
aOptions.signalStrength >= 0 &&
aOptions.signalStrength <= 31) ?
aOptions.signalStrength : UNKNOWN_VALUE;
this.rsrp = (aOptions.rsrp !== undefined && aOptions.rsrp >= 44 &&
aOptions.rsrp <= 140) ? aOptions.rsrp : UNKNOWN_VALUE;
this.rsrq = (aOptions.rsrq !== undefined && aOptions.rsrq >= 3 &&
aOptions.rsrq <= 20) ? aOptions.rsrq : UNKNOWN_VALUE;
this.rssnr = (aOptions.rssnr !== undefined && aOptions.rssnr >= -200 &&
aOptions.rssnr <= 300) ? aOptions.rssnr : UNKNOWN_VALUE;
this.cqi = (aOptions.cqi !== undefined && aOptions.cqi >= 0 &&
aOptions.cqi <= 15) ? aOptions.cqi : UNKNOWN_VALUE;
this.timingAdvance = (aOptions.timingAdvance !== undefined &&
aOptions.timingAdvance >= 0 &&
aOptions.timingAdvance <= 2147483646) ?
aOptions.timingAdvance : UNKNOWN_VALUE;
}
LteCellInfo.prototype = {
__proto__: CellInfo.prototype,
QueryInterface: XPCOMUtils.generateQI([Ci.nsICellInfo,
@@ -250,22 +370,64 @@ LteCellInfo.prototype = {
interfaces: [Ci.nsILteCellInfo]
}),
isValid: function() {
return !(this.mcc == UNKNOWN_VALUE && this.mnc == UNKNOWN_VALUE &&
this.cid == UNKNOWN_VALUE && this.pcid == UNKNOWN_VALUE &&
this.tac == UNKNOWN_VALUE && this.signalStrength == UNKNOWN_VALUE &&
this.rsrp == UNKNOWN_VALUE && this.rsrq == UNKNOWN_VALUE &&
this.rssnr == UNKNOWN_VALUE && this.cqi == UNKNOWN_VALUE &&
this.timingAdvance == UNKNOWN_VALUE);
},
// nsILteCellInfo
mcc: INT32_MAX,
mnc: INT32_MAX,
cid: INT32_MAX,
pcid: INT32_MAX,
tac: INT32_MAX,
signalStrength: UNKNOWN_RSSI,
rsrp: INT32_MAX,
rsrq: INT32_MAX,
rssnr: INT32_MAX,
cqi: INT32_MAX,
timingAdvance: INT32_MAX
mcc: UNKNOWN_VALUE,
mnc: UNKNOWN_VALUE,
cid: UNKNOWN_VALUE,
pcid: UNKNOWN_VALUE,
tac: UNKNOWN_VALUE,
signalStrength: UNKNOWN_VALUE,
rsrp: UNKNOWN_VALUE,
rsrq: UNKNOWN_VALUE,
rssnr: UNKNOWN_VALUE,
cqi: UNKNOWN_VALUE,
timingAdvance: UNKNOWN_VALUE
};
function CdmaCellInfo() {}
function CdmaCellInfo(aOptions) {
CellInfo.call(this, aOptions);
// Cell Identity
this.networkId = (aOptions.networkId !== undefined &&
aOptions.networkId >= 0 && aOptions.networkId <= 65535) ?
aOptions.networkId : UNKNOWN_VALUE;
this.systemId = (aOptions.systemId !== undefined && aOptions.systemId >= 0 &&
aOptions.systemId <= 32767) ?
aOptions.systemId : UNKNOWN_VALUE;
this.baseStationId = (aOptions.baseStationId !== undefined &&
aOptions.baseStationId >= 0 &&
aOptions.baseStationId <= 65535) ?
aOptions.baseStationId : UNKNOWN_VALUE;
this.longitude = (aOptions.longitude !== undefined &&
aOptions.longitude >= -2592000 &&
aOptions.longitude <= 2592000) ?
aOptions.longitude : UNKNOWN_VALUE;
this.latitude = (aOptions.latitude !== undefined &&
aOptions.latitude >= -1296000 &&
aOptions.latitude <= 1296000) ?
aOptions.latitude : UNKNOWN_VALUE;
// Signal Strength
this.cdmaEcio = (aOptions.cdmaEcio !== undefined &&
aOptions.cdmaEcio >= 0) ? aOptions.cdmaEcio : UNKNOWN_VALUE;
this.evdoDbm = (aOptions.evdoDbm !== undefined &&
aOptions.evdoDbm >= 0) ? aOptions.evdoDbm : UNKNOWN_VALUE;
this.evdoEcio = (aOptions.evdoEcio !== undefined &&
aOptions.evdoEcio >= 0) ? aOptions.evdoEcio : UNKNOWN_VALUE;
this.evdoSnr = (aOptions.evdoSnr !== undefined &&
aOptions.evdoSnr >= 0 && aOptions.evdoSnr <= 8) ?
aOptions.evdoSnr : UNKNOWN_VALUE;
}
CdmaCellInfo.prototype = {
__proto__: CellInfo.prototype,
QueryInterface: XPCOMUtils.generateQI([Ci.nsICellInfo,
@@ -277,18 +439,43 @@ CdmaCellInfo.prototype = {
interfaces: [Ci.nsICdmaCellInfo]
}),
isValid: function() {
return !(this.networkId == UNKNOWN_VALUE && this.systemId == UNKNOWN_VALUE &&
this.baseStationId == UNKNOWN_VALUE &&
this.longitude == UNKNOWN_VALUE &&
this.latitude == UNKNOWN_VALUE && this.cdmaDbm == UNKNOWN_VALUE &&
this.cdmaEcio == UNKNOWN_VALUE && this.evdoDbm == UNKNOWN_VALUE &&
this.evdoEcio == UNKNOWN_VALUE && this.evdoSnr == UNKNOWN_VALUE);
},
// nsICdmaCellInfo
networkId: INT32_MAX,
systemId: INT32_MAX,
baseStationId: INT32_MAX,
longitude: INT32_MAX,
latitude: INT32_MAX,
cdmaDbm: INT32_MAX,
cdmaEcio: INT32_MAX,
evdoDbm: INT32_MAX,
evdoEcio: INT32_MAX,
evdoSnr: INT32_MAX
networkId: UNKNOWN_VALUE,
systemId: UNKNOWN_VALUE,
baseStationId: UNKNOWN_VALUE,
longitude: UNKNOWN_VALUE,
latitude: UNKNOWN_VALUE,
cdmaDbm: UNKNOWN_VALUE,
cdmaEcio: UNKNOWN_VALUE,
evdoDbm: UNKNOWN_VALUE,
evdoEcio: UNKNOWN_VALUE,
evdoSnr: UNKNOWN_VALUE
};
function MobileDeviceIdentities(aImei, aImeisv, aEsn, aMeid) {
this.imei = aImei;
this.imeisv = aImeisv;
this.esn = aEsn;
this.meid = aMeid;
}
MobileDeviceIdentities.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileDeviceIdentities]),
// nsIMobileDeviceIdentities
imei: null,
imeisv: null,
esn: null,
meid: null
};
function MobileConnectionProvider(aClientId, aRadioInterface) {
@@ -330,6 +517,7 @@ MobileConnectionProvider.prototype = {
lastKnownNetwork: null,
lastKnownHomeNetwork: null,
supportedNetworkTypes: null,
deviceIdentities: null,
/**
* A utility function to dump debug message.
@@ -790,6 +978,17 @@ MobileConnectionProvider.prototype = {
aServiceClass]);
},
notifyDeviceIdentitiesChanged: function(aImei, aImeisv, aEsn, aMeid) {
if (this.deviceIdentities) {
if (DEBUG) this._debug("deviceIdentities shall not be changed once being updated.");
return;
}
this.deviceIdentities =
new MobileDeviceIdentities(aImei, aImeisv, aEsn, aMeid);
this.deliverListenerEvent("notifyDeviceIdentitiesChanged");
},
getSupportedNetworkTypes: function(aTypes) {
aTypes.value = this.supportedNetworkTypes.slice();
return aTypes.value.length;
@@ -1054,9 +1253,13 @@ MobileConnectionProvider.prototype = {
}).bind(this));
},
setCallWaiting: function(aEnabled, aCallback) {
this._radioInterface.sendWorkerMessage("setCallWaiting",
{enabled: aEnabled},
setCallWaiting: function(aEnabled, aServiceClass, aCallback) {
let options = {
enabled: aEnabled,
serviceClass: aServiceClass
};
this._radioInterface.sendWorkerMessage("setCallWaiting", options,
(function(aResponse) {
if (aResponse.errorMsg) {
aCallback.notifyError(aResponse.errorMsg);
@@ -1076,7 +1279,7 @@ MobileConnectionProvider.prototype = {
return false;
}
aCallback.notifySuccessWithBoolean(aResponse.enabled);
aCallback.notifyGetCallWaitingSuccess(aResponse.serviceClass);
return false;
}).bind(this));
},
@@ -1176,26 +1379,26 @@ MobileConnectionProvider.prototype = {
let cellInfo;
switch (srcCellInfo.type) {
case RIL.CELL_INFO_TYPE_GSM:
cellInfo = new GsmCellInfo();
cellInfo = new GsmCellInfo(srcCellInfo);
break;
case RIL.CELL_INFO_TYPE_WCDMA:
cellInfo = new WcdmaCellInfo();
cellInfo = new WcdmaCellInfo(srcCellInfo);
break;
case RIL.CELL_INFO_TYPE_LTE:
cellInfo = new LteCellInfo();
cellInfo = new LteCellInfo(srcCellInfo);
break;
case RIL.CELL_INFO_TYPE_CDMA:
cellInfo = new CdmaCellInfo();
cellInfo = new CdmaCellInfo(srcCellInfo);
break;
}
if (!cellInfo) {
if (!cellInfo || !cellInfo.isValid()) {
continue;
}
this._updateInfo(cellInfo, srcCellInfo);
cellInfoList.push(cellInfo);
}
aCallback.notifyGetCellInfoList(count, cellInfoList);
aCallback.notifyGetCellInfoList(cellInfoList.length, cellInfoList);
}.bind(this));
},
@@ -1212,11 +1415,13 @@ MobileConnectionProvider.prototype = {
let count = aResponse.result.length;
for (let i = 0; i < count; i++) {
let srcCellInfo = aResponse.result[i];
let cellInfo = new NeighboringCellInfo();
this._updateInfo(cellInfo, srcCellInfo);
neighboringCellIds.push(cellInfo);
let cellInfo = new NeighboringCellInfo(srcCellInfo);
if (cellInfo && cellInfo.isValid()) {
neighboringCellIds.push(cellInfo);
}
}
aCallback.notifyGetNeighboringCellIds(count, neighboringCellIds);
aCallback.notifyGetNeighboringCellIds(neighboringCellIds.length,
neighboringCellIds);
}.bind(this));
},
@@ -1516,6 +1721,12 @@ MobileConnectionService.prototype = {
.notifyCdmaInfoRecAudioControl(aClientId, aUpLink, aDownLink);
},
notifyDeviceIdentitiesChanged: function(aClientId, aImei, aImeisv,
aEsn, aMeid) {
this.getItemByServiceId(aClientId)
.notifyDeviceIdentitiesChanged(aImei, aImeisv, aEsn, aMeid);
},
/**
* nsIObserver interface.
*/
@@ -9,7 +9,7 @@
"@mozilla.org/mobileconnection/gonkmobileconnectionservice;1"
%}
[scriptable, uuid(3a7b8d47-d1c6-44c3-a312-df73fda1161e)]
[scriptable, uuid(3c306f88-86bf-11e5-91af-3b2233acec65)]
interface nsIGonkMobileConnectionService : nsIMobileConnectionService
{
void notifyNetworkInfoChanged(in unsigned long clientId, in jsval networkInfo);
@@ -248,4 +248,27 @@ interface nsIGonkMobileConnectionService : nsIMobileConnectionService
void notifyCdmaInfoRecAudioControl(in unsigned long clientId,
in short upLink,
in short downLink);
/**
* Notify Device Identities.
*
* @param aClientId
* The ID of radioInterface where this info is notified from.
* @param aImei
* Device IMEI, valid if GSM subscription is available.
* @param aImeisv
* Device IMEISV, valid if GSM subscription is available.
* @param aEsn
* Device ESN, valid if CDMA subscription is available.
* @param aMeid
* Device MEID, valid if CDMA subscription is available.
*
* Note: The value might be dummy like "000..." from modem
* if the corresponding subscription is not available.
*/
void notifyDeviceIdentitiesChanged(in unsigned long aClientId,
in DOMString aImei,
in DOMString aImeisv,
in DOMString aEsn,
in DOMString aMeid);
};
+56 -51
View File
@@ -22,20 +22,22 @@ interface nsICellInfoListCallback : nsISupports
void notifyGetCellInfoListFailed(in DOMString error);
};
[scriptable, uuid(86667898-c9ab-44ee-8a9a-026916b3183e)]
[scriptable, uuid(a9a34341-5a33-4e0a-98e1-13e7ea4228be)]
interface nsICellInfo : nsISupports
{
const long CELL_INFO_TYPE_GSM = 1;
const long CELL_INFO_TYPE_CDMA = 2;
const long CELL_INFO_TYPE_LTE = 3;
const long CELL_INFO_TYPE_GSM = 1;
const long CELL_INFO_TYPE_CDMA = 2;
const long CELL_INFO_TYPE_LTE = 3;
const long CELL_INFO_TYPE_WCDMA = 4;
const long TIMESTAMP_TYPE_UNKNOWN = 0;
const long TIMESTAMP_TYPE_ANTENNA = 1;
const long TIMESTAMP_TYPE_MODEM = 2;
const long TIMESTAMP_TYPE_OEM_RIL = 3;
const long TIMESTAMP_TYPE_UNKNOWN = 0;
const long TIMESTAMP_TYPE_ANTENNA = 1;
const long TIMESTAMP_TYPE_MODEM = 2;
const long TIMESTAMP_TYPE_OEM_RIL = 3;
const long TIMESTAMP_TYPE_JAVA_RIL = 4;
const long UNKNOWN_VALUE = 0x7FFFFFFF;
/**
* Network type. One of the CELL_INFO_TYPE_* constants.
*/
@@ -57,204 +59,207 @@ interface nsICellInfo : nsISupports
readonly attribute long long timestamp;
};
[scriptable, uuid(6345967c-61fc-45a1-8362-39e9261df052)]
[scriptable, uuid(cc476ded-350f-4c25-9a57-6a876e32f092)]
interface nsIGsmCellInfo : nsICellInfo
{
/**
* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown.
* 3-digit Mobile Country Code, 0..999, UNKNOWN_VALUE if unknown.
*/
readonly attribute long mcc;
/**
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
* 2 or 3-digit Mobile Network Code, 0..999, UNKNOWN_VALUE if unknown.
*/
readonly attribute long mnc;
/**
* 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
* 16-bit Location Area Code, 0..65535, UNKNOWN_VALUE if unknown.
*/
readonly attribute long lac;
/**
* 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown.
* 16-bit GSM Cell Identity described in TS 27.007, 0..65535,
* UNKNOWN_VALUE if unknown.
*/
readonly attribute long cid;
/**
* Valid values are 0-31 as defined in TS 27.007 8.5, 99 if unknown.
* Valid values are 0-31 as defined in TS 27.007 8.5, UNKNOWN_VALUE if unknown.
*/
readonly attribute long signalStrength;
/**
* Bit error rate 0-7 as defined in TS 27.007 8.5, 99 if unknown.
* Bit error rate 0-7 as defined in TS 27.007 8.5, UNKNOWN_VALUE if unknown.
*/
readonly attribute long bitErrorRate;
};
[scriptable, uuid(19693f98-943d-45e7-a3e8-25373228ce6b)]
[scriptable, uuid(aa52647b-38dd-487c-be36-b46ed2e99554)]
interface nsIWcdmaCellInfo : nsICellInfo
{
/**
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
* 2 or 3-digit Mobile Network Code, 0..999, UNKNOWN_VALUE if unknown.
*/
readonly attribute long mcc;
/**
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
* 2 or 3-digit Mobile Network Code, 0..999, UNKNOWN_VALUE if unknown.
*/
readonly attribute long mnc;
/**
* 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
* 16-bit Location Area Code, 0..65535, UNKNOWN_VALUE if unknown.
*/
readonly attribute long lac;
/**
* 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455,
* INT_MAX if unknown.
* UNKNOWN_VALUE if unknown.
*/
readonly attribute long cid;
/**
* 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511,
* INT_MAX if unknown.
* UNKNOWN_VALUE if unknown.
*/
readonly attribute long psc;
/**
* Valid values are 0-31 as defined in TS 27.007 8.5, 99 if unknown.
* Valid values are 0-31 as defined in TS 27.007 8.5, UNKNOWN_VALUE if unknown.
*/
readonly attribute long signalStrength;
/**
* Bit error rate 0-7 as defined in TS 27.007 8.5, 99 if unknown.
* Bit error rate 0-7 as defined in TS 27.007 8.5, UNKNOWN_VALUE if unknown.
*/
readonly attribute long bitErrorRate;
};
[scriptable, uuid(76b4a35d-7e45-42bc-a2e0-bc07a6434db3)]
[scriptable, uuid(60a38ca7-ca62-4384-aa07-eac7d4893786)]
interface nsICdmaCellInfo : nsICellInfo
{
/**
* Network Id, 0..65535, INT_MAX if unknown.
* Network Id, 0..65535, UNKNOWN_VALUE if unknown.
*/
readonly attribute long networkId;
/**
* CDMA System Id, 0..32767, INT_MAX if unknown.
* CDMA System Id, 0..32767, UNKNOWN_VALUE if unknown.
*/
readonly attribute long systemId;
/**
* Base Station Id, 0..65535, INT_MAX if unknown.
* Base Station Id, 0..65535, UNKNOWN_VALUE if unknown.
*/
readonly attribute long baseStationId;
/**
* Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
* It is represented in units of 0.25 seconds and ranges from -2592000 to
* 2592000, INT_MAX if unknown.
* 2592000, UNKNOWN_VALUE if unknown.
*/
readonly attribute long longitude;
/**
* Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
* It is represented in units of 0.25 seconds and ranges from -1296000 to
* 1296000, INT_MAX if unknown.
* 1296000, UNKNOWN_VALUE if unknown.
*/
readonly attribute long latitude;
/**
* Valid values are positive integers, INT_MAX if unknown. This value is the
* actual RSSI value multiplied by -1.
* Valid values are positive integers, UNKNOWN_VALUE if unknown. This value is
* the actual RSSI value multiplied by -1.
*/
readonly attribute long cdmaDbm;
/**
* Valid values are positive integers, INT_MAX if unknown. This value is the
* actual Ec/Io multiplied by -10. -1 if unknown.
* Valid values are positive integers, UNKNOWN_VALUE if unknown. This value is
* the actual Ec/Io multiplied by -10.
*/
readonly attribute long cdmaEcio;
/**
* Valid values are positive integers, INT_MAX if unknown. This value is the
* actual Evdo RSSI value multiplied by -1.
* Valid values are positive integers, UNKNOWN_VALUE if unknown. This value is
* the actual Evdo RSSI value multiplied by -1.
*/
readonly attribute long evdoDbm;
/**
* Valid values are positive integers, INT_MAX if unknown. This value is the
* actual Evdo Ec/Io multiplied by -10.
* Valid values are positive integers, UNKNOWN_VALUE if unknown. This value is
* the actual Evdo Ec/Io multiplied by -10.
*/
readonly attribute long evdoEcio;
/**
* Valid values are 0-8, INT_MAX if unknown. 8 is the highest signal to noise
* ratio.
* Valid values are 0-8, UNKNOWN_VALUE if unknown. 8 is the highest signal to
* noise ratio.
*/
readonly attribute long evdoSnr;
};
[scriptable, uuid(122937d9-1ee5-45e0-a360-5959d578bc31)]
[scriptable, uuid(e7b3e826-bb85-49b2-a2f1-70af46c47733)]
interface nsILteCellInfo : nsICellInfo
{
/**
* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown.
* 3-digit Mobile Country Code, 0..999, UNKNOWN_VALUE if unknown.
*/
readonly attribute long mcc;
/**
* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown.
* 2 or 3-digit Mobile Network Code, 0..999, UNKNOWN_VALUE if unknown.
*/
readonly attribute long mnc;
/**
* 28-bit Cell Identity, 0..268435455, INT_MAX if unknown.
* 28-bit Cell Identity, 0..268435455, UNKNOWN_VALUE if unknown.
*/
readonly attribute long cid;
/**
* Physical cell id, 0..503, INT_MAX if unknown.
* Physical cell id, 0..503, UNKNOWN_VALUE if unknown.
*/
readonly attribute long pcid;
/**
* 16-bit tracking area code, 0..65535, INT_MAX if unknown.
* 16-bit tracking area code, 0..65535, UNKNOWN_VALUE if unknown.
*/
readonly attribute long tac;
/**
* Valid values are 0-31 as defined in TS 27.007 8.5, 99 if unknown.
* Valid values are 0-31 as defined in TS 27.007 8.5, UNKNOWN_VALUE if unknown.
*/
readonly attribute long signalStrength;
/**
* The current Reference Signal Receive Power in dBm multipled by -1.
* Range: 44 to 140 dBm, INT_MAX if unknown.
* Range: 44 to 140 dBm, UNKNOWN_VALUE if unknown.
*/
readonly attribute long rsrp;
/**
* The current Reference Signal Receive Quality in dB multiplied by -1.
* Range: 3 to 20 dB, INT_MAX if unknown.
* Range: 3 to 20 dB, UNKNOWN_VALUE if unknown.
*/
readonly attribute long rsrq;
/**
* The current reference signal signal-to-noise ratio in 0.1 dB units.
* Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB), INT_MAX if unknown.
* Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB), UNKNOWN_VALUE if
* unknown.
*/
readonly attribute long rssnr;
/**
* The current Channel Quality Indicator. Range: 0 to 15, INT_MAX if unknown.
* The current Channel Quality Indicator. Range: 0 to 15, UNKNOWN_VALUE if
* unknown.
*/
readonly attribute long cqi;
/**
* Timing advance in micro seconds for a one way trip from cell to device.
* Approximate distance can be calculated using 300m/us * timingAdvance.
* Range: 0 to 0x7FFFFFFE, INT_MAX if unknown.
* Range: 0 to 0x7FFFFFFE, UNKNOWN_VALUE if unknown.
*/
readonly attribute long timingAdvance;
};
@@ -8,11 +8,12 @@ interface nsICellInfoListCallback;
interface nsIMobileCallForwardingOptions;
interface nsIMobileConnection;
interface nsIMobileConnectionInfo;
interface nsIMobileDeviceIdentities;
interface nsIMobileNetworkInfo;
interface nsINeighboringCellIdsCallback;
interface nsIVariant;
[scriptable, uuid(d6827b51-61a7-4b7c-8454-42d0cffc1829)]
[scriptable, uuid(8884b326-891c-11e5-a434-67def07c4a41)]
interface nsIMobileConnectionListener : nsISupports
{
/**
@@ -102,13 +103,18 @@ interface nsIMobileConnectionListener : nsISupports
* Notify when network selection mode is changed.
*/
void notifyNetworkSelectionModeChanged();
/**
* Notify when device identities are changed.
*/
void notifyDeviceIdentitiesChanged();
};
%{C++
#define NO_ADDITIONAL_INFORMATION 0
%}
[scriptable, uuid(14d66926-8434-11e4-8c3f-f724194bb5f1)]
[scriptable, uuid(ef5e02a6-adff-4425-8634-ec49ced1f14f)]
interface nsIMobileConnectionCallback : nsISupports
{
/**
@@ -128,6 +134,8 @@ interface nsIMobileConnectionCallback : nsISupports
in boolean enabled,
in unsigned short serviceClass);
void notifyGetCallWaitingSuccess(in unsigned short serviceClass);
void notifyGetClirStatusSuccess(in unsigned short n, in unsigned short m);
void notifyGetPreferredNetworkTypeSuccess(in long type);
@@ -163,7 +171,7 @@ already_AddRefed<nsIMobileConnectionService>
NS_CreateMobileConnectionService();
%}
[scriptable, uuid(b9845f09-7cbb-46d0-b713-773d80844e0d)]
[scriptable, uuid(7a557116-8753-11e5-9f9b-6794b577c0a1)]
interface nsIMobileConnection : nsISupports
{
/*
@@ -214,6 +222,9 @@ interface nsIMobileConnection : nsISupports
const long CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME = 2;
const long CALL_BARRING_PROGRAM_ALL_INCOMING = 3;
const long CALL_BARRING_PROGRAM_INCOMING_ROAMING = 4;
const long CALL_BARRING_PROGRAM_ALL_SERVICE = 5;
const long CALL_BARRING_PROGRAM_OUTGOING_SERVICE = 6;
const long CALL_BARRING_PROGRAM_INCOMING_SERVICE = 7;
/**
* Calling line identification restriction constants.
@@ -315,6 +326,11 @@ interface nsIMobileConnection : nsISupports
*/
readonly attribute long radioState;
/**
* Device Identities, including IMEI, IMEISV, ESN and MEID.
*/
readonly attribute nsIMobileDeviceIdentities deviceIdentities;
/**
* The network types supported by this radio.
*
@@ -598,6 +614,8 @@ interface nsIMobileConnection : nsISupports
*
* @param enabled
* Boolean indicates the desired call waiting status.
* @param serviceClass
* One of the nsIMobileConnection.ICC_SERVICE_CLASS_* values.
* @param requestCallback
* Called when request is finished.
*
@@ -608,6 +626,7 @@ interface nsIMobileConnection : nsISupports
* 'GenericFailure'.
*/
void setCallWaiting(in bool enabled,
in unsigned short serviceClass,
in nsIMobileConnectionCallback requestCallback);
/**
@@ -616,8 +635,12 @@ interface nsIMobileConnection : nsISupports
* @param requestCallback
* Called when request is finished.
*
* If successful, the notifySuccessWithBoolean() will be called. And the result
* will be a boolean indicating the call waiting status.
* If successful, the notifyGetCallWaitingSuccess() will be called. And the
* result will be a service class bit vector of services for which call
* waiting is enabled. e.g. 3 means call waiting is enabled for data
* and voice and disabled for everything else. 0 means call waiting is
* disabled for all service.
* @see nsIMobileConnection.ICC_SERVICE_CLASS_*.
*
* Otherwise, the notifyError() will be called, and the error will be either
* 'RadioNotAvailable', 'RequestNotSupported', 'IllegalSIMorME', or
@@ -0,0 +1,46 @@
/* 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 "nsISupports.idl"
[scriptable, uuid(3fc79ece-8399-11e5-beff-6b8209cb93f6)]
interface nsIMobileDeviceIdentities : nsISupports
{
/**
* Device IMEI, including check digit.
*
* Valid if GSM subscription is available.
*
* Note: The value might be dummy like "000..." from modem if invalid.
*/
readonly attribute DOMString imei;
/**
* Device IMEISV.
*
* Valid if GSM subscription is available.
*
* Note: IMEISV is presented in 2-decimal digits.
* The value might be dummy like "00" from modem if invalid.
*/
readonly attribute DOMString imeisv;
/**
* Device ESN.
*
* Valid if CDMA subscription is available.
*
* Note: The value might be dummy like "000..." from modem if invalid.
*/
readonly attribute DOMString esn;
/**
* Device MEID.
*
* Valid if CDMA subscription is available.
*
* Note: The value might be dummy like "000..." from modem if invalid.
*/
readonly attribute DOMString meid;
};
@@ -36,15 +36,15 @@ interface nsINeighboringCellInfo: nsISupports
* Mobile Location Area Code (LAC) for GSM networks.
*
* Possible ranges from 0x0000 to 0xffff.
* -1 if the LAC is unknown.
* nsICellInfo.UNKNOWN_VALUE if the LAC is unknown.
*/
readonly attribute long gsmLocationAreaCode;
/**
* Mobile Cell ID for GSM networks.
*
* Possible ranges from 0x00000000 to 0xffffffff.
* -1 if the cell id is unknown.
* Possible ranges from 0x0000 to 0xffff.
* nsICellInfo.UNKNOWN_VALUE if the cell id is unknown.
*/
readonly attribute long long gsmCellId;
@@ -52,7 +52,7 @@ interface nsINeighboringCellInfo: nsISupports
* Primary Scrambling Code (PSC) for WCDMA networks.
*
* Possible ranges from 0x0000 to 0x01ff.
* -1 if the psc is unknown.
* nsICellInfo.UNKNOWN_VALUE if the psc is unknown.
*/
readonly attribute long wcdmaPsc;
@@ -61,7 +61,7 @@ interface nsINeighboringCellInfo: nsISupports
* For WCDMA networks, signalStrength is the CPICH Received Signal Code Power,
* ranging from -120 to -25.
*
* 99 if signalStrength is unknown.
* nsICellInfo.UNKNOWN_VALUE if signalStrength is unknown.
*/
readonly attribute long signalStrength;
};
@@ -107,6 +107,12 @@ MobileConnectionChild::GetRadioState(int32_t* aRadioState)
return NS_OK;
}
NS_IMETHODIMP
MobileConnectionChild::GetDeviceIdentities(nsIMobileDeviceIdentities** aIdentities)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
MobileConnectionChild::GetSupportedNetworkTypes(int32_t** aTypes,
uint32_t* aLength)
@@ -276,9 +282,10 @@ MobileConnectionChild::ChangeCallBarringPassword(const nsAString& aPin,
NS_IMETHODIMP
MobileConnectionChild::SetCallWaiting(bool aEnabled,
uint16_t aServiceClass,
nsIMobileConnectionCallback* aCallback)
{
return SendRequest(SetCallWaitingRequest(aEnabled), aCallback)
return SendRequest(SetCallWaitingRequest(aEnabled, aServiceClass), aCallback)
? NS_OK : NS_ERROR_FAILURE;
}
@@ -550,6 +557,12 @@ MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessCallBarr
aReply.serviceClass()));
}
bool
MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessCallWaiting& aReply)
{
return NS_SUCCEEDED(mRequestCallback->NotifyGetCallWaitingSuccess(aReply.serviceClass()));
}
bool
MobileConnectionRequestChild::DoReply(const MobileConnectionReplySuccessClirStatus& aReply)
{
@@ -591,6 +604,8 @@ MobileConnectionRequestChild::Recv__delete__(const MobileConnectionReply& aReply
return DoReply(aReply.get_MobileConnectionReplySuccessCallForwarding());
case MobileConnectionReply::TMobileConnectionReplySuccessCallBarring:
return DoReply(aReply.get_MobileConnectionReplySuccessCallBarring());
case MobileConnectionReply::TMobileConnectionReplySuccessCallWaiting:
return DoReply(aReply.get_MobileConnectionReplySuccessCallWaiting());
case MobileConnectionReply::TMobileConnectionReplySuccessClirStatus:
return DoReply(aReply.get_MobileConnectionReplySuccessClirStatus());
case MobileConnectionReply::TMobileConnectionReplySuccessPreferredNetworkType:
@@ -148,6 +148,9 @@ public:
bool
DoReply(const MobileConnectionReplySuccessCallBarring& aReply);
bool
DoReply(const MobileConnectionReplySuccessCallWaiting& aReply);
bool
DoReply(const MobileConnectionReplySuccessClirStatus& aReply);
@@ -288,6 +288,13 @@ MobileConnectionParent::NotifyNetworkSelectionModeChanged()
return SendNotifyNetworkSelectionModeChanged(mode) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
MobileConnectionParent::NotifyDeviceIdentitiesChanged()
{
// To be supported when bug 1222870 is required in m-c.
return NS_OK;
}
/******************************************************************************
* PMobileConnectionRequestParent
******************************************************************************/
@@ -434,7 +441,9 @@ MobileConnectionRequestParent::DoRequest(const SetCallWaitingRequest& aRequest)
{
NS_ENSURE_TRUE(mMobileConnection, false);
return NS_SUCCEEDED(mMobileConnection->SetCallWaiting(aRequest.enabled(), this));
return NS_SUCCEEDED(mMobileConnection->SetCallWaiting(aRequest.enabled(),
aRequest.serviceClass(),
this));
}
bool
@@ -536,6 +545,12 @@ MobileConnectionRequestParent::NotifyGetCallBarringSuccess(uint16_t aProgram,
aServiceClass));
}
NS_IMETHODIMP
MobileConnectionRequestParent::NotifyGetCallWaitingSuccess(uint16_t aServiceClass)
{
return SendReply(MobileConnectionReplySuccessCallWaiting(aServiceClass));
}
NS_IMETHODIMP
MobileConnectionRequestParent::NotifyGetClirStatusSuccess(uint16_t aN,
uint16_t aM)
@@ -133,6 +133,7 @@ struct ChangeCallBarringPasswordRequest
struct SetCallWaitingRequest
{
bool enabled;
uint16_t serviceClass;
};
struct GetCallWaitingRequest
@@ -52,6 +52,11 @@ struct MobileConnectionReplySuccessCallBarring
uint16_t serviceClass;
};
struct MobileConnectionReplySuccessCallWaiting
{
uint16_t serviceClass;
};
struct MobileConnectionReplySuccessClirStatus
{
uint16_t n;
@@ -82,6 +87,7 @@ union MobileConnectionReply
MobileConnectionReplySuccessNetworks;
MobileConnectionReplySuccessCallForwarding;
MobileConnectionReplySuccessCallBarring;
MobileConnectionReplySuccessCallWaiting;
MobileConnectionReplySuccessClirStatus;
MobileConnectionReplySuccessPreferredNetworkType;
MobileConnectionReplySuccessRoamingPreference;
+1
View File
@@ -27,6 +27,7 @@ XPIDL_SOURCES += [
'interfaces/nsIMobileCellInfo.idl',
'interfaces/nsIMobileConnectionInfo.idl',
'interfaces/nsIMobileConnectionService.idl',
'interfaces/nsIMobileDeviceIdentities.idl',
'interfaces/nsIMobileNetworkInfo.idl',
'interfaces/nsINeighboringCellInfo.idl',
]
@@ -640,6 +640,37 @@ function selectNetworkAutomaticallyAndWait() {
return request.then(null, () => { throw request.error });
}
/**
* Configures call waiting options.
*
* Fulfill params: (none)
* Reject params:
* 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter' or
* 'GenericFailure'.
*
* @return A deferred promise.
*/
function setCallWaitingOption(aEnabled) {
let request = mobileConnection.setCallWaitingOption(aEnabled);
return request.then(null, () => { throw request.error });
}
/**
* Queries current call waiting status.
*
* Fulfill params:
* A boolean indicating the call waiting status.
* Reject params:
* 'RadioNotAvailable', 'RequestNotSupported', 'InvalidParameter' or
* 'GenericFailure'.
*
* @return A deferred promise.
*/
function getCallWaitingOption() {
let request = mobileConnection.getCallWaitingOption();
return request.then(() => request.result, () => { throw request.error });
}
/**
* Set data connection enabling state and wait for "datachange" event.
*
@@ -15,9 +15,10 @@ qemu = true
[test_mobile_data_location.js]
[test_mobile_data_state.js]
[test_mobile_roaming_preference.js]
[test_call_barring_get_option.js]
[test_call_barring_get_error.js]
[test_call_barring_set_error.js]
[test_call_barring_change_password.js]
[test_call_waiting.js]
[test_mobile_set_radio.js]
[test_mobile_last_known_network.js]
[test_mobile_icc_change.js]
@@ -1,5 +1,5 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = "head.js";
@@ -1,5 +1,5 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = "head.js";
@@ -0,0 +1,29 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_HEAD_JS = "head.js";
// Start tests
startTestCommon(function() {
return Promise.resolve()
// TODO: Bug 1090811 - [B2G] support SET_CALL_WAITING and QUERY_CALL_WAITING
// Currently emulator doesn't support RIL_REQUEST_QUERY_CALL_WAITING and
// RIL_REQUEST_SET_CALL_WAITING, so we expect to get a 'RequestNotSupported'
// error here.
.then(() => setCallWaitingOption(true))
.then(() => {
ok(false, "setCallWaitingOption should not success");
}, aError => {
is(aError.name, "RequestNotSupported",
"failed to setCallWaitingOption");
})
.then(() => getCallWaitingOption())
.then(() => {
ok(false, "getCallWaitingOption should not success");
}, aError => {
is(aError.name, "RequestNotSupported",
"failed to getCallWaitingOption");
});
});
+3 -3
View File
@@ -6,14 +6,14 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
let WSP = {};
var WSP = {};
Cu.import("resource://gre/modules/WspPduHelper.jsm", WSP);
Cu.import("resource://gre/modules/mms_consts.js");
Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
let DEBUG; // set to true to see debug messages
var DEBUG; // set to true to see debug messages
this.MMS_VERSION = (function() {
Cu.import("resource://gre/modules/Services.jsm");
@@ -1660,7 +1660,7 @@ const MMS_WELL_KNOWN_PARAMS = (function() {
return params;
})();
let debug;
var debug;
if (DEBUG) {
debug = function(s) {
dump("-$- MmsPduHelper: " + s + "\n");
+4 -3
View File
@@ -17,7 +17,7 @@ Cu.import("resource://gre/modules/Promise.jsm");
const GONK_MMSSERVICE_CONTRACTID = "@mozilla.org/mms/gonkmmsservice;1";
const GONK_MMSSERVICE_CID = Components.ID("{9b069b8c-8697-11e4-a406-474f5190272b}");
let DEBUG = false;
var DEBUG = false;
function debug(s) {
dump("-@- MmsService: " + s + "\n");
};
@@ -1072,8 +1072,9 @@ CancellableTransaction.prototype = {
break;
}
case kSmsDeletedObserverTopic: {
if (subject && subject.deletedMessageIds &&
subject.deletedMessageIds.indexOf(this.cancellableId) >= 0) {
let deletedInfo = subject.QueryInterface(Ci.nsIDeletedMessageInfo);
if (deletedInfo && deletedInfo.deletedMessageIds &&
deletedInfo.deletedMessageIds.indexOf(this.cancellableId) >= 0) {
this.cancelRunning(_MMS_ERROR_MESSAGE_DELETED);
}
break;
@@ -9,7 +9,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
let MMDB = {};
var MMDB = {};
Cu.import("resource://gre/modules/MobileMessageDB.jsm", MMDB);
const GONK_MOBILEMESSAGEDATABASESERVICE_CONTRACTID =
+4 -5
View File
@@ -6,7 +6,7 @@
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
let RIL = {};
var RIL = {};
Cu.import("resource://gre/modules/ril_consts.js", RIL);
/**
@@ -122,10 +122,9 @@ this.SmsSegmentHelper = {
*
* |enabledGsmTableTuples|:
* List of tuples of national language identifier pairs.
* TODO: Support static/runtime settings, see bug 733331.
* |segmentRef16Bit|:
* Use 16-bit reference number for concatenated outgoint messages.
* TODO: Support static/runtime settings, see bug 733331.
* TODO: Support static/runtime settings, see bug 1019443.
*/
enabledGsmTableTuples: [
[RIL.PDU_NL_IDENTIFIER_DEFAULT, RIL.PDU_NL_IDENTIFIER_DEFAULT],
@@ -162,8 +161,8 @@ this.SmsSegmentHelper = {
if ((bodySeptets + headerSeptets) > segmentSeptets) {
headerLen += this.segmentRef16Bit ? 6 : 5;
headerSeptets = Math.ceil((headerLen + 1) * 8 / 7);
segmentSeptets -= headerSeptets;
}
segmentSeptets -= headerSeptets;
let segments = Math.ceil(bodySeptets / segmentSeptets);
let userDataSeptets = bodySeptets + headerSeptets * segments;
@@ -423,4 +422,4 @@ this.SmsSegmentHelper = {
}
};
this.EXPORTED_SYMBOLS = [ 'SmsSegmentHelper' ];
this.EXPORTED_SYMBOLS = [ 'SmsSegmentHelper' ];
+65 -23
View File
@@ -21,6 +21,7 @@ const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
const kPrefDefaultServiceId = "dom.sms.defaultServiceId";
const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
const kPrefLastKnownSimMcc = "ril.lastKnownSimMcc";
const kDiskSpaceWatcherObserverTopic = "disk-space-watcher";
@@ -56,6 +57,10 @@ XPCOMUtils.defineLazyGetter(this, "gRadioInterfaces", function() {
XPCOMUtils.defineLazyGetter(this, "gSmsSegmentHelper", function() {
let ns = {};
Cu.import("resource://gre/modules/SmsSegmentHelper.jsm", ns);
// Initialize enabledGsmTableTuples from current MCC.
ns.SmsSegmentHelper.enabledGsmTableTuples = getEnabledGsmTableTuplesFromMcc();
return ns.SmsSegmentHelper;
});
@@ -71,17 +76,17 @@ XPCOMUtils.defineLazyGetter(this, "gWAP", function() {
return ns;
});
XPCOMUtils.defineLazyGetter(this, "gSmsSendingSchedulars", function() {
XPCOMUtils.defineLazyGetter(this, "gSmsSendingSchedulers", function() {
return {
_schedulars: [],
getSchedularByServiceId: function(aServiceId) {
let schedular = this._schedulars[aServiceId];
if (!schedular) {
schedular = this._schedulars[aServiceId] =
new SmsSendingSchedular(aServiceId);
_schedulers: [],
getSchedulerByServiceId: function(aServiceId) {
let scheduler = this._schedulers[aServiceId];
if (!scheduler) {
scheduler = this._schedulers[aServiceId] =
new SmsSendingScheduler(aServiceId);
}
return schedular;
return scheduler;
}
};
});
@@ -120,6 +125,7 @@ function debug(s) {
}
function SmsService() {
this._updateDebugFlag();
this._silentNumbers = [];
this.smsDefaultServiceId = this._getDefaultServiceId();
@@ -131,6 +137,7 @@ function SmsService() {
Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
Services.prefs.addObserver(kPrefLastKnownSimMcc, this, false);
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
Services.obs.addObserver(this, kDiskSpaceWatcherObserverTopic, false);
}
@@ -331,11 +338,14 @@ SmsService.prototype = {
* Schedule the sending request.
*/
_scheduleSending: function(aServiceId, aDomMessage, aSilent, aOptions, aRequest) {
gSmsSendingSchedulars.getSchedularByServiceId(aServiceId)
gSmsSendingSchedulers.getSchedulerByServiceId(aServiceId)
.schedule({
messageId: aDomMessage.id,
onSend: () => {
if (DEBUG) debug("onSend: " + aDomMessage.id);
if (DEBUG) {
debug("onSend: messageId=" + aDomMessage.id +
", serviceId=" + aServiceId);
}
this._sendToTheAir(aServiceId,
aDomMessage,
aSilent,
@@ -1187,6 +1197,10 @@ SmsService.prototype = {
else if (aData === kPrefDefaultServiceId) {
this.smsDefaultServiceId = this._getDefaultServiceId();
}
else if ( aData === kPrefLastKnownSimMcc) {
gSmsSegmentHelper.enabledGsmTableTuples =
getEnabledGsmTableTuplesFromMcc();
}
break;
case kDiskSpaceWatcherObserverTopic:
if (DEBUG) {
@@ -1206,14 +1220,36 @@ SmsService.prototype = {
}
};
function SmsSendingSchedular(aServiceId) {
/**
* Get enabled GSM national language locking shift / single shift table pairs
* for current SIM MCC.
*
* @return a list of pairs of national language identifiers for locking shift
* table and single shfit table, respectively.
*/
function getEnabledGsmTableTuplesFromMcc() {
let mcc;
try {
mcc = Services.prefs.getCharPref(kPrefLastKnownSimMcc);
} catch (e) {}
let tuples = [[RIL.PDU_NL_IDENTIFIER_DEFAULT,
RIL.PDU_NL_IDENTIFIER_DEFAULT]];
let extraTuples = RIL.PDU_MCC_NL_TABLE_TUPLES_MAPPING[mcc];
if (extraTuples) {
tuples = tuples.concat(extraTuples);
}
return tuples;
};
function SmsSendingScheduler(aServiceId) {
this._serviceId = aServiceId;
this._queue = [];
Services.obs.addObserver(this, kSmsDeletedObserverTopic, false);
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
}
SmsSendingSchedular.prototype = {
SmsSendingScheduler.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionListener]),
_serviceId: 0,
@@ -1263,6 +1299,10 @@ SmsSendingSchedular.prototype = {
*/
schedule: function(aSendingRequest) {
if (aSendingRequest) {
if (DEBUG) {
debug("scheduling message: messageId=" + aSendingRequest.messageId +
", serviceId=" + this._serviceId);
}
this._ensureMoboConnObserverRegistration();
this._queue.push(aSendingRequest)
@@ -1281,7 +1321,7 @@ SmsSendingSchedular.prototype = {
*/
send: function() {
let connection =
gMobileConnectionService.getItemByServiceId(this._servicdeId);
gMobileConnectionService.getItemByServiceId(this._serviceId);
// If the voice connection is temporarily unavailable, pend the request.
let voiceInfo = connection && connection.voice;
@@ -1313,19 +1353,19 @@ SmsSendingSchedular.prototype = {
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case kSmsDeletedObserverTopic:
let deletedInfo = aSubject.QueryInterface(Ci.nsIDeletedMessageInfo);
if (DEBUG) {
debug("Observe " + kSmsDeletedObserverTopic + ": " +
JSON.stringify(aSubject));
JSON.stringify(deletedInfo));
}
if (aSubject && aSubject.deletedMessageIds) {
for (let id of aSubject.deletedMessageIds) {
for (let i = 0; i < this._queue.length; i++) {
if (this._queue[i].messageId === id) {
if (DEBUG) debug("Deleting message with id=" + id);
this._queue.splice(i, 1)[0].onCancel(
Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
}
if (deletedInfo && deletedInfo.deletedMessageIds) {
for (let i = 0; i < this._queue.length; i++) {
let id = this._queue[i].messageId;
if (deletedInfo.deletedMessageIds.includes(id)) {
if (DEBUG) debug("Deleting message with id=" + id);
this._queue.splice(i, 1)[0].onCancel(
Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
}
}
}
@@ -1370,7 +1410,9 @@ SmsSendingSchedular.prototype = {
notifyClirModeChanged: function(mode) {},
notifyLastKnownNetworkChanged: function() {},
notifyLastKnownHomeNetworkChanged: function() {},
notifyNetworkSelectionModeChanged: function() {}
notifyNetworkSelectionModeChanged: function() {},
notifyDeviceIdentitiesChanged: function() {}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SmsService]);
+2 -2
View File
@@ -9,7 +9,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.importGlobalProperties(['Blob']);
Cu.import("resource://gre/modules/wap_consts.js", this);
let DEBUG; // set to true to see debug messages
var DEBUG; // set to true to see debug messages
// Special ASCII characters
const NUL = 0;
@@ -2834,7 +2834,7 @@ this.OMNA_PUSH_APPLICATION_IDS = (function() {
return ids;
})();
let debug;
var debug;
if (DEBUG) {
debug = function(s) {
dump("-@- WspPduHelper: " + s + "\n");
@@ -10,7 +10,7 @@ interface nsIMobileMessageCallback : nsISupports
/**
* All SMS related errors.
* Make sure to keep this list in sync with the list in:
* embedding/android/GeckoSmsManager.java
* mobile/android/base/GeckoSmsManager.java
*/
const unsigned short SUCCESS_NO_ERROR = 0;
const unsigned short NO_SIGNAL_ERROR = 1;
-1
View File
@@ -200,7 +200,6 @@ SmsRequestChild::Recv__delete__(const MessageReply& aReply)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mReplyRequest);
nsCOMPtr<SmsMessage> message;
switch(aReply.type()) {
case MessageReply::TReplyMessageSend: {
const MobileMessageData& data =
+2 -2
View File
@@ -227,7 +227,7 @@ function sendMmsWithFailure(aMmsParameters, aSendParameters) {
/**
* Retrieve message by message id.
*
* Fulfill params: MozSmsMessage
* Fulfill params: SmsMessage
* Reject params:
* event -- a DOMEvent
*
@@ -476,7 +476,7 @@ function sendTextSmsToEmulator(aFrom, aText) {
/**
* Send simple text SMS to emulator and wait for a received event.
*
* Fulfill params: MozSmsMessage
* Fulfill params: SmsMessage
* Reject params: (none)
*
* @param aFrom
@@ -53,7 +53,7 @@ function saveMmsNotification() {
.saveReceivedMessage(notification, function(aRv, aDomMessage) {
log("saveReceivedMessage(): " + aRv);
if (Components.isSuccessCode(aRv)) {
deferred.resolve(aDomMessage);
deferred.resolve(aDomMessage.QueryInterface(Ci.nsIMmsMessage));
} else {
deferred.reject();
}
@@ -12,7 +12,7 @@ const LONG_BODY = new Array(17).join(SHORT_BODY);
ok(LONG_BODY.length > 160, "LONG_BODY.length");
function checkMessage(aMessage, aBody) {
ok(aMessage instanceof MozSmsMessage, "Message is instanceof MozSmsMessage");
ok(aMessage instanceof SmsMessage, "Message is instanceof SmsMessage");
is(aMessage.type, "sms", "message.type");
ok(aMessage.id, "message.id");
@@ -34,7 +34,7 @@ function sendSmsPduToEmulator(pdu) {
}
function checkMessage(message, id, threadId, messageClass) {
ok(message instanceof MozSmsMessage,
ok(message instanceof SmsMessage,
"message is instanceof " + message.constructor);
if (id == null) {
ok(message.id > 0, "message.id");
@@ -24,7 +24,7 @@ const LONG_BODY = "Let me not to the marriage of true minds\n"
function checkMessage(message, delivery, body) {
ok(message, "message is valid");
ok(message instanceof MozSmsMessage,
ok(message instanceof SmsMessage,
"message is instanceof " + message.constructor);
is(message.type, "sms", "message.type");
@@ -15,13 +15,14 @@
/** Test for WebSMS **/
// idl interfaces exposed to every page.
// TODO Bug 859764
const IDL_IFACE_WITH_PREFIX = ["SmsMessage", "MmsMessage", "MobileMessageThread"];
// webidl interfaces guarded by [AvailableIn=CertifiedApps].
const WEBIDL_IFACE_WITH_PREFIX = ["SmsEvent", "MmsEvent", "MessageDeletedEvent"];
const WEBIDL_IFACE = ["DOMMobileMessageError"];
const WEBIDL_IFACE = [
"DOMMobileMessageError",
"MmsMessage",
"MobileMessageThread",
"SmsMessage",
];
function checkSmsDisabled() {
ok(!('mozMobileMessage' in frames[0].navigator), "navigator.mozMobileMessage should not exist");
@@ -42,14 +43,6 @@ function checkSmsEnabled() {
"navigator.mozMobileMessage is an MobileMessageManager object");
}
function checkIdlInterfaceInWindow() {
for (let i = 0; i < IDL_IFACE_WITH_PREFIX.length; i++) {
let iface = IDL_IFACE_WITH_PREFIX[i];
ok(!(iface in window), iface + " should be prefixed");
ok(("Moz" + iface) in window, iface + " should be prefixed");
}
}
function checkWebidlInterfaceInWindow() {
for (let i = 0; i < WEBIDL_IFACE_WITH_PREFIX.length; i++) {
let iface = WEBIDL_IFACE_WITH_PREFIX[i];
@@ -77,7 +70,6 @@ function checkWebidlInterfaceNotInWindow() {
}
function test() {
checkIdlInterfaceInWindow();
checkWebidlInterfaceNotInWindow();
// If sms is disabled and permission is removed, sms is disabled.
@@ -34,7 +34,7 @@ function run_test() {
add_test(function test_interface() {
let sms = newMessage(null, null, ICC_ID, "sent", "success", null, null, null,
"normal", Date.now(), Date.now(), Date.now(), true);
do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
do_check_true(sms instanceof Ci.nsISmsMessage);
do_check_eq(sms.id, 0);
do_check_eq(sms.threadId, 0);
do_check_eq(sms.iccId, ICC_ID);
@@ -54,7 +54,7 @@ add_test(function test_interface() {
add_test(function test_icc_id_not_available() {
let sms = newMessage(null, null, null, "sent", "success", null, null, null,
"normal", Date.now(), Date.now(), Date.now(), true);
do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
do_check_true(sms instanceof Ci.nsISmsMessage);
do_check_eq(sms.id, 0);
do_check_eq(sms.threadId, 0);
do_check_eq(sms.iccId, null);
+17 -4
View File
@@ -231,9 +231,16 @@ PaymentProvider.prototype.removeSilentSmsObserver = function(aNumber, aCallback)
};
PaymentProvider.prototype._onSilentSms = function(aSubject, aTopic, aData) {
_debug && DEBUG("Got silent message! " + aSubject.sender + " - " + aSubject.body);
if (!aSubject || !(aSubject instanceof Ci.nsISmsMessage)) {
_debug && DEBUG("Invalid subject when receiving silent message!");
return;
}
let number = aSubject.sender;
let message = aSubject.QueryInterface(Ci.nsISmsMessage);
_debug && DEBUG("Got silent message! " + message.sender + " - " + message.body);
let number = message.sender;
if (!number || this._silentNumbers.indexOf(number) == -1) {
_debug && DEBUG("No observers for " + number);
return;
@@ -246,7 +253,7 @@ PaymentProvider.prototype._onSilentSms = function(aSubject, aTopic, aData) {
if (this._strategy.paymentServiceId === null) {
let i = 0;
while(i < gRil.numRadioInterfaces) {
if (this.iccInfo[i].iccId === aSubject.iccId) {
if (this.iccInfo[i].iccId === message.iccId) {
this._strategy.paymentServiceId = i;
break;
}
@@ -255,7 +262,13 @@ PaymentProvider.prototype._onSilentSms = function(aSubject, aTopic, aData) {
}
this._silentSmsObservers[number].forEach(function(callback) {
callback(aSubject);
callback({
iccId: message.iccId,
sender: message.sender,
body: message.body,
timestamp: message.timestamp,
sentTimestamp: message.sentTimestamp
});
});
};
File diff suppressed because it is too large Load Diff
+79 -67
View File
@@ -18,7 +18,9 @@
#include "mozilla/HalTypes.h"
#include "mozilla/Observer.h"
#include "mozilla/UniquePtr.h"
#include "nsAutoPtr.h"
#include "nsDataHashtable.h"
#include "nsIAudioManager.h"
#include "nsIObserver.h"
#include "android_audio/AudioSystem.h"
@@ -53,32 +55,7 @@ enum AudioOutputProfiles {
DEVICE_TOTAL_NUMBER = 3,
};
/**
* We have five sound volume settings from UX spec,
* You can see more informations in Bug1068219.
* (1) Media : music, video, FM ...
* (2) Notification : ringer, notification ...
* (3) Alarm : alarm
* (4) Telephony : GSM call, WebRTC call
* (5) Bluetooth SCO : SCO call
**/
enum AudioVolumeCategories {
VOLUME_MEDIA = 0,
VOLUME_NOTIFICATION = 1,
VOLUME_ALARM = 2,
VOLUME_TELEPHONY = 3,
VOLUME_BLUETOOTH_SCO = 4,
VOLUME_TOTAL_NUMBER = 5,
};
struct VolumeData {
const char* mChannelName;
uint32_t mCategory;
};
class RecoverTask;
class VolumeInitCallback;
class AudioProfileData;
class AudioManager final : public nsIAudioManager
, public nsIObserver
@@ -90,27 +67,66 @@ public:
NS_DECL_NSIAUDIOMANAGER
NS_DECL_NSIOBSERVER
// When audio backend is dead, recovery task needs to read all volume
// settings then set back into audio backend.
friend class RecoverTask;
friend class VolumeInitCallback;
// Open or close the specific profile
void SwitchProfileData(AudioOutputProfiles aProfile, bool aActive);
// Validate whether the volume index is within the range
nsresult ValidateVolumeIndex(uint32_t aCategory, uint32_t aIndex) const;
nsresult ValidateVolumeIndex(int32_t aStream, uint32_t aIndex) const;
// Called when android AudioFlinger in mediaserver is died
void HandleAudioFlingerDied();
void HandleHeadphoneSwitchEvent(const hal::SwitchEvent& aEvent);
class VolumeStreamState {
public:
explicit VolumeStreamState(AudioManager& aManager, int32_t aStreamType);
int32_t GetStreamType()
{
return mStreamType;
}
bool IsDevicesChanged(bool aFromCache = true);
void ClearDevicesChanged();
uint32_t GetLastDevices()
{
return mLastDevices;
}
bool IsVolumeIndexesChanged();
void ClearVolumeIndexesChanged();
void InitStreamVolume();
uint32_t GetMaxIndex();
uint32_t GetDefaultIndex();
uint32_t GetVolumeIndex();
uint32_t GetVolumeIndex(uint32_t aDevice);
void ClearCurrentVolumeUpdated();
// Set volume index to all active devices.
// Active devices are chosen by android AudioPolicyManager.
nsresult SetVolumeIndexToActiveDevices(uint32_t aIndex);
// Set volume index to all alias streams. Alias streams have same volume.
// It is used to update volume based on audio output profile data.
nsresult SetVolumeIndexToAliasStreams(uint32_t aIndex, uint32_t aDevice);
// Set volume index to all alias devices in audio output profile.
// Alias devices have same volume.
nsresult SetVolumeIndexToAliasDevices(uint32_t aIndex, uint32_t aDevice);
nsresult SetVolumeIndex(uint32_t aIndex, uint32_t aDevice, bool aUpdateCache = true);
// Restore volume index to all devices. Called when AudioFlinger is restarted.
void RestoreVolumeIndexToAllDevices();
private:
AudioManager& mManager;
const int32_t mStreamType;
uint32_t mLastDevices;
bool mIsDevicesChanged;
bool mIsVolumeIndexesChanged;
nsDataHashtable<nsUint32HashKey, uint32_t> mVolumeIndexes;
};
protected:
int32_t mPhoneState;
// A bitwise variable for recording what kind of headset/headphone is attached.
int32_t mHeadsetState;
bool mIsVolumeInited;
// A bitwise variable for volume update of audio output profiles
uint32_t mAudioOutProfileUpdated;
// Connected devices that are controlled by setDeviceConnectionState()
nsDataHashtable<nsUint32HashKey, nsCString> mConnectedDevices;
bool mSwitchDone;
@@ -120,11 +136,23 @@ protected:
#ifdef MOZ_B2G_BT
bool mA2dpSwitchDone;
#endif
uint32_t mCurrentStreamVolumeTbl[AUDIO_STREAM_CNT];
nsTArray<UniquePtr<VolumeStreamState> > mStreamStates;
uint32_t mLastChannelVolume[AUDIO_STREAM_CNT];
bool IsFmOutConnected();
nsresult SetStreamVolumeForProfile(AudioOutputProfiles aProfile,
int32_t aStream,
uint32_t aIndex);
nsresult SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex);
nsresult GetStreamVolumeIndex(int32_t aStream, uint32_t *aIndex);
void UpdateCachedActiveDevicesForStreams();
uint32_t GetDevicesForStream(int32_t aStream, bool aFromCache = true);
uint32_t GetDeviceForStream(int32_t aStream);
// Choose one device as representative of active devices.
static uint32_t SelectDeviceFromDevices(uint32_t aOutDevices);
private:
nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
#ifdef MOZ_B2G_RIL
@@ -132,57 +160,41 @@ private:
// mIsMicMuted is only used for toggling mute call to RIL.
bool mIsMicMuted;
#endif
nsTArray<nsAutoPtr<AudioProfileData>> mAudioProfiles;
AudioOutputProfiles mPresentProfile;
void HandleBluetoothStatusChanged(nsISupports* aSubject,
const char* aTopic,
const nsCString aAddress);
void HandleAudioChannelProcessChanged();
void CreateAudioProfilesData();
// Initialize volume index for audio output profile
void InitVolumeForProfile(AudioOutputProfiles aProfile,
int32_t aStreamType,
uint32_t aIndex);
// Init the volume setting from the init setting callback
void InitProfileVolume(AudioOutputProfiles aProfile,
uint32_t aCatogory, uint32_t aIndex);
// Update volume data of profiles
void UpdateVolumeToProfile(AudioProfileData* aProfileData);
// Apply the volume data to device
void UpdateVolumeFromProfile(AudioProfileData* aProfileData);
// Send the volume changing event to Gaia
void SendVolumeChangeNotification(AudioProfileData* aProfileData);
// Update the mPresentProfile and profiles active status
void UpdateProfileState(AudioOutputProfiles aProfile, bool aActive);
// Volume control functions
nsresult SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex);
uint32_t GetVolumeByCategory(uint32_t aCategory) const;
uint32_t GetMaxVolumeByCategory(uint32_t aCategory) const;
AudioProfileData* FindAudioProfileData(AudioOutputProfiles aProfile);
// Append the profile to the volume setting string.
// Append the audio output profile to the volume setting string.
nsAutoCString AppendProfileToVolumeSetting(const char* aName,
AudioOutputProfiles aProfile);
// We store the volume setting in the database, these are related functions.
void InitVolumeFromDatabase();
void UpdateVolumeSettingToDatabase(nsISettingsServiceLock* aLock,
const char* aTopic,
uint32_t aVolIndex);
void MaybeUpdateVolumeSettingToDatabase(bool aForce = false);
// Promise functions.
void InitProfileVolumeSucceeded();
void InitProfileVolumeFailed(const char* aError);
void AudioOutProfileUpdated(AudioOutputProfiles aProfile);
void UpdateHeadsetConnectionState(hal::SwitchState aState);
void UpdateDeviceConnectionState(bool aIsConnected, uint32_t aDevice, const nsCString& aDeviceName);
void SetAllDeviceConnectionStates();
AudioManager();
~AudioManager();
friend class VolumeInitCallback;
friend class VolumeStreamState;
friend class GonkAudioPortCallback;
};
} /* namespace gonk */
+3 -1
View File
@@ -71,7 +71,9 @@ DataCall.prototype = {
ifname: null,
addreses: null,
dnses: null,
gateways: null
gateways: null,
pcscf: null,
mtu: -1
};
function DataCallInterfaceService() {
+38 -3
View File
@@ -941,7 +941,9 @@ DataCallHandler.prototype = {
notifyLastKnownHomeNetworkChanged: function() {},
notifyNetworkSelectionModeChanged: function() {}
notifyNetworkSelectionModeChanged: function() {},
notifyDeviceIdentitiesChanged: function() {}
};
function DataCall(aClientId, aApnSetting, aDataCallHandler) {
@@ -960,7 +962,9 @@ function DataCall(aClientId, aApnSetting, aDataCallHandler) {
ifname: null,
addresses: [],
dnses: [],
gateways: []
gateways: [],
pcscf: [],
mtu: null
};
this.state = NETWORK_STATE_UNKNOWN;
this.requestedNetworkIfaces = [];
@@ -1026,6 +1030,10 @@ DataCall.prototype = {
}
}
if (aCurrentDataCall.mtu != aUpdatedDataCall.mtu) {
return "changed";
}
return "identical";
},
@@ -1091,6 +1099,8 @@ DataCall.prototype = {
this.linkInfo.addresses = aDataCall.addresses ? aDataCall.addresses.split(" ") : [];
this.linkInfo.gateways = aDataCall.gateways ? aDataCall.gateways.split(" ") : [];
this.linkInfo.dnses = aDataCall.dnses ? aDataCall.dnses.split(" ") : [];
this.linkInfo.pcscf = aDataCall.pcscf ? aDataCall.pcscf.split(" ") : [];
this.linkInfo.mtu = aDataCall.mtu > 0 ? aDataCall.mtu : 0;
this.state = this._getGeckoDataCallState(aDataCall);
// Notify DataCallHandler about data call connected.
@@ -1143,7 +1153,9 @@ DataCall.prototype = {
ifname: aUpdatedDataCall.ifname,
addresses: aUpdatedDataCall.addresses ? aUpdatedDataCall.addresses.split(" ") : [],
dnses: aUpdatedDataCall.dnses ? aUpdatedDataCall.dnses.split(" ") : [],
gateways: aUpdatedDataCall.gateways ? aUpdatedDataCall.gateways.split(" ") : []
gateways: aUpdatedDataCall.gateways ? aUpdatedDataCall.gateways.split(" ") : [],
pcscf: aUpdatedDataCall.pcscf ? aUpdatedDataCall.pcscf.split(" ") : [],
mtu: aUpdatedDataCall.mtu > 0 ? aUpdatedDataCall.mtu : 0
};
switch (dataCallState) {
@@ -1169,6 +1181,8 @@ DataCall.prototype = {
this.linkInfo.addresses = newLinkInfo.addresses.slice();
this.linkInfo.gateways = newLinkInfo.gateways.slice();
this.linkInfo.dnses = newLinkInfo.dnses.slice();
this.linkInfo.pcscf = newLinkInfo.pcscf.slice();
this.linkInfo.mtu = newLinkInfo.mtu;
}
break;
case NETWORK_STATE_DISCONNECTED:
@@ -1267,6 +1281,8 @@ DataCall.prototype = {
this.linkInfo.addresses = [];
this.linkInfo.dnses = [];
this.linkInfo.gateways = [];
this.linkInfo.pcscf = [];
this.linkInfo.mtu = null;
},
reset: function() {
@@ -1604,6 +1620,20 @@ RILNetworkInfo.prototype = {
// See http://www.iana.org/assignments/port-numbers
return this.getApnSetting().mmsport || -1;
},
getPcscf: function(aCount) {
if (this.type != NETWORK_TYPE_MOBILE_IMS) {
if (DEBUG) this.debug("Error! Only IMS network can get pcscf.");
throw Cr.NS_ERROR_UNEXPECTED;
}
let linkInfo = this.getDataCall().linkInfo;
if (aCount) {
aCount.value = linkInfo.pcscf.length;
}
return linkInfo.pcscf.slice();
},
};
function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) {
@@ -1647,6 +1677,11 @@ RILNetworkInterface.prototype = {
return this.apnSetting.port || "";
},
get mtu() {
// Value provided by network has higher priority than apn settings.
return this.dataCall.linkInfo.mtu || this.apnSetting.mtu || -1;
},
// Helpers
debug: function(aMsg) {
+21 -24
View File
@@ -30,26 +30,11 @@ XPCOMUtils.defineLazyGetter(this, "RIL", function () {
return obj;
});
// Ril quirk to attach data registration on demand.
let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND =
libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true";
// Ril quirk to control the uicc/data subscription.
let RILQUIRKS_SUBSCRIPTION_CONTROL =
libcutils.property_get("ro.moz.ril.subscription_control", "false") == "true";
// Ril quirk to always turn the radio off for the client without SIM card
// except hw default client.
var RILQUIRKS_RADIO_OFF_WO_CARD =
libcutils.property_get("ro.moz.ril.radio_off_wo_card", "false") == "true";
// Ril quirk to enable IPv6 protocol/roaming protocol in APN settings.
let RILQUIRKS_HAVE_IPV6 =
libcutils.property_get("ro.moz.ril.ipv6", "false") == "true";
let RILQUIRKS_SIGNAL_EXTRA_INT32 =
libcutils.property_get("ro.moz.ril.signal_extra_int", "false") == "true";
const RADIOINTERFACELAYER_CID =
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
const RADIOINTERFACE_CID =
@@ -407,7 +392,9 @@ DataCall.prototype = {
ifname: null,
addreses: null,
dnses: null,
gateways: null
gateways: null,
pcscf: null,
mtu: -1
};
function RadioInterfaceLayer() {
@@ -522,23 +509,26 @@ WorkerMessenger.prototype = {
quirks: {
callstateExtraUint32:
libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
v5Legacy:
libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true",
requestUseDialEmergencyCall:
libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
simAppStateExtraFields:
libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true",
extraUint2ndCall:
libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") == "true",
libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") === "true",
haveQueryIccLockRetryCount:
libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true",
libcutils.property_get("ro.moz.ril.query_icc_count", "false") === "true",
sendStkProfileDownload:
libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") === "true",
smscAddressFormat:
libcutils.property_get("ro.moz.ril.smsc_address_format", "text"),
dataRegistrationOnDemand: RILQUIRKS_DATA_REGISTRATION_ON_DEMAND,
subscriptionControl: RILQUIRKS_SUBSCRIPTION_CONTROL,
signalExtraInt: RILQUIRKS_SIGNAL_EXTRA_INT32
dataRegistrationOnDemand:
libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") === "true",
subscriptionControl:
libcutils.property_get("ro.moz.ril.subscription_control", "false") === "true",
signalExtraInt:
libcutils.property_get("ro.moz.ril.signal_extra_int", "false") === "true",
availableNetworkExtraStr:
libcutils.property_get("ro.moz.ril.avlbl_nw_extra_str", "false") === "true",
}
};
@@ -778,6 +768,13 @@ RadioInterface.prototype = {
case "otastatuschange":
gMobileConnectionService.notifyOtaStatusChanged(this.clientId, message.status);
break;
case "deviceidentitieschange":
gMobileConnectionService.notifyDeviceIdentitiesChanged(this.clientId,
message.deviceIdentities.imei,
message.deviceIdentities.imeisv,
message.deviceIdentities.esn,
message.deviceIdentities.meid);
break;
case "radiostatechange":
// gRadioEnabledController should know the radio state for each client,
// so notify gRadioEnabledController here.
+24 -3
View File
@@ -112,11 +112,33 @@ Volume::Dump(const char* aLabel) const
: (IsUnmounting() ? "y" : "n"));
}
void
Volume::ResolveAndSetMountPoint(const nsCSubstring& aMountPoint)
{
nsCString mountPoint(aMountPoint);
char realPathBuf[PATH_MAX];
// Call realpath so that we wind up with a path which is compatible with
// functions like nsVolumeService::GetVolumeByPath.
if (realpath(mountPoint.get(), realPathBuf) < 0) {
// The path we were handed doesn't exist. Warn about it, but use it
// anyways assuming that the user knows what they're doing.
ERR("ResolveAndSetMountPoint: realpath on '%s' failed: %d",
mountPoint.get(), errno);
mMountPoint = mountPoint;
} else {
mMountPoint = realPathBuf;
}
DBG("Volume %s: Setting mountpoint to '%s'", NameStr(), mMountPoint.get());
}
void Volume::SetFakeVolume(const nsACString& aMountPoint)
{
this->mMountLocked = false;
this->mCanBeShared = false;
this->mMountPoint = aMountPoint;
ResolveAndSetMountPoint(aMountPoint);
SetState(nsIVolume::STATE_MOUNTED);
}
@@ -386,8 +408,7 @@ Volume::SetMountPoint(const nsCSubstring& aMountPoint)
if (mMountPoint.Equals(aMountPoint)) {
return;
}
mMountPoint = aMountPoint;
DBG("Volume %s: Setting mountpoint to '%s'", NameStr(), mMountPoint.get());
ResolveAndSetMountPoint(aMountPoint);
}
void
+2
View File
@@ -119,6 +119,8 @@ private:
void SetMountPoint(const nsCSubstring& aMountPoint);
void StartCommand(VolumeCommand* aCommand);
void ResolveAndSetMountPoint(const nsCSubstring& aMountPoint);
bool BoolConfigValue(const nsCString& aConfigValue, bool& aBoolValue);
void SetConfig(const nsCString& aConfigName, const nsCString& aConfigValue);
+32
View File
@@ -156,6 +156,27 @@ VolumeManager::FindAddVolumeByName(const nsCSubstring& aName)
return vol.forget();
}
//static
bool
VolumeManager::RemoveVolumeByName(const nsCSubstring& aName)
{
if (!sVolumeManager) {
return false;
}
VolumeArray::size_type numVolumes = NumVolumes();
VolumeArray::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<Volume> vol = GetVolume(volIndex);
if (vol->Name().Equals(aName)) {
sVolumeManager->mVolumeArray.RemoveElementAt(volIndex);
return true;
}
}
// No volume found. Return false to indicate this.
return false;
}
//static
void VolumeManager::InitConfig()
{
@@ -236,6 +257,17 @@ void VolumeManager::InitConfig()
}
continue;
}
if (command.EqualsLiteral("ignore")) {
// This command is useful to remove volumes which are being tracked by
// vold, but for which we have no interest.
if (!tokenizer.hasMoreTokens()) {
ERR("No vol_name in %s line %d", filename, n);
continue;
}
nsCString volName(tokenizer.nextToken());
RemoveVolumeByName(volName);
continue;
}
ERR("Unrecognized command: '%s'", command.get());
}
}
+1
View File
@@ -128,6 +128,7 @@ public:
static already_AddRefed<Volume> GetVolume(VolumeArray::index_type aIndex);
static already_AddRefed<Volume> FindVolumeByName(const nsCSubstring& aName);
static already_AddRefed<Volume> FindAddVolumeByName(const nsCSubstring& aName);
static bool RemoveVolumeByName(const nsCSubstring& aName);
static void InitConfig();
static void PostCommand(VolumeCommand* aCommand);
@@ -969,6 +969,9 @@ public:
static status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index);
static uint32_t getStrategyForStream(stream_type stream);
#if ANDROID_VERSION >= 17
static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
#endif
static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
static status_t registerEffect(effect_descriptor_t *desc,
@@ -995,6 +998,23 @@ public:
static bool isLinearPCM(uint32_t format);
static bool isModeInCall();
#if ANDROID_VERSION >= 21
class AudioPortCallback : public RefBase
{
public:
AudioPortCallback() {}
virtual ~AudioPortCallback() {}
virtual void onAudioPortListUpdate() = 0;
virtual void onAudioPatchListUpdate() = 0;
virtual void onServiceDied() = 0;
};
static void setAudioPortCallback(sp<AudioPortCallback> callBack);
#endif
private:
class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
@@ -4,7 +4,7 @@
#include "nsISupports.idl"
[scriptable, uuid(d27ce247-9c7c-4582-826b-125e8275e9c2)]
[scriptable, uuid(6b66446a-7000-438f-8e1b-b56b4cbf4fa9)]
interface nsIDataCall : nsISupports
{
/**
@@ -55,6 +55,17 @@ interface nsIDataCall : nsISupports
* A space-delimited list of default gateway addresses.
*/
readonly attribute DOMString gateways;
/**
* A space-delimited list of Proxy Call State Control Function addresses for
* IMS client.
*/
readonly attribute DOMString pcscf;
/**
* MTU received from network, -1 if not set or invalid.
*/
readonly attribute long mtu;
};
[scriptable, uuid(e119c54b-9354-4ad6-a1ee-18608bde9320)]
+12 -1
View File
@@ -5,7 +5,7 @@
#include "nsISupports.idl"
#include "nsINetworkInterface.idl"
[scriptable, uuid(501b7041-0754-4ddb-9174-946e2c2ebd83)]
[scriptable, uuid(b8bcd6aa-5b06-4362-a68c-317878429e51)]
interface nsIRilNetworkInfo : nsINetworkInfo
{
readonly attribute unsigned long serviceId;
@@ -15,6 +15,17 @@ interface nsIRilNetworkInfo : nsINetworkInfo
readonly attribute DOMString mmsc; // Empty string if not set.
readonly attribute DOMString mmsProxy; // Empty string if not set.
readonly attribute long mmsPort; // -1 if not set.
/**
* Get the list of pcscf addresses, could be IPv4 or IPv6.
*
* @param count
* The length of the list of pcscf addresses.
*
* @returns the list of pcscf addresses.
*/
void getPcscf([optional] out unsigned long count,
[array, size_is(count), retval] out wstring pcscf);
};
[scriptable, function, uuid(cb2f0f5b-67f4-4c14-93e8-01e66b630464)]
+25 -21
View File
@@ -66,6 +66,22 @@ nsVolume::nsVolume(const Volume* aVolume)
{
}
nsVolume::nsVolume(const nsVolume* aVolume)
: mName(aVolume->mName),
mMountPoint(aVolume->mMountPoint),
mState(aVolume->mState),
mMountGeneration(aVolume->mMountGeneration),
mMountLocked(aVolume->mMountLocked),
mIsFake(aVolume->mIsFake),
mIsMediaPresent(aVolume->mIsMediaPresent),
mIsSharing(aVolume->mIsSharing),
mIsFormatting(aVolume->mIsFormatting),
mIsUnmounting(aVolume->mIsUnmounting),
mIsRemovable(aVolume->mIsRemovable),
mIsHotSwappable(aVolume->mIsHotSwappable)
{
}
void nsVolume::Dump(const char* aLabel) const
{
LOG("%s: Volume: %s is %s and %s @ %s gen %d locked %d",
@@ -333,40 +349,28 @@ nsVolume::LogState() const
LOG("nsVolume: %s state %s", NameStr().get(), StateStr());
}
void nsVolume::Set(nsIVolume* aVolume)
void nsVolume::UpdateMountLock(nsVolume* aOldVolume)
{
MOZ_ASSERT(NS_IsMainThread());
aVolume->GetName(mName);
aVolume->GetMountPoint(mMountPoint);
aVolume->GetState(&mState);
aVolume->GetIsFake(&mIsFake);
aVolume->GetIsMediaPresent(&mIsMediaPresent);
aVolume->GetIsSharing(&mIsSharing);
aVolume->GetIsFormatting(&mIsFormatting);
aVolume->GetIsUnmounting(&mIsUnmounting);
aVolume->GetIsRemovable(&mIsRemovable);
aVolume->GetIsHotSwappable(&mIsHotSwappable);
int32_t volMountGeneration;
aVolume->GetMountGeneration(&volMountGeneration);
bool oldMountLocked = aOldVolume ? aOldVolume->mMountLocked : false;
if (mState != nsIVolume::STATE_MOUNTED) {
// Since we're not in the mounted state, we need to
// forgot whatever mount generation we may have had.
mMountGeneration = -1;
return;
}
if (mMountGeneration == volMountGeneration) {
// No change in mount generation, nothing else to do
mMountLocked = oldMountLocked;
return;
}
mMountGeneration = volMountGeneration;
int32_t oldMountGeneration = aOldVolume ? aOldVolume->mMountGeneration : -1;
if (mMountGeneration == oldMountGeneration) {
// No change in mount generation, nothing else to do
mMountLocked = oldMountLocked;
return;
}
if (!XRE_IsParentProcess()) {
// Child processes just track the state, not maintain it.
aVolume->GetIsMountLocked(&mMountLocked);
return;
}
+4 -18
View File
@@ -24,6 +24,9 @@ public:
// This constructor is used by the UpdateVolumeRunnable constructor
nsVolume(const Volume* aVolume);
// This constructor is used by nsVolumeService::SetFakeVolumeState
nsVolume(const nsVolume* aVolume);
// This constructor is used by ContentChild::RecvFileSystemUpdate which is
// used to update the volume cache maintained in the child process.
nsVolume(const nsAString& aName, const nsAString& aMountPoint,
@@ -47,25 +50,8 @@ public:
{
}
// This constructor is used by nsVolumeService::FindAddVolumeByName, and
// will be followed shortly by a Set call.
nsVolume(const nsAString& aName)
: mName(aName),
mState(STATE_INIT),
mMountGeneration(-1),
mMountLocked(true), // Needs to agree with Volume::Volume
mIsFake(false),
mIsMediaPresent(false),
mIsSharing(false),
mIsFormatting(false),
mIsUnmounting(false),
mIsRemovable(false),
mIsHotSwappable(false)
{
}
bool Equals(nsIVolume* aVolume);
void Set(nsIVolume* aVolume);
void UpdateMountLock(nsVolume* aOldVolume);
void LogState() const;
+28 -48
View File
@@ -368,7 +368,7 @@ nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
}
already_AddRefed<nsVolume>
nsVolumeService::FindVolumeByName(const nsAString& aName)
nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex)
{
mArrayMonitor.AssertCurrentThreadOwns();
@@ -377,52 +377,35 @@ nsVolumeService::FindVolumeByName(const nsAString& aName)
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<nsVolume> vol = mVolumeArray[volIndex];
if (vol->Name().Equals(aName)) {
if (aIndex) {
*aIndex = volIndex;
}
return vol.forget();
}
}
return nullptr;
}
//static
already_AddRefed<nsVolume>
nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake /*= false*/)
{
MonitorAutoLock autoLock(mArrayMonitor);
RefPtr<nsVolume> vol;
vol = FindVolumeByName(aName);
if (vol) {
return vol.forget();
}
// Volume not found - add a new one
vol = new nsVolume(aName);
vol->SetIsFake(aIsFake);
mVolumeArray.AppendElement(vol);
return vol.forget();
}
void
nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
{
MOZ_ASSERT(NS_IsMainThread());
nsString volName;
aVolume->GetName(volName);
bool aIsFake;
aVolume->GetIsFake(&aIsFake);
RefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName, aIsFake);
if (vol->Equals(aVolume)) {
// Nothing has really changed. Don't bother telling anybody.
return;
{
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::index_type volIndex;
RefPtr<nsVolume> vol = FindVolumeByName(aVolume->Name(), &volIndex);
if (!vol) {
mVolumeArray.AppendElement(aVolume);
} else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) {
// Ignore if nothing changed or if a fake tries to override a real volume.
return;
} else {
mVolumeArray.ReplaceElementAt(volIndex, aVolume);
}
aVolume->UpdateMountLock(vol);
}
if (!vol->IsFake() && aIsFake) {
// Prevent an incoming fake volume from overriding an existing real volume.
return;
}
vol->Set(aVolume);
if (!aNotifyObservers) {
return;
}
@@ -431,8 +414,8 @@ nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
if (!obs) {
return;
}
NS_ConvertUTF8toUTF16 stateStr(vol->StateStr());
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr());
obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get());
}
NS_IMETHODIMP
@@ -471,11 +454,8 @@ nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
return NS_ERROR_NOT_AVAILABLE;
}
// UpdateVolume expects the volume passed in to NOT be the
// same pointer as what CreateOrFindVolumeByName would return,
// which is why we allocate a temporary volume here.
RefPtr<nsVolume> volume = new nsVolume(name);
volume->Set(vol);
// Clone the existing volume so we can replace it
RefPtr<nsVolume> volume = new nsVolume(vol);
volume->SetState(state);
volume->LogState();
UpdateVolume(volume.get());
@@ -502,15 +482,15 @@ nsVolumeService::RemoveFakeVolume(const nsAString& name)
void
nsVolumeService::RemoveVolumeByName(const nsAString& aName)
{
RefPtr<nsVolume> vol;
{
MonitorAutoLock autoLock(mArrayMonitor);
vol = FindVolumeByName(aName);
nsVolume::Array::index_type volIndex;
RefPtr<nsVolume> vol = FindVolumeByName(aName, &volIndex);
if (!vol) {
return;
}
mVolumeArray.RemoveElementAt(volIndex);
}
if (!vol) {
return;
}
mVolumeArray.RemoveElement(vol);
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = GetObserverService();
+4 -3
View File
@@ -47,7 +47,7 @@ public:
void DumpNoLock(const char* aLabel);
// To use this function, you have to create a new volume and pass it in.
void UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers = true);
void UpdateVolume(nsVolume* aVolume, bool aNotifyObservers = true);
void UpdateVolumeIOThread(const Volume* aVolume);
void RecvVolumesFromParent(const nsTArray<dom::VolumeInfo>& aVolumes);
@@ -61,8 +61,9 @@ private:
void CheckMountLock(const nsAString& aMountLockName,
const nsAString& aMountLockState);
already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake = false);
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName,
nsVolume::Array::index_type* aIndex = nullptr);
Monitor mArrayMonitor;
nsVolume::Array mVolumeArray;
+24 -158
View File
@@ -278,17 +278,7 @@ this.SMS_RETRY_MAX = 3;
this.RADIO_STATE_OFF = 0;
this.RADIO_STATE_UNAVAILABLE = 1;
this.RADIO_STATE_ON = 10; // RIL v7
// RIL v5 legacy constants:
this.RADIO_STATE_SIM_NOT_READY = 2;
this.RADIO_STATE_SIM_LOCKED_OR_ABSENT = 3;
this.RADIO_STATE_SIM_READY = 4;
this.RADIO_STATE_RUIM_NOT_READY = 5;
this.RADIO_STATE_RUIM_READY = 6;
this.RADIO_STATE_RUIM_LOCKED_OR_ABSENT = 7;
this.RADIO_STATE_NV_NOT_READY = 8;
this.RADIO_STATE_NV_READY = 9;
this.RADIO_STATE_ON = 10; // since RIL v7
this.CARD_STATE_ABSENT = 0;
this.CARD_STATE_PRESENT = 1;
@@ -582,6 +572,12 @@ this.ADN_MAX_BCD_NUMBER_BYTES = 11;
// Maximum digits of the Dialling Number in ADN.
// See TS 151.011 clause 10.5.1 EF_ADN, 'Dialling Number'.
this.ADN_MAX_NUMBER_DIGITS = 20;
// Maximum size of BCD numbers in EXT.
// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
this.EXT_MAX_BCD_NUMBER_BYTES = 10;
// Maximum digits of the Dialling Number in EXT.
// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
this.EXT_MAX_NUMBER_DIGITS = 20;
// READ_RECORD mode, TS 102.221
this.READ_RECORD_ABSOLUTE_MODE = 4;
@@ -1270,10 +1266,13 @@ this.GECKO_ICC_SERVICES = {
FDN: 3,
PLMNSEL: 7,
MSISDN: 9,
EXT1: 10,
EXT2: 11,
CBMI: 14,
GID1: 15,
SPN: 17,
SDN: 18,
EXT3: 19,
DATA_DOWNLOAD_SMS_CB: 25,
DATA_DOWNLOAD_SMS_PP: 26,
CBMIR: 30,
@@ -1288,7 +1287,9 @@ this.GECKO_ICC_SERVICES = {
// @see 3GPP TS 31.102 4.2.8 (USIM).
usim: {
FDN: 2,
EXT2: 3,
SDN: 4,
EXT3: 5,
BDN: 6,
CBMI: 15,
CBMIR: 16,
@@ -1308,8 +1309,11 @@ this.GECKO_ICC_SERVICES = {
ruim: {
FDN: 3,
ENHANCED_PHONEBOOK: 6,
EXT1: 10,
EXT2: 11,
SPN: 17,
SDN: 18
SDN: 18,
EXT3: 19,
},
// @see B.3.1.1 CPHS Information in CPHS Phase 2:
// Indicates which of the CPHS 'optional' data-fields are present in the SIM card:
@@ -1419,7 +1423,8 @@ this.CALLED_PARTY_BCD_NPI_PRIVATE = 9;
/**
* Array of number plan identification values which can be used to map an
* enumeration to the corresponding value.
* enumeration to the corresponding value. The indices should be consistent
* with nsISmsService::NUMBER_PLAN_IDENTIFICATION_* constants.
*/
this.CALLED_PARTY_BCD_NPI = [
CALLED_PARTY_BCD_NPI_UNKNOWN,
@@ -2970,6 +2975,9 @@ this.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL = 1;
this.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME = 2;
this.CALL_BARRING_PROGRAM_ALL_INCOMING = 3;
this.CALL_BARRING_PROGRAM_INCOMING_ROAMING = 4;
this.CALL_BARRING_PROGRAM_ALL_SERVICE = 5;
this.CALL_BARRING_PROGRAM_OUTGOING_SERVICE = 6;
this.CALL_BARRING_PROGRAM_INCOMING_SERVICE = 7;
this.CALL_BARRING_PROGRAM_TO_FACILITY = {};
CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_OUTGOING] = ICC_CB_FACILITY_BAOC;
@@ -2977,152 +2985,10 @@ CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL] =
CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME] = ICC_CB_FACILITY_BAOICxH;
CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_INCOMING] = ICC_CB_FACILITY_BAIC;
CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_INCOMING_ROAMING] = ICC_CB_FACILITY_BAICr;
CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_ALL_SERVICE] = ICC_CB_FACILITY_BA_ALL;
CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_OUTGOING_SERVICE] = ICC_CB_FACILITY_BA_MO;
CALL_BARRING_PROGRAM_TO_FACILITY[CALL_BARRING_PROGRAM_INCOMING_SERVICE] = ICC_CB_FACILITY_BA_MT;
// CLIR constants. Must be in sync with nsIMobileConnectionService interface
this.CLIR_DEFAULT = 0;
this.CLIR_INVOCATION = 1;
this.CLIR_SUPPRESSION = 2;
// MMI procedure as defined in TS.22.030 6.5.2
this.MMI_PROCEDURE_ACTIVATION = "*";
this.MMI_PROCEDURE_DEACTIVATION = "#";
this.MMI_PROCEDURE_INTERROGATION = "*#";
this.MMI_PROCEDURE_REGISTRATION = "**";
this.MMI_PROCEDURE_ERASURE = "##";
this.MMI_PROC_TO_CF_ACTION = {};
MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_ACTIVATION] = CALL_FORWARD_ACTION_ENABLE;
MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_DEACTIVATION] = CALL_FORWARD_ACTION_DISABLE;
MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_INTERROGATION] = CALL_FORWARD_ACTION_QUERY_STATUS;
MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_REGISTRATION] = CALL_FORWARD_ACTION_REGISTRATION;
MMI_PROC_TO_CF_ACTION[MMI_PROCEDURE_ERASURE] = CALL_FORWARD_ACTION_ERASURE;
// MMI call forwarding service codes as defined in TS.22.030 Annex B
this.MMI_SC_CFU = "21";
this.MMI_SC_CF_BUSY = "67";
this.MMI_SC_CF_NO_REPLY = "61";
this.MMI_SC_CF_NOT_REACHABLE = "62";
this.MMI_SC_CF_ALL = "002";
this.MMI_SC_CF_ALL_CONDITIONAL = "004";
this.MMI_SC_TO_CF_REASON = {};
MMI_SC_TO_CF_REASON[MMI_SC_CFU] = CALL_FORWARD_REASON_UNCONDITIONAL;
MMI_SC_TO_CF_REASON[MMI_SC_CF_BUSY] = CALL_FORWARD_REASON_MOBILE_BUSY;
MMI_SC_TO_CF_REASON[MMI_SC_CF_NO_REPLY] = CALL_FORWARD_REASON_NO_REPLY;
MMI_SC_TO_CF_REASON[MMI_SC_CF_NOT_REACHABLE] = CALL_FORWARD_REASON_NOT_REACHABLE;
MMI_SC_TO_CF_REASON[MMI_SC_CF_ALL] = CALL_FORWARD_REASON_ALL_CALL_FORWARDING;
MMI_SC_TO_CF_REASON[MMI_SC_CF_ALL_CONDITIONAL] = CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING;
// MMI service codes for PIN/PIN2/PUK/PUK2 management as defined in TS.22.030
// sec 6.6
this.MMI_SC_PIN = "04";
this.MMI_SC_PIN2 = "042";
this.MMI_SC_PUK = "05";
this.MMI_SC_PUK2 = "052";
// MMI service code for IMEI presentation as defined in TS.22.030 sec 6.7
this.MMI_SC_IMEI = "06";
// MMI called line presentation service codes
this.MMI_SC_CLIP = "30";
this.MMI_SC_CLIR = "31";
// MMI call waiting service code
this.MMI_SC_CALL_WAITING = "43";
// MMI service code for registration new password as defined in TS 22.030 6.5.4
this.MMI_SC_CHANGE_PASSWORD = "03";
this.MMI_ZZ_BARRING_SERVICE = "330";
// MMI call barring service codes
this.MMI_SC_BAOC = "33";
this.MMI_SC_BAOIC = "331";
this.MMI_SC_BAOICxH = "332";
this.MMI_SC_BAIC = "35";
this.MMI_SC_BAICr = "351";
this.MMI_SC_BA_ALL = "330";
this.MMI_SC_BA_MO = "333";
this.MMI_SC_BA_MT = "353";
this.MMI_SC_TO_CB_FACILITY = {};
MMI_SC_TO_CB_FACILITY[MMI_SC_BAOC] = ICC_CB_FACILITY_BAOC;
MMI_SC_TO_CB_FACILITY[MMI_SC_BAOIC] = ICC_CB_FACILITY_BAOIC;
MMI_SC_TO_CB_FACILITY[MMI_SC_BAOICxH] = ICC_CB_FACILITY_BAOICxH;
MMI_SC_TO_CB_FACILITY[MMI_SC_BAIC] = ICC_CB_FACILITY_BAIC;
MMI_SC_TO_CB_FACILITY[MMI_SC_BAICr] = ICC_CB_FACILITY_BAICr;
MMI_SC_TO_CB_FACILITY[MMI_SC_BA_ALL] = ICC_CB_FACILITY_BA_ALL;
MMI_SC_TO_CB_FACILITY[MMI_SC_BA_MO] = ICC_CB_FACILITY_BA_MO;
MMI_SC_TO_CB_FACILITY[MMI_SC_BA_MT] = ICC_CB_FACILITY_BA_MT;
// MMI service code key strings.
this.MMI_KS_SC_CALL_BARRING = "scCallBarring";
this.MMI_KS_SC_CALL_FORWARDING = "scCallForwarding";
this.MMI_KS_SC_CLIP = "scClip";
this.MMI_KS_SC_CLIR = "scClir";
this.MMI_KS_SC_PWD = "scPwd";
this.MMI_KS_SC_CALL_WAITING = "scCallWaiting";
this.MMI_KS_SC_PIN = "scPin";
this.MMI_KS_SC_PIN2 = "scPin2";
this.MMI_KS_SC_PUK = "scPuk";
this.MMI_KS_SC_PUK2 = "scPuk2";
this.MMI_KS_SC_CHANGE_PASSWORD = "scChangePassword";
this.MMI_KS_SC_IMEI = "scImei";
this.MMI_KS_SC_USSD = "scUssd";
this.MMI_KS_SC_CALL = "scCall";
// MMI error messages key strings.
this.MMI_ERROR_KS_ERROR = "emMmiError";
this.MMI_ERROR_KS_NOT_SUPPORTED = "emMmiErrorNotSupported";
this.MMI_ERROR_KS_INVALID_ACTION = "emMmiErrorInvalidAction";
this.MMI_ERROR_KS_MISMATCH_PIN = "emMmiErrorMismatchPin";
this.MMI_ERROR_KS_MISMATCH_PASSWORD = "emMmiErrorMismatchPassword";
this.MMI_ERROR_KS_BAD_PIN = "emMmiErrorBadPin";
this.MMI_ERROR_KS_BAD_PUK = "emMmiErrorBadPuk";
this.MMI_ERROR_KS_INVALID_PIN = "emMmiErrorInvalidPin";
this.MMI_ERROR_KS_INVALID_PASSWORD = "emMmiErrorInvalidPassword";
this.MMI_ERROR_KS_NEEDS_PUK = "emMmiErrorNeedsPuk";
this.MMI_ERROR_KS_SIM_BLOCKED = "emMmiErrorSimBlocked";
// MMI status message.
this.MMI_SM_KS_PASSWORD_CHANGED = "smPasswordChanged";
this.MMI_SM_KS_PIN_CHANGED = "smPinChanged";
this.MMI_SM_KS_PIN2_CHANGED = "smPin2Changed";
this.MMI_SM_KS_PIN_UNBLOCKED = "smPinUnblocked";
this.MMI_SM_KS_PIN2_UNBLOCKED = "smPin2Unblocked";
this.MMI_SM_KS_SERVICE_ENABLED = "smServiceEnabled";
this.MMI_SM_KS_SERVICE_ENABLED_FOR = "smServiceEnabledFor";
this.MMI_SM_KS_SERVICE_DISABLED = "smServiceDisabled";
this.MMI_SM_KS_SERVICE_REGISTERED = "smServiceRegistered";
this.MMI_SM_KS_SERVICE_ERASED = "smServiceErased";
this.MMI_SM_KS_SERVICE_INTERROGATED = "smServiceInterrogated";
this.MMI_SM_KS_SERVICE_NOT_PROVISIONED = "smServiceNotProvisioned";
this.MMI_SM_KS_CLIR_PERMANENT = "smClirPermanent";
this.MMI_SM_KS_CLIR_DEFAULT_ON_NEXT_CALL_ON = "smClirDefaultOnNextCallOn";
this.MMI_SM_KS_CLIR_DEFAULT_ON_NEXT_CALL_OFF = "smClirDefaultOnNextCallOff";
this.MMI_SM_KS_CLIR_DEFAULT_OFF_NEXT_CALL_ON = "smClirDefaultOffNextCallOn";
this.MMI_SM_KS_CLIR_DEFAULT_OFF_NEXT_CALL_OFF = "smClirDefaultOffNextCallOff";
this.MMI_SM_KS_CALL_CONTROL = "smCallControl";
// MMI Service class
this.MMI_KS_SERVICE_CLASS_VOICE = "serviceClassVoice";
this.MMI_KS_SERVICE_CLASS_DATA = "serviceClassData";
this.MMI_KS_SERVICE_CLASS_FAX = "serviceClassFax";
this.MMI_KS_SERVICE_CLASS_SMS = "serviceClassSms";
this.MMI_KS_SERVICE_CLASS_DATA_SYNC = "serviceClassDataSync";
this.MMI_KS_SERVICE_CLASS_DATA_ASYNC = "serviceClassDataAsync";
this.MMI_KS_SERVICE_CLASS_PACKET = "serviceClassPacket";
this.MMI_KS_SERVICE_CLASS_PAD = "serviceClassPad";
this.MMI_KS_SERVICE_CLASS_MAPPING = {};
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_VOICE] = MMI_KS_SERVICE_CLASS_VOICE;
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_DATA] = MMI_KS_SERVICE_CLASS_DATA;
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_FAX] = MMI_KS_SERVICE_CLASS_FAX;
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_SMS] = MMI_KS_SERVICE_CLASS_SMS;
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_DATA_SYNC] = MMI_KS_SERVICE_CLASS_DATA_SYNC;
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_DATA_ASYNC] = MMI_KS_SERVICE_CLASS_DATA_ASYNC;
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_PACKET] = MMI_KS_SERVICE_CLASS_PACKET;
MMI_KS_SERVICE_CLASS_MAPPING[ICC_SERVICE_CLASS_PAD] = MMI_KS_SERVICE_CLASS_PAD;
/**
* CDMA PDU constants
*/
File diff suppressed because it is too large Load Diff
@@ -156,7 +156,7 @@ add_test(function test_ril_worker_cellbroadcast_set_search_list() {
context.RIL.setCellBroadcastSearchList(options);
// Enforce the MMI result to string for comparison.
equal("" + context.RIL.cellBroadcastConfigs.MMI, aExpected);
equal(options.success, true);
do_check_eq(options.errorMsg, undefined);
}
let searchListStr = "1,2,3,4";
+2 -4
View File
@@ -71,8 +71,7 @@ add_test(function test_setCallForward_unconditional() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
equal(postedMessage.errorMsg, undefined);
run_next_test();
});
@@ -116,8 +115,7 @@ add_test(function test_queryCallForwardStatus_unconditional() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
equal(postedMessage.errorMsg, undefined);
ok(Array.isArray(postedMessage.rules));
do_print(postedMessage.rules.length);
equal(postedMessage.rules.length, 1);
@@ -29,7 +29,6 @@ add_test(function test_queryCLIP_provisioned() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
equal(postedMessage.provisioned, 1);
run_next_test();
});
@@ -55,7 +54,6 @@ add_test(function test_getCLIP_error_generic_failure_invalid_length() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, "GenericFailure");
ok(!postedMessage.success);
equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
run_next_test();
});
@@ -34,7 +34,6 @@ add_test(function test_setCLIR_success() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
run_next_test();
});
@@ -57,8 +56,7 @@ add_test(function test_setCLIR_generic_failure() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, "GenericFailure");
ok(!postedMessage.success);
equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
run_next_test();
});
@@ -89,7 +87,6 @@ add_test(function test_getCLIR_n0_m1() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
equal(postedMessage.n, 0);
equal(postedMessage.m, 1);
run_next_test();
@@ -120,7 +117,6 @@ add_test(function test_getCLIR_error_generic_failure_invalid_length() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, "GenericFailure");
ok(!postedMessage.success);
equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
run_next_test();
});
+5 -11
View File
@@ -23,7 +23,6 @@ add_test(function test_setCallWaiting_success() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
run_next_test();
});
@@ -45,8 +44,7 @@ add_test(function test_setCallWaiting_generic_failure() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, "GenericFailure");
ok(!postedMessage.success);
equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
run_next_test();
});
@@ -64,7 +62,7 @@ add_test(function test_queryCallWaiting_success_enabled_true() {
context.Buf.int32Array = [
1, // serviceClass
1, // enabled
1 // length
2 // length
];
context.RIL[REQUEST_QUERY_CALL_WAITING](1, {});
};
@@ -74,9 +72,7 @@ add_test(function test_queryCallWaiting_success_enabled_true() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
equal(postedMessage.length, 1);
ok(postedMessage.enabled);
equal(postedMessage.serviceClass, 1);
run_next_test();
});
@@ -93,7 +89,7 @@ add_test(function test_queryCallWaiting_success_enabled_false() {
context.Buf.int32Array = [
1, // serviceClass
0, // enabled
1 // length
2 // length
];
context.RIL[REQUEST_QUERY_CALL_WAITING](1, {});
};
@@ -103,8 +99,6 @@ add_test(function test_queryCallWaiting_success_enabled_false() {
let postedMessage = workerHelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
equal(postedMessage.length, 1);
ok(!postedMessage.enabled);
equal(postedMessage.serviceClass, ICC_SERVICE_CLASS_NONE);
run_next_test();
});
@@ -16,7 +16,6 @@ add_test(function test_icc_get_card_lock_enabled() {
let buf = context.Buf;
let ril = context.RIL;
ril.aid = "123456789";
ril.v5Legacy = false;
function do_test(aLock) {
const serviceClass = ICC_SERVICE_CLASS_VOICE |
@@ -32,13 +31,11 @@ add_test(function test_icc_get_card_lock_enabled() {
// Data
let parcel = this.readStringList();
equal(parcel.length, ril.v5Legacy ? 3 : 4);
equal(parcel.length, 4);
equal(parcel[0], GECKO_CARDLOCK_TO_FACILITY[aLock]);
equal(parcel[1], "");
equal(parcel[2], serviceClass.toString());
if (!ril.v5Legacy) {
equal(parcel[3], ril.aid);
}
equal(parcel[3], ril.aid);
};
ril.iccGetCardLockEnabled({lockType: aLock});
@@ -87,7 +84,6 @@ add_test(function test_icc_set_card_lock_enabled() {
let buf = context.Buf;
let ril = context.RIL;
ril.aid = "123456789";
ril.v5Legacy = false;
function do_test(aLock, aPassword, aEnabled) {
const serviceClass = ICC_SERVICE_CLASS_VOICE |
@@ -103,14 +99,12 @@ add_test(function test_icc_set_card_lock_enabled() {
// Data
let parcel = this.readStringList();
equal(parcel.length, ril.v5Legacy ? 4 : 5);
equal(parcel.length, 5);
equal(parcel[0], GECKO_CARDLOCK_TO_FACILITY[aLock]);
equal(parcel[1], aEnabled ? "1" : "0");
equal(parcel[2], aPassword);
equal(parcel[3], serviceClass.toString());
if (!ril.v5Legacy) {
equal(parcel[4], ril.aid);
}
equal(parcel[4], ril.aid);
};
ril.iccSetCardLockEnabled({
@@ -151,12 +145,10 @@ add_test(function test_icc_change_card_lock_password() {
// Data
let parcel = this.readStringList();
equal(parcel.length, ril.v5Legacy ? 2 : 3);
equal(parcel.length, 3);
equal(parcel[0], aPassword);
equal(parcel[1], aNewPassword);
if (!ril.v5Legacy) {
equal(parcel[2], ril.aid);
}
equal(parcel[2], ril.aid);
};
ril.iccChangeCardLockPassword({
@@ -180,7 +172,6 @@ add_test(function test_icc_unlock_card_lock_pin() {
let ril = context.RIL;
let buf = context.Buf;
ril.aid = "123456789";
ril.v5Legacy = false;
function do_test(aLock, aPassword) {
let GECKO_CARDLOCK_TO_REQUEST = {};
@@ -196,11 +187,9 @@ add_test(function test_icc_unlock_card_lock_pin() {
// Data
let parcel = this.readStringList();
equal(parcel.length, ril.v5Legacy ? 1 : 2);
equal(parcel.length, 2);
equal(parcel[0], aPassword);
if (!ril.v5Legacy) {
equal(parcel[1], ril.aid);
}
equal(parcel[1], ril.aid);
};
ril.iccUnlockCardLock({
@@ -224,7 +213,6 @@ add_test(function test_icc_unlock_card_lock_puk() {
let ril = context.RIL;
let buf = context.Buf;
ril.aid = "123456789";
ril.v5Legacy = false;
function do_test(aLock, aPassword, aNewPin) {
let GECKO_CARDLOCK_TO_REQUEST = {};
@@ -240,12 +228,10 @@ add_test(function test_icc_unlock_card_lock_puk() {
// Data
let parcel = this.readStringList();
equal(parcel.length, ril.v5Legacy ? 2 : 3);
equal(parcel.length, 3);
equal(parcel[0], aPassword);
equal(parcel[1], aNewPin);
if (!ril.v5Legacy) {
equal(parcel[2], ril.aid);
}
equal(parcel[2], ril.aid);
};
ril.iccUnlockCardLock({
@@ -352,7 +352,7 @@ add_test(function test_read_icc_contacts() {
onsuccess(JSON.parse(JSON.stringify(aTestData.pbrs)));
};
record.readADNLike = function readADNLike(fileId, onsuccess, onerror) {
record.readADNLike = function readADNLike(fileId, extFileId, onsuccess, onerror) {
onsuccess(JSON.parse(JSON.stringify(aTestData.adnLike)));
};
@@ -398,6 +398,7 @@ add_test(function test_update_icc_contact() {
const EMAIL_RECORD_ID = 20;
const ANR0_FILE_ID = 0x4f11;
const ANR0_RECORD_ID = 30;
const EXT_RECORD_ID = 0x01;
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
@@ -408,11 +409,11 @@ add_test(function test_update_icc_contact() {
function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
ril.appType = aSimType;
ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x20, 0x0C, 0x0, 0x0, 0x0]
: [0x20, 0x00, 0x0, 0x0, 0x0];
ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x20, 0x0C, 0x28, 0x0, 0x20]
: [0x20, 0x0, 0x28, 0x0, 0x20];
ril.iccInfoPrivate.sst = (aSimType === CARD_APPTYPE_SIM)?
[0x20, 0x0, 0x0, 0x0, 0x0]:
[0x2, 0x0, 0x0, 0x0, 0x0];
[0x20, 0x0, 0x28, 0x0, 0x20]:
[0x16, 0x0, 0x0, 0x0, 0x0];
recordHelper.readPBR = function(onsuccess, onerror) {
if (aFileType === ICC_USIM_TYPE1_TAG) {
@@ -421,7 +422,9 @@ add_test(function test_update_icc_contact() {
email: {fileId: EMAIL_FILE_ID,
fileType: ICC_USIM_TYPE1_TAG},
anr0: {fileId: ANR0_FILE_ID,
fileType: ICC_USIM_TYPE1_TAG}
fileType: ICC_USIM_TYPE1_TAG},
ext1: {fileId: ICC_EF_EXT1}
}]);
} else if (aFileType === ICC_USIM_TYPE2_TAG) {
onsuccess([{
@@ -433,23 +436,48 @@ add_test(function test_update_icc_contact() {
indexInIAP: 0},
anr0: {fileId: ANR0_FILE_ID,
fileType: ICC_USIM_TYPE2_TAG,
indexInIAP: 1}
indexInIAP: 1},
ext1: {fileId: ICC_EF_EXT1}
}]);
}
};
recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
if (aContactType === GECKO_CARDCONTACT_TYPE_FDN) {
equal(fileId, ICC_EF_FDN);
} else if (aContactType === GECKO_CARDCONTACT_TYPE_ADN) {
equal(fileId, ICC_EF_ADN);
}
if (aContact.number.length > ADN_MAX_NUMBER_DIGITS) {
equal(extRecordNumber, EXT_RECORD_ID);
} else {
equal(extRecordNumber, 0xff);
}
equal(pin2, aPin2);
equal(contact.alphaId, aContact.alphaId);
equal(contact.number, aContact.number);
onsuccess({alphaId: contact.alphaId,
number: contact.number.substring(0, ADN_MAX_NUMBER_DIGITS)});
};
recordHelper.getADNLikeExtensionRecordNumber = function(fileId, recordNumber, onsuccess, onerror) {
onsuccess(EXT_RECORD_ID);
};
recordHelper.updateExtension = function(fileId, recordNumber, number, onsuccess, onerror) {
onsuccess();
};
recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
onsuccess(EXT_RECORD_ID);
};
recordHelper.cleanEFRecord = function(fileId, recordNumber, onsuccess, onerror) {
onsuccess();
}
recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
equal(fileId, IAP_FILE_ID);
equal(recordNumber, ADN_RECORD_ID);
@@ -471,7 +499,7 @@ add_test(function test_update_icc_contact() {
equal(recordNumber, EMAIL_RECORD_ID);
}
equal(email, aContact.email);
onsuccess();
onsuccess(email);
};
recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
@@ -484,7 +512,7 @@ add_test(function test_update_icc_contact() {
if (Array.isArray(aContact.anr)) {
equal(number, aContact.anr[0]);
}
onsuccess();
onsuccess(number);
};
recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
@@ -498,7 +526,25 @@ add_test(function test_update_icc_contact() {
};
let isSuccess = false;
let onsuccess = function onsuccess() {
let onsuccess = function onsuccess(updatedContact) {
equal(ADN_RECORD_ID, updatedContact.recordId);
equal(aContact.alphaId, updatedContact.alphaId);
equal(aContact.number.substring(0, ADN_MAX_NUMBER_DIGITS + EXT_MAX_NUMBER_DIGITS),
updatedContact.number);
if ((aSimType == CARD_APPTYPE_USIM || aSimType == CARD_APPTYPE_RUIM) &&
(aFileType == ICC_USIM_TYPE1_TAG || aFileType == ICC_USIM_TYPE2_TAG)) {
if (aContact.hasOwnProperty('email')) {
equal(aContact.email, updatedContact.email);
}
if (aContact.hasOwnProperty('anr')) {
equal(aContact.anr[0], updatedContact.anr[0]);
}
} else {
equal(updatedContact.email, null);
equal(updatedContact.anr, null);
}
do_print("updateICCContact success");
isSuccess = true;
};
@@ -542,6 +588,22 @@ add_test(function test_update_icc_contact() {
alphaId: "test4",
number: "123456",
anr: ["+654321"]
},
// a contact number over 20 digits.
{
pbrIndex: 0,
recordId: ADN_RECORD_ID,
alphaId: "test4",
number: "0123456789012345678901234567890123456789",
anr: ["+654321"]
},
// a contact number over 40 digits.
{
pbrIndex: 0,
recordId: ADN_RECORD_ID,
alphaId: "test5",
number: "01234567890123456789012345678901234567890123456789",
anr: ["+654321"]
}];
for (let i = 0; i < contacts.length; i++) {
@@ -589,6 +651,111 @@ add_test(function test_update_icc_contact() {
run_next_test();
});
/**
* Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM and
* insufficient space to store Type 2 USIM contact fields.
*/
add_test(function test_update_icc_contact_full_email_and_anr_field() {
const ADN_RECORD_ID = 100;
const ADN_SFI = 1;
const IAP_FILE_ID = 0x4f17;
const EMAIL_FILE_ID = 0x4f50;
const EMAIL_RECORD_ID = 20;
const ANR0_FILE_ID = 0x4f11;
const ANR0_RECORD_ID = 30;
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let recordHelper = context.ICCRecordHelper;
let contactHelper = context.ICCContactHelper;
let ril = context.RIL;
function do_test(aSimType, aContactType, aContact, aPin2) {
ril.appType = CARD_APPTYPE_USIM;
ril.iccInfoPrivate.sst = [0x2, 0x0, 0x0, 0x0, 0x0];
recordHelper.readPBR = function(onsuccess, onerror) {
onsuccess([{
adn: {fileId: ICC_EF_ADN,
sfi: ADN_SFI},
iap: {fileId: IAP_FILE_ID},
email: {fileId: EMAIL_FILE_ID,
fileType: ICC_USIM_TYPE2_TAG,
indexInIAP: 0},
anr0: {fileId: ANR0_FILE_ID,
fileType: ICC_USIM_TYPE2_TAG,
indexInIAP: 1}
}]);
};
recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
if (aContactType === GECKO_CARDCONTACT_TYPE_ADN) {
equal(fileId, ICC_EF_ADN);
}
equal(pin2, aPin2);
equal(contact.alphaId, aContact.alphaId);
equal(contact.number, aContact.number);
onsuccess({alphaId: contact.alphaId,
number: contact.number});
};
recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
equal(fileId, IAP_FILE_ID);
equal(recordNumber, ADN_RECORD_ID);
onsuccess([0xff, 0xff]);
};
recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
equal(fileId, IAP_FILE_ID);
equal(recordNumber, ADN_RECORD_ID);
onsuccess();
};
recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
let recordId = 0;
// emulate email and anr don't have free record.
if (fileId === EMAIL_FILE_ID || fileId === ANR0_FILE_ID) {
onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
} else {
onsuccess(recordId);
}
};
let isSuccess = false;
let onsuccess = function onsuccess(updatedContact) {
equal(ADN_RECORD_ID, updatedContact.recordId);
equal(aContact.alphaId, updatedContact.alphaId);
equal(updatedContact.email, null);
equal(updatedContact.anr, null);
do_print("updateICCContact success");
isSuccess = true;
};
let onerror = function onerror(errorMsg) {
do_print("updateICCContact failed: " + errorMsg);
};
contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
ok(isSuccess);
}
let contact = {
pbrIndex: 0,
recordId: ADN_RECORD_ID,
alphaId: "test",
number: "123456",
email: "test@mail.com",
anr: ["+654321"]
};
// USIM
do_print("Test update USIM adn contacts");
do_test(CARD_APPTYPE_USIM, GECKO_CARDCONTACT_TYPE_ADN, contact, null);
run_next_test();
});
/**
* Verify updateICCContact with removal of anr and email with File Type 1.
*/
@@ -605,8 +772,9 @@ add_test(function test_update_icc_contact_with_remove_type1_attr() {
let recordHelper = context.ICCRecordHelper;
let contactHelper = context.ICCContactHelper;
recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
onsuccess();
recordHelper.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
onsuccess({alphaId: contact.alphaId,
number: contact.number});
};
let contact = {
@@ -622,12 +790,12 @@ add_test(function test_update_icc_contact_with_remove_type1_attr() {
recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
ok(email == null);
onsuccess();
onsuccess(email);
};
recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
ok(number == null);
onsuccess();
onsuccess(number);
};
function do_test(type) {
@@ -652,7 +820,9 @@ add_test(function test_update_icc_contact_with_remove_type1_attr() {
}
};
let successCb = function() {
let successCb = function(updatedContact) {
equal(updatedContact.email, null);
equal(updatedContact.anr, null);
ok(true);
};
@@ -782,3 +952,91 @@ add_test(function test_find_free_icc_contact_usim() {
run_next_test();
});
/**
* Verify ICCContactHelper.updateADNLikeWithExtension
*/
add_test(function test_update_adn_like_with_extension() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let ril = context.RIL;
let record = context.ICCRecordHelper;
let contactHelper = context.ICCContactHelper;
ril.appType = CARD_APPTYPE_SIM;
// Correct record Id starts from 1, so put a null element at index 0.
// ext_records contains data at index 1, and it only has 1 free record at index 2.
let notFree = 0x01;
let ext_records = [null, notFree, null];
function do_test(contact, extRecordNumber, expectedExtRecordNumber, expectedNumber, expectedCleanEFRecord) {
// Override some functions to test.
record.getADNLikeExtensionRecordNumber = function(fileId, recordNumber, onsuccess, onerror) {
onsuccess(extRecordNumber);
}
record.updateADNLike = function(fileId, extRecordNumber, contact, pin2, onsuccess, onerror) {
equal(extRecordNumber, expectedExtRecordNumber);
onsuccess({alphaId: contact.alphaId,
number: contact.number.substring(0, ADN_MAX_NUMBER_DIGITS)});
}
record.updateExtension = function(fileId, recordNumber, number, onsuccess, onerror) {
if (recordNumber > ext_records.length) {
onerror("updateExtension failed.");
return;
}
ext_records[recordNumber] = number;
onsuccess();
}
record.findFreeRecordId = function(fileId, onsuccess, onerror) {
for (let i = 1; i < ext_records.length; i++) {
if (!ext_records[i]) {
onsuccess(i);
return;
}
}
onerror("No free record found.");
}
let isCleanEFRecord = false;
record.cleanEFRecord = function(fileId, recordNumber, onsuccess, onerror) {
if (recordNumber > ext_records.length) {
onerror("cleanEFRecord failed.");
return;
}
ext_records[recordNumber] = null;
isCleanEFRecord = true;
onsuccess();
}
let successCb = function successCb(updatedContact) {
equal(updatedContact.number, expectedNumber);
};
let errorCb = function errorCb(errorMsg) {
do_print("updateADNLikeWithExtension failed, msg = " + errorMsg);
ok(false);
};
contactHelper.updateADNLikeWithExtension(ICC_EF_ADN, ICC_EF_EXT1, contact, null, successCb, errorCb);
if (expectedCleanEFRecord) {
ok(isCleanEFRecord);
}
}
// Update extension record with previous extension record number.
do_test({recordId: 1, alphaId: "test", number: "001122334455667788991234"}, 0x01, 0x01, "001122334455667788991234");
// Update extension record and find a free record.
do_test({recordId: 1, alphaId: "test", number: "001122334455667788995678"}, 0xff, 0x02, "001122334455667788995678");
// Update extension record with no free extension record.
do_test({recordId: 1, alphaId: "test", number: "001122334455667788994321"}, 0xff, 0xff, "00112233445566778899");
// Update extension record with clean previous extension record.
do_test({recordId: 1, alphaId: "test", number: "00112233445566778899"}, 0x01, 0xff, "00112233445566778899", true);
// Update extension record with no extension record and previous extension record.
do_test({recordId: 1, alphaId: "test", number: "00112233445566778899"}, 0xff, 0xff, "00112233445566778899");
run_next_test();
});
@@ -47,6 +47,84 @@ add_test(function test_read_icc_ucs2_string() {
run_next_test();
});
/**
* Verify ICCPDUHelper#writeICCUCS2String()
*/
add_test(function test_write_icc_ucs2_string() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let helper = context.GsmPDUHelper;
let iccHelper = context.ICCPDUHelper;
let alphaLen = 18;
let test_data = [
{
encode: 0x80,
// string only contain one character.
data: "\u82b3"
}, {
encode: 0x80,
// 2 UCS2 character not located in the same half-page.
data: "Fire \u82b3\u8233"
}, {
encode: 0x80,
// 2 UCS2 character not located in the same half-page.
data: "\u694a\u704a"
}, {
encode: 0x81,
// 2 UCS2 character within same half-page.
data: "Fire \u6901\u697f"
}, {
encode: 0x81,
// 2 UCS2 character within same half-page.
data: "Fire \u6980\u69ff"
}, {
encode: 0x82,
// 2 UCS2 character within same half-page, but bit 8 is different.
data: "Fire \u0514\u0593"
}, {
encode: 0x82,
// 2 UCS2 character over 0x81 can encode range.
data: "Fire \u8000\u8001"
}, {
encode: 0x82,
// 2 UCS2 character over 0x81 can encode range.
data: "Fire \ufffd\ufffe"
}];
for (let i = 0; i < test_data.length; i++) {
let test = test_data[i];
let writtenStr = iccHelper.writeICCUCS2String(alphaLen, test.data);
equal(writtenStr, test.data);
equal(helper.readHexOctet(), test.encode);
equal(iccHelper.readICCUCS2String(test.encode, alphaLen - 1), test.data);
}
// This string use 0x80 encoded and the maximum capacity is 17 octets.
// Each alphabet takes 2 octets, thus the first 8 alphabets can be written.
let str = "Mozilla \u82b3\u8233 On Fire";
let writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
equal(writtenStr, str.substring(0, 8));
equal(helper.readHexOctet(), 0x80);
equal(iccHelper.readICCUCS2String(0x80, alphaLen - 1), str.substring(0, 8));
// This string use 0x81 encoded and the maximum capacity is 15 octets.
// Each alphabet takes 1 octets, thus the first 15 alphabets can be written.
str = "Mozilla \u6901\u697f On Fire";
writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
equal(writtenStr, str.substring(0, 15));
equal(helper.readHexOctet(), 0x81);
equal(iccHelper.readICCUCS2String(0x81, alphaLen - 1), str.substring(0, 15));
// This string use 0x82 encoded and the maximum capacity is 14 octets.
// Each alphabet takes 1 octets, thus the first 14 alphabets can be written.
str = "Mozilla \u0514\u0593 On Fire";
writtenStr = iccHelper.writeICCUCS2String(alphaLen, str);
equal(writtenStr, str.substring(0, 14));
equal(helper.readHexOctet(), 0x82);
equal(iccHelper.readICCUCS2String(0x82, alphaLen - 1), str.substring(0, 14));
run_next_test();
});
/**
* Verify ICCPDUHelper#readDiallingNumber
*/
@@ -154,7 +232,8 @@ add_test(function test_write_string_to_8bit_unpacked() {
let str;
// Test 1, write GSM alphabets.
iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
let writtenStr = iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
equal(writtenStr, langTable);
for (let i = 0; i < langTable.length; i++) {
equal(helper.readHexOctet(), i);
@@ -166,8 +245,8 @@ add_test(function test_write_string_to_8bit_unpacked() {
// Test 2, write GSM extended alphabets.
str = "\u000c\u20ac";
iccHelper.writeStringTo8BitUnpacked(4, str);
writtenStr = iccHelper.writeStringTo8BitUnpacked(4, str);
equal(writtenStr, str);
equal(iccHelper.read8BitUnpackedToString(4), str);
// Test 3, write GSM and GSM extended alphabets.
@@ -179,8 +258,8 @@ add_test(function test_write_string_to_8bit_unpacked() {
// 1 octet for 1 gsm alphabet,
// 2 octes for trailing 0xff.
// "Totally 7 octets are to be written."
iccHelper.writeStringTo8BitUnpacked(7, str);
writtenStr = iccHelper.writeStringTo8BitUnpacked(7, str);
equal(writtenStr, str);
equal(iccHelper.read8BitUnpackedToString(7), str);
run_next_test();
@@ -199,7 +278,8 @@ add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
// The maximum of the number of octets that can be written is 3.
// Only 3 characters shall be written even the length of the string is 4.
iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
let writtenStr = iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
equal(writtenStr, langTable.substring(0, 3));
helper.writeHexOctet(0xff); // dummy octet.
for (let i = 0; i < 3; i++) {
equal(helper.readHexOctet(), i);
@@ -209,18 +289,21 @@ add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
// \u000c is GSM extended alphabet, 2 octets.
// \u00a3 is GSM alphabet, 1 octet.
let str = "\u000c\u00a3";
iccHelper.writeStringTo8BitUnpacked(3, str);
writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
equal(writtenStr, str.substring(0, 2));
equal(iccHelper.read8BitUnpackedToString(3), str);
str = "\u00a3\u000c";
iccHelper.writeStringTo8BitUnpacked(3, str);
writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
equal(writtenStr, str.substring(0, 2));
equal(iccHelper.read8BitUnpackedToString(3), str);
// 2 GSM extended alphabets cost 4 octets, but maximum is 3, so only the 1st
// alphabet can be written.
str = "\u000c\u000c";
iccHelper.writeStringTo8BitUnpacked(3, str);
writtenStr = iccHelper.writeStringTo8BitUnpacked(3, str);
helper.writeHexOctet(0xff); // dummy octet.
equal(writtenStr, str.substring(0, 1));
equal(iccHelper.read8BitUnpackedToString(4), str.substring(0, 1));
run_next_test();
@@ -283,36 +366,42 @@ add_test(function test_write_alpha_identifier() {
let ffLen = 2;
// Removal
iccHelper.writeAlphaIdentifier(10, null);
let writenAlphaId = iccHelper.writeAlphaIdentifier(10, null);
equal(writenAlphaId, null);
equal(iccHelper.readAlphaIdentifier(10), "");
// GSM 8 bit
let str = "Mozilla";
iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
writenAlphaId = iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
equal(writenAlphaId , str);
equal(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
// UCS2
str = "Mozilla\u694a";
iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
str = "Mozilla\u8000";
writenAlphaId = iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
equal(writenAlphaId , str);
// * 2 for each character will be encoded to UCS2 alphabets.
equal(iccHelper.readAlphaIdentifier(str.length * 2 + ffLen), str);
// Test with maximum octets written.
// 1 coding scheme (0x80) and 1 UCS2 character, total 3 octets.
str = "\u694a";
iccHelper.writeAlphaIdentifier(3, str);
writenAlphaId = iccHelper.writeAlphaIdentifier(3, str);
equal(writenAlphaId , str);
equal(iccHelper.readAlphaIdentifier(3), str);
// 1 coding scheme (0x80) and 2 UCS2 characters, total 5 octets.
// numOctets is limited to 4, so only 1 UCS2 character can be written.
str = "\u694a\u694a";
iccHelper.writeAlphaIdentifier(4, str);
str = "\u694a\u69ca";
writenAlphaId = iccHelper.writeAlphaIdentifier(4, str);
helper.writeHexOctet(0xff); // dummy octet.
equal(writenAlphaId , str.substring(0, 1));
equal(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
// Write 0 octet.
iccHelper.writeAlphaIdentifier(0, "1");
writenAlphaId = iccHelper.writeAlphaIdentifier(0, "1");
helper.writeHexOctet(0xff); // dummy octet.
equal(writenAlphaId, null);
equal(iccHelper.readAlphaIdentifier(1), "");
run_next_test();
@@ -373,28 +462,36 @@ add_test(function test_write_alpha_id_dialling_number() {
alphaId: "Mozilla",
number: "1234567890"
};
helper.writeAlphaIdDiallingNumber(recordSize, contactW.alphaId,
contactW.number);
let writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
contactW.alphaId,
contactW.number, 0xff);
let contactR = helper.readAlphaIdDiallingNumber(recordSize);
equal(contactW.alphaId, contactR.alphaId);
equal(contactW.number, contactR.number);
equal(writtenContact.alphaId, contactR.alphaId);
equal(writtenContact.number, contactR.number);
equal(0xff, contactR.extRecordNumber);
// Write a contact with alphaId encoded in UCS2 and number has '+'.
let contactUCS2 = {
alphaId: "火狐",
number: "+1234567890"
};
helper.writeAlphaIdDiallingNumber(recordSize, contactUCS2.alphaId,
contactUCS2.number);
writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
contactUCS2.alphaId,
contactUCS2.number, 0xff);
contactR = helper.readAlphaIdDiallingNumber(recordSize);
equal(contactUCS2.alphaId, contactR.alphaId);
equal(contactUCS2.number, contactR.number);
equal(writtenContact.alphaId, contactR.alphaId);
equal(writtenContact.number, contactR.number);
equal(0xff, contactR.extRecordNumber);
// Write a null contact (Removal).
helper.writeAlphaIdDiallingNumber(recordSize);
writtenContact = helper.writeAlphaIdDiallingNumber(recordSize);
contactR = helper.readAlphaIdDiallingNumber(recordSize);
equal(contactR, null);
equal(writtenContact.alphaId, null);
equal(writtenContact.number, null);
// Write a longer alphaId/dialling number
// Dialling Number : Maximum 20 digits(10 octets).
@@ -405,19 +502,24 @@ add_test(function test_write_alpha_id_dialling_number() {
alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
number: "123456789012345678901234567890",
};
helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
longContact.number);
writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
longContact.alphaId,
longContact.number, 0xff);
contactR = helper.readAlphaIdDiallingNumber(recordSize);
equal(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
equal(contactR.number, "12345678901234567890");
equal(writtenContact.alphaId, contactR.alphaId);
equal(writtenContact.number, contactR.number);
equal(0xff, contactR.extRecordNumber);
// Add '+' to number and test again.
longContact.number = "+123456789012345678901234567890";
helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
longContact.number);
writtenContact = helper.writeAlphaIdDiallingNumber(recordSize,
longContact.alphaId,
longContact.number, 0xff);
contactR = helper.readAlphaIdDiallingNumber(recordSize);
equal(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
equal(contactR.number, "+12345678901234567890");
equal(writtenContact.alphaId, contactR.alphaId);
equal(writtenContact.number, contactR.number);
equal(0xff, contactR.extRecordNumber);
run_next_test();
});
@@ -511,7 +613,8 @@ add_test(function test_write_number_with_length() {
function test(number, expectedNumber) {
expectedNumber = expectedNumber || number;
iccHelper.writeNumberWithLength(number);
let writeNumber = iccHelper.writeNumberWithLength(number);
equal(writeNumber, expectedNumber);
let numLen = helper.readHexOctet();
equal(expectedNumber, iccHelper.readDiallingNumber(numLen));
for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
@@ -536,6 +639,9 @@ add_test(function test_write_number_with_length() {
test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
// over maximum 20 digits should be truncated.
test("012345678901234567890123456789", "01234567890123456789");
// null
iccHelper.writeNumberWithLength(null);
for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
@@ -204,10 +204,8 @@ add_test(function test_update_email() {
// pin2.
equal(this.readString(), null);
if (!ril.v5Legacy) {
// AID. Ignore because it's from modem.
this.readInt32();
}
// AID. Ignore because it's from modem.
this.readInt32();
if (count == NUM_TESTS) {
run_next_test();
@@ -350,10 +348,8 @@ add_test(function test_update_anr() {
// pin2.
equal(this.readString(), null);
if (!ril.v5Legacy) {
// AID. Ignore because it's from modem.
this.readInt32();
}
// AID. Ignore because it's from modem.
this.readInt32();
if (count == NUM_TESTS) {
run_next_test();
@@ -487,10 +483,8 @@ add_test(function test_update_iap() {
// pin2.
equal(this.readString(), null);
if (!ril.v5Legacy) {
// AID. Ignore because it's from modem.
this.readInt32();
}
// AID. Ignore because it's from modem.
this.readInt32();
run_next_test();
};
@@ -500,6 +494,74 @@ add_test(function test_update_iap() {
do_test([1, 2]);
});
/**
* Verify ICCRecordHelper.readADNLike.
*/
add_test(function test_read_adn_like() {
const RECORD_SIZE = 0x20;
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let helper = context.GsmPDUHelper;
let record = context.ICCRecordHelper;
let buf = context.Buf;
let io = context.ICCIOHelper;
let ril = context.RIL;
function do_test(extFileId, rawEF, expectedExtRecordNumber, expectedNumber) {
io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
// Write data size
buf.writeInt32(rawEF.length * 2);
// Write adn
for (let i = 0; i < rawEF.length; i += 2) {
helper.writeHexOctet(parseInt(rawEF.substr(i, 2), 16));
}
// Write string delimiter
buf.writeStringDelimiter(rawEF.length * 2);
options.p1 = 1;
options.recordSize = RECORD_SIZE;
options.totalRecords = 1;
if (options.callback) {
options.callback(options);
}
};
record.readExtension = function(fileId, recordNumber, onsuccess, onerror) {
onsuccess("1234");
}
let successCb = function successCb(contacts) {
ok(contacts[0].number == expectedNumber);
};
let errorCb = function errorCb(errorMsg) {
do_print("Reading ADNLike failed, msg = " + errorMsg);
ok(false);
};
record.readADNLike(ICC_EF_ADN, extFileId, successCb, errorCb);
}
ril.appType = CARD_APPTYPE_SIM;
// Valid extension
do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ff01",
0x01,"998877665544332211001234");
// Empty extension
do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
0xff, "99887766554433221100");
// Unsupport extension
do_test(null,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
0xff, "99887766554433221100");
// Empty dialling number contact
do_test(null,"436f6e74616374303031ffffffffffffffffffffffffffffffffffffffffffff",
0xff, "");
run_next_test();
});
/**
* Verify ICCRecordHelper.updateADNLike.
*/
@@ -555,6 +617,7 @@ add_test(function test_update_adn_like() {
let contact = pdu.readAlphaIdDiallingNumber(0x20);
equal(contact.alphaId, "test");
equal(contact.number, "123456");
equal(contact.extRecordNumber, "0xff");
// pin2.
if (fileId == ICC_EF_ADN) {
@@ -563,10 +626,8 @@ add_test(function test_update_adn_like() {
equal(this.readString(), "1111");
}
if (!ril.v5Legacy) {
// AID. Ignore because it's from modem.
this.readInt32();
}
// AID. Ignore because it's from modem.
this.readInt32();
if (fileId == ICC_EF_FDN) {
run_next_test();
@@ -574,11 +635,11 @@ add_test(function test_update_adn_like() {
};
fileId = ICC_EF_ADN;
record.updateADNLike(fileId,
record.updateADNLike(fileId, 0xff,
{recordId: 1, alphaId: "test", number: "123456"});
fileId = ICC_EF_FDN;
record.updateADNLike(fileId,
record.updateADNLike(fileId, 0xff,
{recordId: 1, alphaId: "test", number: "123456"},
"1111");
});
@@ -729,3 +790,291 @@ add_test(function test_handling_iccid() {
run_next_test();
});
/**
* Verify ICCRecordHelper.readExtension
*/
add_test(function test_read_extension() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let helper = context.GsmPDUHelper;
let record = context.ICCRecordHelper;
let buf = context.Buf;
let io = context.ICCIOHelper;
function do_test(rawExtension, expectedExtensionNumber) {
io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
// Write data size
buf.writeInt32(rawExtension.length * 2);
// Write ext
for (let i = 0; i < rawExtension.length; i += 2) {
helper.writeHexOctet(parseInt(rawExtension.substr(i, 2), 16));
}
// Write string delimiter
buf.writeStringDelimiter(rawExtension.length);
if (options.callback) {
options.callback(options);
}
};
let successCb = function successCb(number) {
do_print("extension number:" + number);
equal(number, expectedExtensionNumber);
};
let errorCb = function errorCb() {
ok(expectedExtensionNumber == null);
};
record.readExtension(0x6f4a, 1, successCb, errorCb);
}
// Test unsupported record type 0x01
do_test("010a10325476981032547698ff", "");
// Test invalid length 0xc1
do_test("020c10325476981032547698ff", null);
// Test extension chain which we don't support
do_test("020a1032547698103254769802", "01234567890123456789");
// Test valid Extension
do_test("020a10325476981032547698ff", "01234567890123456789");
// Test valid Extension
do_test("0209103254769810325476ffff", "012345678901234567");
// Test empty Extension
do_test("02ffffffffffffffffffffffff", "");
run_next_test();
});
/**
* Verify ICCRecordHelper.updateExtension
*/
add_test(function test_update_extension() {
const RECORD_SIZE = 13;
const RECORD_NUMBER = 1;
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let ril = context.RIL;
let recordHelper = context.ICCRecordHelper;
let buf = context.Buf;
let ioHelper = context.ICCIOHelper;
// Override.
ioHelper.updateLinearFixedEF = function(options) {
options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
options.command = ICC_COMMAND_UPDATE_RECORD;
options.p1 = options.recordNumber;
options.p2 = READ_RECORD_ABSOLUTE_MODE;
options.p3 = RECORD_SIZE;
ril.iccIO(options);
};
function do_test(fileId, number, expectedNumber) {
buf.sendParcel = function() {
// Request Type.
equal(this.readInt32(), REQUEST_SIM_IO);
// Token : we don't care
this.readInt32();
// command.
equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
// fileId.
equal(this.readInt32(), fileId);
// pathId.
if (ril.appType == CARD_APPTYPE_SIM || ril.appType == CARD_APPTYPE_RUIM) {
equal(this.readString(),
EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
} else{
equal(this.readString(),
EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
}
// p1.
equal(this.readInt32(), RECORD_NUMBER);
// p2.
equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
// p3.
equal(this.readInt32(), RECORD_SIZE);
// data.
let strLen = this.readInt32();
// Extension record
let recordType = pduHelper.readHexOctet();
equal(recordType, 0x02);
equal(pduHelper.readHexOctet(), 10);
equal(
pduHelper.readSwappedNibbleExtendedBcdString(EXT_MAX_NUMBER_DIGITS - 1),
expectedNumber);
this.readStringDelimiter(strLen);
// pin2.
equal(this.readString(), null);
// AID. Ignore because it's from modem.
this.readInt32();
};
recordHelper.updateExtension(fileId, RECORD_NUMBER, number);
}
ril.appType = CARD_APPTYPE_SIM;
do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
// We don't support extension chain.
do_test(ICC_EF_EXT1, "012345678901234567891234", "01234567890123456789");
ril.appType = CARD_APPTYPE_USIM;
do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
ril.appType = CARD_APPTYPE_RUIM;
do_test(ICC_EF_EXT1, "01234567890123456789", "01234567890123456789");
run_next_test();
});
/**
* Verify ICCRecordHelper.cleanEFRecord
*/
add_test(function test_clean_ef_record() {
const RECORD_SIZE = 13;
const RECORD_NUMBER = 1;
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let pduHelper = context.GsmPDUHelper;
let ril = context.RIL;
let recordHelper = context.ICCRecordHelper;
let buf = context.Buf;
let ioHelper = context.ICCIOHelper;
// Override.
ioHelper.updateLinearFixedEF = function(options) {
options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
options.command = ICC_COMMAND_UPDATE_RECORD;
options.p1 = options.recordNumber;
options.p2 = READ_RECORD_ABSOLUTE_MODE;
options.p3 = RECORD_SIZE;
ril.iccIO(options);
};
function do_test(fileId) {
buf.sendParcel = function() {
// Request Type.
equal(this.readInt32(), REQUEST_SIM_IO);
// Token : we don't care
this.readInt32();
// command.
equal(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
// fileId.
equal(this.readInt32(), fileId);
// pathId.
if (ril.appType == CARD_APPTYPE_SIM || ril.appType == CARD_APPTYPE_RUIM) {
equal(this.readString(),
EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
} else{
equal(this.readString(),
EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
}
// p1.
equal(this.readInt32(), RECORD_NUMBER);
// p2.
equal(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
// p3.
equal(this.readInt32(), RECORD_SIZE);
// data.
let strLen = this.readInt32();
// Extension record
for (let i = 0; i < RECORD_SIZE; i++) {
equal(pduHelper.readHexOctet(), 0xff);
}
this.readStringDelimiter(strLen);
// pin2.
equal(this.readString(), null);
// AID. Ignore because it's from modem.
this.readInt32();
};
recordHelper.cleanEFRecord(fileId, RECORD_NUMBER);
}
ril.appType = CARD_APPTYPE_SIM;
do_test(ICC_EF_EXT1);
run_next_test();
});
/**
* Verify ICCRecordHelper.getADNLikeExtensionRecordNumber
*/
add_test(function test_get_adn_like_extension_record_number() {
const RECORD_SIZE = 0x20;
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let helper = context.GsmPDUHelper;
let record = context.ICCRecordHelper;
let buf = context.Buf;
let io = context.ICCIOHelper;
function do_test(rawEF, expectedRecordNumber) {
io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
// Write data size
buf.writeInt32(rawEF.length * 2);
// Write ext
for (let i = 0; i < rawEF.length; i += 2) {
helper.writeHexOctet(parseInt(rawEF.substr(i, 2), 16));
}
// Write string delimiter
buf.writeStringDelimiter(rawEF.length);
options.recordSize = RECORD_SIZE;
if (options.callback) {
options.callback(options);
}
};
let isSuccess = false;
let successCb = function successCb(number) {
equal(number, expectedRecordNumber);
isSuccess = true;
};
let errorCb = function errorCb(errorMsg) {
do_print("Reading ADNLike failed, msg = " + errorMsg);
ok(false);
};
record.getADNLikeExtensionRecordNumber(ICC_EF_ADN, 1, successCb, errorCb);
ok(isSuccess);
}
// Valid Extension, Alpha Id(Encoded with GSM 8 bit): "Contact001",
// Dialling Number: 99887766554433221100, Ext1: 0x01
do_test("436f6e74616374303031ffffffffffffffff0b8199887766554433221100ff01", 0x01);
// Empty Extension, Alpha Id(Encoded with GSM 8 bit): "Contact001", Ext1: 0xff
do_test("436f6e74616374303031ffffffffffffffffffffffffffffffffffffffffffff", 0xff);
run_next_test();
});
@@ -355,10 +355,8 @@ add_test(function test_update_mwis() {
// pin2.
equal(this.readString(), null);
if (!ril.v5Legacy) {
// AID. Ignore because it's from modem.
this.readInt32();
}
// AID. Ignore because it's from modem.
this.readInt32();
};
ok(!isUpdated);
@@ -1,525 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
function run_test() {
run_next_test();
}
function createMMIOptions(procedure, serviceCode, sia, sib, sic) {
let mmi = {
fullMMI: Array.slice(arguments).join("*") + "#",
procedure: procedure,
serviceCode: serviceCode,
sia: sia,
sib: sib,
sic: sic
};
return mmi;
}
function testSendMMI(mmi, error) {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
do_print("worker.postMessage " + worker.postMessage);
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({rilMessageType: "sendMMI", mmi: mmi});
let postedMessage = workerhelper.postedMessage;
equal(postedMessage.rilMessageType, "sendMMI");
equal(postedMessage.errorMsg, error);
}
/**
* sendMMI tests.
*/
add_test(function test_sendMMI_null() {
testSendMMI(null, MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_short_code() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
let ussdOptions;
context.RIL.sendUSSD = function fakeSendUSSD(options){
ussdOptions = options;
context.RIL[REQUEST_SEND_USSD](0, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: {fullMMI: "**"}});
let postedMessage = workerhelper.postedMessage;
equal(ussdOptions.ussd, "**");
equal (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
ok(context.RIL._ussdSession);
run_next_test();
});
add_test(function test_sendMMI_change_PIN() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
context.RIL.changeICCPIN = function fakeChangeICCPIN(options) {
context.RIL[REQUEST_ENTER_SIM_PIN](0, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("**", "04", "1234", "4567",
"4567")});
let postedMessage = workerhelper.postedMessage;
equal (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
run_next_test();
});
add_test(function test_sendMMI_change_PIN_no_new_PIN() {
testSendMMI(createMMIOptions("**", "04", "1234", "", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_change_PIN_no_old_PIN() {
testSendMMI(createMMIOptions("**", "04", "", "1234", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_change_PIN_wrong_procedure() {
testSendMMI(createMMIOptions("*", "04", "1234", "4567", "4567"),
MMI_ERROR_KS_INVALID_ACTION);
run_next_test();
});
add_test(function test_sendMMI_change_PIN_new_PIN_mismatch() {
testSendMMI(createMMIOptions("**", "04", "4567", "1234", "4567"),
MMI_ERROR_KS_MISMATCH_PIN);
run_next_test();
});
add_test(function test_sendMMI_change_PIN2() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
context.RIL.changeICCPIN2 = function fakeChangeICCPIN2(options) {
context.RIL[REQUEST_ENTER_SIM_PIN2](0, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("**", "042", "1234", "4567",
"4567")});
let postedMessage = workerhelper.postedMessage;
equal (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
run_next_test();
});
add_test(function test_sendMMI_change_PIN2_no_new_PIN2() {
testSendMMI(createMMIOptions("**", "042", "1234", "", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_change_PIN2_no_old_PIN2() {
testSendMMI(createMMIOptions("**", "042", "", "1234", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_change_PIN2_wrong_procedure() {
testSendMMI(createMMIOptions("*", "042", "1234", "4567", "4567"),
MMI_ERROR_KS_INVALID_ACTION);
run_next_test();
});
add_test(function test_sendMMI_change_PIN2_new_PIN2_mismatch() {
testSendMMI(createMMIOptions("**", "042", "4567", "1234", "4567"),
MMI_ERROR_KS_MISMATCH_PIN);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
context.RIL.enterICCPUK = function fakeEnterICCPUK(options) {
context.RIL[REQUEST_ENTER_SIM_PUK](0, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("**", "05", "1234", "4567",
"4567")});
let postedMessage = workerhelper.postedMessage;
equal (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN_no_new_PIN() {
testSendMMI(createMMIOptions("**", "05", "1234", "", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN_no_PUK() {
testSendMMI(createMMIOptions("**", "05", "", "1234", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN_wrong_procedure() {
testSendMMI(createMMIOptions("*", "05", "1234", "4567", "4567"),
MMI_ERROR_KS_INVALID_ACTION);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN_new_PIN_mismatch() {
testSendMMI(createMMIOptions("**", "05", "4567", "1234", "4567"),
MMI_ERROR_KS_MISMATCH_PIN);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN2() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
context.RIL.enterICCPUK2 = function fakeEnterICCPUK2(options) {
context.RIL[REQUEST_ENTER_SIM_PUK2](0, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("**", "052", "1234", "4567",
"4567")});
let postedMessage = workerhelper.postedMessage;
equal (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN2_no_new_PIN2() {
testSendMMI(createMMIOptions("**", "052", "1234", "", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN2_no_PUK2() {
testSendMMI(createMMIOptions("**", "052", "", "1234", "4567"),
MMI_ERROR_KS_ERROR);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN2_wrong_procedure() {
testSendMMI(createMMIOptions("*", "052", "1234", "4567", "4567"),
MMI_ERROR_KS_INVALID_ACTION);
run_next_test();
});
add_test(function test_sendMMI_unblock_PIN2_new_PIN_mismatch() {
testSendMMI(createMMIOptions("**", "052", "4567", "1234", "4567"),
MMI_ERROR_KS_MISMATCH_PIN);
run_next_test();
});
add_test(function test_sendMMI_get_IMEI() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
let mmiOptions;
context.RIL.getIMEI = function getIMEI(options) {
mmiOptions = options;
context.RIL[REQUEST_SEND_USSD](0, {});
};
context.RIL.sendMMI({mmi: createMMIOptions("*#", "06")});
let postedMessage = workerhelper.postedMessage;
notEqual(mmiOptions.mmi, null);
equal (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
run_next_test();
});
add_test(function test_sendMMI_get_IMEI_error() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
let mmiOptions;
context.RIL.getIMEI = function getIMEI(options){
mmiOptions = options;
context.RIL[REQUEST_SEND_USSD](0, {
errorMsg: GECKO_ERROR_RADIO_NOT_AVAILABLE
});
};
context.RIL.sendMMI({mmi: createMMIOptions("*#", "06")});
let postedMessage = workerhelper.postedMessage;
notEqual(mmiOptions.mmi, null);
equal (postedMessage.errorMsg, GECKO_ERROR_RADIO_NOT_AVAILABLE);
ok(!postedMessage.success);
run_next_test();
});
add_test(function test_sendMMI_call_barring_BAIC_interrogation_voice() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
context.Buf.readInt32List = function fakeReadUint32List() {
return [1];
};
context.RIL.queryICCFacilityLock =
function fakeQueryICCFacilityLock(options) {
context.RIL[REQUEST_QUERY_FACILITY_LOCK](1, {
rilMessageType: "sendMMI"
});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("*#", "33")});
let postedMessage = workerhelper.postedMessage;
ok(postedMessage.success);
ok(postedMessage.enabled);
equal(postedMessage.statusMessage, MMI_SM_KS_SERVICE_ENABLED_FOR);
ok(Array.isArray(postedMessage.additionalInformation));
equal(postedMessage.additionalInformation[0], "serviceClassVoice");
run_next_test();
});
add_test(function test_sendMMI_call_barring_BAIC_activation() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
let mmiOptions;
context.RIL.setICCFacilityLock =
function fakeSetICCFacilityLock(options) {
mmiOptions = options;
context.RIL[REQUEST_SET_FACILITY_LOCK](0, {
rilMessageType: "sendMMI",
procedure: MMI_PROCEDURE_ACTIVATION
});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("*", "33")});
let postedMessage = workerhelper.postedMessage;
equal(mmiOptions.procedure, MMI_PROCEDURE_ACTIVATION);
ok(postedMessage.success);
equal(postedMessage.statusMessage, MMI_SM_KS_SERVICE_ENABLED);
run_next_test();
});
add_test(function test_sendMMI_call_barring_BAIC_deactivation() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
let mmiOptions;
context.RIL.setICCFacilityLock =
function fakeSetICCFacilityLock(options) {
mmiOptions = options;
context.RIL[REQUEST_SET_FACILITY_LOCK](0, {
rilMessageType: "sendMMI",
procedure: MMI_PROCEDURE_DEACTIVATION
});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("#", "33")});
let postedMessage = workerhelper.postedMessage;
equal(mmiOptions.procedure, MMI_PROCEDURE_DEACTIVATION);
ok(postedMessage.success);
equal(postedMessage.statusMessage, MMI_SM_KS_SERVICE_DISABLED);
run_next_test();
});
add_test(function test_sendMMI_call_barring_BAIC_procedure_not_supported() {
testSendMMI(createMMIOptions("**", "33", "0000"), MMI_ERROR_KS_NOT_SUPPORTED);
run_next_test();
});
add_test(function test_sendMMI_USSD() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
let ussdOptions;
context.RIL.sendUSSD = function fakeSendUSSD(options) {
ussdOptions = options;
context.RIL[REQUEST_SEND_USSD](0, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("*", "123")});
let postedMessage = workerhelper.postedMessage;
equal(ussdOptions.ussd, "**123#");
equal (postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
ok(context.RIL._ussdSession);
run_next_test();
});
add_test(function test_sendMMI_USSD_error() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
let ussdOptions;
context.RIL.sendUSSD = function fakeSendUSSD(options){
ussdOptions = options;
context.RIL[REQUEST_SEND_USSD](0, {
errorMsg: GECKO_ERROR_GENERIC_FAILURE
});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("*", "123")});
let postedMessage = workerhelper.postedMessage;
equal(ussdOptions.ussd, "**123#");
equal (postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
ok(!postedMessage.success);
ok(!context.RIL._ussdSession);
run_next_test();
});
function setCallWaitingSuccess(mmi) {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
context.RIL[REQUEST_SET_CALL_WAITING](0, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: mmi});
let postedMessage = workerhelper.postedMessage;
equal(postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
}
add_test(function test_sendMMI_call_waiting_activation() {
setCallWaitingSuccess(createMMIOptions("*", "43", "10"));
run_next_test();
});
add_test(function test_sendMMI_call_waiting_deactivation() {
setCallWaitingSuccess(createMMIOptions("#", "43"));
run_next_test();
});
add_test(function test_sendMMI_call_waiting_registration() {
testSendMMI(createMMIOptions("**", "43"), MMI_ERROR_KS_NOT_SUPPORTED);
run_next_test();
});
add_test(function test_sendMMI_call_waiting_erasure() {
testSendMMI(createMMIOptions("##", "43"), MMI_ERROR_KS_NOT_SUPPORTED);
run_next_test();
});
add_test(function test_sendMMI_call_waiting_interrogation() {
let workerhelper = newInterceptWorker();
let worker = workerhelper.worker;
let context = worker.ContextPool._contexts[0];
context.Buf.readInt32 = function fakeReadUint32() {
return context.Buf.int32Array.pop();
};
context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
context.Buf.int32Array = [
7, // serviceClass
1, // enabled
2 // length
];
context.RIL[REQUEST_QUERY_CALL_WAITING](1, {});
};
context.RIL.radioState = GECKO_RADIOSTATE_ENABLED;
context.RIL.sendMMI({mmi: createMMIOptions("*#", "43")});
let postedMessage = workerhelper.postedMessage;
equal(postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
ok(postedMessage.success);
equal(postedMessage.length, 2);
ok(postedMessage.enabled);
run_next_test();
});
@@ -36,7 +36,6 @@ function setCallForwardSuccess(procedure, serviceCode, sia, sib, sic) {
let postedMessage = workerhelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
}
add_test(function test_sendMMI_call_forwarding_activation() {
@@ -82,7 +81,6 @@ add_test(function test_sendMMI_call_forwarding_interrogation() {
let postedMessage = workerhelper.postedMessage;
equal(postedMessage.errorMsg, undefined);
ok(postedMessage.success);
ok(Array.isArray(postedMessage.rules));
equal(postedMessage.rules.length, 1);
ok(postedMessage.rules[0].active);
@@ -110,7 +108,6 @@ add_test(function test_sendMMI_call_forwarding_interrogation_no_rules() {
let postedMessage = workerhelper.postedMessage;
equal(postedMessage.errorMsg, GECKO_ERROR_GENERIC_FAILURE);
ok(!postedMessage.success);
run_next_test();
});
@@ -6,20 +6,26 @@ subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
const SMSC_ATT = '+13123149810';
const SMSC_ATT_TYPO = '+++1312@@@314$$$9,8,1,0';
const SMSC_ATT_TEXT = '"+13123149810",145';
const SMSC_ATT_TEXT_INCORRECT_TOA = '"+13123149810",129';
const SMSC_ATT_PDU = '07913121139418F0';
const SMSC_O2 = '+447802000332';
const SMSC_O2_TEXT = '"+447802000332",145';
const SMSC_O2_PDU = '0791448720003023';
const SMSC_EMPTY = '';
const SMSC_TON_UNKNOWN = '0407485455'
const SMSC_TON_UNKNOWN_TEXT = '"0407485455",129';
const SMSC_TON_UNKNOWN_TEXT_NO_TOA = '"0407485455"';
const SMSC_TON_UNKNOWN_TEXT_INVALID_TOA = '"0407485455",abc';
const SMSC_TON_UNKNOWN_PDU = '06814070844555';
const SMSC_EMPTY_PDU = 'FFFFFFFFFFFFFFFFFFFFFFFF';
const SMSC_EMPTY_TEXT = '';
function run_test() {
run_next_test();
}
function setSmsc(context, smsc, ton, npi, expected) {
context.Buf.sendParcel = function() {
context.Buf.postRILMessage = function() {
equal(this.readString(), expected);
};
@@ -30,6 +36,17 @@ function setSmsc(context, smsc, ton, npi, expected) {
});
}
function getSmsc(worker, context, raw, smsc, ton, npi) {
worker.postMessage = function(message) {
equal(message.smscAddress, smsc);
equal(message.typeOfNumber, ton);
equal(message.numberPlanIdentification, npi);
}
context.Buf.writeString(raw);
context.RIL[REQUEST_GET_SMSC_ADDRESS](0, { rilMessageType: "getSmscAddress"});
}
add_test(function test_setSmscAddress() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
@@ -69,3 +86,27 @@ add_test(function test_setSmscAddress() {
run_next_test();
});
add_test(function test_getSmscAddress() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
// Test text mode.
worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "text";
getSmsc(worker, context, SMSC_ATT_TEXT, SMSC_ATT, 1, 1);
getSmsc(worker, context, SMSC_ATT_TEXT_INCORRECT_TOA, SMSC_ATT, 1, 1);
getSmsc(worker, context, SMSC_O2_TEXT, SMSC_O2, 1, 1);
getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT, SMSC_TON_UNKNOWN, 0, 1);
getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT_NO_TOA, SMSC_TON_UNKNOWN, 0, 1);
getSmsc(worker, context, SMSC_TON_UNKNOWN_TEXT_INVALID_TOA, SMSC_TON_UNKNOWN,
0, 1);
getSmsc(worker, context, SMSC_EMPTY_TEXT, SMSC_EMPTY, 0, 1);
// Test pdu mode.
worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "pdu";
getSmsc(worker, context, SMSC_ATT_PDU, SMSC_ATT, 1, 1);
getSmsc(worker, context, SMSC_O2_PDU, SMSC_O2, 1, 1);
getSmsc(worker, context, SMSC_TON_UNKNOWN_PDU, SMSC_TON_UNKNOWN, 0, 1);
getSmsc(worker, context, SMSC_EMPTY_PDU, SMSC_EMPTY, 0, 1);
run_next_test();
});
-2
View File
@@ -23,8 +23,6 @@ skip-if = true
[test_ril_worker_sms_gsmpduhelper.js]
[test_ril_worker_sms_segment_info.js]
[test_ril_worker_smsc_address.js]
[test_ril_worker_mmi.js]
[test_ril_worker_mmi_cf.js]
[test_ril_worker_cf.js]
[test_ril_worker_cellbroadcast_config.js]
[test_ril_worker_cellbroadcast.js]
+90 -127
View File
@@ -165,38 +165,27 @@ Telephony::IsValidServiceId(uint32_t aServiceId)
return aServiceId < GetNumServices();
}
// static
bool
Telephony::IsActiveState(uint16_t aCallState) {
return aCallState == nsITelephonyService::CALL_STATE_DIALING ||
aCallState == nsITelephonyService::CALL_STATE_ALERTING ||
aCallState == nsITelephonyService::CALL_STATE_CONNECTED;
}
uint32_t
Telephony::ProvidedOrDefaultServiceId(const Optional<uint32_t>& aServiceId)
Telephony::GetServiceId(const Optional<uint32_t>& aServiceId,
bool aGetIfActiveCall)
{
if (aServiceId.WasPassed()) {
return aServiceId.Value();
} else {
uint32_t serviceId = 0;
mService->GetDefaultServiceId(&serviceId);
return serviceId;
}
}
bool
Telephony::HasDialingCall()
{
for (uint32_t i = 0; i < mCalls.Length(); i++) {
const RefPtr<TelephonyCall>& call = mCalls[i];
if (call->CallState() > nsITelephonyService::CALL_STATE_UNKNOWN &&
call->CallState() < nsITelephonyService::CALL_STATE_CONNECTED) {
return true;
} else if (aGetIfActiveCall) {
nsTArray<RefPtr<TelephonyCall> > &calls = mCalls;
if (mGroup->IsActive()) {
calls = mGroup->CallsArray();
}
for (uint32_t i = 0; i < calls.Length(); i++) {
if (calls[i]->IsActive()) {
return calls[i]->mServiceId;
}
}
}
return false;
uint32_t serviceId = 0;
mService->GetDefaultServiceId(&serviceId);
return serviceId;
}
already_AddRefed<Promise>
@@ -218,12 +207,6 @@ Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
return promise.forget();
}
// We only support one outgoing call at a time.
if (HasDialingCall()) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsCOMPtr<nsITelephonyDialCallback> callback =
new TelephonyDialCallback(GetOwner(), this, promise);
@@ -265,17 +248,17 @@ Telephony::CreateCallId(const nsAString& aNumber, uint16_t aNumberPresentation,
already_AddRefed<TelephonyCall>
Telephony::CreateCall(TelephonyCallId* aId, uint32_t aServiceId,
uint32_t aCallIndex, uint16_t aCallState,
uint32_t aCallIndex, TelephonyCallState aState,
bool aEmergency, bool aConference,
bool aSwitchable, bool aMergeable)
{
// We don't have to create an already ended call.
if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
if (aState == TelephonyCallState::Disconnected) {
return nullptr;
}
RefPtr<TelephonyCall> call =
TelephonyCall::Create(this, aId, aServiceId, aCallIndex, aCallState,
TelephonyCall::Create(this, aId, aServiceId, aCallIndex, aState,
aEmergency, aConference, aSwitchable, aMergeable);
NS_ASSERTION(call, "This should never fail!");
@@ -346,57 +329,66 @@ Telephony::HandleCallInfo(nsITelephonyCallInfo* aInfo)
aInfo->GetIsSwitchable(&isSwitchable);
aInfo->GetIsMergeable(&isMergeable);
RefPtr<TelephonyCall> call = GetCallFromEverywhere(serviceId, callIndex);
TelephonyCallState state = TelephonyCall::ConvertToTelephonyCallState(callState);
RefPtr<TelephonyCall> call = GetCallFromEverywhere(serviceId, callIndex);
// Handle a newly created call.
if (!call) {
RefPtr<TelephonyCallId> id = CreateCallId(aInfo);
call = CreateCall(id, serviceId, callIndex, callState, isEmergency,
call = CreateCall(id, serviceId, callIndex, state, isEmergency,
isConference, isSwitchable, isMergeable);
if (call && callState == nsITelephonyService::CALL_STATE_INCOMING) {
// The newly created call is an incoming call.
if (call &&
state == TelephonyCallState::Incoming) {
nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("incoming"), call);
NS_ENSURE_SUCCESS(rv, rv);
}
} else {
call->UpdateEmergency(isEmergency);
call->UpdateSwitchable(isSwitchable);
call->UpdateMergeable(isMergeable);
return NS_OK;
}
nsAutoString number;
aInfo->GetNumber(number);
RefPtr<TelephonyCallId> id = call->Id();
id->UpdateNumber(number);
// Update an existing call
call->UpdateEmergency(isEmergency);
call->UpdateSwitchable(isSwitchable);
call->UpdateMergeable(isMergeable);
// State changed.
if (call->CallState() != callState) {
if (callState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
call->ChangeStateInternal(callState, true);
return NS_OK;
}
nsAutoString number;
aInfo->GetNumber(number);
RefPtr<TelephonyCallId> id = call->Id();
id->UpdateNumber(number);
// We don't fire the statechange event on a call in conference here.
// Instead, the event will be fired later in
// TelephonyCallGroup::ChangeState(). Thus the sequence of firing the
// statechange events is guaranteed: first on TelephonyCallGroup then on
// individual TelephonyCall objects.
bool fireEvent = !isConference;
call->ChangeStateInternal(callState, fireEvent);
nsAutoString disconnectedReason;
aInfo->GetDisconnectedReason(disconnectedReason);
// State changed.
if (call->State() != state) {
if (state == TelephonyCallState::Disconnected) {
call->UpdateDisconnectedReason(disconnectedReason);
call->ChangeState(TelephonyCallState::Disconnected);
return NS_OK;
}
// Group changed.
RefPtr<TelephonyCallGroup> group = call->GetGroup();
// We don't fire the statechange event on a call in conference here.
// Instead, the event will be fired later in
// TelephonyCallGroup::ChangeState(). Thus the sequence of firing the
// statechange events is guaranteed: first on TelephonyCallGroup then on
// individual TelephonyCall objects.
bool fireEvent = !isConference;
call->ChangeStateInternal(state, fireEvent);
}
if (!group && isConference) {
// Add to conference.
NS_ASSERTION(mCalls.Contains(call), "Should in mCalls");
mGroup->AddCall(call);
RemoveCall(call);
} else if (group && !isConference) {
// Remove from conference.
NS_ASSERTION(mGroup->CallsArray().Contains(call), "Should in mGroup");
mGroup->RemoveCall(call);
AddCall(call);
}
// Group changed.
RefPtr<TelephonyCallGroup> group = call->GetGroup();
if (!group && isConference) {
// Add to conference.
NS_ASSERTION(mCalls.Contains(call), "Should in mCalls");
mGroup->AddCall(call);
RemoveCall(call);
} else if (group && !isConference) {
// Remove from conference.
NS_ASSERTION(mGroup->CallsArray().Contains(call), "Should in mGroup");
mGroup->RemoveCall(call);
AddCall(call);
}
return NS_OK;
@@ -437,7 +429,7 @@ already_AddRefed<Promise>
Telephony::Dial(const nsAString& aNumber, const Optional<uint32_t>& aServiceId,
ErrorResult& aRv)
{
uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
uint32_t serviceId = GetServiceId(aServiceId);
RefPtr<Promise> promise = DialInternal(serviceId, aNumber, false, aRv);
return promise.forget();
}
@@ -447,7 +439,7 @@ Telephony::DialEmergency(const nsAString& aNumber,
const Optional<uint32_t>& aServiceId,
ErrorResult& aRv)
{
uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
uint32_t serviceId = GetServiceId(aServiceId);
RefPtr<Promise> promise = DialInternal(serviceId, aNumber, true, aRv);
return promise.forget();
}
@@ -459,7 +451,8 @@ Telephony::SendTones(const nsAString& aDTMFChars,
const Optional<uint32_t>& aServiceId,
ErrorResult& aRv)
{
uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
uint32_t serviceId = GetServiceId(aServiceId,
true /* aGetIfActiveCall */);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (!global) {
@@ -496,7 +489,8 @@ Telephony::StartTone(const nsAString& aDTMFChar,
const Optional<uint32_t>& aServiceId,
ErrorResult& aRv)
{
uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
uint32_t serviceId = GetServiceId(aServiceId,
true /* aGetIfActiveCall */);
if (aDTMFChar.IsEmpty()) {
NS_WARNING("Empty tone string will be ignored");
@@ -514,7 +508,8 @@ Telephony::StartTone(const nsAString& aDTMFChar,
void
Telephony::StopTone(const Optional<uint32_t>& aServiceId, ErrorResult& aRv)
{
uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
uint32_t serviceId = GetServiceId(aServiceId,
true /* aGetIfActiveCall */);
if (!IsValidServiceId(serviceId)) {
aRv.Throw(NS_ERROR_INVALID_ARG);
@@ -625,18 +620,21 @@ Telephony::SetSpeakerEnabled(bool aEnabled, ErrorResult& aRv)
void
Telephony::GetActive(Nullable<OwningTelephonyCallOrTelephonyCallGroup>& aValue)
{
if (mGroup->CallState() == nsITelephonyService::CALL_STATE_CONNECTED) {
if (mGroup->IsActive()) {
aValue.SetValue().SetAsTelephonyCallGroup() = mGroup;
} else {
// Search the first active call.
for (uint32_t i = 0; i < mCalls.Length(); i++) {
if (IsActiveState(mCalls[i]->CallState())) {
aValue.SetValue().SetAsTelephonyCall() = mCalls[i];
return;
}
}
aValue.SetNull();
return;
}
// Search for the active call.
for (uint32_t i = 0; i < mCalls.Length(); i++) {
if (mCalls[i]->IsActive()) {
aValue.SetValue().SetAsTelephonyCall() = mCalls[i];
return;
}
}
// Nothing active found.
aValue.SetNull();
}
already_AddRefed<CallsList>
@@ -725,6 +723,7 @@ Telephony::WindowAudioCaptureChanged()
NS_IMETHODIMP
Telephony::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo)
{
// Update call state
nsresult rv;
for (uint32_t i = 0; i < aLength; ++i) {
rv = HandleCallInfo(aAllInfo[i]);
@@ -733,6 +732,9 @@ Telephony::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllInfo)
}
}
// Update conference state
mGroup->ChangeState();
rv = HandleAudioAgentState();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@@ -746,30 +748,11 @@ Telephony::EnumerateCallState(nsITelephonyCallInfo* aInfo)
return HandleCallInfo(aInfo);
}
NS_IMETHODIMP
Telephony::ConferenceCallStateChanged(uint16_t aCallState)
{
mGroup->ChangeState(aCallState);
return NS_OK;
}
NS_IMETHODIMP
Telephony::EnumerateCallStateComplete()
{
// Set conference state.
if (mGroup->CallsArray().Length() >= 2) {
const nsTArray<RefPtr<TelephonyCall> > &calls = mGroup->CallsArray();
uint16_t callState = calls[0]->CallState();
for (uint32_t i = 1; i < calls.Length(); i++) {
if (calls[i]->CallState() != callState) {
callState = nsITelephonyService::CALL_STATE_UNKNOWN;
break;
}
}
mGroup->ChangeState(callState);
}
mGroup->ChangeState();
HandleAudioAgentState();
if (mReadyPromise) {
@@ -809,26 +792,6 @@ Telephony::SupplementaryServiceNotification(uint32_t aServiceId,
return NS_OK;
}
NS_IMETHODIMP
Telephony::NotifyError(uint32_t aServiceId,
int32_t aCallIndex,
const nsAString& aError)
{
RefPtr<TelephonyCall> callToNotify =
GetCallFromEverywhere(aServiceId, aCallIndex);
if (!callToNotify) {
NS_ERROR("Don't call me with a bad call index!");
return NS_ERROR_UNEXPECTED;
}
// Set the call state to 'disconnected' and remove it from the calls list.
callToNotify->UpdateDisconnectedReason(aError);
callToNotify->NotifyError(aError);
callToNotify->ChangeState(nsITelephonyService::CALL_STATE_DISCONNECTED);
return NS_OK;
}
NS_IMETHODIMP
Telephony::NotifyCdmaCallWaiting(uint32_t aServiceId, const nsAString& aNumber,
uint16_t aNumberPresentation,
+9 -10
View File
@@ -189,14 +189,9 @@ private:
static bool
IsValidServiceId(uint32_t aServiceId);
static bool
IsActiveState(uint16_t aCallState);
uint32_t
ProvidedOrDefaultServiceId(const Optional<uint32_t>& aServiceId);
bool
HasDialingCall();
GetServiceId(const Optional<uint32_t>& aServiceId,
bool aGetIfActiveCall = false);
already_AddRefed<Promise>
DialInternal(uint32_t aServiceId, const nsAString& aNumber, bool aEmergency,
@@ -213,9 +208,13 @@ private:
already_AddRefed<TelephonyCall>
CreateCall(TelephonyCallId* aId,
uint32_t aServiceId, uint32_t aCallIndex, uint16_t aCallState,
bool aEmergency = false, bool aConference = false,
bool aSwitchable = true, bool aMergeable = true);
uint32_t aServiceId,
uint32_t aCallIndex,
TelephonyCallState aState,
bool aEmergency = false,
bool aConference = false,
bool aSwitchable = true,
bool aMergeable = true);
nsresult
NotifyEvent(const nsAString& aType);
+123 -82
View File
@@ -34,16 +34,51 @@
} \
}
#ifdef TELEPHONY_CALL_STATE
#undef TELEPHONY_CALL_STATE
#endif
#define TELEPHONY_CALL_STATE(_state) \
(TelephonyCallStateValues::strings[static_cast<int32_t>(_state)].value)
using namespace mozilla::dom;
using namespace mozilla::dom::telephony;
using mozilla::ErrorResult;
// static
TelephonyCallState
TelephonyCall::ConvertToTelephonyCallState(uint32_t aCallState)
{
switch (aCallState) {
case nsITelephonyService::CALL_STATE_DIALING:
return TelephonyCallState::Dialing;
case nsITelephonyService::CALL_STATE_ALERTING:
return TelephonyCallState::Alerting;
case nsITelephonyService::CALL_STATE_CONNECTED:
return TelephonyCallState::Connected;
case nsITelephonyService::CALL_STATE_HELD:
return TelephonyCallState::Held;
case nsITelephonyService::CALL_STATE_DISCONNECTED:
return TelephonyCallState::Disconnected;
case nsITelephonyService::CALL_STATE_INCOMING:
return TelephonyCallState::Incoming;
}
NS_NOTREACHED("Unknown state!");
return TelephonyCallState::Disconnected;
}
// static
already_AddRefed<TelephonyCall>
TelephonyCall::Create(Telephony* aTelephony, TelephonyCallId* aId,
uint32_t aServiceId, uint32_t aCallIndex,
uint16_t aCallState, bool aEmergency, bool aConference,
bool aSwitchable, bool aMergeable)
TelephonyCall::Create(Telephony* aTelephony,
TelephonyCallId* aId,
uint32_t aServiceId,
uint32_t aCallIndex,
TelephonyCallState aState,
bool aEmergency,
bool aConference,
bool aSwitchable,
bool aMergeable)
{
NS_ASSERTION(aTelephony, "Null aTelephony pointer!");
NS_ASSERTION(aId, "Null aId pointer!");
@@ -61,8 +96,7 @@ TelephonyCall::Create(Telephony* aTelephony, TelephonyCallId* aId,
call->mMergeable = aMergeable;
call->mError = nullptr;
call->ChangeStateInternal(aCallState, false);
call->ChangeStateInternal(aState, false);
return call.forget();
}
@@ -83,35 +117,15 @@ TelephonyCall::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
}
void
TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
TelephonyCall::ChangeStateInternal(TelephonyCallState aState, bool aFireEvents)
{
RefPtr<TelephonyCall> kungFuDeathGrip(this);
mCallState = aCallState;
switch (aCallState) {
case nsITelephonyService::CALL_STATE_DIALING:
mState.AssignLiteral("dialing");
break;
case nsITelephonyService::CALL_STATE_ALERTING:
mState.AssignLiteral("alerting");
break;
case nsITelephonyService::CALL_STATE_CONNECTED:
mState.AssignLiteral("connected");
break;
case nsITelephonyService::CALL_STATE_HELD:
mState.AssignLiteral("held");
break;
case nsITelephonyService::CALL_STATE_DISCONNECTED:
mState.AssignLiteral("disconnected");
break;
case nsITelephonyService::CALL_STATE_INCOMING:
mState.AssignLiteral("incoming");
break;
default:
NS_NOTREACHED("Unknown state!");
}
// Update current state
mState = aState;
if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
// Handle disconnected calls
if (mState == TelephonyCallState::Disconnected) {
NS_ASSERTION(mLive, "Should be live!");
mLive = false;
if (mGroup) {
@@ -119,8 +133,7 @@ TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
} else {
mTelephony->RemoveCall(this);
}
UpdateDisconnectedReason(NS_LITERAL_STRING("NormalCallClearingError"));
} else if (!mLive) {
} else if (!mLive) { // Handle newly added calls
mLive = true;
if (mGroup) {
mGroup->AddCall(this);
@@ -129,23 +142,39 @@ TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
}
}
// Dispatch call state changed and call state event
if (aFireEvents) {
nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), this);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
// This can change if the statechange handler called back here... Need to
// figure out something smarter.
if (mCallState == aCallState) {
rv = DispatchCallEvent(mState, this);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
}
NotifyStateChanged();
}
}
nsresult
TelephonyCall::NotifyStateChanged()
{
// Since |mState| can be changed after statechange handler called back here,
// we must save current state. Maybe we should figure out something smarter.
TelephonyCallState prevState = mState;
nsresult res = DispatchCallEvent(NS_LITERAL_STRING("statechange"), this);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch specific event!");
}
// Check whether |mState| remains the same after the statechange handler.
if (mState != prevState) {
NS_WARNING("Call State has changed by statechange handler!");
return res;
}
res = DispatchCallEvent(NS_ConvertASCIItoUTF16(TELEPHONY_CALL_STATE(mState)),
this);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch a specific event!");
}
return res;
}
nsresult
TelephonyCall::DispatchCallEvent(const nsAString& aType,
TelephonyCall* aCall)
@@ -196,16 +225,23 @@ TelephonyCall::NotifyError(const nsAString& aError)
void
TelephonyCall::UpdateDisconnectedReason(const nsAString& aDisconnectedReason)
{
NS_ASSERTION(Substring(aDisconnectedReason, aDisconnectedReason.Length() - 5).EqualsLiteral("Error"),
NS_ASSERTION(Substring(aDisconnectedReason,
aDisconnectedReason.Length() - 5).EqualsLiteral("Error"),
"Disconnected reason should end with 'Error'");
if (mDisconnectedReason.IsNull()) {
// There is no 'Error' suffix in the corresponding enum. We should skip
// that part for comparison.
CONVERT_STRING_TO_NULLABLE_ENUM(
Substring(aDisconnectedReason, 0, aDisconnectedReason.Length() - 5),
TelephonyCallDisconnectedReason,
mDisconnectedReason);
if (!mDisconnectedReason.IsNull()) {
return;
}
// There is no 'Error' suffix in the corresponding enum. We should skip
// that part for comparison.
CONVERT_STRING_TO_NULLABLE_ENUM(
Substring(aDisconnectedReason, 0, aDisconnectedReason.Length() - 5),
TelephonyCallDisconnectedReason,
mDisconnectedReason);
if (!aDisconnectedReason.EqualsLiteral("NormalCallClearingError")) {
NotifyError(aDisconnectedReason);
}
}
@@ -272,9 +308,10 @@ TelephonyCall::Answer(ErrorResult& aRv)
return nullptr;
}
if (mCallState != nsITelephonyService::CALL_STATE_INCOMING) {
if (mState != TelephonyCallState::Incoming) {
NS_WARNING(nsPrintfCString("Answer on non-incoming call is rejected!"
" (State: %u)", mCallState).get());
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
@@ -294,15 +331,16 @@ TelephonyCall::HangUp(ErrorResult& aRv)
return nullptr;
}
if (mCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
NS_WARNING(nsPrintfCString("HangUp on previously disconnected call"
" is rejected! (State: %u)", mCallState).get());
if (mState == TelephonyCallState::Disconnected) {
NS_WARNING(nsPrintfCString("HangUp on a disconnected call is rejected!"
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mCallState == nsITelephonyService::CALL_STATE_INCOMING ?
aRv = mState == TelephonyCallState::Incoming ?
mTelephony->Service()->RejectCall(mServiceId, mCallIndex, callback) :
mTelephony->Service()->HangUpCall(mServiceId, mCallIndex, callback);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
@@ -328,30 +366,13 @@ TelephonyCall::Hold(ErrorResult& aRv)
return promise.forget();
}
already_AddRefed<Promise>
TelephonyCall::Resume(ErrorResult& aRv)
{
RefPtr<Promise> promise = CreatePromise(aRv);
if (!promise) {
return nullptr;
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = Resume(callback);
if (NS_WARN_IF(aRv.Failed() &&
!aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) {
return nullptr;
}
return promise.forget();
}
nsresult
TelephonyCall::Hold(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
if (mState != TelephonyCallState::Connected) {
NS_WARNING(nsPrintfCString("Hold non-connected call is rejected!"
" (State: %u)", mCallState).get());
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
@@ -383,11 +404,31 @@ TelephonyCall::Hold(nsITelephonyCallback* aCallback)
return NS_OK;
}
already_AddRefed<Promise>
TelephonyCall::Resume(ErrorResult& aRv)
{
RefPtr<Promise> promise = CreatePromise(aRv);
if (!promise) {
return nullptr;
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = Resume(callback);
if (NS_WARN_IF(aRv.Failed() &&
!aRv.ErrorCodeIs(NS_ERROR_DOM_INVALID_STATE_ERR))) {
return nullptr;
}
return promise.forget();
}
nsresult
TelephonyCall::Resume(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
NS_WARNING("Resume non-held call is rejected!");
if (mState != TelephonyCallState::Held) {
NS_WARNING(nsPrintfCString("Resume non-held call is rejected!"
" (State: %s)",
TELEPHONY_CALL_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
+22 -15
View File
@@ -29,7 +29,7 @@ class TelephonyCall final : public DOMEventTargetHelper
RefPtr<TelephonyCallId> mSecondId;
uint32_t mServiceId;
nsString mState;
TelephonyCallState mState;
bool mEmergency;
RefPtr<DOMError> mError;
Nullable<TelephonyCallDisconnectedReason> mDisconnectedReason;
@@ -38,7 +38,6 @@ class TelephonyCall final : public DOMEventTargetHelper
bool mMergeable;
uint32_t mCallIndex;
uint16_t mCallState;
bool mLive;
public:
@@ -65,10 +64,10 @@ public:
already_AddRefed<TelephonyCallId>
GetSecondId() const;
void
GetState(nsString& aState) const
TelephonyCallState
State() const
{
aState.Assign(mState);
return mState;
}
bool
@@ -89,6 +88,14 @@ public:
return mMergeable;
}
bool
IsActive() const
{
return mState == TelephonyCallState::Dialing ||
mState == TelephonyCallState::Alerting ||
mState == TelephonyCallState::Connected;
}
already_AddRefed<DOMError>
GetError() const;
@@ -122,18 +129,24 @@ public:
IMPL_EVENT_HANDLER(error)
IMPL_EVENT_HANDLER(groupchange)
static TelephonyCallState
ConvertToTelephonyCallState(uint32_t aCallState);
static already_AddRefed<TelephonyCall>
Create(Telephony* aTelephony, TelephonyCallId* aId,
uint32_t aServiceId, uint32_t aCallIndex, uint16_t aCallState,
uint32_t aServiceId, uint32_t aCallIndex, TelephonyCallState aState,
bool aEmergency = false, bool aConference = false,
bool aSwitchable = true, bool aMergeable = true);
void
ChangeState(uint16_t aCallState)
ChangeState(TelephonyCallState aState)
{
ChangeStateInternal(aCallState, true);
ChangeStateInternal(aState, true);
}
nsresult
NotifyStateChanged();
uint32_t
ServiceId() const
{
@@ -146,12 +159,6 @@ public:
return mCallIndex;
}
uint16_t
CallState() const
{
return mCallState;
}
void
UpdateEmergency(bool aEmergency)
{
@@ -194,7 +201,7 @@ private:
Resume(nsITelephonyCallback* aCallback);
void
ChangeStateInternal(uint16_t aCallState, bool aFireEvents);
ChangeStateInternal(TelephonyCallState aState, bool aFireEvents);
nsresult
DispatchCallEvent(const nsAString& aType,
+122 -67
View File
@@ -10,16 +10,23 @@
#include "Telephony.h"
#include "mozilla/dom/CallEvent.h"
#include "mozilla/dom/CallGroupErrorEvent.h"
#include "mozilla/dom/TelephonyCallGroupBinding.h"
#include "mozilla/dom/telephony/TelephonyCallback.h"
#include "nsPrintfCString.h"
#ifdef TELEPHONY_GROUP_STATE
#undef TELEPHONY_GROUP_STATE
#endif
#define TELEPHONY_GROUP_STATE(_state) \
(TelephonyCallGroupStateValues::strings[static_cast<int32_t>(_state)].value)
using namespace mozilla::dom;
using namespace mozilla::dom::telephony;
using mozilla::ErrorResult;
TelephonyCallGroup::TelephonyCallGroup(nsPIDOMWindow* aOwner)
: DOMEventTargetHelper(aOwner)
, mCallState(nsITelephonyService::CALL_STATE_UNKNOWN)
{
}
@@ -37,6 +44,7 @@ TelephonyCallGroup::Create(Telephony* aTelephony)
new TelephonyCallGroup(aTelephony->GetOwner());
group->mTelephony = aTelephony;
group->mState = TelephonyCallGroupState::_empty;
group->mCallsList = new CallsList(aTelephony, group);
return group.forget();
@@ -82,48 +90,84 @@ TelephonyCallGroup::NotifyError(const nsAString& aName, const nsAString& aMessag
}
void
TelephonyCallGroup::ChangeState(uint16_t aCallState)
TelephonyCallGroup::ChangeState()
{
if (mCallState == aCallState) {
MOZ_ASSERT(mCalls.Length() != 1);
if (mCalls.Length() == 0) {
ChangeStateInternal(TelephonyCallGroupState::_empty);
return;
}
mCallState = aCallState;
switch (aCallState) {
case nsITelephonyService::CALL_STATE_UNKNOWN:
mState.AssignLiteral("");
break;
case nsITelephonyService::CALL_STATE_CONNECTED:
mState.AssignLiteral("connected");
break;
case nsITelephonyService::CALL_STATE_HELD:
mState.AssignLiteral("held");
break;
default:
NS_NOTREACHED("Unknown state!");
}
nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
if (!mState.IsEmpty()) {
// This can change if the statechange handler called back here... Need to
// figure out something smarter.
if (mCallState == aCallState) {
rv = DispatchCallEvent(mState, nullptr);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch specific event!");
}
TelephonyCallState state = mCalls[0]->State();
for (uint32_t i = 1; i < mCalls.Length(); i++) {
if (mCalls[i]->State() != state) {
MOZ_ASSERT(false, "Various call states are found in a call group!");
ChangeStateInternal(TelephonyCallGroupState::_empty);
return;
}
}
for (uint32_t index = 0; index < mCalls.Length(); index++) {
RefPtr<TelephonyCall> call = mCalls[index];
call->ChangeState(aCallState);
MOZ_ASSERT(call->CallState() == aCallState);
TelephonyCallGroupState groupState = TelephonyCallGroupState::_empty;
switch (state) {
case TelephonyCallState::Connected:
groupState = TelephonyCallGroupState::Connected;
break;
case TelephonyCallState::Held:
groupState = TelephonyCallGroupState::Held;
break;
default:
NS_NOTREACHED(nsPrintfCString("Invavild call state for a call group(%s)!",
TELEPHONY_CALL_STATE(state)).get());
}
ChangeStateInternal(groupState);
}
void
TelephonyCallGroup::ChangeStateInternal(TelephonyCallGroupState aState)
{
if (mState == aState) {
return;
}
// Update Current State
mState = aState;
// Dispatch related events
NotifyStateChanged();
}
nsresult
TelephonyCallGroup::NotifyStateChanged()
{
// Since |mState| can be changed after statechange handler called back here,
// we must save current state. Maybe we should figure out something smarter.
TelephonyCallGroupState prevState = mState;
nsresult res = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch specific event!");
}
// Check whether |mState| remains the same after the statechange handler.
// Besides, If there is no conference call at all, then we dont't have to
// dispatch the state evnet.
if (mState == prevState) {
res = DispatchCallEvent(NS_ConvertASCIItoUTF16(TELEPHONY_GROUP_STATE(mState)),
nullptr);
if (NS_FAILED(res)) {
NS_WARNING("Failed to dispatch specific event!");
}
}
// Notify each call within to dispatch call state change event
for (uint32_t index = 0; index < mCalls.Length(); index++) {
if (NS_FAILED(mCalls[index]->NotifyStateChanged())){
res = NS_ERROR_FAILURE;
}
}
return res;
}
nsresult
@@ -172,14 +216,13 @@ TelephonyCallGroup::CanConference(const TelephonyCall& aCall,
if (!aSecondCall) {
MOZ_ASSERT(!mCalls.IsEmpty());
return (mCallState == nsITelephonyService::CALL_STATE_CONNECTED &&
aCall.CallState() == nsITelephonyService::CALL_STATE_HELD) ||
(mCallState == nsITelephonyService::CALL_STATE_HELD &&
aCall.CallState() == nsITelephonyService::CALL_STATE_CONNECTED);
return (mState == TelephonyCallGroupState::Connected &&
aCall.State() == TelephonyCallState::Held) ||
(mState == TelephonyCallGroupState::Held &&
aCall.State() == TelephonyCallState::Connected);
}
MOZ_ASSERT(mCallState == nsITelephonyService::CALL_STATE_UNKNOWN);
MOZ_ASSERT(mState != TelephonyCallGroupState::_empty);
if (aCall.ServiceId() != aSecondCall->ServiceId()) {
return false;
@@ -189,10 +232,10 @@ TelephonyCallGroup::CanConference(const TelephonyCall& aCall,
return false;
}
return (aCall.CallState() == nsITelephonyService::CALL_STATE_CONNECTED &&
aSecondCall->CallState() == nsITelephonyService::CALL_STATE_HELD) ||
(aCall.CallState() == nsITelephonyService::CALL_STATE_HELD &&
aSecondCall->CallState() == nsITelephonyService::CALL_STATE_CONNECTED);
return (aCall.State() == TelephonyCallState::Connected &&
aSecondCall->State() == TelephonyCallState::Held) ||
(aCall.State() == TelephonyCallState::Held &&
aSecondCall->State() == TelephonyCallState::Connected);
}
already_AddRefed<TelephonyCall>
@@ -297,7 +340,7 @@ TelephonyCallGroup::Remove(TelephonyCall& aCall, ErrorResult& aRv)
return nullptr;
}
if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
if (mState != TelephonyCallGroupState::Connected) {
NS_WARNING("Remove call from a non-connected call group. Ignore!");
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
@@ -330,6 +373,14 @@ TelephonyCallGroup::HangUp(ErrorResult& aRv)
return nullptr;
}
if (mState == TelephonyCallGroupState::_empty) {
NS_WARNING(nsPrintfCString("We don't have a call group now!"
" (State: %s)",
TELEPHONY_GROUP_STATE(mState)).get());
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
aRv = mTelephony->Service()->HangUpConference(mCalls[0]->ServiceId(),
callback);
@@ -357,6 +408,26 @@ TelephonyCallGroup::Hold(ErrorResult& aRv)
return promise.forget();
}
nsresult
TelephonyCallGroup::Hold(nsITelephonyCallback* aCallback)
{
if (mState != TelephonyCallGroupState::Connected) {
NS_WARNING(nsPrintfCString("Resume non-connected call group is rejected!"
" (State: %s)",
TELEPHONY_GROUP_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
nsresult rv = mTelephony->Service()->HoldConference(mCalls[0]->ServiceId(),
aCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
already_AddRefed<Promise>
TelephonyCallGroup::Resume(ErrorResult& aRv)
{
@@ -377,29 +448,13 @@ TelephonyCallGroup::Resume(ErrorResult& aRv)
return promise.forget();
}
nsresult
TelephonyCallGroup::Hold(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
NS_WARNING("Holding a non-connected call is rejected!");
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
nsresult rv = mTelephony->Service()->HoldConference(mCalls[0]->ServiceId(),
aCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
TelephonyCallGroup::Resume(nsITelephonyCallback* aCallback)
{
if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
NS_WARNING("Resuming a non-held call is rejected!");
if (mState != TelephonyCallGroupState::Held) {
NS_WARNING(nsPrintfCString("Resume non-held call group is rejected!"
" (State: %s)",
TELEPHONY_GROUP_STATE(mState)).get());
aCallback->NotifyError(NS_LITERAL_STRING("InvalidStateError"));
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
+18 -13
View File
@@ -8,6 +8,7 @@
#define mozilla_dom_telephony_telephonycallgroup_h__
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/TelephonyCallGroupBinding.h"
#include "mozilla/dom/telephony/TelephonyCommon.h"
namespace mozilla {
@@ -21,9 +22,7 @@ class TelephonyCallGroup final : public DOMEventTargetHelper
RefPtr<CallsList> mCallsList;
nsString mState;
uint16_t mCallState;
TelephonyCallGroupState mState;
public:
NS_DECL_ISUPPORTS_INHERITED
@@ -64,10 +63,15 @@ public:
already_AddRefed<Promise>
Resume(ErrorResult& aRv);
void
GetState(nsString& aState) const
TelephonyCallGroupState
State() const
{
aState = mState;
return mState;
}
bool
IsActive() {
return mState == TelephonyCallGroupState::Connected;
}
IMPL_EVENT_HANDLER(statechange)
@@ -94,14 +98,9 @@ public:
return mCalls;
}
// Update its call state according to the calls wihtin itself.
void
ChangeState(uint16_t aCallState);
uint16_t
CallState() const
{
return mCallState;
}
ChangeState();
nsresult
NotifyError(const nsAString& aName, const nsAString& aMessage);
@@ -116,9 +115,15 @@ private:
nsresult
Resume(nsITelephonyCallback* aCallback);
nsresult
NotifyStateChanged();
nsresult
NotifyCallsChanged(TelephonyCall* aCall);
void
ChangeStateInternal(TelephonyCallGroupState aState);
nsresult
DispatchCallEvent(const nsAString& aType,
TelephonyCall* aCall);
+13
View File
@@ -15,10 +15,13 @@ NS_IMPL_ISUPPORTS(TelephonyCallInfo, nsITelephonyCallInfo)
TelephonyCallInfo::TelephonyCallInfo(uint32_t aClientId,
uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aDisconnectedReason,
const nsAString& aNumber,
uint16_t aNumberPresentation,
const nsAString& aName,
uint16_t aNamePresentation,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference,
@@ -27,10 +30,13 @@ TelephonyCallInfo::TelephonyCallInfo(uint32_t aClientId,
: mClientId(aClientId),
mCallIndex(aCallIndex),
mCallState(aCallState),
mDisconnectedReason(aDisconnectedReason),
mNumber(aNumber),
mNumberPresentation(aNumberPresentation),
mName(aName),
mNamePresentation(aNamePresentation),
mIsOutgoing(aIsOutgoing),
mIsEmergency(aIsEmergency),
mIsConference(aIsConference),
@@ -60,6 +66,13 @@ TelephonyCallInfo::GetCallState(uint16_t* aCallState)
return NS_OK;
}
NS_IMETHODIMP
TelephonyCallInfo::GetDisconnectedReason(nsAString& aDisconnectedReason)
{
aDisconnectedReason = mDisconnectedReason;
return NS_OK;
}
NS_IMETHODIMP
TelephonyCallInfo::GetNumber(nsAString& aNumber)
{
+18 -6
View File
@@ -21,12 +21,21 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSITELEPHONYCALLINFO
TelephonyCallInfo(uint32_t aClientId, uint32_t aCallIndex,
uint16_t aCallState, const nsAString& aNumber,
uint16_t aNumberPresentation, const nsAString& aName,
uint16_t aNamePresentation, bool aIsOutgoing,
bool aIsEmergency, bool aIsConference,
bool aIsSwitchable, bool aIsMergeable);
TelephonyCallInfo(uint32_t aClientId,
uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aDisconnectedReason,
const nsAString& aNumber,
uint16_t aNumberPresentation,
const nsAString& aName,
uint16_t aNamePresentation,
bool aIsOutgoing,
bool aIsEmergency,
bool aIsConference,
bool aIsSwitchable,
bool aIsMergeable);
private:
// Don't try to use the default constructor.
@@ -37,10 +46,13 @@ private:
uint32_t mClientId;
uint32_t mCallIndex;
uint16_t mCallState;
nsString mDisconnectedReason;
nsString mNumber;
uint16_t mNumberPresentation;
nsString mName;
uint16_t mNamePresentation;
bool mIsOutgoing;
bool mIsEmergency;
bool mIsConference;
+1 -1
View File
@@ -59,7 +59,7 @@ TelephonyDialCallback::NotifyDialCallSuccess(uint32_t aClientId,
RefPtr<TelephonyCallId> id = mTelephony->CreateCallId(aNumber);
RefPtr<TelephonyCall> call =
mTelephony->CreateCall(id, aClientId, aCallIndex,
nsITelephonyService::CALL_STATE_DIALING);
TelephonyCallState::Dialing);
mPromise->MaybeResolve(call);
return NS_OK;
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,3 @@
component {67d26434-d063-4d28-9f48-5b3189788155} TelephonyService.js
contract @mozilla.org/telephony/gonktelephonyservice;1 {67d26434-d063-4d28-9f48-5b3189788155}
component {d03684ed-ede4-4210-8206-f4f32772d9f5} TelephonyService.js
contract @mozilla.org/dom/system-messages/wrapper/ussd-received;1 {d03684ed-ede4-4210-8206-f4f32772d9f5}
+109
View File
@@ -0,0 +1,109 @@
/* 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";
this.EXPORTED_SYMBOLS = ["TelephonyUtils"];
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
/* global TelephonyService */
XPCOMUtils.defineLazyServiceGetter(this,
"TelephonyService",
"@mozilla.org/telephony/telephonyservice;1",
"nsITelephonyService");
function getCurrentCalls(aFilter) {
if (aFilter === undefined) {
aFilter = call => true;
}
let calls = [];
// nsITelephonyService.enumerateCalls is synchronous.
TelephonyService.enumerateCalls({
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
enumerateCallStateComplete: function() {},
enumerateCallState: function(call) {
if (aFilter(call)) {
calls.push(call);
}
},
});
return calls;
}
this.TelephonyUtils = {
/**
* Check whether there are any calls.
*
* @param aClientId [optional] If provided, only check on aClientId
* @return boolean
*/
hasAnyCalls: function(aClientId) {
let calls = getCurrentCalls(call => {
if (aClientId !== undefined && call.clientId !== aClientId) {
return false;
}
return true;
});
return calls.length !== 0;
},
/**
* Check whether there are any connected calls.
*
* @param aClientId [optional] If provided, only check on aClientId
* @return boolean
*/
hasConnectedCalls: function(aClientId) {
let calls = getCurrentCalls(call => {
if (aClientId !== undefined && call.clientId !== aClientId) {
return false;
}
return call.callState === Ci.nsITelephonyService.CALL_STATE_CONNECTED;
});
return calls.length !== 0;
},
/**
* Return a promise which will be resolved when there are no calls.
*
* @param aClientId [optional] only check on aClientId if provided
* @return Promise
*/
waitForNoCalls: function(aClientId) {
if (!this.hasAnyCalls(aClientId)) {
return Promise.resolve();
}
let self = this;
return new Promise(resolve => {
let listener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
enumerateCallStateComplete: function() {},
enumerateCallState: function() {},
callStateChanged: function() {
if (!self.hasAnyCalls(aClientId)) {
TelephonyService.unregisterListener(this);
resolve();
}
},
supplementaryServiceNotification: function() {},
notifyError: function() {},
notifyCdmaCallWaiting: function() {},
notifyConferenceError: function() {}
};
TelephonyService.registerListener(listener);
});
}
};
+82
View File
@@ -0,0 +1,82 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 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/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
let DEBUG;
function debug(s) {
dump("USSDReceivedWrapper: " + s + "\n");
}
XPCOMUtils.defineLazyGetter(this, "RIL", function () {
let obj = {};
Cu.import("resource://gre/modules/ril_consts.js", obj);
return obj;
});
/**
* This implements nsISystemMessagesWrapper.wrapMessage(), which provides a
* plugable way to wrap a "ussd-received" type system message.
*
* Please see SystemMessageManager.js to know how it customizes the wrapper.
*/
function USSDReceivedWrapper() {
this._updateDebugFlag();
Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
if (DEBUG) debug("USSDReceivedWrapper()");
}
USSDReceivedWrapper.prototype = {
_updateDebugFlag: function() {
try {
DEBUG = RIL.DEBUG_RIL ||
Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
} catch (e) {}
},
/**
* nsIObserver interface.
*/
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
if (aData === kPrefRilDebuggingEnabled) {
this._updateDebugFlag();
}
break;
}
},
// nsISystemMessagesWrapper implementation.
wrapMessage: function(aMessage, aWindow) {
if (DEBUG) debug("wrapMessage: " + JSON.stringify(aMessage));
let session = aMessage.sessionEnded ? null :
new aWindow.USSDSession(aMessage.serviceId);
let event = new aWindow.USSDReceivedEvent("ussdreceived", {
serviceId: aMessage.serviceId,
message: aMessage.message,
session: session
});
return event;
},
classDescription: "USSDReceivedWrapper",
classID: Components.ID("{d03684ed-ede4-4210-8206-f4f32772d9f5}"),
contractID: "@mozilla.org/dom/system-messages/wrapper/ussd-received;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISystemMessagesWrapper])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([USSDReceivedWrapper]);
@@ -0,0 +1,2 @@
component {d03684ed-ede4-4210-8206-f4f32772d9f5} USSDReceivedWrapper.js
contract @mozilla.org/dom/system-messages/wrapper/ussd-received;1 {d03684ed-ede4-4210-8206-f4f32772d9f5}
-4
View File
@@ -125,14 +125,10 @@ sync protocol PTelephony {
manages PTelephonyRequest;
child:
NotifyCallError(uint32_t aClientId, int32_t aCallIndex, nsString aError);
NotifyCallStateChanged(nsTelephonyCallInfo[] aAllInfo);
NotifyCdmaCallWaiting(uint32_t aClientId, IPCCdmaWaitingCallData aData);
NotifyConferenceCallStateChanged(uint16_t aCallState);
NotifyConferenceError(nsString aName, nsString aMessage);
NotifySupplementaryService(uint32_t aClientId, int32_t aCallIndex,
-20
View File
@@ -47,17 +47,6 @@ TelephonyChild::DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor)
return true;
}
bool
TelephonyChild::RecvNotifyCallError(const uint32_t& aClientId,
const int32_t& aCallIndex,
const nsString& aError)
{
MOZ_ASSERT(mService);
mService->NotifyError(aClientId, aCallIndex, aError);
return true;
}
bool
TelephonyChild::RecvNotifyCallStateChanged(nsTArray<nsITelephonyCallInfo*>&& aAllInfo)
{
@@ -91,15 +80,6 @@ TelephonyChild::RecvNotifyCdmaCallWaiting(const uint32_t& aClientId,
return true;
}
bool
TelephonyChild::RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState)
{
MOZ_ASSERT(mService);
mService->ConferenceCallStateChanged(aCallState);
return true;
}
bool
TelephonyChild::RecvNotifyConferenceError(const nsString& aName,
const nsString& aMessage)
-7
View File
@@ -34,10 +34,6 @@ protected:
virtual bool
DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor) override;
virtual bool
RecvNotifyCallError(const uint32_t& aClientId, const int32_t& aCallIndex,
const nsString& aError) override;
virtual bool
RecvNotifyCallStateChanged(nsTArray<nsITelephonyCallInfo*>&& aAllInfo) override;
@@ -45,9 +41,6 @@ protected:
RecvNotifyCdmaCallWaiting(const uint32_t& aClientId,
const IPCCdmaWaitingCallData& aData) override;
virtual bool
RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState) override;
virtual bool
RecvNotifyConferenceError(const nsString& aName,
const nsString& aMessage) override;
+30 -4
View File
@@ -37,10 +37,13 @@ struct ParamTraits<nsITelephonyCallInfo*>
uint32_t clientId;
uint32_t callIndex;
uint16_t callState;
nsString disconnectedReason;
nsString number;
uint16_t numberPresentation;
nsString name;
uint16_t namePresentation;
bool isOutgoing;
bool isEmergency;
bool isConference;
@@ -50,10 +53,13 @@ struct ParamTraits<nsITelephonyCallInfo*>
aParam->GetClientId(&clientId);
aParam->GetCallIndex(&callIndex);
aParam->GetCallState(&callState);
aParam->GetDisconnectedReason(disconnectedReason);
aParam->GetNumber(number);
aParam->GetNumberPresentation(&numberPresentation);
aParam->GetName(name);
aParam->GetNamePresentation(&namePresentation);
aParam->GetIsOutgoing(&isOutgoing);
aParam->GetIsEmergency(&isEmergency);
aParam->GetIsConference(&isConference);
@@ -63,10 +69,13 @@ struct ParamTraits<nsITelephonyCallInfo*>
WriteParam(aMsg, clientId);
WriteParam(aMsg, callIndex);
WriteParam(aMsg, callState);
WriteParam(aMsg, disconnectedReason);
WriteParam(aMsg, number);
WriteParam(aMsg, numberPresentation);
WriteParam(aMsg, name);
WriteParam(aMsg, namePresentation);
WriteParam(aMsg, isOutgoing);
WriteParam(aMsg, isEmergency);
WriteParam(aMsg, isConference);
@@ -90,10 +99,13 @@ struct ParamTraits<nsITelephonyCallInfo*>
uint32_t clientId;
uint32_t callIndex;
uint16_t callState;
nsString disconnectedReason;
nsString number;
uint16_t numberPresentation;
nsString name;
uint16_t namePresentation;
bool isOutgoing;
bool isEmergency;
bool isConference;
@@ -104,10 +116,13 @@ struct ParamTraits<nsITelephonyCallInfo*>
if (!(ReadParam(aMsg, aIter, &clientId) &&
ReadParam(aMsg, aIter, &callIndex) &&
ReadParam(aMsg, aIter, &callState) &&
ReadParam(aMsg, aIter, &disconnectedReason) &&
ReadParam(aMsg, aIter, &number) &&
ReadParam(aMsg, aIter, &numberPresentation) &&
ReadParam(aMsg, aIter, &name) &&
ReadParam(aMsg, aIter, &namePresentation) &&
ReadParam(aMsg, aIter, &isOutgoing) &&
ReadParam(aMsg, aIter, &isEmergency) &&
ReadParam(aMsg, aIter, &isConference) &&
@@ -117,10 +132,21 @@ struct ParamTraits<nsITelephonyCallInfo*>
}
nsCOMPtr<nsITelephonyCallInfo> info =
new TelephonyCallInfo(clientId, callIndex, callState, number,
numberPresentation, name, namePresentation,
isOutgoing, isEmergency, isConference,
isSwitchable, isMergeable);
new TelephonyCallInfo(clientId,
callIndex,
callState,
disconnectedReason,
number,
numberPresentation,
name,
namePresentation,
isOutgoing,
isEmergency,
isConference,
isSwitchable,
isMergeable);
info.forget(aResult);
-19
View File
@@ -376,15 +376,6 @@ TelephonyIPCService::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** a
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCService::ConferenceCallStateChanged(uint16_t aCallState)
{
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->ConferenceCallStateChanged(aCallState);
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCService::EnumerateCallStateComplete()
{
@@ -421,16 +412,6 @@ TelephonyIPCService::NotifyConferenceError(const nsAString& aName,
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCService::NotifyError(uint32_t aClientId, int32_t aCallIndex,
const nsAString& aError)
{
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->NotifyError(aClientId, aCallIndex, aError);
}
return NS_OK;
}
NS_IMETHODIMP
TelephonyIPCService::SupplementaryServiceNotification(uint32_t aClientId,
int32_t aCallIndex,
-34
View File
@@ -286,15 +286,6 @@ TelephonyParent::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo** aAllI
return SendNotifyCallStateChanged(allInfo) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::ConferenceCallStateChanged(uint16_t aCallState)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
return SendNotifyConferenceCallStateChanged(aCallState) ? NS_OK
: NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::EnumerateCallStateComplete()
{
@@ -331,17 +322,6 @@ TelephonyParent::NotifyConferenceError(const nsAString& aName,
: NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::NotifyError(uint32_t aClientId,
int32_t aCallIndex,
const nsAString& aError)
{
NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
return SendNotifyCallError(aClientId, aCallIndex, nsString(aError))
? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
TelephonyParent::SupplementaryServiceNotification(uint32_t aClientId,
int32_t aCallIndex,
@@ -392,12 +372,6 @@ TelephonyRequestParent::CallStateChanged(uint32_t aLength, nsITelephonyCallInfo*
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::ConferenceCallStateChanged(uint16_t aCallState)
{
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::EnumerateCallStateComplete()
{
@@ -431,14 +405,6 @@ TelephonyRequestParent::NotifyConferenceError(const nsAString& aName,
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::NotifyError(uint32_t aClientId,
int32_t aCallIndex,
const nsAString& aError)
{
MOZ_CRASH("Not a TelephonyParent!");
}
NS_IMETHODIMP
TelephonyRequestParent::SupplementaryServiceNotification(uint32_t aClientId,
int32_t aCallIndex,
+7 -1
View File
@@ -63,6 +63,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
EXTRA_COMPONENTS += [
'gonk/TelephonyAudioService.js',
'gonk/TelephonyAudioService.manifest',
'gonk/USSDReceivedWrapper.js',
'gonk/USSDReceivedWrapper.manifest',
]
if not CONFIG['DISABLE_MOZ_RIL_GEOLOC']:
EXTRA_COMPONENTS += [
@@ -70,9 +72,13 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
'gonk/TelephonyService.manifest',
]
EXTRA_JS_MODULES += [
'gonk/DialNumberUtils.jsm'
'gonk/DialNumberUtils.jsm',
'gonk/TelephonyUtils.jsm',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
+9 -1
View File
@@ -4,7 +4,7 @@
#include "nsISupports.idl"
[scriptable, uuid(3ea2d155-8ea2-42be-85d7-bd8ede8afc40)]
[scriptable, uuid(e5e1be26-a3d4-49b3-8d9f-c1df5192b364)]
interface nsITelephonyCallInfo : nsISupports
{
/**
@@ -22,6 +22,14 @@ interface nsITelephonyCallInfo : nsISupports
*/
readonly attribute unsigned short callState;
/**
* The disconnectedReason of a call is defualt to an empty string when the
* call is "not disconnected", but once the call becomes "disconnected" the
* disconnectedReason should be a non-empty string no matter the call is
* disconnected for a noraml reason or an error.
*/
readonly attribute DOMString disconnectedReason;
/**
* Number of the other party.
*/
+1 -26
View File
@@ -7,7 +7,7 @@
interface nsIMobileCallForwardingOptions;
interface nsITelephonyCallInfo;
[scriptable, uuid(37fb45bb-ae10-4cfd-b24e-d656a9787a0a)]
[scriptable, uuid(baa9f5f3-5cab-40e0-81e9-ae0abd917907)]
interface nsITelephonyListener : nsISupports
{
/**
@@ -29,17 +29,6 @@ interface nsITelephonyListener : nsISupports
void callStateChanged(in unsigned long length,
[array, size_is(length)] in nsITelephonyCallInfo allInfo);
/**
* Called when participants of a conference call have been updated, and the
* conference call state changes.
*
* @param callState
* Possible values are: nsITelephonyService::CALL_STATE_UNKNOWN,
* nsITelephonyService::CALL_STATE_HELD,
* nsITelephonyService::CALL_STATE_CONNECTED.
*/
void conferenceCallStateChanged(in unsigned short callState);
/**
* Notify when RIL receives supplementary service notification.
*
@@ -54,20 +43,6 @@ interface nsITelephonyListener : nsISupports
in long callIndex,
in unsigned short notification);
/**
* Called when RIL error occurs.
*
* @param clientId
Indicate the RIL client, 0 ~ (number of client - 1).
* @param callIndex
* Call identifier assigned by the RIL. -1 if no connection
* @param error
* Error from RIL.
*/
void notifyError(in unsigned long clientId,
in long callIndex,
in AString error);
/**
* Called when a waiting call comes in CDMA networks.
*
+6
View File
@@ -1022,6 +1022,11 @@ let emulator = (function() {
});
}
function sendTone(tone, pause, serviceId) {
log("Send DTMF " + tone + " serviceId " + serviceId);
return telephony.sendTones(tone, pause, null, serviceId);
}
/**
* Config radio.
*
@@ -1085,6 +1090,7 @@ let emulator = (function() {
this.gRemoveCallInConference = removeCallInConference;
this.gHangUpCallInConference = hangUpCallInConference;
this.gHangUpConference = hangUpConference;
this.gSendTone = sendTone;
this.gSetupConference = setupConference;
this.gSetRadioEnabled = setRadioEnabled;
}());
+3 -1
View File
@@ -21,6 +21,7 @@ qemu = true
[test_dsds_connection_conflict.js]
[test_dsds_default_service_id.js]
[test_dsds_normal_call.js]
[test_dtmf.js]
[test_emergency.js]
[test_emergency_label.js]
[test_incall_mmi_call_hold.js]
@@ -32,7 +33,6 @@ qemu = true
[test_incoming_answer_hangup_oncallschanged.js]
[test_incoming_basic_operations.js]
[test_incoming_onstatechange.js]
[test_mmi.js]
[test_mmi_call_barring.js]
[test_mmi_call_forwarding.js]
[test_mmi_call_waiting.js]
@@ -41,6 +41,7 @@ qemu = true
[test_mmi_change_pin2.js]
[test_mmi_clip.js]
[test_mmi_clir.js]
[test_mmi_imei.js]
[test_mmi_unlock_puk.js]
[test_mmi_unlock_puk2.js]
[test_mmi_ussd.js]
@@ -58,4 +59,5 @@ qemu = true
[test_ready.js]
[test_redundant_operations.js]
[test_swap_held_and_active.js]
[test_TelephonyUtils.js]
[test_temporary_clir.js]
@@ -0,0 +1,91 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 60000;
MARIONETTE_CONTEXT = "chrome";
MARIONETTE_HEAD_JS = 'head.js';
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyServiceGetter(this,
"TelephonyService",
"@mozilla.org/telephony/telephonyservice;1",
"nsIGonkTelephonyService");
XPCOMUtils.defineLazyModuleGetter(this, "TelephonyUtils",
"resource://gre/modules/TelephonyUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "RIL", function () {
let ns = {};
Cu.import("resource://gre/modules/ril_consts.js", ns);
return ns;
});
const number = "0912345678";
function dial() {
return new Promise(resolve => {
TelephonyService.dial(0, number, false, {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyDialCallback]),
notifyDialCallSuccess: function() { resolve(); }
});
});
}
function waitForStateChanged() {
return new Promise(resolve => {
let listener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
callStateChanged: function(length, allInfo) {
resolve(allInfo);
TelephonyService.unregisterListener(listener);
},
conferenceCallStateChanged: function() {},
supplementaryServiceNotification: function() {},
notifyError: function() {},
notifyCdmaCallWaiting: function() {},
notifyConferenceError: function() {}
};
TelephonyService.registerListener(listener);
});
}
function test_noCall() {
log("== test_noCall ==");
is(TelephonyUtils.hasAnyCalls(), false, "hasAnyCalls");
is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls");
return TelephonyUtils.waitForNoCalls();
}
function test_oneCall() {
log("== test_oneCall ==");
return dial()
.then(() => {
is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls");
is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls");
})
.then(() => {
let p = waitForStateChanged();
emulator.runCmd("gsm accept " + number);
return p;
})
.then(allInfo => {
is(allInfo[0].callState, Ci.nsITelephonyService.CALL_STATE_CONNECTED);
is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls");
is(TelephonyUtils.hasConnectedCalls(), true, "hasConnectedCalls");
})
.then(() => {
let p = TelephonyUtils.waitForNoCalls();
emulator.runCmd("gsm cancel " + number);
return p;
});
}
test_noCall()
.then(test_oneCall)
.catch(error => ok(false, "Promise reject: " + error))
.then(finish);

Some files were not shown because too many files have changed in this diff Show More