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; 23a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Log; 24a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Logging.Runnable; 25a3eccfee788c3ac3c831a443b085b141b39bb63dBrad Ebingerimport android.telecom.Logging.Session; 26a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 27d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebingerimport com.android.internal.annotations.VisibleForTesting; 28d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger 29a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon/** 30a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Play a call-related tone (ringback, busy signal, etc.) through ToneGenerator. To use, create an 31a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * instance using InCallTonePlayer.Factory (passing in the TONE_* constant for the tone you want) 32a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * and start() it. Implemented on top of {@link Thread} so that the tone plays in its own thread. 33a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 34d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebingerpublic class InCallTonePlayer extends Thread { 35a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 36a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 37a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Factory used to create InCallTonePlayers. Exists to aid with testing mocks. 38a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 39a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon public static class Factory { 40e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu private CallAudioManager mCallAudioManager; 41f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter; 42abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad private final TelecomSystem.SyncRoot mLock; 437bba1112556e122254013562650aac6a6af80ac6Brad Ebinger private final ToneGeneratorFactory mToneGeneratorFactory; 44a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 45e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu Factory(CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, 467bba1112556e122254013562650aac6a6af80ac6Brad Ebinger TelecomSystem.SyncRoot lock, ToneGeneratorFactory toneGeneratorFactory) { 47f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; 48abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad mLock = lock; 497bba1112556e122254013562650aac6a6af80ac6Brad Ebinger mToneGeneratorFactory = toneGeneratorFactory; 50a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 51a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 52e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu public void setCallAudioManager(CallAudioManager callAudioManager) { 53e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu mCallAudioManager = callAudioManager; 54e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu } 55e091ab90e37845cf4771051a6d2ce0ebadee4fe7Hall Liu 56d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger public InCallTonePlayer createPlayer(int tone) { 57f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu return new InCallTonePlayer(tone, mCallAudioManager, 587bba1112556e122254013562650aac6a6af80ac6Brad Ebinger mCallAudioRoutePeripheralAdapter, mLock, mToneGeneratorFactory); 59a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 60a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 61a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 627bba1112556e122254013562650aac6a6af80ac6Brad Ebinger public interface ToneGeneratorFactory { 637bba1112556e122254013562650aac6a6af80ac6Brad Ebinger ToneGenerator get (int streamType, int volume); 647bba1112556e122254013562650aac6a6af80ac6Brad Ebinger } 657bba1112556e122254013562650aac6a6af80ac6Brad Ebinger 66a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // The possible tones that we can play. 67c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_INVALID = 0; 68c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_BUSY = 1; 69c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CALL_ENDED = 2; 70c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_OTA_CALL_ENDED = 3; 71c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CALL_WAITING = 4; 72c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CDMA_DROP = 5; 73c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_CONGESTION = 6; 74c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_INTERCEPT = 7; 75c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_OUT_OF_SERVICE = 8; 76c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_REDIAL = 9; 77c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_REORDER = 10; 78c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_RING_BACK = 11; 79c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_UNOBTAINABLE_NUMBER = 12; 80c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon public static final int TONE_VOICE_PRIVACY = 13; 8186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn public static final int TONE_VIDEO_UPGRADE = 14; 82a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 83a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_EMERGENCY = 100; 84a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_HIPRI = 80; 85a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int RELATIVE_VOLUME_LOPRI = 50; 86a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 87a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // Buffer time (in msec) to add on to the tone timeout value. Needed mainly when the timeout 88a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // value for a tone is exact duration of the tone itself. 898c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private static final int TIMEOUT_BUFFER_MILLIS = 20; 90a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 91a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // The tone state. 92a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_OFF = 0; 93a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_ON = 1; 94a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static final int STATE_STOPPED = 2; 95a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 96a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 97a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Keeps count of the number of actively playing tones so that we can notify CallAudioManager 98a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * when we need focus and when it can be release. This should only be manipulated from the main 99a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * thread. 100a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 101a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private static int sTonesPlaying = 0; 102a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 103a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final CallAudioManager mCallAudioManager; 104f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu private final CallAudioRoutePeripheralAdapter mCallAudioRoutePeripheralAdapter; 105a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 106a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); 107a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 108a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** The ID of the tone to play. */ 109a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private final int mToneId; 110a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 111a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** Current state of the tone player. */ 112a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private int mState; 113a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 114abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad /** Telecom lock object. */ 115abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad private final TelecomSystem.SyncRoot mLock; 116abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad 117d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu private Session mSession; 118d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu private final Object mSessionLock = new Object(); 119d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu 1207bba1112556e122254013562650aac6a6af80ac6Brad Ebinger private final ToneGeneratorFactory mToneGenerator; 1217bba1112556e122254013562650aac6a6af80ac6Brad Ebinger 122a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 123a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Initializes the tone player. Private; use the {@link Factory} to create tone players. 124a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * 125a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * @param toneId ID of the tone to play, see TONE_* constants. 126a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 127abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad private InCallTonePlayer( 128abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad int toneId, 129abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad CallAudioManager callAudioManager, 130f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter, 1317bba1112556e122254013562650aac6a6af80ac6Brad Ebinger TelecomSystem.SyncRoot lock, 1327bba1112556e122254013562650aac6a6af80ac6Brad Ebinger ToneGeneratorFactory toneGeneratorFactory) { 133a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_OFF; 134a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mToneId = toneId; 135a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager = callAudioManager; 136f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter; 137abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad mLock = lock; 1387bba1112556e122254013562650aac6a6af80ac6Brad Ebinger mToneGenerator = toneGeneratorFactory; 139a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 140a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 141a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** {@inheritDoc} */ 142a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon @Override 143a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon public void run() { 144a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon ToneGenerator toneGenerator = null; 145a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 146d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu synchronized (mSessionLock) { 147d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu if (mSession != null) { 148d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu Log.continueSession(mSession, "ICTP.r"); 149d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu mSession = null; 150d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 151d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 152a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.d(this, "run(toneId = %s)", mToneId); 153a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 154a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon final int toneType; // Passed to ToneGenerator.startTone. 155a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon final int toneVolume; // Passed to the ToneGenerator constructor. 1568c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal final int toneLengthMillis; 157a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 158a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon switch (mToneId) { 159c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_BUSY: 160c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: CDMA-specific tones 161c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_BUSY; 162c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1638c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 164c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 165c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CALL_ENDED: 166c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_PROP_PROMPT; 167c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1687062bb96f567e7dc9c7bf933b7bee17bb2c8108cYorke Lee toneLengthMillis = 200; 169c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 170c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_OTA_CALL_ENDED: 171c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: fill in 172c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon throw new IllegalStateException("OTA Call ended NYI."); 173c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CALL_WAITING: 17440f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon toneType = ToneGenerator.TONE_SUP_CALL_WAITING; 17540f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 17640f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; 17740f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon break; 178c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CDMA_DROP: 179c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; 180c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1818c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 375; 182c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 183c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_CONGESTION: 184c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_CONGESTION; 185c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 1868c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 187c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 188c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_INTERCEPT: 189c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT; 190c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1918c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 500; 192c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 193c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_OUT_OF_SERVICE: 194c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE; 195c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 1968c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 375; 197c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 198c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_REDIAL: 199c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE; 200c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_LOPRI; 2018c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 5000; 202c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 203c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_REORDER: 204c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_CDMA_REORDER; 205c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 2067062bb96f567e7dc9c7bf933b7bee17bb2c8108cYorke Lee toneLengthMillis = 4000; 207c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 208a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon case TONE_RING_BACK: 209a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneType = ToneGenerator.TONE_SUP_RINGTONE; 210a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 2118c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS; 212a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon break; 213c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_UNOBTAINABLE_NUMBER: 214c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneType = ToneGenerator.TONE_SUP_ERROR; 215c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon toneVolume = RELATIVE_VOLUME_HIPRI; 2168c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis = 4000; 217c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon break; 218c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon case TONE_VOICE_PRIVACY: 219c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon // TODO: fill in. 220c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon throw new IllegalStateException("Voice privacy tone NYI."); 22186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn case TONE_VIDEO_UPGRADE: 22286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn // Similar to the call waiting tone, but does not repeat. 22386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn toneType = ToneGenerator.TONE_SUP_CALL_WAITING; 22486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn toneVolume = RELATIVE_VOLUME_HIPRI; 22586014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn toneLengthMillis = 4000; 22686014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn break; 227a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon default: 228a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon throw new IllegalStateException("Bad toneId: " + mToneId); 229a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 230a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 231a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon int stream = AudioManager.STREAM_VOICE_CALL; 232f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu if (mCallAudioRoutePeripheralAdapter.isBluetoothAudioOn()) { 233c7e85d4fa0bb3325133a79d4c89f3149e0af430eSantos Cordon stream = AudioManager.STREAM_BLUETOOTH_SCO; 234c7e85d4fa0bb3325133a79d4c89f3149e0af430eSantos Cordon } 235a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 236a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // If the ToneGenerator creation fails, just continue without it. It is a local audio 237a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // signal, and is not as important. 238a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 239a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.v(this, "Creating generator"); 2407bba1112556e122254013562650aac6a6af80ac6Brad Ebinger toneGenerator = mToneGenerator.get(stream, toneVolume); 241a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } catch (RuntimeException e) { 242a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.w(this, "Failed to create ToneGenerator.", e); 243a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon return; 244a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 245a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 246df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon // TODO: Certain CDMA tones need to check the ringer-volume state before 247a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // playing. See CallNotifier.InCallTonePlayer. 248a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 249df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon // TODO: Some tones play through the end of a call so we need to inform 250a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // CallAudioManager that we want focus the same way that Ringer does. 251a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 252a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon synchronized (this) { 253a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (mState != STATE_STOPPED) { 254a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_ON; 255a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator.startTone(toneType); 256a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon try { 257a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.v(this, "Starting tone %d...waiting for %d ms.", mToneId, 2588c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal toneLengthMillis + TIMEOUT_BUFFER_MILLIS); 2598c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal wait(toneLengthMillis + TIMEOUT_BUFFER_MILLIS); 260a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } catch (InterruptedException e) { 261a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.w(this, "wait interrupted", e); 262a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 263a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 264a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 265a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_OFF; 266a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } finally { 267a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (toneGenerator != null) { 268a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon toneGenerator.release(); 269a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 270a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon cleanUpTonePlayer(); 271efa8d2ad756e2ef5928bdf9171f52226096822ffBrad Ebinger Log.endSession(); 272a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 273a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 274d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger 275d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger @VisibleForTesting 276d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger public void startTone() { 277a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon sTonesPlaying++; 278a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (sTonesPlaying == 1) { 279a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mCallAudioManager.setIsTonePlaying(true); 280a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 281a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 282d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu synchronized (mSessionLock) { 283d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu if (mSession != null) { 284d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu Log.cancelSubsession(mSession); 285d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 286d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu mSession = Log.createSubsession(); 287d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu } 288d8ca5458f6ee1d47098a5934ddcef7e24cb074a9Hall Liu 289b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu super.start(); 290b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu } 291b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu 292b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu @Override 293b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu public void start() { 294b626c02daaae6757299cdb2b8228ef0635b6b5ddHall Liu Log.w(this, "Do not call the start method directly; use startTone instead."); 295a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 296a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 297a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon /** 298a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon * Stops the tone. 299a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon */ 300d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger @VisibleForTesting 301d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger public void stopTone() { 302a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon synchronized (this) { 303a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon if (mState == STATE_ON) { 304a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon Log.d(this, "Stopping the tone %d.", mToneId); 305a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon notify(); 306a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 307a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon mState = STATE_STOPPED; 308a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 309a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 310a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon 311a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon private void cleanUpTonePlayer() { 312a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon // Release focus on the main thread. 313f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger mMainThreadHandler.post(new Runnable("ICTP.cUTP", mLock) { 314e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger @Override 315e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger public void loggedRun() { 316f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger if (sTonesPlaying == 0) { 317f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger Log.wtf(this, "Over-releasing focus for tone player."); 318f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger } else if (--sTonesPlaying == 0) { 319f5e066609d0acc7ff53752bd6b9e3f2634bd0746Brad Ebinger mCallAudioManager.setIsTonePlaying(false); 320a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 321a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 322e62e9e83a17824b8e2057be35c2adcca20af9e35Brad Ebinger }.prepare()); 323a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon } 324a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon} 325