1 /*
2  * Copyright (C) 2015 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 android.telecom.cts;
18 
19 import android.net.Uri;
20 import android.os.Bundle;
21 import android.telecom.Conference;
22 import android.telecom.Connection;
23 import android.telecom.DisconnectCause;
24 import android.telecom.PhoneAccountHandle;
25 import android.telecom.RemoteConference;
26 import android.telecom.TelecomManager;
27 import android.telecom.VideoProfile;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.concurrent.CompletableFuture;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.TimeUnit;
34 import java.util.concurrent.TimeoutException;
35 
36 /**
37  * {@link Conference} subclass that immediately performs any state changes that are a result of
38  * callbacks sent from Telecom.
39  */
40 public class MockConference extends Conference {
41 
42     private RemoteConference mRemoteConference = null;
43     private String mDtmfString = "";
44     public TestUtils.InvokeCounter mOnExtrasChanged =
45             new TestUtils.InvokeCounter("onExtrasChanged");
46     public List<Uri> mParticipants = new ArrayList<>();
47     public CompletableFuture<Void> mLock = new CompletableFuture<>();
48     private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
49 
MockConference(PhoneAccountHandle phoneAccount)50     public MockConference(PhoneAccountHandle phoneAccount) {
51         super(phoneAccount);
52     }
53 
MockConference(MockConnection a, MockConnection b)54     public MockConference(MockConnection a, MockConnection b) {
55         super(a.getMockPhoneAccountHandle());
56         addConnection(a);
57         addConnection(b);
58         // a is the primary connection, so inherit the properties from it.
59         setConnectionCapabilities(a.getConnectionCapabilities());
60         setStatusHints(a.getStatusHints());
61         setExtras(a.getExtras());
62     }
63 
64     @Override
onDisconnect()65     public void onDisconnect() {
66         super.onDisconnect();
67         for (Connection c : getConnections()) {
68             c.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE));
69             c.destroy();
70         }
71         destroy();
72         if (mRemoteConference != null) {
73             mRemoteConference.disconnect();
74         }
75     }
76 
77     @Override
onReject()78     public void onReject() {
79         super.onReject();
80         for (Connection c : getConnections()) {
81             c.setDisconnected(new DisconnectCause(DisconnectCause.REJECTED));
82             c.destroy();
83         }
84         destroy();
85         if (mRemoteConference != null) {
86             mRemoteConference.disconnect();
87         }
88         mLock.complete(null);
89     }
90 
91     @Override
onSeparate(Connection connection)92     public void onSeparate(Connection connection) {
93         super.onSeparate(connection);
94         if (getConnections().contains(connection)) {
95             removeConnection(connection);
96         }
97         if (mRemoteConference != null) {
98             mRemoteConference.separate(((MockConnection)connection).getRemoteConnection());
99         }
100     }
101 
102     @Override
onMerge()103     public void onMerge() {
104         super.onMerge();
105         // Let's just change the connection display name for testing that onMerge was invoked.
106         for (Connection c : getConnections()) {
107             c.setCallerDisplayName(
108                     TestUtils.MERGE_CALLER_NAME, TelecomManager.PRESENTATION_ALLOWED);
109         }
110         if (mRemoteConference != null) {
111             mRemoteConference.merge();
112         }
113     }
114 
115     @Override
onSwap()116     public void onSwap() {
117         super.onSwap();
118         // Let's just change the connection display name for testing that onSwap was invoked.
119         for (Connection c : getConnections()) {
120             c.setCallerDisplayName(
121                     TestUtils.SWAP_CALLER_NAME, TelecomManager.PRESENTATION_ALLOWED);
122         }
123         if (mRemoteConference != null) {
124             mRemoteConference.swap();
125         }
126     }
127 
128     @Override
onHold()129     public void onHold() {
130         super.onHold();
131         for (Connection c : getConnections()) {
132             c.setOnHold();
133         }
134         setOnHold();
135         if (mRemoteConference != null) {
136             mRemoteConference.hold();
137         }
138     }
139 
140     @Override
onUnhold()141     public void onUnhold() {
142         super.onUnhold();
143         for (Connection c : getConnections()) {
144             c.setActive();
145         }
146         setActive();
147         if (mRemoteConference != null) {
148             mRemoteConference.unhold();
149         }
150     }
151 
152     @Override
onPlayDtmfTone(char c)153     public void onPlayDtmfTone(char c) {
154         super.onPlayDtmfTone(c);
155         mDtmfString += c;
156         if (mRemoteConference != null) {
157             mRemoteConference.playDtmfTone(c);
158         }
159     }
160 
161     @Override
onStopDtmfTone()162     public void onStopDtmfTone() {
163         super.onStopDtmfTone();
164         mDtmfString += ".";
165         if (mRemoteConference != null) {
166             mRemoteConference.stopDtmfTone();
167         }
168     }
169 
170     @Override
onAddConferenceParticipants(List<Uri> participants)171     public void onAddConferenceParticipants(List<Uri> participants) {
172         super.onAddConferenceParticipants(participants);
173         mParticipants.addAll(participants);
174         mLock.complete(null);
175     }
176 
177     @Override
onAnswer(int videoState)178     public void onAnswer(int videoState) {
179         super.onAnswer(videoState);
180         mVideoState = videoState;
181         mLock.complete(null);
182     }
183 
setRemoteConference(RemoteConference remoteConference)184     public void setRemoteConference(RemoteConference remoteConference) {
185         mRemoteConference = remoteConference;
186         Bundle bundle = remoteConference.getExtras();
187         if (bundle != null) {
188             this.putExtras(bundle);
189         }
190     }
191 
getRemoteConference()192     public RemoteConference getRemoteConference() {
193         return mRemoteConference;
194     }
195 
getDtmfString()196     public String getDtmfString() {
197         return mDtmfString;
198     }
199 
getVideoState()200     public int getVideoState() {
201         return mVideoState;
202     }
203 
204     @Override
onExtrasChanged(Bundle extras)205     public void onExtrasChanged(Bundle extras) {
206         setExtras(extras);
207         mOnExtrasChanged.invoke(extras);
208     }
209 
acquireLock(long time, TimeUnit unit)210     public boolean acquireLock(long time, TimeUnit unit) {
211         try {
212             mLock.get(time, unit);
213         } catch (InterruptedException | ExecutionException | TimeoutException e) {
214             return false;
215         }
216         return true;
217     }
218 
resetLock()219     public void resetLock() {
220         mLock = new CompletableFuture<>();
221     }
222 }
223