sysapps / telephony

API to manage telephony calls
15 stars 12 forks source link

UC: send a tone as long as you are pressing a button #7

Closed mounirlamouri closed 11 years ago

zolkis commented 11 years ago

This is not possible to implement with many middleware. In addition, in some cases it must not be manually controlled, see 4.2.4 in http://www.etsi.org/deliver/etsi_ts/101200_101299/10123502/01.01.01_60/ts_10123502v010101p.pdf .

The current API supports setting the tone duration (aka mark) and the gap (aka space), and should be enough for every application. The original use case is not to "send a tone as long as you are pressing a button", which is already a proposed solution, but it is "in some cases the tone sent by pressing the keys is too short", which is covered by the current API.

Therefore I suggest keeping the DTMF API unchanged. Please ack.

mounirlamouri commented 11 years ago

CC @sicking who mentioned that UC during the F2F.

sicking commented 11 years ago

What is the recommended way to use the current API to implement a dialer?

If the UI simply uses a hard-coded tone length when the user presses a button then the user is stuck if that hard-coded length is not long enough.

If the UI measures how long the user holds the button it means that the app can't start sending the tone until the user has held and then released the button. This is a very confusing user experience.

Providing the ability to start/stop a tone seems like very basic functionality. Is it really not possible to implement on any platforms where someone is planning on implementing a webapp platform? Which? What does the built-in dialer do on these platforms?

zolkis commented 11 years ago

The mark and space depend on telephony network. Some impose that it is not bigger than a certain value, some impose it is not less. There is a golden range which is usually used. Some middleware like ofono do not expose start/stop, only setting the mark and space. How would the user select between the API setting mark/space vs start/stop in the scenario described by you?

etiennesegonzac commented 11 years ago

Looks like the GCF certification test for DTMF includes: "While on a call, DTMF tone should play as long as button is pressed." [1].

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=815439

zolkis commented 11 years ago

I could not quickly find the test case, please provide a GCF link if possible. The bugzilla link does not seem to contain reference. If the request is valid, and if I understand it right, then we need a different DTMF interface on the TelephonyCall interface with start/stop functionality, supposed to work only while the call is active, and keep the current interface on TelephonyManager. Could you please confirm?

etiennesegonzac commented 11 years ago

If don't have direct access to the GCF stuffs, you can try to contact the reporter of the bug.

zolkis commented 11 years ago

OK, I will get this checked. The problem is that TS 27.007 does not support long tones (see C.2.11.-12.) An innocent question: is this actually supported in your modem? Some vendors probably do, but this does not seem to be standard, so I really need the GCF reference to accept the use case as generic.

sicking commented 11 years ago

Oh, yes, I definitely think that these functions should only work when there is an active call. You should not be able to use these function to place a call. Sorry if that wasn't clear. I think the same restriction should apply to the sendTones function.

sicking commented 11 years ago

I would prefer to put the functions on the TelephonyManager interface still though. Otherwise it creates a lot of strange edge cases when you are on a conference call since you can't send the tones to just one person if several are connected in a conference.

zolkis commented 11 years ago

Jonas - DTMF messages can generally be sent in the active state of a call in speech transmission mode or when a traffic channel is available during setup or release and the progress indicator IE has been received. So not only during an active call. Conf calls have voice channel merged by network, let's not mess them in: when a call is in a conference, you cannot use anything but disconnect() on the TelephonyCall, so it's irrelevant there. Based on the specs, it is more correct to put the DTMF interface to TelephonyCall, even though I myself would be inclined to leave it on TelephonyManager.

OK, let's get everyone in one page about DTMF. Please read the DTMF sections in: http://www.etsi.org/deliver/etsi_gts/03/0314/03.00.02_60/gsmts_0314sv030002p.pdf http://www.etsi.org/deliver/etsi_gts/04/0408/05.00.00_60/gsmts_0408v050000p.pdf Now how is it done in modems is a different story (currently they use +XVTS on Android, so it's likely that's how you've got to it) http://www.etsi.org/deliver/etsi_ts/127000_127099/127007/08.05.00_60/ts_127007v080500p.pdf

I have checked the TS 34.123 and TS 51.010 suites and found similar use case you mentioned, but ages, ages old. http://www.3gpp.org/ftp/Specs/archive/51_series/51.010-1/ In more convenient pdf (older): http://www.3gpp.org/ftp/tsg_geran/WG4_Terminal_Testing-Radio_Aspects/PDF_versions/older_versions/51010-1-430.pdf

Besides the start/stop use case, if an app wants to specify an exact timing, the start/stop interface is not good enough, for the latency issues. Therefore we need to keep the current interface, too.

zolkis commented 11 years ago

Now wait for a moment. Jonas, could you tell how exactly are you implementing this start/stop, since you seem to use AT+VTS [1], which does not support long tones [2]? Am I looking in the right place? [1] https://github.com/mozilla-b2g/android-hardware-ril/blob/master/reference-ril/reference-ril.c line 1424 [2] http://www.etsi.org/deliver/etsi_ts/127000_127099/127007/08.05.00_60/ts_127007v080500p.pdf section C.2.11

The only way +VTS works in GSM is to provide the tone [+ duration]. When duration is set to 0 it sets the manufacturer specific duration. This is fully aligned with the current DTMF spec. Please prove you can implement the required use case.

sicking commented 11 years ago

We should definitely put sendTones and startTone/endTone on the same object. The two do the same thing with sendTones just providing a more convenient syntax if you are sending a particular number sequence rather than reacting to the users presses on a keypad.

And we should make it possible to use those functions when on a conference call since it would be a surprising UI if the numeric buttons suddenly worked differently when you were connected to a conference rather than just a single other call. There's no reason the user shouldn't be able to call a voice mail system while still being on a conference for example.

I don't know how we implement the startTone/endTone API currently. If broken it's obviously something that needs to be fixed. If needed i could find the right person to answer the question?

sicking commented 11 years ago

And I'm happy to leave it to others to decide which exact states these functions should work in. As long as they work at least in all states required by the GSM standard. I would expect the functions to work in exactly the same states that enable the transmission of audio from the microphone.

My point is that I don't think it should be possible to use sendTones or startTone/endTone to dial a number in order to connect a new call. I wouldn't have expected GSM to support dialing through audio but maybe that's wrong?

zolkis commented 11 years ago

To summarize: currently there is no proof you can possibly implement start/stop with a modem. Even if you did, the current way to do it is via the +VTS command by specifying the tone [+ duration], as the current API supports it, and as the vast majority of modems support it. Now from what I've heard the GCF refers to the mobile terminal /modem, rather then to the phone UI, so it may even happen that you have misinterpreted the GCF and created a false use case. Please double check. If the use case would be real it would mean that no modem which supports only +VTS could possibly be certified, which is very likely false.

A given phone UI using the current API could give the user means to adjust the duration/gap in an established range if the user notices any error (though the manufacturer default values should work well in 99% of the networks). By all means that would be enough to ensure DTMF work in all networks, so no need for start/stop. Waiting for your implementation details :).

zolkis commented 11 years ago

BTW in Gaia it seems the way you are using the start/stop is to emulate the sendTone(tone, duration). https://github.com/mozilla-b2g/gaia/blob/master/apps/communications/dialer/js/keypad.js

etiennesegonzac commented 11 years ago

BTW in Gaia it seems the way you are using the start/stop is to emulate the sendTone(tone, duration). https://github.com/mozilla-b2g/gaia/blob/master/apps/communications/dialer/js/keypad.js

Only for the DTMF tones initiated from bluetooth. The regular flow is startTone on mousedown and stopTone on mouseup.

And it is working, if you call a B2G phone, then long press a key on the B2G phone's keypad you'll hear the long DTMF tone on the calling device.

zolkis commented 11 years ago

"The regular flow is startTone on mousedown and stopTone on mouseup."

That is broken. I am not here to fix your platform, but how do you ensure minimum duration that way? Trust the user to know the network timing and pray that your system's latency doesn't screw it up?

"And it is working, if you call a B2G phone, then long press a key on the B2G phone's keypad you'll hear the long DTMF tone on the calling device."

Yes, on the calling device, but do you hear the same length on the called device? Looks like this is the source of all this misunderstanding of the use case. On the calling device you can generate a tone when you press the button, and stop when you release it, but this has nothing to do with what the modem actually puts on the network. Yes, e.g. on Nokia phones with the ISI modem you do hear the long press on the other device (ISI supports long press), but an iPhone sends the same duration/length tones regardless how long you press the keys. Despite of this, the iPhone did get certified ;).

So if a modem supports start/stop, I agree we may also support it - although not strictly required, especially nowadays. Otherwise the sendTones is the standard way, and a good way to start with (BTW covers 100% of use cases, see [1]). We can add startTone/stopTone later, if a real need arises, but it complicates things. WebRTC does not use it either. Network equipment vendors try to use signaling for DTMF and focus expensive DSP handling to a gateway, especially as more and more network infra is moving to IP domain (smaller packetization price as well). You are sticking to a 20 years old requirement, despite it's not really needed today, not even for certification.

[1] From RFC-4733, free wording. Conform ITU-T Recommendation Q.24, legacy switching equipment in the countries surveyed expects a minimum recognizable signal duration of 40 ms, a minimum pause between signals of 40 ms, and a maximum signalling rate of 8 to 10 digits per second depending on the country. That will always work. In addition, human generated tones are also recognized, with special meaning and constraints. In this case, DTMF is sent alternately from either end (half-duplex mode), with a minimum 300-ms turn-around time, with tone durations and the pauses between them must exceed specified minimum durations corresponding to those of a V.18 DTMF sender (tones >=70 ms, pauses >=50 ms).

zolkis commented 11 years ago

So what is the resolution? Generally the sendTones() functionality covers all a dialer needs to transmit tones correctly. If you need startTone/stopTone, it sounds like a private method of your platform, since it's modem dependent. But it is impossible to implement it on systems where the modem uses +VTS, therefore IMO it should not be part of the Web API at this moment, in this version.

If we somehow could make it a special case of sendTones() invocation, we may support it, but we need feature detection.

etiennesegonzac commented 11 years ago

"The regular flow is startTone on mousedown and stopTone on mouseup."

That is broken. I am not here to fix your platform, but how do you ensure minimum duration that way? Trust the user to know the network timing and pray that your system's latency doesn't screw it up?

We just add a minimum delay, that's probably why you thought we were just using it in a startTone(tone, duration) fashion.

etiennesegonzac commented 11 years ago

"And it is working, if you call a B2G phone, then long press a key on the B2G phone's keypad you'll hear the long DTMF tone on the calling device."

Yes, on the calling device, but do you hear the same length on the called device?

Like I said, we're sending the tone from the B2G device, hearing it on the other one.

Looks like this is the source of all this misunderstanding of the use case. On the calling device you can generate a tone > when you press the button, and stop when you release it, but this has nothing to do with what the modem actually puts on the network.

We don't hear the DTMF tone from the B2G device sending the tone, we're actually just playing a matching tone for the user. If we de-activate the non-DTMF tone, we only hear the tone on the other end, so pretty sure it goes through the network :)

zolkis commented 11 years ago

"If we de-activate the non-DTMF tone, we only hear the tone on the other end, so pretty sure it goes through the network" I don't challenge that, it also works for Nokia phones (see above), but doesn't work for iPhone. If you read my previous comment, the point was the iPhone did not need this feature for certifications, it is a 20 years old GCF requirement, losing importance today, and it shifts to be a niche feature, at least modem-dependent. So it's not generic enough to be included in a web API. Using sendTones() is enough to get DTMF correctly transmitted (again see the previous comment). Supporting long-press is optional and modem specific.

zolkis commented 11 years ago

However, we could have a generic API which deals with such special cases too. We could have something like these options:

The way to use the last one:

Does any of these make sense, and which makes most sense? Other suggestions? (I'd prefer the last one, as it is the simplest, and hides the special case).

Even more, I would prefer moving DTMF into a separate object, available on TelephonyService object (meaning API change to use explicitly visible TelephonyService objects):

[NoInterfaceObject] interface TelephonyService { readonly attribute DOMString serviceId; readonly attribute DOMString provider; attribute DOMString displayName attribute boolean enabled; readonly attribute DTMF? dtmf; // later extended to contain other interfaces like // readonly attribute SimSettings? simsettings; }

[NoInterfaceObject] interface DTMF : EventTarget { readonly DOMString serviceId; readonly DOMError error; attribute EventHandler onerror; readonly attribute longPress; startTone(); // invoke error when not supported stopTone(); // invoke error when not supported void sendTones(DOMString tones, optional long duration, optional unsigned long gap); }

Example: // enumerate service id's var sId = navigator.telephony.defaultServiceId; // get service object service = navigator.telephony.getService(sId); if (service.dtmf) { if (service.dtmf.longPress) { // use startTone(), or sendTones() } else { // use sendTones() } }

Or, just make sendTone/stopTone a special case of sendTones, but still expose DTMF on the TelephonyService object. We are also applying the same concept in Messaging API with MessagingService, suggested by Mounir on the F2F (and I happily agree). This would clean up the telephony API, and encapsulate DTMF functionality better.

@sicking, @mounirlamouri, please chime in for helping decision, and take the pain of reading through these lengthy comments.

sicking commented 11 years ago

I don't think we need to have a separate DTMF object unless the use cases warrant it. Whether certification requires holding the button to continuously send the tone or not, I think it's a UI which most users expect and which applications will want to support. I know we definitely want to support it in Firefox OS.

I think simply adding void startTone(DOMString tone, optional DOMString serviceID) void endTone(optional DOMString serviceID)

next to sendTones is enough. Unless we know of anyone planning on implementing this API on platforms where this isn't implementable? I.e. where the hardware doesn't support either getting access to the voice channel and thus letting the API implementation synthesize the audio into it, or where the modem supports start-tone/end-tone directly.

Optional features are bad for interoperability and so should be avoided.

As far as I can tell we fully support this in the Firefox OS dialer right now. I'm not sure why incoming vs. outgoing calls makes a difference? Once a call is connected the audio handling is the same whether the call is incoming or outgoing, but maybe I'm misunderstanding something?

zolkis commented 11 years ago

"I think it's a UI which most users expect and which applications will want to support. I know we definitely want to support it in Firefox OS."

OK, we change arguments and say that it is supported in FF OS and users want it. I'd say the users don't care about long press vs default mark/space, since the use case is to send DTMF, not to play music :). It does not work on the iPhone and it is not a feature people crave for, they just want to send the tones to the network. It is the job of the platform/dialer to ensure that happens. Long press is supported on Nokia phones too, but I never actually used it in the past 15 years.

It could be well supported for FF OS, but it is not widely supported for modems, therefore it cannot be implemented in general, therefore it should not be in the Web API, by your own logic applied elsewhere in Telephony API. You cannot force a not implementable API onto the world, just because your modem supports it. Most modems (using +VTS) won't support it, please read the references above. QED.

By the same logic, should we restore supporting IMS/LTE in the Telephony API, since there are current requirements and specifications for it (much more than for long press DTMF), and there are device makers who support it?

The only acceptable way I see is to detect whether long press is supported on the given modem (device). If we can have API for this, then yes, we can include startTone/stopTone as well. Please feel free to suggest a solution for this: boolean flag? error on startTone if not supported? something else?

zolkis commented 11 years ago

@sicking "I don't think we need to have a separate DTMF object unless the use cases warrant it."

We will likely introduce the TelephonyService objects anyway, for supporting network, sim, supplementary services, etc. DTMF could be part of this, too. This would clean the TelephonyManager from all the optional 'serviceId' constructs, resulting in simpler, more coherent and better designed API. Note that dial() would also move to the TelephonyService object, which makes sense, since you cannot dial a call without having a telephony service object available. Similarly, since it would be possible to maintain a TelephonyService object for emergency services too (when no SIM, or flight mode, but emergency mode being possible), this would elegantly and transparently solve also the discussion on how emergency calls should be handled. See 3GPP TS 24.008 on emergency calls. It would also be aligned with Messaging API, using similar concepts and solution. Should I prepare a WebIDL to show how the Telephony API would look like with this design? Perhaps by email on the mailing list?

sicking commented 11 years ago

Like I said, I'm happy to add error handling if someone is planning on shipping a web runtime that implements this API on hardware that doesn't support start-tone/end-tone. Is that the case? If not, I don't understand the benefit of adding it?

zolkis commented 11 years ago

OK, let me try to do it using an error if not supported (or should it be exception?) I will also send a proposal with TelephonyService.

hsinyi commented 11 years ago

Hi all, According to "3GPP TS 03.14 -- Support of Dual Tone Multi-Frequency Signalling (DTMF) via the GSM System"[1], it clearly shows "On receipt of a START DTMF message, the MSC will connect the correct dual-tone to line. This tone will remain connected until either the call is cleared or a STOP DTMF message is received." in Section 6.2. You may also refer to Figure 1 which presents "Key X Released triggers STOP DTMF message." IMO it's no problem we have startTone/stopTone in web API. Also, as a user, I would like to be able to cease the sound whenever I want.

[1] http://www.3gpp.org/ftp/Specs/html-info/0314.htm

zolkis commented 11 years ago

@hsinyi That is the air interface, obviously, which I also know how it works. I was speaking about the modems being the problem... Apart from the new firmware on the IFX modems and the Nokia ISI modems, it seems that no modem supports long press ATM. For sure, there are a lot (majority) of modems which don't support it. On those you cannot implement start/stop, that's it.

Therefore you have to deal with a feature which may not be implemented on the platform.

I repeat the n'th time, for fulfilling the use case of sending DTMF we don't need long press at all, as there is the +VTS that works as well (show me a case when it does not work). There must be an API to know if long-press is supported, and we can map out the startTone/stopTone, otherwise we should not have it.

The current status-quo is to support the startTone()/stopTone() methods, and if the platform does not support them, should fire an error.

zolkis commented 11 years ago

As an alternative, this is how the same problem is solved in a multi-protocol framework like Telepathy: http://telepathy.freedesktop.org/spec/Channel_Interface_DTMF.html "Start sending a DTMF tone to all eligible streams in the channel. Where possible, the tone will continue until StopTone is called. On certain protocols, it may only be possible to send events with a predetermined length. In this case, the implementation MAY emit a fixed-length tone, and the StopTone method call SHOULD return NotAvailable."

I like more the way Jonas preferred, i.e. startTone() fire an error if long-press is not supported, in which case the developer has to use sendTones(). It is more clear separation of the two models, and of the concerns. The advantage of sendTones() over a hypothetical sendTone(tone, optional duration, optional gap) is better control of timing for sequences of tones (e.g. in a cycle one cannot control the exact timing of a sequence using only sendTone).

Since the error is specific to the telephony service, optimally the DTMF interface should be on a TelephonyService object, rather than carrying the serviceId as parameter in every method, and error, but that is a separate discussion.