blob: eb3f9a00cb746cf29b8c22714f6929011c838356 [file] [log] [blame]
Santos Cordon92a2d812014-04-30 15:19:01 -07001/*
2 * Copyright 2014, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tyler Gunn7cc70b42014-09-12 22:17:27 -070017package com.android.server.telecom;
Santos Cordon92a2d812014-04-30 15:19:01 -070018
19import android.media.AudioManager;
20import android.media.ToneGenerator;
21import android.provider.Settings;
22
Santos Cordon92a2d812014-04-30 15:19:01 -070023import com.google.common.collect.ImmutableMap;
24
25import java.util.Map;
26
27/**
28 * Plays DTMF tones locally for the caller to hear. In order to reduce (1) the amount of times we
29 * check the "play local tones" setting and (2) the length of time we keep the tone generator, this
30 * class employs a concept of a call "session" that starts and stops when the foreground call
31 * changes.
32 */
33class DtmfLocalTonePlayer extends CallsManagerListenerBase {
34 private static final Map<Character, Integer> TONE_MAP =
35 ImmutableMap.<Character, Integer>builder()
36 .put('1', ToneGenerator.TONE_DTMF_1)
37 .put('2', ToneGenerator.TONE_DTMF_2)
38 .put('3', ToneGenerator.TONE_DTMF_3)
39 .put('4', ToneGenerator.TONE_DTMF_4)
40 .put('5', ToneGenerator.TONE_DTMF_5)
41 .put('6', ToneGenerator.TONE_DTMF_6)
42 .put('7', ToneGenerator.TONE_DTMF_7)
43 .put('8', ToneGenerator.TONE_DTMF_8)
44 .put('9', ToneGenerator.TONE_DTMF_9)
45 .put('0', ToneGenerator.TONE_DTMF_0)
46 .put('#', ToneGenerator.TONE_DTMF_P)
47 .put('*', ToneGenerator.TONE_DTMF_S)
48 .build();
49
50 /** Generator used to actually play the tone. */
51 private ToneGenerator mToneGenerator;
52
53 /** The current call associated with an existing dtmf session. */
54 private Call mCall;
55
56 /** {@inheritDoc} */
57 @Override
58 public void onForegroundCallChanged(Call oldForegroundCall, Call newForegroundCall) {
Jay Shrauneracb91eb2014-08-08 16:04:53 -070059 endDtmfSession(oldForegroundCall);
60 startDtmfSession(newForegroundCall);
Santos Cordon92a2d812014-04-30 15:19:01 -070061 }
62
63 /**
64 * Starts playing the dtmf tone specified by c.
65 *
66 * @param call The associated call.
67 * @param c The digit to play.
68 */
69 void playTone(Call call, char c) {
70 // Do nothing if it is not the right call.
71 if (mCall != call) {
72 return;
73 }
74
75 if (mToneGenerator == null) {
76 Log.d(this, "playTone: mToneGenerator == null, %c.", c);
77 } else {
78 Log.d(this, "starting local tone: %c.", c);
79 if (TONE_MAP.containsKey(c)) {
80 mToneGenerator.startTone(TONE_MAP.get(c), -1 /* toneDuration */);
81 }
82 }
83 }
84
85 /**
86 * Stops any currently playing dtmf tone.
87 *
88 * @param call The associated call.
89 */
90 void stopTone(Call call) {
91 // Do nothing if it's not the right call.
92 if (mCall != call) {
93 return;
94 }
95
96 if (mToneGenerator == null) {
97 Log.d(this, "stopTone: mToneGenerator == null.");
98 } else {
99 Log.d(this, "stopping local tone.");
100 mToneGenerator.stopTone();
101 }
102 }
103
104 /**
105 * Runs initialization requires to play local tones during a call.
106 *
107 * @param call The call associated with this dtmf session.
108 */
109 private void startDtmfSession(Call call) {
Jay Shrauneracb91eb2014-08-08 16:04:53 -0700110 if (call == null) {
111 return;
112 }
Tyler Gunn7cc70b42014-09-12 22:17:27 -0700113 TelecomApp app = TelecomApp.getInstance();
Santos Cordon92a2d812014-04-30 15:19:01 -0700114
115 final boolean areLocalTonesEnabled;
116 if (app.getResources().getBoolean(R.bool.allow_local_dtmf_tones)) {
117 areLocalTonesEnabled = Settings.System.getInt(
118 app.getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
119 } else {
120 areLocalTonesEnabled = false;
121 }
122
123 mCall = call;
124
125 if (areLocalTonesEnabled) {
126 if (mToneGenerator == null) {
127 try {
128 mToneGenerator = new ToneGenerator(AudioManager.STREAM_DTMF, 80);
129 } catch (RuntimeException e) {
130 Log.e(this, e, "Error creating local tone generator.");
131 mToneGenerator = null;
132 }
133 }
134 }
135 }
136
137 /**
138 * Releases resources needed for playing local dtmf tones.
139 *
140 * @param call The call associated with the session to end.
141 */
142 private void endDtmfSession(Call call) {
Jay Shrauneracb91eb2014-08-08 16:04:53 -0700143 if (call != null && mCall == call) {
Santos Cordon92a2d812014-04-30 15:19:01 -0700144 // Do a stopTone() in case the sessions ends before we are told to stop the tone.
145 stopTone(call);
146
147 mCall = null;
148
149 if (mToneGenerator != null) {
150 mToneGenerator.release();
151 mToneGenerator = null;
152 }
153 }
154 }
155}