InCallTonePlayer.java revision e091ab90e37845cf4771051a6d2ce0ebadee4fe7
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
108a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    /**
109a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon     * Initializes the tone player. Private; use the {@link Factory} to create tone players.
110a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon     *
111a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon     * @param toneId ID of the tone to play, see TONE_* constants.
112a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon     */
113abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad    private InCallTonePlayer(
114abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad            int toneId,
115abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad            CallAudioManager callAudioManager,
116f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu            CallAudioRoutePeripheralAdapter callAudioRoutePeripheralAdapter,
117abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad            TelecomSystem.SyncRoot lock) {
118a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        mState = STATE_OFF;
119a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        mToneId = toneId;
120a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        mCallAudioManager = callAudioManager;
121f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu        mCallAudioRoutePeripheralAdapter = callAudioRoutePeripheralAdapter;
122abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad        mLock = lock;
123a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    }
124a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
125a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    /** {@inheritDoc} */
126a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    @Override
127a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    public void run() {
128a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        ToneGenerator toneGenerator = null;
129a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        try {
130a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            Log.d(this, "run(toneId = %s)", mToneId);
131a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
132a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            final int toneType;  // Passed to ToneGenerator.startTone.
133a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            final int toneVolume;  // Passed to the ToneGenerator constructor.
1348c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal            final int toneLengthMillis;
135a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
136a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            switch (mToneId) {
137c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_BUSY:
138c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    // TODO: CDMA-specific tones
139c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_SUP_BUSY;
140c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_HIPRI;
1418c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = 4000;
142c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
143c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_CALL_ENDED:
144c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_PROP_PROMPT;
145c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_HIPRI;
1467062bb96f567e7dc9c7bf933b7bee17bb2c8108cYorke Lee                    toneLengthMillis = 200;
147c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
148c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_OTA_CALL_ENDED:
149c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    // TODO: fill in
150c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    throw new IllegalStateException("OTA Call ended NYI.");
151c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_CALL_WAITING:
15240f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon                    toneType = ToneGenerator.TONE_SUP_CALL_WAITING;
15340f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon                    toneVolume = RELATIVE_VOLUME_HIPRI;
15440f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon                    toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS;
15540f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon                    break;
156c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_CDMA_DROP:
157c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE;
158c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_LOPRI;
1598c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = 375;
160c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
161c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_CONGESTION:
162c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_SUP_CONGESTION;
163c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_HIPRI;
1648c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = 4000;
165c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
166c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_INTERCEPT:
167c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT;
168c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_LOPRI;
1698c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = 500;
170c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
171c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_OUT_OF_SERVICE:
172c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE;
173c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_LOPRI;
1748c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = 375;
175c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
176c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_REDIAL:
177c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE;
178c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_LOPRI;
1798c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = 5000;
180c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
181c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_REORDER:
182c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_CDMA_REORDER;
183c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_HIPRI;
1847062bb96f567e7dc9c7bf933b7bee17bb2c8108cYorke Lee                    toneLengthMillis = 4000;
185c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
186a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                case TONE_RING_BACK:
187a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    toneType = ToneGenerator.TONE_SUP_RINGTONE;
188a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    toneVolume = RELATIVE_VOLUME_HIPRI;
1898c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = Integer.MAX_VALUE - TIMEOUT_BUFFER_MILLIS;
190a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    break;
191c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_UNOBTAINABLE_NUMBER:
192c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneType = ToneGenerator.TONE_SUP_ERROR;
193c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    toneVolume = RELATIVE_VOLUME_HIPRI;
1948c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                    toneLengthMillis = 4000;
195c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    break;
196c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                case TONE_VOICE_PRIVACY:
197c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    // TODO: fill in.
198c7b8ebabf904aa70a7a2a2a0ad01883088c56180Santos Cordon                    throw new IllegalStateException("Voice privacy tone NYI.");
19986014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn                case TONE_VIDEO_UPGRADE:
20086014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn                    // Similar to the call waiting tone, but does not repeat.
20186014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn                    toneType = ToneGenerator.TONE_SUP_CALL_WAITING;
20286014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn                    toneVolume = RELATIVE_VOLUME_HIPRI;
20386014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn                    toneLengthMillis = 4000;
20486014fcf9ec86e198a1ebac7c46e0e5c630735d7Tyler Gunn                    break;
205a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                default:
206a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    throw new IllegalStateException("Bad toneId: " + mToneId);
207a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            }
208a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
209a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            int stream = AudioManager.STREAM_VOICE_CALL;
210f62630a57de0d52be2bdbc92a9bf8f305cc0892dHall Liu            if (mCallAudioRoutePeripheralAdapter.isBluetoothAudioOn()) {
211c7e85d4fa0bb3325133a79d4c89f3149e0af430eSantos Cordon                stream = AudioManager.STREAM_BLUETOOTH_SCO;
212c7e85d4fa0bb3325133a79d4c89f3149e0af430eSantos Cordon            }
213a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
214a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            // If the ToneGenerator creation fails, just continue without it. It is a local audio
215a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            // signal, and is not as important.
216a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            try {
217a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                Log.v(this, "Creating generator");
218a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                toneGenerator = new ToneGenerator(stream, toneVolume);
219a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            } catch (RuntimeException e) {
220a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                Log.w(this, "Failed to create ToneGenerator.", e);
221a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                return;
222a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            }
223a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
224df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon            // TODO: Certain CDMA tones need to check the ringer-volume state before
225a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            // playing. See CallNotifier.InCallTonePlayer.
226a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
227df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon            // TODO: Some tones play through the end of a call so we need to inform
228a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            // CallAudioManager that we want focus the same way that Ringer does.
229a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
230a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            synchronized (this) {
231a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                if (mState != STATE_STOPPED) {
232a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    mState = STATE_ON;
233a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    toneGenerator.startTone(toneType);
234a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    try {
235a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                        Log.v(this, "Starting tone %d...waiting for %d ms.", mToneId,
2368c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                                toneLengthMillis + TIMEOUT_BUFFER_MILLIS);
2378c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal                        wait(toneLengthMillis + TIMEOUT_BUFFER_MILLIS);
238a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    } catch (InterruptedException e) {
239a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                        Log.w(this, "wait interrupted", e);
240a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                    }
241a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                }
242a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            }
243a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            mState = STATE_OFF;
244a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        } finally {
245a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            if (toneGenerator != null) {
246a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                toneGenerator.release();
247a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            }
248a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            cleanUpTonePlayer();
249a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        }
250a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    }
251d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger
252d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger    @VisibleForTesting
253d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger    public void startTone() {
254a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        sTonesPlaying++;
255a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        if (sTonesPlaying == 1) {
256a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            mCallAudioManager.setIsTonePlaying(true);
257a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        }
258a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
259a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        start();
260a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    }
261a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
262a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    /**
263a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon     * Stops the tone.
264a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon     */
265d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger    @VisibleForTesting
266d931a017a0abea32ad4485a91402b5f62b9ddb0eBrad Ebinger    public void stopTone() {
267a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        synchronized (this) {
268a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            if (mState == STATE_ON) {
269a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                Log.d(this, "Stopping the tone %d.", mToneId);
270a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                notify();
271a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            }
272a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            mState = STATE_STOPPED;
273a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        }
274a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    }
275a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon
276a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    private void cleanUpTonePlayer() {
277a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        // Release focus on the main thread.
278a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        mMainThreadHandler.post(new Runnable() {
279a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            @Override public void run() {
280abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad                synchronized (mLock) {
281abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad                    if (sTonesPlaying == 0) {
282abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad                        Log.wtf(this, "Over-releasing focus for tone player.");
283abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad                    } else if (--sTonesPlaying == 0) {
284abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad                        mCallAudioManager.setIsTonePlaying(false);
285abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad                    }
286a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon                }
287a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon            }
288a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon        });
289a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon    }
290a56f276cafcad80ab3a28996b6a0d72cffa4b2bcSantos Cordon}
291