DtmfLocalTonePlayer.java revision 91d43cf9c985cc5a83795f256ef5c46ebb8fbdc1
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;
2292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordonimport android.provider.Settings;
2392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
2491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn// TODO: Needed for move to system service: import com.android.internal.R;
2592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordonimport com.google.common.collect.ImmutableMap;
2692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
2792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordonimport java.util.Map;
2892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
2992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon/**
3092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * Plays DTMF tones locally for the caller to hear. In order to reduce (1) the amount of times we
3192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * check the "play local tones" setting and (2) the length of time we keep the tone generator, this
3292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * class employs a concept of a call "session" that starts and stops when the foreground call
3392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon * changes.
3492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon */
3592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordonclass DtmfLocalTonePlayer extends CallsManagerListenerBase {
3692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private static final Map<Character, Integer> TONE_MAP =
3792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            ImmutableMap.<Character, Integer>builder()
3892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('1', ToneGenerator.TONE_DTMF_1)
3992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('2', ToneGenerator.TONE_DTMF_2)
4092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('3', ToneGenerator.TONE_DTMF_3)
4192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('4', ToneGenerator.TONE_DTMF_4)
4292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('5', ToneGenerator.TONE_DTMF_5)
4392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('6', ToneGenerator.TONE_DTMF_6)
4492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('7', ToneGenerator.TONE_DTMF_7)
4592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('8', ToneGenerator.TONE_DTMF_8)
4692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('9', ToneGenerator.TONE_DTMF_9)
4792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('0', ToneGenerator.TONE_DTMF_0)
4892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('#', ToneGenerator.TONE_DTMF_P)
4992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .put('*', ToneGenerator.TONE_DTMF_S)
5092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    .build();
5192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
5292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /** Generator used to actually play the tone. */
5392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private ToneGenerator mToneGenerator;
5492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
5592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /** The current call associated with an existing dtmf session. */
5692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private Call mCall;
5792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
5891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    /** The context. */
5991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    private final Context mContext;
6091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn
6191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    public DtmfLocalTonePlayer(Context context) {
6291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mContext = context;
6391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    }
6491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn
6592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /** {@inheritDoc} */
6692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    @Override
6792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
68acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        endDtmfSession(oldForegroundCall);
69acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        startDtmfSession(newForegroundCall);
7092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
7192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
7292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
7392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Starts playing the dtmf tone specified by c.
7492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
7592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The associated call.
7692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param c The digit to play.
7792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
7892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    void playTone(Call call, char c) {
7992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        // Do nothing if it is not the right call.
8092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (mCall != call) {
8192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            return;
8292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
8392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
8492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (mToneGenerator == null) {
8592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            Log.d(this, "playTone: mToneGenerator == null, %c.", c);
8692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        } else {
8792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            Log.d(this, "starting local tone: %c.", c);
8892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            if (TONE_MAP.containsKey(c)) {
8992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                mToneGenerator.startTone(TONE_MAP.get(c), -1 /* toneDuration */);
9092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            }
9192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
9292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
9392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
9492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
9592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Stops any currently playing dtmf tone.
9692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
9792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The associated call.
9892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
9992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    void stopTone(Call call) {
10092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        // Do nothing if it's not the right call.
10192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (mCall != call) {
10292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            return;
10392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
10492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
10592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (mToneGenerator == null) {
10692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            Log.d(this, "stopTone: mToneGenerator == null.");
10792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        } else {
10892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            Log.d(this, "stopping local tone.");
10992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            mToneGenerator.stopTone();
11092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
11192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
11292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
11392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
11492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Runs initialization requires to play local tones during a call.
11592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
11692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The call associated with this dtmf session.
11792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
11892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private void startDtmfSession(Call call) {
119acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        if (call == null) {
120acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner            return;
121acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        }
12291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        final Context context = call.getContext();
12392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        final boolean areLocalTonesEnabled;
12491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        if (context.getResources().getBoolean(R.bool.allow_local_dtmf_tones)) {
12592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            areLocalTonesEnabled = Settings.System.getInt(
12691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    context.getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
12792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        } else {
12892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            areLocalTonesEnabled = false;
12992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
13092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
13192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        mCall = call;
13292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
13392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        if (areLocalTonesEnabled) {
13492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            if (mToneGenerator == null) {
13592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                try {
13692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    mToneGenerator = new ToneGenerator(AudioManager.STREAM_DTMF, 80);
13792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                } catch (RuntimeException e) {
13892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    Log.e(this, e, "Error creating local tone generator.");
13992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                    mToneGenerator = null;
14092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                }
14192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            }
14292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
14392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
14492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
14592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    /**
14692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * Releases resources needed for playing local dtmf tones.
14792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     *
14892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     * @param call The call associated with the session to end.
14992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon     */
15092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    private void endDtmfSession(Call call) {
151acb91eb8e9d0f08a7ccce72062a7eb2cf958aa51Jay Shrauner        if (call != null && mCall == call) {
15292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            // Do a stopTone() in case the sessions ends before we are told to stop the tone.
15392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            stopTone(call);
15492a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
15592a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            mCall = null;
15692a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon
15792a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            if (mToneGenerator != null) {
15892a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                mToneGenerator.release();
15992a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon                mToneGenerator = null;
16092a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon            }
16192a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon        }
16292a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon    }
16392a2d811b6206eec84b3c21100dd64f660dae3a2Santos Cordon}
164