InCallTonePlayer.java revision 8c85dee84fbbd8c36cf1c7b061001c6129623f92
1a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon/* 2a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Copyright 2014, The Android Open Source Project 3a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * 4a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License"); 5a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * you may not use this file except in compliance with the License. 6a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * You may obtain a copy of the License at 7a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * 8a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * http://www.apache.org/licenses/LICENSE-2.0 9a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * 10a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Unless required by applicable law or agreed to in writing, software 11a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS, 12a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * See the License for the specific language governing permissions and 14a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * limitations under the License. 15a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 16a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 17a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonpackage com.android.telecomm; 18a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 19a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.media.AudioManager; 20a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.media.ToneGenerator; 21a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.os.Handler; 22a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.os.Looper; 23a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 24a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon/** 25a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Play a call-related tone (ringback, busy signal, etc.) through ToneGenerator. To use, create an 26a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * instance using InCallTonePlayer.Factory (passing in the TONE_* constant for the tone you want) 27a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * and start() it. Implemented on top of {@link Thread} so that the tone plays in its own thread. 28a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 29a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonpublic final class InCallTonePlayer extends Thread { 30a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 31a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 32a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Factory used to create InCallTonePlayers. Exists to aid with testing mocks. 33a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 34a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon public static class Factory { 35a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final CallAudioManager mCallAudioManager; 36a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 37a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Factory(CallAudioManager callAudioManager) { 38a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager = callAudioManager; 39a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 40a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 41a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon InCallTonePlayer createPlayer(int tone) { 42a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon return new InCallTonePlayer(tone, mCallAudioManager); 43a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 44a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 45a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 46a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // The possible tones that we can play. 47c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_INVALID = 0; 48c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_BUSY = 1; 49c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CALL_ENDED = 2; 50c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_OTA_CALL_ENDED = 3; 51c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CALL_WAITING = 4; 52c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CDMA_DROP = 5; 53c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CONGESTION = 6; 54c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_INTERCEPT = 7; 55c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_OUT_OF_SERVICE = 8; 56c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_REDIAL = 9; 57c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_REORDER = 10; 58c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_RING_BACK = 11; 59c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_UNOBTAINABLE_NUMBER = 12; 60c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_VOICE_PRIVACY = 13; 61a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 62a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_EMERGENCY = 100; 63a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_HIPRI = 80; 64a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_LOPRI = 50; 65a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 66a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // Buffer time (in msec) to add on to the tone timeout value. Needed mainly when the timeout 67a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // value for a tone is exact duration of the tone itself. 688c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private static final int TIMEOUT_BUFFER_MILLIS = 20; 69a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 70a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // The tone state. 71a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_OFF = 0; 72a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_ON = 1; 73a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_STOPPED = 2; 74a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 75a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 76a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Keeps count of the number of actively playing tones so that we can notify CallAudioManager 77a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * when we need focus and when it can be release. This should only be manipulated from the main 78a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * thread. 79a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 80a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static int sTonesPlaying = 0; 81a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 82a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final CallAudioManager mCallAudioManager; 83a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 84a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); 85a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 86a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** The ID of the tone to play. */ 87a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final int mToneId; 88a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 89a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** Current state of the tone player. */ 90a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private int mState; 91a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 92a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 93a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Initializes the tone player. Private; use the {@link Factory} to create tone players. 94a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * 95a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * @param toneId ID of the tone to play, see TONE_* constants. 96a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 97a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private InCallTonePlayer(int toneId, CallAudioManager callAudioManager) { 98a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_OFF; 99a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mToneId = toneId; 100a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager = callAudioManager; 101a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 102a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 103a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** {@inheritDoc} */ 104a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon @Override 105a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon public void run() { 106a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon ToneGenerator toneGenerator = null; 107a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 108a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.d(this, "run(toneId = %s)", mToneId); 109a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 110a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon final int toneType; // Passed to ToneGenerator.startTone. 111a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon final int toneVolume; // Passed to the ToneGenerator constructor. 1128c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal final int toneLengthMillis; 113a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 114a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon switch (mToneId) { 115c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_BUSY: 116c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: CDMA-specific tones 117c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_BUSY; 118c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1198c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 120c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 121c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CALL_ENDED: 122c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_PROP_PROMPT; 123c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1248c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 125c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 126c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_OTA_CALL_ENDED: 127c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: fill in 128c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon throw new IllegalStateException("OTA Call ended NYI."); 129c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CALL_WAITING: 130c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: fill in. 131c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon throw new IllegalStateException("Call waiting NYI."); 132c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CDMA_DROP: 133c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; 134c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1358c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 375; 136c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 137c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CONGESTION: 138c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_CONGESTION; 139c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1408c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 141c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 142c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_INTERCEPT: 143c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT; 144c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1458c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 500; 146c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 147c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_OUT_OF_SERVICE: 148c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; 149c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1508c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 375; 151c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 152c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_REDIAL: 153c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE; 154c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1558c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 5000; 156c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 157c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_REORDER: 158c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_REORDER; 159c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1608c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 5000; 161c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 162a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon case TONE_RING_BACK: 163a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneType = ToneGenerator.TONE_SUP_RINGTONE; 164a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1658c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; 166a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon break; 167c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_UNOBTAINABLE_NUMBER: 168c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_ERROR; 169c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1708c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 171c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 172c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_VOICE_PRIVACY: 173c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: fill in. 174c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon throw new IllegalStateException("Voice privacy tone NYI."); 175a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon default: 176a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon throw new IllegalStateException("Bad toneId: " + mToneId); 177a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 178a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 179a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // TODO(santoscordon): Bluetooth should be set manually (STREAM_BLUETOOTH_SCO) for tone 180a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // generator. 181a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon int stream = AudioManager.STREAM_VOICE_CALL; 182a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 183a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // If the ToneGenerator creation fails, just continue without it. It is a local audio 184a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // signal, and is not as important. 185a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 186a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.v(this, "Creating generator"); 187a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator = new ToneGenerator(stream, toneVolume); 188a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } catch (RuntimeException e) { 189a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.w(this, "Failed to create ToneGenerator.", e); 190a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon return; 191a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 192a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 193a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // TODO(santoscordon): Certain CDMA tones need to check the ringer-volume state before 194a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // playing. See CallNotifier.InCallTonePlayer. 195a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 196a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // TODO(santoscordon): Some tones play through the end of a call so we need to inform 197a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // CallAudioManager that we want focus the same way that Ringer does. 198a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 199a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon synchronized (this) { 200a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (mState != STATE_STOPPED) { 201a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_ON; 202a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator.startTone(toneType); 203a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 204a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.v(this, "Starting tone %d...waiting for %d ms.", mToneId, 2058c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis + TIMEOUT_BUFFER_MILLIS); 2068c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal wait(toneLengthMillis + TIMEOUT_BUFFER_MILLIS); 207a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } catch (InterruptedException e) { 208a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.w(this, "wait interrupted", e); 209a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 210a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 211a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 212a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_OFF; 213a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } finally { 214a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (toneGenerator != null) { 215a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator.release(); 216a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 217a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon cleanUpTonePlayer(); 218a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 219a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 220a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 221a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon void startTone() { 222a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon ThreadUtil.checkOnMainThread(); 223a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 224a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon sTonesPlaying++; 225a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (sTonesPlaying == 1) { 226a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager.setIsTonePlaying(true); 227a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 228a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 229a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon start(); 230a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 231a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 232a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 233a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Stops the tone. 234a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 235a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon void stopTone() { 236a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon synchronized (this) { 237a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (mState == STATE_ON) { 238a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.d(this, "Stopping the tone %d.", mToneId); 239a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon notify(); 240a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 241a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_STOPPED; 242a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 243a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 244a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 245a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private void cleanUpTonePlayer() { 246a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // Release focus on the main thread. 247a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mMainThreadHandler.post(new Runnable() { 248a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon @Override public void run() { 249a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (sTonesPlaying == 0) { 250a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.wtf(this, "Over-releasing focus for tone player."); 251a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } else if (--sTonesPlaying == 0) { 252a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager.setIsTonePlaying(false); 253a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 254a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 255a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon }); 256a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 257a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon} 258