192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon/*
292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * Copyright 2014, The Android Open Source Project
392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon *
492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * you may not use this file except in compliance with the License.
692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * You may obtain a copy of the License at
792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon *
892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon *     http://www.apache.org/licenses/LICENSE-2.0
992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon *
1092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * Unless required by applicable law or agreed to in writing, software
1192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
1292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * See the License for the specific language governing permissions and
1492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * limitations under the License.
1592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon */
1692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom;
1892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
1991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.content.Context;
2092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordonimport android.media.AudioManager;
2192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordonimport android.media.ToneGenerator;
229bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Piusimport android.os.Handler;
239bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Piusimport android.os.HandlerThread;
249bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Piusimport android.os.Message;
2592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordonimport android.provider.Settings;
2692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
279bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Piusimport com.android.internal.util.Preconditions;
289bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
2991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R;
3092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
3192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon/**
3292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * Plays DTMF tones locally for the caller to hear. In order to reduce (1) the amount of times we
3392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * check the "play local tones" setting and (2) the length of time we keep the tone generator, this
3492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * class employs a concept of a call "session" that starts and stops when the foreground call
3592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * changes.
3692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon */
37e792b33c2aa95d97db74e4c0b1e7ea6896cf99eeHall Liupublic class DtmfLocalTonePlayer {
3892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /** Generator used to actually play the tone. */
3992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private ToneGenerator mToneGenerator;
4092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
4192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /** The current call associated with an existing dtmf session. */
4292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private Call mCall;
4392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
449bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    /**
459bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     * Message codes to be used for creating and deleting ToneGenerator object in the tonegenerator
469bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     * thread.
479bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     */
489bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    private static final int EVENT_CREATE_OBJECT = 1;
499bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    private static final int EVENT_DELETE_OBJECT = 2;
509bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
519bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    /** Handler running on the tonegenerator thread. */
529bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    private Handler mHandler;
539bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
54e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu    public DtmfLocalTonePlayer() { }
559bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
5692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
57acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        endDtmfSession(oldForegroundCall);
58acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        startDtmfSession(newForegroundCall);
5992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
6092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
6192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
6292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Starts playing the dtmf tone specified by c.
6392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
6492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The associated call.
6592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param c The digit to play.
6692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
6792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    void playTone(Call call, char c) {
6892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        // Do nothing if it is not the right call.
6992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (mCall != call) {
7092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            return;
7192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
729bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        synchronized(this) {
739bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            if (mToneGenerator == null) {
749bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                Log.d(this, "playTone: mToneGenerator == null, %c.", c);
759bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            } else {
769bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                Log.d(this, "starting local tone: %c.", c);
779bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                int tone = getMappedTone(c);
789bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                if (tone != ToneGenerator.TONE_UNKNOWN) {
799bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                    mToneGenerator.startTone(tone, -1 /* toneDuration */);
809bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                }
8192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            }
8292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
8392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
8492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
8592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
8692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Stops any currently playing dtmf tone.
8792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
8892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The associated call.
8992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
9092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    void stopTone(Call call) {
9192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        // Do nothing if it's not the right call.
9292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (mCall != call) {
9392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            return;
9492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
959bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        synchronized(this) {
969bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            if (mToneGenerator == null) {
979bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                Log.d(this, "stopTone: mToneGenerator == null.");
989bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            } else {
999bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                Log.d(this, "stopping local tone.");
1009bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                mToneGenerator.stopTone();
1019bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            }
10292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
10392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
10492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
10592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
10692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Runs initialization requires to play local tones during a call.
10792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
10892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The call associated with this dtmf session.
10992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
11092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private void startDtmfSession(Call call) {
111acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        if (call == null) {
112acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner            return;
113acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        }
11491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        final Context context = call.getContext();
11592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        final boolean areLocalTonesEnabled;
11691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        if (context.getResources().getBoolean(R.bool.allow_local_dtmf_tones)) {
11792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            areLocalTonesEnabled = Settings.System.getInt(
11891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    context.getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
11992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        } else {
12092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            areLocalTonesEnabled = false;
12192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
12292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
12392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        mCall = call;
12492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
12592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (areLocalTonesEnabled) {
1269bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            Log.d(this, "Posting create.");
1279bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            postMessage(EVENT_CREATE_OBJECT);
12892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
12992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
13092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
13192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
13292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Releases resources needed for playing local dtmf tones.
13392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
13492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The call associated with the session to end.
13592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
13692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private void endDtmfSession(Call call) {
137acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        if (call != null && mCall == call) {
13892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            // Do a stopTone() in case the sessions ends before we are told to stop the tone.
13992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            stopTone(call);
14092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
14192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            mCall = null;
1429bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            Log.d(this, "Posting delete.");
1439bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            postMessage(EVENT_DELETE_OBJECT);
1449bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        }
1459bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    }
14692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
1479bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    /**
1489bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     * Posts a message to the tonegenerator-thread handler. Creates the handler if the handler
1499bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     * has not been instantiated.
1509bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     *
1519bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     * @param messageCode The message to post.
1529bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     */
1539bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    private void postMessage(int messageCode) {
1549bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        synchronized(this) {
1559bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            if (mHandler == null) {
1569bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                mHandler = getNewHandler();
1579bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            }
1589bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
1599bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            if (mHandler == null) {
1609bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                Log.d(this, "Message %d skipped because there is no handler.", messageCode);
1619bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            } else {
1629bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                mHandler.obtainMessage(messageCode, null).sendToTarget();
16392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            }
16492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
16592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
1664bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon
1679bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    /**
1689bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     * Creates a new tonegenerator Handler running in its own thread.
1699bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius     */
1709bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    private Handler getNewHandler() {
1719bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        Preconditions.checkState(mHandler == null);
1729bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
1739bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        HandlerThread thread = new HandlerThread("tonegenerator-dtmf");
1749bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        thread.start();
1759bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
1769bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        return new Handler(thread.getLooper()) {
1779bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            @Override
1789bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            public void handleMessage(Message msg) {
1799bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                switch(msg.what) {
1809bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                    case EVENT_CREATE_OBJECT:
1819bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                        synchronized(DtmfLocalTonePlayer.this) {
1829bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            if (mToneGenerator == null) {
1839bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                try {
1849bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                    mToneGenerator = new ToneGenerator(
1859bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                            AudioManager.STREAM_DTMF, 80);
1869bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                } catch (RuntimeException e) {
1879bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                    Log.e(this, e, "Error creating local tone generator.");
1889bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                    mToneGenerator = null;
1899bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                }
1909bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            }
1919bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                        }
1929bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                        break;
1939bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                    case EVENT_DELETE_OBJECT:
1949bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                        synchronized(DtmfLocalTonePlayer.this) {
1959bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            if (mToneGenerator != null) {
1969bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                mToneGenerator.release();
1979bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                mToneGenerator = null;
1989bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            }
1999bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            // Delete the handler after the tone generator object is deleted by
2009bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            // the tonegenerator thread.
2019bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            if (mHandler != null && !mHandler.hasMessages(EVENT_CREATE_OBJECT)) {
2029bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                // Stop the handler only if there are no pending CREATE messages.
2039bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                mHandler.removeMessages(EVENT_DELETE_OBJECT);
2049bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                mHandler.getLooper().quitSafely();
2059bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                                mHandler = null;
2069bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                            }
2079bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                        }
2089bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                        break;
2099bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius                }
2109bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius            }
2119bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius        };
2129bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius    }
2139bb88e9ce53449aa6f612b98d36fbfa80a1624e4Roshan Pius
214e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu    private static int getMappedTone(char digit) {
2154bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon        if (digit >= '0' && digit <= '9') {
2164bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon            return ToneGenerator.TONE_DTMF_0 + digit - '0';
2174bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon        } else if (digit == '#') {
2184bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon            return ToneGenerator.TONE_DTMF_P;
2194bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon        } else if (digit == '*') {
2204bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon            return ToneGenerator.TONE_DTMF_S;
2214bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon        }
2224bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon        return ToneGenerator.TONE_UNKNOWN;
2234bc0245eb5c09ab48dcbb673eefdf7175ae8ac9cSantos Cordon    }
22492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon}
225