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
17package com.android.server.telecom.testapps;
18
19import android.content.Context;
20import android.telecom.Call;
21import android.telecom.InCallService;
22import android.telecom.VideoProfile;
23import android.telecom.VideoProfile.CameraCapabilities;
24import android.util.ArrayMap;
25import android.util.ArraySet;
26import android.util.Log;
27import android.widget.Toast;
28
29import java.util.LinkedList;
30import java.util.List;
31import java.util.Map;
32import java.util.Set;
33
34/**
35 * Maintains a list of calls received via the {@link TestInCallServiceImpl}.
36 */
37public class TestCallList extends Call.Callback {
38
39    public static abstract class Listener {
40        public void onCallAdded(Call call) {}
41        public void onCallRemoved(Call call) {}
42        public void onRttStarted(Call call) {}
43        public void onRttStopped(Call call) {}
44        public void onRttInitiationFailed(Call call, int reason) {}
45        public void onRttRequest(Call call, int id) {}
46    }
47
48    private static final TestCallList INSTANCE = new TestCallList();
49    private static final String TAG = "TestCallList";
50
51    private class TestVideoCallListener extends InCallService.VideoCall.Callback {
52        private Call mCall;
53
54        public TestVideoCallListener(Call call) {
55            mCall = call;
56        }
57
58        @Override
59        public void onSessionModifyRequestReceived(VideoProfile videoProfile) {
60            Log.v(TAG,
61                    "onSessionModifyRequestReceived: videoState = " + videoProfile.getVideoState()
62                            + " call = " + mCall);
63        }
64
65        @Override
66        public void onSessionModifyResponseReceived(int status, VideoProfile requestedProfile,
67                VideoProfile responseProfile) {
68            Log.v(TAG,
69                    "onSessionModifyResponseReceived: status = " + status + " videoState = "
70                            + responseProfile.getVideoState()
71                            + " call = " + mCall);
72        }
73
74        @Override
75        public void onCallSessionEvent(int event) {
76
77        }
78
79        @Override
80        public void onPeerDimensionsChanged(int width, int height) {
81
82        }
83
84        @Override
85        public void onVideoQualityChanged(int videoQuality) {
86            Log.v(TAG,
87                    "onVideoQualityChanged: videoQuality = " + videoQuality + " call = " + mCall);
88        }
89
90        @Override
91        public void onCallDataUsageChanged(long dataUsage) {
92
93        }
94
95        @Override
96        public void onCameraCapabilitiesChanged(CameraCapabilities cameraCapabilities) {
97
98        }
99    }
100
101    // The calls the call list knows about.
102    private List<Call> mCalls = new LinkedList<Call>();
103    private Map<Call, TestVideoCallListener> mVideoCallListeners =
104            new ArrayMap<Call, TestVideoCallListener>();
105    private Set<Listener> mListeners = new ArraySet<Listener>();
106    private Context mContext;
107    private int mLastRttRequestId = -1;
108
109    /**
110     * Singleton accessor.
111     */
112    public static TestCallList getInstance() {
113        return INSTANCE;
114    }
115
116    public void addListener(Listener listener) {
117        if (listener != null) {
118            mListeners.add(listener);
119        }
120    }
121
122    public boolean removeListener(Listener listener) {
123        return mListeners.remove(listener);
124    }
125
126    public Call getCall(int position) {
127        return mCalls.get(position);
128    }
129
130    public void addCall(Call call) {
131        if (mCalls.contains(call)) {
132            Log.e(TAG, "addCall: Call already added.");
133            return;
134        }
135        Log.i(TAG, "addCall: " + call + " " + System.identityHashCode(this));
136        mCalls.add(call);
137        call.registerCallback(this);
138
139        for (Listener l : mListeners) {
140            l.onCallAdded(call);
141        }
142    }
143
144    public void removeCall(Call call) {
145        if (!mCalls.contains(call)) {
146            Log.e(TAG, "removeCall: Call cannot be removed -- doesn't exist.");
147            return;
148        }
149        Log.i(TAG, "removeCall: " + call);
150        mCalls.remove(call);
151        call.unregisterCallback(this);
152
153        for (Listener l : mListeners) {
154            if (l != null) {
155                l.onCallRemoved(call);
156            }
157        }
158    }
159
160    public void clearCalls() {
161        for (Call call : new LinkedList<Call>(mCalls)) {
162            removeCall(call);
163        }
164
165        for (Call call : mVideoCallListeners.keySet()) {
166            if (call.getVideoCall() != null) {
167                call.getVideoCall().destroy();
168            }
169        }
170        mVideoCallListeners.clear();
171    }
172
173    public int size() {
174        return mCalls.size();
175    }
176
177    public int getLastRttRequestId() {
178        return mLastRttRequestId;
179    }
180
181    /**
182     * For any video calls tracked, sends an upgrade to video request.
183     */
184    public void sendUpgradeToVideoRequest(int videoState) {
185        Log.v(TAG, "sendUpgradeToVideoRequest : videoState = " + videoState);
186
187        for (Call call : mCalls) {
188            InCallService.VideoCall videoCall = call.getVideoCall();
189            Log.v(TAG, "sendUpgradeToVideoRequest: checkCall "+call);
190            if (videoCall == null) {
191                continue;
192            }
193
194            Log.v(TAG, "send upgrade to video request for call: " + call);
195            videoCall.sendSessionModifyRequest(new VideoProfile(videoState));
196        }
197    }
198
199    /**
200     * For any video calls which are active, sends an upgrade to video response with the specified
201     * video state.
202     *
203     * @param videoState The video state to respond with.
204     */
205    public void sendUpgradeToVideoResponse(int videoState) {
206        Log.v(TAG, "sendUpgradeToVideoResponse : videoState = " + videoState);
207
208        for (Call call : mCalls) {
209            InCallService.VideoCall videoCall = call.getVideoCall();
210            if (videoCall == null) {
211                continue;
212            }
213
214            Log.v(TAG, "send upgrade to video response for call: " + call);
215            videoCall.sendSessionModifyResponse(new VideoProfile(videoState));
216        }
217    }
218
219    @Override
220    public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {
221        Log.v(TAG, "onVideoCallChanged: call = " + call + " " + System.identityHashCode(this));
222        if (videoCall != null) {
223            if (!mVideoCallListeners.containsKey(call)) {
224                TestVideoCallListener listener = new TestVideoCallListener(call);
225                videoCall.registerCallback(listener);
226                mVideoCallListeners.put(call, listener);
227                Log.v(TAG, "onVideoCallChanged: added new listener");
228            }
229        }
230    }
231
232    @Override
233    public void onRttStatusChanged(Call call, boolean enabled, Call.RttCall rttCall) {
234        Log.v(TAG, "onRttStatusChanged: call = " + call + " " + System.identityHashCode(this));
235        if (enabled) {
236            for (Listener l : mListeners) {
237                l.onRttStarted(call);
238            }
239        } else {
240            for (Listener l : mListeners) {
241                l.onRttStopped(call);
242            }
243        }
244    }
245
246    @Override
247    public void onRttInitiationFailure(Call call, int reason) {
248        for (Listener l : mListeners) {
249            l.onRttInitiationFailed(call, reason);
250        }
251    }
252
253    @Override
254    public void onRttRequest(Call call, int id) {
255        mLastRttRequestId = id;
256        for (Listener l : mListeners) {
257            l.onRttRequest(call, id);
258        }
259    }
260}
261