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