InCallTonePlayer.java revision b626c02daaae6757299cdb2b8228ef0635b6b5dd
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 177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom; 18a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 19a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.media.AudioManager; 20a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.media.ToneGenerator; 21a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.os.Handler; 22a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordonimport android.os.Looper; 23a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 24d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebingerimport com.android.internal.annotations.VisibleForTesting; 25d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger 26a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon/** 27a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Play a call-related tone (ringback, busy signal, etc.) through ToneGenerator. To use, create an 28a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * instance using InCallTonePlayer.Factory (passing in the TONE_* constant for the tone you want) 29a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * and start() it. Implemented on top of {@link Thread} so that the tone plays in its own thread. 30a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 31d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebingerpublic class InCallTonePlayer extends Thread { 32a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 33a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 34a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Factory used to create InCallTonePlayers. Exists to aid with testing mocks. 35a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 36a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon public static class Factory { 37e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private CallAudioManager mCallAudioManager; 38f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter; 39abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad private final TelecomSystem.SyncRoot mLock; 40a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 41e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, 42f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu TelecomSystem.SyncRoot lock) { 43f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; 44abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad mLock = lock; 45a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 46a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 47e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void setCallAudioManager(CallAudioManager callAudioManager) { 48e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager = callAudioManager; 49e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 50e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 51d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger public InCallTonePlayer createPlayer(int tone) { 52f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu return new InCallTonePlayer(tone, mCallAudioManager, 53f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu mCallAudioRoutePeripheralAdapter, mLock); 54a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 55a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 56a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 57a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // The possible tones that we can play. 58c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_INVALID = 0; 59c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_BUSY = 1; 60c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CALL_ENDED = 2; 61c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_OTA_CALL_ENDED = 3; 62c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CALL_WAITING = 4; 63c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CDMA_DROP = 5; 64c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CONGESTION = 6; 65c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_INTERCEPT = 7; 66c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_OUT_OF_SERVICE = 8; 67c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_REDIAL = 9; 68c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_REORDER = 10; 69c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_RING_BACK = 11; 70c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_UNOBTAINABLE_NUMBER = 12; 71c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_VOICE_PRIVACY = 13; 7286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public static final int TONE_VIDEO_UPGRADE = 14; 73a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 74a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_EMERGENCY = 100; 75a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_HIPRI = 80; 76a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_LOPRI = 50; 77a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 78a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // Buffer time (in msec) to add on to the tone timeout value. Needed mainly when the timeout 79a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // value for a tone is exact duration of the tone itself. 808c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private static final int TIMEOUT_BUFFER_MILLIS = 20; 81a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 82a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // The tone state. 83a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_OFF = 0; 84a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_ON = 1; 85a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_STOPPED = 2; 86a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 87a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 88a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Keeps count of the number of actively playing tones so that we can notify CallAudioManager 89a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * when we need focus and when it can be release. This should only be manipulated from the main 90a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * thread. 91a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 92a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static int sTonesPlaying = 0; 93a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 94a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final CallAudioManager mCallAudioManager; 95f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter; 96a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 97a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); 98a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 99a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** The ID of the tone to play. */ 100a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final int mToneId; 101a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 102a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** Current state of the tone player. */ 103a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private int mState; 104a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 105abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad /** Telecom lock object. */ 106abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad private final TelecomSystem.SyncRoot mLock; 107abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad 108d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu private Session mSession; 109d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu private final Object mSessionLock = new Object(); 110d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu 111a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 112a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Initializes the tone player. Private; use the {@link Factory} to create tone players. 113a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * 114a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * @param toneId ID of the tone to play, see TONE_* constants. 115a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 116abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad private InCallTonePlayer( 117abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad int toneId, 118abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad CallAudioManager callAudioManager, 119f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, 120abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad TelecomSystem.SyncRoot lock) { 121a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_OFF; 122a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mToneId = toneId; 123a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager = callAudioManager; 124f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; 125abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad mLock = lock; 126a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 127a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 128a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** {@inheritDoc} */ 129a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon @Override 130a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon public void run() { 131a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon ToneGenerator toneGenerator = null; 132a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 133d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu synchronized (mSessionLock) { 134d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu if (mSession != null) { 135d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu Log.continueSession(mSession, "ICTP.r"); 136d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu mSession = null; 137d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 138d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 139a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.d(this, "run(toneId = %s)", mToneId); 140a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 141a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon final int toneType; // Passed to ToneGenerator.startTone. 142a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon final int toneVolume; // Passed to the ToneGenerator constructor. 1438c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal final int toneLengthMillis; 144a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 145a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon switch (mToneId) { 146c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_BUSY: 147c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: CDMA-specific tones 148c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_BUSY; 149c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1508c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 151c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 152c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CALL_ENDED: 153c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_PROP_PROMPT; 154c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1557062bb96f567e7dc9c7bf933b7bee17bb2c8108cYorke Lee toneLengthMillis = 200; 156c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 157c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_OTA_CALL_ENDED: 158c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: fill in 159c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon throw new IllegalStateException("OTA Call ended NYI."); 160c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CALL_WAITING: 16140f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon toneType = ToneGenerator.TONE_SUP_CALL_WAITING; 16240f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 16340f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; 16440f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon break; 165c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CDMA_DROP: 166c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; 167c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1688c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 375; 169c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 170c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CONGESTION: 171c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_CONGESTION; 172c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1738c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 174c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 175c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_INTERCEPT: 176c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT; 177c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1788c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 500; 179c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 180c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_OUT_OF_SERVICE: 181c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; 182c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1838c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 375; 184c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 185c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_REDIAL: 186c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE; 187c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1888c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 5000; 189c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 190c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_REORDER: 191c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_REORDER; 192c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1937062bb96f567e7dc9c7bf933b7bee17bb2c8108cYorke Lee toneLengthMillis = 4000; 194c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 195a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon case TONE_RING_BACK: 196a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneType = ToneGenerator.TONE_SUP_RINGTONE; 197a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1988c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; 199a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon break; 200c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_UNOBTAINABLE_NUMBER: 201c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_ERROR; 202c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 2038c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 204c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 205c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_VOICE_PRIVACY: 206c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: fill in. 207c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon throw new IllegalStateException("Voice privacy tone NYI."); 20886014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn case TONE_VIDEO_UPGRADE: 20986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn // Similar to the call waiting tone, but does not repeat. 21086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn toneType = ToneGenerator.TONE_SUP_CALL_WAITING; 21186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn toneVolume = RELATIVE_VOLUME_HIPRI; 21286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn toneLengthMillis = 4000; 21386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn break; 214a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon default: 215a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon throw new IllegalStateException("Bad toneId: " + mToneId); 216a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 217a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 218a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon int stream = AudioManager.STREAM_VOICE_CALL; 219f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu if (mCallAudioRoutePeripheralAdapter.isBluetoothAudioOn()) { 220c7e85d4fa0bb3325133a79d4c89f3149e0af430eSantos Cordon stream = AudioManager.STREAM_BLUETOOTH_SCO; 221c7e85d4fa0bb3325133a79d4c89f3149e0af430eSantos Cordon } 222a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 223a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // If the ToneGenerator creation fails, just continue without it. It is a local audio 224a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // signal, and is not as important. 225a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 226a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.v(this, "Creating generator"); 227a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator = new ToneGenerator(stream, toneVolume); 228a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } catch (RuntimeException e) { 229a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.w(this, "Failed to create ToneGenerator.", e); 230a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon return; 231a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 232a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 233df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon // TODO: Certain CDMA tones need to check the ringer-volume state before 234a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // playing. See CallNotifier.InCallTonePlayer. 235a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 236df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon // TODO: Some tones play through the end of a call so we need to inform 237a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // CallAudioManager that we want focus the same way that Ringer does. 238a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 239a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon synchronized (this) { 240a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (mState != STATE_STOPPED) { 241a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_ON; 242a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator.startTone(toneType); 243a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 244a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.v(this, "Starting tone %d...waiting for %d ms.", mToneId, 2458c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis + TIMEOUT_BUFFER_MILLIS); 2468c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal wait(toneLengthMillis + TIMEOUT_BUFFER_MILLIS); 247a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } catch (InterruptedException e) { 248a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.w(this, "wait interrupted", e); 249a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 250a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 251a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 252a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_OFF; 253a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } finally { 254a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (toneGenerator != null) { 255a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator.release(); 256a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 257a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon cleanUpTonePlayer(); 258efa8d2ad756e2ef5928bdf9171f52226096822ffBrad Ebinger Log.endSession(); 259a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 260a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 261d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger 262d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger @VisibleForTesting 263d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger public void startTone() { 264a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon sTonesPlaying++; 265a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (sTonesPlaying == 1) { 266a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager.setIsTonePlaying(true); 267a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 268a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 269d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu synchronized (mSessionLock) { 270d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu if (mSession != null) { 271d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu Log.cancelSubsession(mSession); 272d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 273d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu mSession = Log.createSubsession(); 274d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 275d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu 276b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu super.start(); 277b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu } 278b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu 279b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu @Override 280b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu public void start() { 281b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu Log.w(this, "Do not call the start method directly; use startTone instead."); 282a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 283a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 284a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 285a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Stops the tone. 286a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 287d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger @VisibleForTesting 288d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger public void stopTone() { 289a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon synchronized (this) { 290a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (mState == STATE_ON) { 291a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.d(this, "Stopping the tone %d.", mToneId); 292a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon notify(); 293a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 294a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_STOPPED; 295a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 296a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 297a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 298a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private void cleanUpTonePlayer() { 299a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // Release focus on the main thread. 300e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger mMainThreadHandler.post(new Runnable("ICTP.cUTP") { 301e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger @Override 302e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger public void loggedRun() { 303abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad synchronized (mLock) { 304abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad if (sTonesPlaying == 0) { 305abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad Log.wtf(this, "Over-releasing focus for tone player."); 306abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad } else if (--sTonesPlaying == 0) { 307abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad mCallAudioManager.setIsTonePlaying(false); 308abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad } 309a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 310a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 311e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger }.prepare()); 312a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 313a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon} 314