diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index a332a160c836..feaafbb93466 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 8ad0c6f2a938..8b4a531b49ca 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 7a095ece86d5..fa37d5d70e55 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + @@ -134,7 +134,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index ed2102d4a01f..ff6b48609111 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 8ad0c6f2a938..8b4a531b49ca 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 90cf921d6666..7db74a4d186a 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -151,7 +151,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index bb3a9eeefb1a..2076adf92a1a 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + @@ -145,7 +145,7 @@ - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 423126337474..e89440c295b4 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "69b4d72a6b80008de044e535d9ff785631bd7f2b", + "revision": "291b607f32e6173d8fe225c644cc7397cdf82fa5", "repo_path": "/integration/gaia-central" } diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 0f562a1b1bf4..dc0128dfa926 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index b166606dab89..51d5693379bf 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index dab254806024..a5b5ee9fc4e3 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + @@ -129,7 +129,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 1a3d431a85a1..373ecf9cc9bf 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/dom/mobileconnection/gonk/MobileConnectionService.js b/dom/mobileconnection/gonk/MobileConnectionService.js index 74786b3f3a6c..8d865d351e32 100644 --- a/dom/mobileconnection/gonk/MobileConnectionService.js +++ b/dom/mobileconnection/gonk/MobileConnectionService.js @@ -950,6 +950,11 @@ MobileConnectionService.prototype = { } catch (e) {} }, + _broadcastCdmaInfoRecordSystemMessage: function(aMessage) { + // TODO: Bug 1072808, Broadcast System Message with proxy. + gSystemMessenger.broadcastMessage("cdma-info-rec-received", aMessage); + }, + /** * nsIMobileConnectionService interface. */ @@ -1167,6 +1172,111 @@ MobileConnectionService.prototype = { aServiceClass); }, + notifyCdmaInfoRecDisplay: function(aClientId, aDisplay) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + display: aDisplay + }); + }, + + notifyCdmaInfoRecCalledPartyNumber: function(aClientId, aType, aPlan, aNumber, + aPi, aSi) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + calledNumber: { + type: aType, + plan: aPlan, + number: aNumber, + pi: aPi, + si: aSi + } + }); + }, + + notifyCdmaInfoRecCallingPartyNumber: function(aClientId, aType, aPlan, aNumber, + aPi, aSi) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + callingNumber: { + type: aType, + plan: aPlan, + number: aNumber, + pi: aPi, + si: aSi + } + }); + }, + + notifyCdmaInfoRecConnectedPartyNumber: function(aClientId, aType, aPlan, aNumber, + aPi, aSi) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + connectedNumber: { + type: aType, + plan: aPlan, + number: aNumber, + pi: aPi, + si: aSi + } + }); + }, + + notifyCdmaInfoRecSignal: function(aClientId, aType, aAlertPitch, aSignal){ + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + signal: { + type: aType, + alertPitch: aAlertPitch, + signal: aSignal + } + }); + }, + + notifyCdmaInfoRecRedirectingNumber: function(aClientId, aType, aPlan, aNumber, + aPi, aSi, aReason) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + redirect: { + type: aType, + plan: aPlan, + number: aNumber, + pi: aPi, + si: aSi, + reason: aReason + } + }); + }, + + notifyCdmaInfoRecLineControl: function(aClientId, aPolarityIncluded, aToggle, + aReverse, aPowerDenial) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + lineControl: { + polarityIncluded: aPolarityIncluded, + toggle: aToggle, + reverse: aReverse, + powerDenial: aPowerDenial + } + }); + }, + + notifyCdmaInfoRecClir: function(aClientId, aCause) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + clirCause: aCause + }); + }, + + notifyCdmaInfoRecAudioControl: function(aClientId, aUplink, aDownLink) { + this._broadcastCdmaInfoRecordSystemMessage({ + clientId: aClientId, + audioControl: { + upLink: aUplink, + downLink: aDownLink + } + }); + }, + /** * nsIObserver interface. */ diff --git a/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl b/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl index 1692e896a098..652ca4c66143 100644 --- a/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl +++ b/dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl @@ -9,7 +9,7 @@ "@mozilla.org/mobileconnection/gonkmobileconnectionservice;1" %} -[scriptable, uuid(b0310517-e7f6-4fa5-a52e-fa6ff35c8fc1)] +[scriptable, uuid(2d574f0e-4a02-11e4-b1b3-cbc14b7608ce)] interface nsIGonkMobileConnectionService : nsIMobileConnectionService { void notifyNetworkInfoChanged(in unsigned long clientId, in jsval networkInfo); @@ -53,4 +53,205 @@ interface nsIGonkMobileConnectionService : nsIMobileConnectionService in DOMString number, in unsigned short timeSeconds, in unsigned short serviceClass); + + /** + * Notify Display Info from received Cdma-Info-Record. + * See 3.7.4.1 Display in 3GPP2 C.S0005-F. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param display + The string to be displayed. + */ + void notifyCdmaInfoRecDisplay(in unsigned long clientId, + in DOMString display); + + /** + * Notify Called Party Number from received Cdma-Info-Record. + * See 3.7.4.2 Called Party Number in 3GPP2 C.S0005-F. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param type + * The type of number. (3-bit binary) + * See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F. + * @param plan + * The numbering plan. (4-bit binary) + * See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F. + * @param number + * The string presentation of the number. + * @param pi (2-bit binary) + * The Presentation indicator of the number. + * See Table 2.7.4.4-1 in 3GPP2 C.S0005-F. + * @param si (2-bit binary) + * The Screening Indicator of the number. + * See Table 2.7.4.4-2 in 3GPP2 C.S0005-F. + */ + void notifyCdmaInfoRecCalledPartyNumber(in unsigned long clientId, + in unsigned short type, + in unsigned short plan, + in DOMString number, + in unsigned short pi, + in unsigned short si); + + /** + * Notify Calling Party Number from received Cdma-Info-Record. + * See 3.7.4.3 Calling Party Number in 3GPP2 C.S0005-F. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param type + * The type of number. (3-bit binary) + * See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F. + * @param plan + * The numbering plan. (4-bit binary) + * See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F. + * @param number + * The string presentation of the number. + * @param pi (2-bit binary) + * The Presentation indicator of the number. + * See Table 2.7.4.4-1 in 3GPP2 C.S0005-F. + * @param si (2-bit binary) + * The Screening Indicator of the number. + * See Table 2.7.4.4-2 in 3GPP2 C.S0005-F. + */ + void notifyCdmaInfoRecCallingPartyNumber(in unsigned long clientId, + in unsigned short type, + in unsigned short plan, + in DOMString number, + in unsigned short pi, + in unsigned short si); + + /** + * Notify Connected Party Number from received Cdma-Info-Record. + * See 3.7.4.4 Connected Party Number in 3GPP2 C.S0005-F. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param type + * The type of number. (3-bit binary) + * See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F. + * @param plan + * The numbering plan. (4-bit binary) + * See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F. + * @param number + * The string presentation of the number. + * @param pi (2-bit binary) + * The Presentation indicator of the number. + * See Table 2.7.4.4-1 in 3GPP2 C.S0005-F. + * @param si (2-bit binary) + * The Screening Indicator of the number. + * See Table 2.7.4.4-2 in 3GPP2 C.S0005-F. + */ + void notifyCdmaInfoRecConnectedPartyNumber(in unsigned long clientId, + in unsigned short type, + in unsigned short plan, + in DOMString number, + in unsigned short pi, + in unsigned short si); + + /** + * Notify Signal Info from received Cdma-Info-Record. + * See 3.7.4.5 Signal in 3GPP2 C.S0005-F. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param type + * The signal type. (2-bit binary) + * See Table 3.7.5.5-1 in 3GPP2 C.S0005-F. + * @param alertPitch + * The pitch of the alerting signal. (2-bit binary) + * See Table 3.7.5.5-2 in 3GPP2 C.S0005-F. + * @param signal + * The signal code. (6-bit binary) + * See Table 3.7.5.5-3, 3.7.5.5-4, 3.7.5.5-5 in 3GPP2 C.S0005-F. + */ + void notifyCdmaInfoRecSignal(in unsigned long clientId, + in unsigned short type, + in unsigned short alertPitch, + in unsigned short signal); + + /** + * Notify Redirecting Number from received Cdma-Info-Record. + * See 3.7.4.11 Redirecting Number in 3GPP2 C.S0005-F. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param type + * The type of number. (3-bit binary) + * See Table 2.7.1.3.2.4-2 in 3GPP2 C.S0005-F. + * @param plan + * The numbering plan. (4-bit binary) + * See Table 2.7.1.3.2.4-3 in 3GPP2 C.S0005-F. + * @param number + * The string presentation of the number. + * @param pi (2-bit binary) + * The Presentation indicator of the number. + * See Table 2.7.4.4-1 in 3GPP2 C.S0005-F. + * @param si (2-bit binary) + * The Screening Indicator of the number. + * See Table 2.7.4.4-2 in 3GPP2 C.S0005-F. + * @param reason (4-bit binary) + * The redirection reason. + * See Table 3.7.5.11-1 in 3GPP2 C.S0005-F. + */ + void notifyCdmaInfoRecRedirectingNumber(in unsigned long clientId, + in unsigned short type, + in unsigned short plan, + in DOMString number, + in unsigned short pi, + in unsigned short si, + in unsigned short reason); + + /** + * Notify Line Control from received Cdma-Info-Record. + * See 3.7.4.15 Line Control in 3GPP2 C.S0005-F. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param polarityIncluded (1-bit) + * Polarity parameter included. + * @param toggle (1-bit) + * Toggle mode. + * @param reverse (1-bit) + * Reverse polarity. + * @param powerDenial (8-bit) + * Power denial timeout. + */ + void notifyCdmaInfoRecLineControl(in unsigned long clientId, + in unsigned short polarityIncluded, + in unsigned short toggle, + in unsigned short reverse, + in unsigned short powerDenial); + + /** + * Notify CLIR from received Cdma-Info-Record. + * See 'ANNEX 1 Country-Specific Record Type for Japan' in T53. + * http://www.arib.or.jp/english/html/overview/doc/T53v6_5_pdf/5_ANNEX_v6_5.pdf + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param cause + * Reason code. (8-bit binary) + * See Table A 1.1-1 in T53. + */ + void notifyCdmaInfoRecClir(in unsigned long clientId, + in unsigned short cause); + + /** + * Notify Audio Control from received Cdma-Info-Record. + * + * Note: No information from ARIB about Audio Control. + * It seems obsolete according to ANNEX 1 in T53. + * upLink/downLink are 'byte' value according to ril.h. + * Treat them as 'signed short' to preserve the flexibility when needed. + * + * @param clientId + * The ID of radioInterface where this info is notified from. + * @param upLink + * @param downLink + */ + void notifyCdmaInfoRecAudioControl(in unsigned long clientId, + in short upLink, + in short downLink); }; diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 65578af7cafe..14999940d94d 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -396,13 +396,6 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() { } }, - sendMobileConnectionMessage: function(message, clientId, data) { - this._sendTargetMessage("mobileconnection", message, { - clientId: clientId, - data: data - }); - }, - sendIccMessage: function(message, clientId, data) { this._sendTargetMessage("icc", message, { clientId: clientId, @@ -1163,7 +1156,7 @@ DataConnectionHandler.prototype = { _compareDataCallOptions: function(dataCall, newDataCall) { return dataCall.apnProfile.apn == newDataCall.apn && dataCall.apnProfile.user == newDataCall.user && - dataCall.apnProfile.password == newDataCall.password && + dataCall.apnProfile.password == newDataCall.passwd && dataCall.chappap == newDataCall.chappap && dataCall.pdptype == newDataCall.pdptype; }, @@ -2091,8 +2084,7 @@ RadioInterface.prototype = { gMessageManager.sendIccMessage("RIL:StkSessionEnd", this.clientId, null); break; case "cdma-info-rec-received": - if (DEBUG) this.debug("cdma-info-rec-received: " + JSON.stringify(message)); - gSystemMessenger.broadcastMessage("cdma-info-rec-received", message); + this.handleCdmaInformationRecords(message.records); break; default: throw new Error("Don't know about this message type: " + @@ -2920,6 +2912,99 @@ RadioInterface.prototype = { hasEtwsInfo ? etwsInfo.popup : false); }, + handleCdmaInformationRecords: function(aRecords) { + if (DEBUG) this.debug("cdma-info-rec-received: " + JSON.stringify(aRecords)); + + let clientId = this.clientId; + + aRecords.forEach(function(aRecord) { + if (aRecord.display) { + gMobileConnectionService + .notifyCdmaInfoRecDisplay(clientId, aRecord.display); + return; + } + + if (aRecord.calledNumber) { + gMobileConnectionService + .notifyCdmaInfoRecCalledPartyNumber(clientId, + aRecord.calledNumber.type, + aRecord.calledNumber.plan, + aRecord.calledNumber.number, + aRecord.calledNumber.pi, + aRecord.calledNumber.si); + return; + } + + if (aRecord.callingNumber) { + gMobileConnectionService + .notifyCdmaInfoRecCallingPartyNumber(clientId, + aRecord.callingNumber.type, + aRecord.callingNumber.plan, + aRecord.callingNumber.number, + aRecord.callingNumber.pi, + aRecord.callingNumber.si); + return; + } + + if (aRecord.connectedNumber) { + gMobileConnectionService + .notifyCdmaInfoRecConnectedPartyNumber(clientId, + aRecord.connectedNumber.type, + aRecord.connectedNumber.plan, + aRecord.connectedNumber.number, + aRecord.connectedNumber.pi, + aRecord.connectedNumber.si); + return; + } + + if (aRecord.signal) { + gMobileConnectionService + .notifyCdmaInfoRecSignal(clientId, + aRecord.signal.type, + aRecord.signal.alertPitch, + aRecord.signal.signal); + return; + } + + if (aRecord.redirect) { + gMobileConnectionService + .notifyCdmaInfoRecRedirectingNumber(clientId, + aRecord.redirect.type, + aRecord.redirect.plan, + aRecord.redirect.number, + aRecord.redirect.pi, + aRecord.redirect.si, + aRecord.redirect.reason); + return; + } + + if (aRecord.lineControl) { + gMobileConnectionService + .notifyCdmaInfoRecLineControl(clientId, + aRecord.lineControl.polarityIncluded, + aRecord.lineControl.toggle, + aRecord.lineControl.reverse, + aRecord.lineControl.powerDenial); + return; + } + + if (aRecord.clirCause) { + gMobileConnectionService + .notifyCdmaInfoRecClir(clientId, + aRecord.clirCause); + return; + } + + if (aRecord.audioControl) { + gMobileConnectionService + .notifyCdmaInfoRecAudioControl(clientId, + aRecord.audioControl.upLink, + aRecord.audioControl.downLink); + return; + } + }); + }, + // nsIObserver observe: function(subject, topic, data) { diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 455ec31c4148..8970f8b07602 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -6920,9 +6920,10 @@ RilObject.prototype[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function UNSOLICITE status: status}); }; RilObject.prototype[UNSOLICITED_CDMA_INFO_REC] = function UNSOLICITED_CDMA_INFO_REC(length) { - let record = this.context.CdmaPDUHelper.decodeInformationRecord(); - record.rilMessageType = "cdma-info-rec-received"; - this.sendChromeMessage(record); + this.sendChromeMessage({ + rilMessageType: "cdma-info-rec-received", + records: this.context.CdmaPDUHelper.decodeInformationRecord() + }); }; RilObject.prototype[UNSOLICITED_OEM_HOOK_RAW] = null; RilObject.prototype[UNSOLICITED_RINGBACK_TONE] = null; @@ -9987,11 +9988,13 @@ CdmaPDUHelperObject.prototype = { */ decodeInformationRecord: function() { let Buf = this.context.Buf; - let record = {}; + let records = []; let numOfRecords = Buf.readInt32(); let type; + let record; for (let i = 0; i < numOfRecords; i++) { + record = {}; type = Buf.readInt32(); switch (type) { @@ -9999,6 +10002,7 @@ CdmaPDUHelperObject.prototype = { * Every type is encaped by ril, except extended display */ case PDU_CDMA_INFO_REC_TYPE_DISPLAY: + case PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY: record.display = Buf.readString(); break; case PDU_CDMA_INFO_REC_TYPE_CALLED_PARTY_NUMBER: @@ -10027,7 +10031,10 @@ CdmaPDUHelperObject.prototype = { break; case PDU_CDMA_INFO_REC_TYPE_SIGNAL: record.signal = {}; - record.signal.present = Buf.readInt32(); + if (!Buf.readInt32()) { // Non-zero if signal is present. + Buf.seekIncoming(3 * Buf.UINT32_SIZE); + continue; + } record.signal.type = Buf.readInt32(); record.signal.alertPitch = Buf.readInt32(); record.signal.signal = Buf.readInt32(); @@ -10045,40 +10052,11 @@ CdmaPDUHelperObject.prototype = { record.lineControl = {}; record.lineControl.polarityIncluded = Buf.readInt32(); record.lineControl.toggle = Buf.readInt32(); - record.lineControl.recerse = Buf.readInt32(); + record.lineControl.reverse = Buf.readInt32(); record.lineControl.powerDenial = Buf.readInt32(); break; - case PDU_CDMA_INFO_REC_TYPE_EXTENDED_DISPLAY: - let length = Buf.readInt32(); - /* - * Extended display is still in format defined in - * C.S0005-F v1.0, 3.7.5.16 - */ - record.extendedDisplay = {}; - - let headerByte = Buf.readInt32(); - length--; - // Based on spec, headerByte must be 0x80 now - record.extendedDisplay.indicator = (headerByte >> 7); - record.extendedDisplay.type = (headerByte & 0x7F); - record.extendedDisplay.records = []; - - while (length > 0) { - let display = {}; - - display.tag = Buf.readInt32(); - length--; - if (display.tag !== INFO_REC_EXTENDED_DISPLAY_BLANK && - display.tag !== INFO_REC_EXTENDED_DISPLAY_SKIP) { - display.content = Buf.readString(); - length -= (display.content.length + 1); - } - - record.extendedDisplay.records.push(display); - } - break; case PDU_CDMA_INFO_REC_TYPE_T53_CLIR: - record.cause = Buf.readInt32(); + record.clirCause = Buf.readInt32(); break; case PDU_CDMA_INFO_REC_TYPE_T53_AUDIO_CONTROL: record.audioControl = {}; @@ -10088,11 +10066,13 @@ CdmaPDUHelperObject.prototype = { case PDU_CDMA_INFO_REC_TYPE_T53_RELEASE: // Fall through default: - throw new Error("UNSOLICITED_CDMA_INFO_REC(), Unsupported information record type " + record.type + "\n"); + throw new Error("UNSOLICITED_CDMA_INFO_REC(), Unsupported information record type " + type + "\n"); } + + records.push(record); } - return record; + return records; } }; diff --git a/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js b/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js index aa5f85caaa8c..3eaab37efaf0 100644 --- a/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js +++ b/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js @@ -36,6 +36,10 @@ function newWorkerWithParcel(parcelBuf) { return buf[index++]; }; + context.Buf.seekIncoming = function(offset) { + index += offset / context.Buf.UINT32_SIZE; + }; + return worker; } @@ -53,9 +57,9 @@ add_test(function test_display() { 0x6F, 0x00]); let context = worker.ContextPool._contexts[0]; let helper = context.CdmaPDUHelper; - let record = helper.decodeInformationRecord(); + let records = helper.decodeInformationRecord(); - do_check_eq(record.display, "Test Info"); + do_check_eq(records[0].display, "Test Info"); run_next_test(); }); @@ -67,27 +71,19 @@ add_test(function test_extended_display() { let worker = newWorkerWithParcel([ 0x01, // one inforemation record 0x07, // type: extended display - 0x0E, // length: 14 - 0x80, // header byte - 0x80, // Blank - 0x81, // Skip - 0x9B, // Text - 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, - 0x66, 0x6F, 0x00]); + 0x12, // length: 18 + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x78, 0x74, + 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x49, 0x6E, + 0x66, 0x6F, 0x00, 0x00]); let context = worker.ContextPool._contexts[0]; let helper = context.CdmaPDUHelper; - let record = helper.decodeInformationRecord(); + let records = helper.decodeInformationRecord(); - do_check_eq(record.extendedDisplay.indicator, 1); - do_check_eq(record.extendedDisplay.type, 0); - do_check_eq(record.extendedDisplay.records.length, 3); - do_check_eq(record.extendedDisplay.records[0].tag, 0x80); - do_check_eq(record.extendedDisplay.records[1].tag, 0x81); - do_check_eq(record.extendedDisplay.records[2].tag, 0x9B); - do_check_eq(record.extendedDisplay.records[2].content, "Test Info"); + do_check_eq(records[0].display, "Test Extended Info"); run_next_test(); }); + /** * Verify decoder for mixed type */ @@ -95,29 +91,144 @@ add_test(function test_mixed() { let worker = newWorkerWithParcel([ 0x02, // two inforemation record 0x00, // type: display - 0x09, // length: 9 + 0x0B, // length: 11 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66, - 0x6F, 0x00, + 0x6F, 0x20, 0x31, 0x00, 0x07, // type: extended display - 0x0E, // length: 14 - 0x80, // header byte - 0x80, // Blank - 0x81, // Skip - 0x9B, // Text - 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, - 0x66, 0x6F, 0x00]); + 0x0B, // length: 11 + 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66, + 0x6F, 0x20, 0x32, 0x00]); let context = worker.ContextPool._contexts[0]; let helper = context.CdmaPDUHelper; - let record = helper.decodeInformationRecord(); + let records = helper.decodeInformationRecord(); - do_check_eq(record.display, "Test Info"); - do_check_eq(record.extendedDisplay.indicator, 1); - do_check_eq(record.extendedDisplay.type, 0); - do_check_eq(record.extendedDisplay.records.length, 3); - do_check_eq(record.extendedDisplay.records[0].tag, 0x80); - do_check_eq(record.extendedDisplay.records[1].tag, 0x81); - do_check_eq(record.extendedDisplay.records[2].tag, 0x9B); - do_check_eq(record.extendedDisplay.records[2].content, "Test Info"); + do_check_eq(records[0].display, "Test Info 1"); + do_check_eq(records[1].display, "Test Info 2"); + + run_next_test(); +}); + +/** + * Verify decoder for multiple types + */ +add_test(function test_multiple() { + let worker = newWorkerWithParcel([ + 0x02, // two inforemation record + 0x00, // type: display + 0x0B, // length: 11 + 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66, + 0x6F, 0x20, 0x31, 0x00, + 0x00, // type: display + 0x0B, // length: 11 + 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66, + 0x6F, 0x20, 0x32, 0x00]); + let context = worker.ContextPool._contexts[0]; + let helper = context.CdmaPDUHelper; + let records = helper.decodeInformationRecord(); + + do_check_eq(records[0].display, "Test Info 1"); + do_check_eq(records[1].display, "Test Info 2"); + + run_next_test(); +}); + +/** + * Verify decoder for Signal Type + */ +add_test(function test_signal() { + let worker = newWorkerWithParcel([ + 0x01, // one inforemation record + 0x04, // type: signal + 0x01, // isPresent: non-zero + 0x00, // signalType: Tone signal (00) + 0x01, // alertPitch: High pitch + 0x03]); // signal: Abbreviated intercept (000011) + let context = worker.ContextPool._contexts[0]; + let helper = context.CdmaPDUHelper; + let records = helper.decodeInformationRecord(); + + do_check_eq(records[0].signal.type, 0x00); + do_check_eq(records[0].signal.alertPitch, 0x01); + do_check_eq(records[0].signal.signal, 0x03); + + run_next_test(); +}); + +/** + * Verify decoder for Signal Type for Not Presented + */ +add_test(function test_signal_not_present() { + let worker = newWorkerWithParcel([ + 0x01, // one inforemation record + 0x04, // type: signal + 0x00, // isPresent: zero + 0x00, // signalType: Tone signal (00) + 0x01, // alertPitch: High pitch + 0x03]); // signal: Abbreviated intercept (000011) + let context = worker.ContextPool._contexts[0]; + let helper = context.CdmaPDUHelper; + let records = helper.decodeInformationRecord(); + + do_check_eq(records.length, 0); + + run_next_test(); +}); + +/** + * Verify decoder for Line Control + */ +add_test(function test_line_control() { + let worker = newWorkerWithParcel([ + 0x01, // one inforemation record + 0x06, // type: line control + 0x01, // polarity included + 0x00, // not toggled + 0x01, // reversed + 0xFF]); // Power denial timeout: 255 * 5 ms + let context = worker.ContextPool._contexts[0]; + let helper = context.CdmaPDUHelper; + let records = helper.decodeInformationRecord(); + + do_check_eq(records[0].lineControl.polarityIncluded, 1); + do_check_eq(records[0].lineControl.toggle, 0); + do_check_eq(records[0].lineControl.reverse, 1); + do_check_eq(records[0].lineControl.powerDenial, 255); + + run_next_test(); +}); + +/** + * Verify decoder for CLIR Cause + */ +add_test(function test_clir() { + let worker = newWorkerWithParcel([ + 0x01, // one inforemation record + 0x08, // type: clir + 0x01]); // cause: Rejected by user + let context = worker.ContextPool._contexts[0]; + let helper = context.CdmaPDUHelper; + let records = helper.decodeInformationRecord(); + + do_check_eq(records[0].clirCause, 1); + + run_next_test(); +}); + +/** + * Verify decoder for Audio Control + */ +add_test(function test_clir() { + let worker = newWorkerWithParcel([ + 0x01, // one inforemation record + 0x0A, // type: audio control + 0x01, // uplink + 0xFF]); // downlink + let context = worker.ContextPool._contexts[0]; + let helper = context.CdmaPDUHelper; + let records = helper.decodeInformationRecord(); + + do_check_eq(records[0].audioControl.upLink, 1); + do_check_eq(records[0].audioControl.downLink, 255); run_next_test(); }); diff --git a/dom/wifi/WifiCertService.cpp b/dom/wifi/WifiCertService.cpp index 23bca42f24e4..7ce7d0bcbd22 100644 --- a/dom/wifi/WifiCertService.cpp +++ b/dom/wifi/WifiCertService.cpp @@ -227,13 +227,6 @@ WifiCertService::Start(nsIWifiEventListener* aListener) { MOZ_ASSERT(aListener); - nsresult rv = NS_NewThread(getter_AddRefs(mRequestThread)); - if (NS_FAILED(rv)) { - NS_WARNING("Certn't create wifi control thread"); - Shutdown(); - return NS_ERROR_FAILURE; - } - mListener = aListener; return NS_OK; @@ -243,10 +236,6 @@ NS_IMETHODIMP WifiCertService::Shutdown() { MOZ_ASSERT(NS_IsMainThread()); - if (mRequestThread) { - mRequestThread->Shutdown(); - mRequestThread = nullptr; - } mListener = nullptr; diff --git a/dom/wifi/WifiCertService.h b/dom/wifi/WifiCertService.h index 219764c57e39..7f7bff5c8812 100644 --- a/dom/wifi/WifiCertService.h +++ b/dom/wifi/WifiCertService.h @@ -27,7 +27,6 @@ public: private: WifiCertService(); ~WifiCertService(); - nsCOMPtr mRequestThread; nsCOMPtr mListener; }; diff --git a/dom/wifi/WifiWorker.js b/dom/wifi/WifiWorker.js index a778050eb4e6..ee636f1d1a40 100644 --- a/dom/wifi/WifiWorker.js +++ b/dom/wifi/WifiWorker.js @@ -1859,7 +1859,7 @@ function WifiWorker() { var pub = new Network(ssid, security, password); if (net.identity) pub.identity = dequote(net.identity); - if (net.netId) + if ("netId" in net) pub.known = true; if (net.scan_ssid === 1) pub.hidden = true; diff --git a/netwerk/protocol/rtsp/controller/RtspController.cpp b/netwerk/protocol/rtsp/controller/RtspController.cpp index c01d33389677..5d5b9b703887 100644 --- a/netwerk/protocol/rtsp/controller/RtspController.cpp +++ b/netwerk/protocol/rtsp/controller/RtspController.cpp @@ -47,8 +47,6 @@ extern PRLogModuleInfo* gRtspLog; #undef LOG #define LOG(args) PR_LOG(gRtspLog, PR_LOG_DEBUG, args) -const unsigned long kCommandDelayMs = 200; - namespace mozilla { namespace net { @@ -59,10 +57,7 @@ NS_IMPL_ISUPPORTS(RtspController, nsIStreamingProtocolController) RtspController::RtspController(nsIChannel *channel) - : mState(INIT), - mTimerLock("RtspController.mTimerLock"), - mPlayTimer(nullptr), - mPauseTimer(nullptr) + : mState(INIT) { LOG(("RtspController::RtspController()")); } @@ -99,26 +94,7 @@ RtspController::Play(void) return NS_ERROR_NOT_CONNECTED; } - MutexAutoLock lock(mTimerLock); - // Cancel the pause timer if it is active because successive pause-play in a - // short duration is unnecessary but could impair playback smoothing. - if (mPauseTimer) { - mPauseTimer->Cancel(); - mPauseTimer = nullptr; - } - - // Start a timer to delay the play operation for a short duration. - if (!mPlayTimer) { - mPlayTimer = do_CreateInstance("@mozilla.org/timer;1"); - if (!mPlayTimer) { - return NS_ERROR_NOT_INITIALIZED; - } - mPlayTimer->InitWithFuncCallback( - RtspController::PlayTimerCallback, - this, kCommandDelayMs, - nsITimer::TYPE_ONE_SHOT); - } - + mRtspSource->play(); return NS_OK; } @@ -135,26 +111,7 @@ RtspController::Pause(void) return NS_ERROR_NOT_CONNECTED; } - MutexAutoLock lock(mTimerLock); - // Cancel the play timer if it is active because successive play-pause in a - // short duration is unnecessary but could impair playback smoothing. - if (mPlayTimer) { - mPlayTimer->Cancel(); - mPlayTimer = nullptr; - } - - // Start a timer to delay the pause operation for a short duration. - if (!mPauseTimer) { - mPauseTimer = do_CreateInstance("@mozilla.org/timer;1"); - if (!mPauseTimer) { - return NS_ERROR_NOT_INITIALIZED; - } - mPauseTimer->InitWithFuncCallback( - RtspController::PauseTimerCallback, - this, kCommandDelayMs, - nsITimer::TYPE_ONE_SHOT); - } - + mRtspSource->pause(); return NS_OK; } @@ -360,19 +317,6 @@ RtspController::OnDisconnected(uint8_t index, LOG(("RtspController::OnDisconnected() for track %d reason = 0x%x", index, reason)); mState = DISCONNECTED; - // Ensure play and pause timer are stopped. - { - MutexAutoLock lock(mTimerLock); - if (mPlayTimer) { - mPlayTimer->Cancel(); - mPlayTimer = nullptr; - } - if (mPauseTimer) { - mPauseTimer->Cancel(); - mPauseTimer = nullptr; - } - } - if (mListener) { nsRefPtr task = new SendOnDisconnectedTask(mListener, index, reason); @@ -436,40 +380,5 @@ RtspController::PlaybackEnded() return NS_OK; } -//----------------------------------------------------------------------------- -// RtspController static member methods -//----------------------------------------------------------------------------- -//static -void RtspController::PlayTimerCallback(nsITimer *aTimer, void *aClosure) -{ - MOZ_ASSERT(aTimer); - MOZ_ASSERT(aClosure); - - RtspController *self = static_cast(aClosure); - MOZ_ASSERT(self->mRtspSource.get()); - - MutexAutoLock lock(self->mTimerLock); - if (self->mPlayTimer) { - self->mRtspSource->play(); - self->mPlayTimer = nullptr; - } -} - -//static -void RtspController::PauseTimerCallback(nsITimer *aTimer, void *aClosure) -{ - MOZ_ASSERT(aTimer); - MOZ_ASSERT(aClosure); - - RtspController *self = static_cast(aClosure); - MOZ_ASSERT(self->mRtspSource.get()); - - MutexAutoLock lock(self->mTimerLock); - if (self->mPauseTimer) { - self->mRtspSource->pause(); - self->mPauseTimer = nullptr; - } -} - } // namespace mozilla::net } // namespace mozilla diff --git a/netwerk/protocol/rtsp/controller/RtspController.h b/netwerk/protocol/rtsp/controller/RtspController.h index 6700eedf821b..f938430944b2 100644 --- a/netwerk/protocol/rtsp/controller/RtspController.h +++ b/netwerk/protocol/rtsp/controller/RtspController.h @@ -7,12 +7,10 @@ #ifndef RtspController_h #define RtspController_h -#include "mozilla/Mutex.h" #include "nsIStreamingProtocolController.h" #include "nsIChannel.h" #include "nsCOMPtr.h" #include "nsString.h" -#include "nsITimer.h" #include "RTSPSource.h" namespace mozilla { @@ -29,10 +27,6 @@ public: RtspController(nsIChannel *channel); ~RtspController(); - // These callbacks will be called when mPlayTimer/mPauseTimer fires. - static void PlayTimerCallback(nsITimer *aTimer, void *aClosure); - static void PauseTimerCallback(nsITimer *aTimer, void *aClosure); - private: enum State { INIT, @@ -53,13 +47,6 @@ private: State mState; // Rtsp Streaming source. android::sp mRtspSource; - // This lock protects mPlayTimer and mPauseTimer. - Mutex mTimerLock; - // Timers to delay the play and pause operations. - // They are used for optimization and avoid sending unnecessary requests to - // the server. - nsCOMPtr mPlayTimer; - nsCOMPtr mPauseTimer; }; } diff --git a/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp b/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp index 276e7dde9584..163619fa9330 100644 --- a/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp +++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp @@ -21,6 +21,8 @@ PRLogModuleInfo* gRtspChildLog = nullptr; #define LOG(args) PR_LOG(gRtspChildLog, PR_LOG_DEBUG, args) const uint32_t kRtspTotalTracks = 2; +const unsigned long kRtspCommandDelayMs = 200; + using namespace mozilla::ipc; namespace mozilla { @@ -64,6 +66,9 @@ RtspControllerChild::RtspControllerChild(nsIChannel *channel) , mChannel(channel) , mTotalTracks(0) , mSuspendCount(0) + , mTimerLock("RtspControllerChild.mTimerLock") + , mPlayTimer(nullptr) + , mPauseTimer(nullptr) { #if defined(PR_LOGGING) if (!gRtspChildLog) @@ -108,6 +113,20 @@ RtspControllerChild::DisallowIPC() mIPCAllowed = false; } +void +RtspControllerChild::StopPlayAndPauseTimer() +{ + MutexAutoLock lock(mTimerLock); + if (mPlayTimer) { + mPlayTimer->Cancel(); + mPlayTimer = nullptr; + } + if (mPauseTimer) { + mPauseTimer->Cancel(); + mPauseTimer = nullptr; + } +} + //----------------------------------------------------------------------------- // RtspControllerChild::PRtspControllerChild //----------------------------------------------------------------------------- @@ -174,6 +193,7 @@ RtspControllerChild::RecvOnDisconnected( const uint8_t& index, const nsresult& reason) { + StopPlayAndPauseTimer(); DisallowIPC(); LOG(("RtspControllerChild::RecvOnDisconnected for track %d reason = 0x%x", index, reason)); if (mListener) { @@ -186,6 +206,7 @@ RtspControllerChild::RecvOnDisconnected( bool RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason) { + StopPlayAndPauseTimer(); DisallowIPC(); LOG(("RtspControllerChild::RecvAsyncOpenFailed reason = 0x%x", reason)); if (mListener) { @@ -234,8 +255,6 @@ enum IPCEvent SendPlayEvent, SendPauseEvent, SendSeekEvent, - SendResumeEvent, - SendSuspendEvent, SendStopEvent, SendPlaybackEndedEvent }; @@ -275,10 +294,6 @@ public: rv = mController->SendPause(); } else if (mEvent == SendSeekEvent) { rv = mController->SendSeek(mSeekTime); - } else if (mEvent == SendResumeEvent) { - rv = mController->SendResume(); - } else if (mEvent == SendSuspendEvent) { - rv = mController->SendSuspend(); } else if (mEvent == SendStopEvent) { rv = mController->SendStop(); } else if (mEvent == SendPlaybackEndedEvent) { @@ -305,14 +320,30 @@ RtspControllerChild::Play(void) { LOG(("RtspControllerChild::Play()")); - if (NS_IsMainThread()) { - if (!OKToSendIPC() || !SendPlay()) { - return NS_ERROR_FAILURE; + MutexAutoLock lock(mTimerLock); + // Cancel the pause timer if it is active because successive pause-play in a + // short duration is unncessary but could impair playback smoothing. + if (mPauseTimer) { + mPauseTimer->Cancel(); + mPauseTimer = nullptr; + } + + // Start a timer to delay the play operation for a short duration. + if (!mPlayTimer) { + mPlayTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (!mPlayTimer) { + return NS_ERROR_NOT_INITIALIZED; } - } else { - nsresult rv = NS_DispatchToMainThread( - new SendIPCEvent(this, SendPlayEvent)); - NS_ENSURE_SUCCESS(rv, rv); + // We have to dispatch the timer callback to the main thread because the + // decoder thread is a thread from nsIThreadPool and cannot be the timer + // target. Furthermore, IPC send functions should only be called from the + // main thread. + nsCOMPtr mainThread = do_GetMainThread(); + mPlayTimer->SetTarget(mainThread); + mPlayTimer->InitWithFuncCallback( + RtspControllerChild::PlayTimerCallback, + this, kRtspCommandDelayMs, + nsITimer::TYPE_ONE_SHOT); } return NS_OK; @@ -323,14 +354,29 @@ RtspControllerChild::Pause(void) { LOG(("RtspControllerChild::Pause()")); - if (NS_IsMainThread()) { - if (!OKToSendIPC() || !SendPause()) { - return NS_ERROR_FAILURE; + MutexAutoLock lock(mTimerLock); + // Cancel the play timer if it is active because successive play-pause in a + // shrot duration is unnecessary but could impair playback smoothing. + if (mPlayTimer) { + mPlayTimer->Cancel(); + mPlayTimer = nullptr; + } + + // Start a timer to delay the pause operation for a short duration. + if (!mPauseTimer) { + mPauseTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (!mPauseTimer) { + return NS_ERROR_NOT_INITIALIZED; } - } else { - nsresult rv = NS_DispatchToMainThread( - new SendIPCEvent(this, SendPauseEvent)); - NS_ENSURE_SUCCESS(rv, rv); + // We have to dispatch the timer callback to the main thread because the + // decoder thread is a thread from nsIThreadPool and cannot be the timer + // target. + nsCOMPtr mainThread = do_GetMainThread(); + mPauseTimer->SetTarget(mainThread); + mPauseTimer->InitWithFuncCallback( + RtspControllerChild::PauseTimerCallback, + this, kRtspCommandDelayMs, + nsITimer::TYPE_ONE_SHOT); } return NS_OK; @@ -343,15 +389,7 @@ RtspControllerChild::Resume(void) NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED); if (!--mSuspendCount) { - if (NS_IsMainThread()) { - if (!OKToSendIPC() || !SendResume()) { - return NS_ERROR_FAILURE; - } - } else { - nsresult rv = NS_DispatchToMainThread( - new SendIPCEvent(this, SendResumeEvent)); - NS_ENSURE_SUCCESS(rv, rv); - } + return Play(); } return NS_OK; @@ -363,15 +401,7 @@ RtspControllerChild::Suspend(void) LOG(("RtspControllerChild::Suspend()")); if (!mSuspendCount++) { - if (NS_IsMainThread()) { - if (!OKToSendIPC() || !SendSuspend()) { - return NS_ERROR_FAILURE; - } - } else { - nsresult rv = NS_DispatchToMainThread( - new SendIPCEvent(this, SendSuspendEvent)); - NS_ENSURE_SUCCESS(rv, rv); - } + return Pause(); } return NS_OK; @@ -399,6 +429,7 @@ NS_IMETHODIMP RtspControllerChild::Stop() { LOG(("RtspControllerChild::Stop()")); + StopPlayAndPauseTimer(); if (NS_IsMainThread()) { if (!OKToSendIPC() || !SendStop()) { @@ -542,5 +573,44 @@ RtspControllerChild::AsyncOpen(nsIStreamingProtocolListener *aListener) return NS_OK; } +//----------------------------------------------------------------------------- +// RtspControllerChild static member methods +//----------------------------------------------------------------------------- +//static +void +RtspControllerChild::PlayTimerCallback(nsITimer *aTimer, void *aClosure) +{ + MOZ_ASSERT(aTimer); + MOZ_ASSERT(aClosure); + MOZ_ASSERT(NS_IsMainThread()); + + RtspControllerChild *self = static_cast(aClosure); + + MutexAutoLock lock(self->mTimerLock); + if (!self->mPlayTimer || !self->OKToSendIPC()) { + return; + } + self->SendPlay(); + self->mPlayTimer = nullptr; +} + +//static +void +RtspControllerChild::PauseTimerCallback(nsITimer *aTimer, void *aClosure) +{ + MOZ_ASSERT(aTimer); + MOZ_ASSERT(aClosure); + MOZ_ASSERT(NS_IsMainThread()); + + RtspControllerChild *self = static_cast(aClosure); + + MutexAutoLock lock(self->mTimerLock); + if (!self->mPauseTimer || !self->OKToSendIPC()) { + return; + } + self->SendPause(); + self->mPauseTimer = nullptr; +} + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/rtsp/controller/RtspControllerChild.h b/netwerk/protocol/rtsp/controller/RtspControllerChild.h index 298dc9e556ad..febae6ae21af 100644 --- a/netwerk/protocol/rtsp/controller/RtspControllerChild.h +++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.h @@ -14,6 +14,8 @@ #include "nsString.h" #include "nsTArray.h" #include "mozilla/net/RtspChannelChild.h" +#include "mozilla/Mutex.h" +#include "nsITimer.h" namespace mozilla { namespace net { @@ -52,6 +54,10 @@ class RtspControllerChild : public nsIStreamingProtocolController void AllowIPC(); void DisallowIPC(); + // These callbacks will be called when mPlayTimer/mPauseTimer fires. + static void PlayTimerCallback(nsITimer *aTimer, void *aClosure); + static void PauseTimerCallback(nsITimer *aTimer, void *aClosure); + private: bool mIPCOpen; // The intention of this variable is just to avoid any IPC message to be sent @@ -73,6 +79,16 @@ class RtspControllerChild : public nsIStreamingProtocolController uint32_t mSuspendCount; // Detach channel-controller relationship. void ReleaseChannel(); + // This lock protects mPlayTimer and mPauseTimer. + Mutex mTimerLock; + // Timers to delay the play and pause operations. + // They are used for optimization and to avoid sending unnecessary requests to + // the server. + nsCOMPtr mPlayTimer; + nsCOMPtr mPauseTimer; + // Timers should be stopped if we are going to terminate, such as when + // receiving Stop command or OnDisconnected event. + void StopPlayAndPauseTimer(); }; } // namespace net } // namespace mozilla