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