1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.telecom;
18 
19 import com.android.internal.util.Preconditions;
20 
21 /**
22  * Plays ringback tones. Ringback is different from other tones because it operates as the current
23  * audio for a call, whereas most tones play as simple timed events. This means ringback must be
24  * able to turn off and on as the user switches between calls. This is why it is implemented as its
25  * own class.
26  */
27 public class RingbackPlayer {
28 
29     private final InCallTonePlayer.Factory mPlayerFactory;
30 
31     /**
32      * The current call for which the ringback tone is being played.
33      */
34     private Call mCall;
35 
36     /**
37      * The currently active player.
38      */
39     private InCallTonePlayer mTonePlayer;
40 
RingbackPlayer(InCallTonePlayer.Factory playerFactory)41     RingbackPlayer(InCallTonePlayer.Factory playerFactory) {
42         mPlayerFactory = playerFactory;
43     }
44 
45     /**
46      * Starts ringback for the specified dialing call as needed.
47      *
48      * @param call The call for which to ringback.
49      */
startRingbackForCall(Call call)50     public void startRingbackForCall(Call call) {
51         Preconditions.checkState(call.getState() == CallState.DIALING);
52 
53         if (mCall == call) {
54             Log.w(this, "Ignoring duplicate requests to ring for %s.", call);
55             return;
56         }
57 
58         if (mCall != null) {
59             // We only get here for the foreground call so, there's no reason why there should
60             // exist a current dialing call.
61             Log.wtf(this, "Ringback player thinks there are two foreground-dialing calls.");
62         }
63 
64         mCall = call;
65         if (mTonePlayer == null) {
66             Log.d(this, "Playing the ringback tone for %s.", call);
67             mTonePlayer = mPlayerFactory.createPlayer(InCallTonePlayer.TONE_RING_BACK);
68             mTonePlayer.startTone();
69         }
70     }
71 
72     /**
73      * Stops the ringback for the specified dialing call as needed.
74      *
75      * @param call The call for which to stop ringback.
76      */
stopRingbackForCall(Call call)77     public void stopRingbackForCall(Call call) {
78         if (mCall == call) {
79             // The foreground call is no longer dialing or is no longer the foreground call. In
80             // either case, stop the ringback tone.
81             mCall = null;
82 
83             if (mTonePlayer == null) {
84                 Log.w(this, "No player found to stop.");
85             } else {
86                 Log.i(this, "Stopping the ringback tone for %s.", call);
87                 mTonePlayer.stopTone();
88                 mTonePlayer = null;
89             }
90         }
91     }
92 }