• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.cts.verifier.telecom;
18 
19 import android.content.Context;
20 import android.media.AudioAttributes;
21 import android.media.AudioManager;
22 import android.media.MediaPlayer;
23 import android.telecom.CallAudioState;
24 import android.telecom.Connection;
25 import android.telecom.DisconnectCause;
26 import android.telecom.VideoProfile;
27 import android.util.ArraySet;
28 import android.util.Log;
29 
30 import com.android.compatibility.common.util.ApiTest;
31 import com.android.cts.verifier.R;
32 
33 import java.util.Set;
34 import java.util.concurrent.CountDownLatch;
35 import java.util.concurrent.TimeUnit;
36 
37 /**
38  * An implementation of the {@link android.telecom.Connection} class used by the
39  * {@link CtsConnectionService}.
40  */
41 @ApiTest(apis={"android.Telecom.Connection"})
42 public class CtsConnection extends Connection {
43     public static final String TAG = "CtsConnection";
44 
45     /**
46      * Listener used to inform the CtsVerifier app of changes to a connection.
47      */
48     public static abstract class Listener {
onDestroyed(CtsConnection connection)49         void onDestroyed(CtsConnection connection) { };
onDisconnect(CtsConnection connection)50         void onDisconnect(CtsConnection connection) { };
onHold(CtsConnection connection)51         void onHold(CtsConnection connection) { };
onUnhold(CtsConnection connection)52         void onUnhold(CtsConnection connection) { };
onAnswer(CtsConnection connection, int videoState)53         void onAnswer(CtsConnection connection, int videoState) { };
onReject(CtsConnection connection)54         void onReject(CtsConnection connection) { };
onShowIncomingCallUi(CtsConnection connection)55         void onShowIncomingCallUi(CtsConnection connection) { };
56     }
57 
58     public static final String EXTRA_PLAY_CS_AUDIO =
59             "com.android.cts.verifier.telecom.PLAY_CS_AUDIO";
60 
61     private final boolean mIsIncomingCall;
62     private final Set<Listener> mListener = new ArraySet<>();
63     private final MediaPlayer mMediaPlayer;
64     private final Context mContext;
65     private CountDownLatch mWaitForCallAudioStateChanged = new CountDownLatch(1);
66 
CtsConnection(Context context, boolean isIncomingCall, Listener listener, boolean hasAudio)67     public CtsConnection(Context context, boolean isIncomingCall,
68             Listener listener, boolean hasAudio) {
69         mContext = context;
70         mIsIncomingCall = isIncomingCall;
71         mListener.add(listener);
72         if (hasAudio) {
73             mMediaPlayer = createMediaPlayer();
74         } else {
75             mMediaPlayer = null;
76         }
77     }
78 
isIncomingCall()79     public boolean isIncomingCall() {
80         return mIsIncomingCall;
81     }
82 
addListener(Listener listener)83     public void addListener(Listener listener) {
84         mListener.add(listener);
85     }
86 
87     @Override
onDisconnect()88     public void onDisconnect() {
89         setDisconnectedAndDestroy(new DisconnectCause(DisconnectCause.LOCAL));
90 
91         if (mListener != null) {
92             mListener.forEach(l -> l.onDisconnect(CtsConnection.this));
93         }
94     }
95 
96 
97     @Override
onHold()98     public void onHold() {
99         setOnHold();
100 
101         if (mListener != null) {
102             mListener.forEach(l -> l.onHold(CtsConnection.this));
103         }
104 
105         if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
106             Log.d(TAG, "onHold: pausing media player");
107             mMediaPlayer.pause();
108         }
109     }
110 
111     @Override
onUnhold()112     public void onUnhold() {
113         setActive();
114 
115         if (mListener != null) {
116             mListener.forEach(l -> l.onUnhold(CtsConnection.this));
117         }
118 
119         if (mMediaPlayer != null) {
120             Log.d(TAG, "onUnhold: starting media player");
121             mMediaPlayer.start();
122         }
123     }
124 
125     @Override
onAnswer(int videoState)126     public void onAnswer(int videoState) {
127         setVideoState(videoState);
128         setActive();
129 
130         if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
131             Log.d(TAG, "onAnswer: playing media");
132             mMediaPlayer.start();
133         }
134 
135         if (mListener != null) {
136             mListener.forEach(l -> l.onAnswer(CtsConnection.this, videoState));
137         }
138     }
139 
140     @Override
onAnswer()141     public void onAnswer() {
142         onAnswer(VideoProfile.STATE_AUDIO_ONLY);
143     }
144 
145     @Override
onReject()146     public void onReject() {
147         setDisconnectedAndDestroy(new DisconnectCause(DisconnectCause.REJECTED));
148 
149         if (mListener != null) {
150             mListener.forEach(l -> l.onReject(CtsConnection.this));
151         }
152     }
153 
154     @Override
onShowIncomingCallUi()155     public void onShowIncomingCallUi() {
156         if (mListener != null) {
157             mListener.forEach(l -> l.onShowIncomingCallUi(CtsConnection.this));
158         }
159     }
160 
onCallAudioStateChanged(CallAudioState state)161     public void onCallAudioStateChanged(CallAudioState state) {
162         mWaitForCallAudioStateChanged.countDown();
163         mWaitForCallAudioStateChanged = new CountDownLatch(1);
164 
165     }
166 
waitForAudioStateChanged()167     public void waitForAudioStateChanged() {
168         try {
169             mWaitForCallAudioStateChanged.await(CtsConnectionService.TIMEOUT_MILLIS,
170                     TimeUnit.MILLISECONDS);
171         } catch (InterruptedException e) {
172         }
173     }
174 
setDisconnectedAndDestroy(DisconnectCause cause)175     private void setDisconnectedAndDestroy(DisconnectCause cause) {
176         setDisconnected(cause);
177         destroy();
178 
179         if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
180             mMediaPlayer.stop();
181         }
182 
183         if (mListener != null) {
184             mListener.forEach(l -> l.onDestroyed(CtsConnection.this));
185         }
186     }
187 
createMediaPlayer()188     private MediaPlayer createMediaPlayer() {
189         Log.d(TAG, "createMediaPlayer");
190         AudioAttributes voiceCallAttributes = new AudioAttributes.Builder()
191                 .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
192                 .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
193                 .build();
194         int audioSessionId = ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
195                 .generateAudioSessionId();
196         // Prepare the media player to play a tone when there is a call.
197         MediaPlayer mediaPlayer = MediaPlayer.create(mContext, R.raw.telecom_test_call_audio,
198                 voiceCallAttributes, audioSessionId);
199         mediaPlayer.setLooping(true);
200         return mediaPlayer;
201     }
202 }
203