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.incallui;
18 
19 import com.google.common.base.Preconditions;
20 
21 import java.util.Collections;
22 import java.util.Set;
23 import java.util.concurrent.ConcurrentHashMap;
24 
25 /**
26  * Class used by {@link InCallService.VideoCallListener} to notify interested parties of incoming
27  * events.
28  */
29 public class InCallVideoCallListenerNotifier {
30     /**
31      * Singleton instance of this class.
32      */
33     private static InCallVideoCallListenerNotifier sInstance = new InCallVideoCallListenerNotifier();
34 
35     /**
36      * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
37      * load factor before resizing, 1 means we only expect a single thread to
38      * access the map so make only a single shard
39      */
40     private final Set<SessionModificationListener> mSessionModificationListeners =
41             Collections.newSetFromMap(new ConcurrentHashMap<SessionModificationListener, Boolean>
42                     (8, 0.9f, 1));
43     private final Set<VideoEventListener> mVideoEventListeners = Collections.newSetFromMap(
44             new ConcurrentHashMap<VideoEventListener, Boolean>(8, 0.9f, 1));
45     private final Set<SurfaceChangeListener> mSurfaceChangeListeners = Collections.newSetFromMap(
46             new ConcurrentHashMap<SurfaceChangeListener, Boolean>(8, 0.9f, 1));
47 
48     /**
49      * Static singleton accessor method.
50      */
getInstance()51     public static InCallVideoCallListenerNotifier getInstance() {
52         return sInstance;
53     }
54 
55     /**
56      * Private constructor.  Instance should only be acquired through getInstance().
57      */
InCallVideoCallListenerNotifier()58     private InCallVideoCallListenerNotifier() {
59     }
60 
61     /**
62      * Adds a new {@link SessionModificationListener}.
63      *
64      * @param listener The listener.
65      */
addSessionModificationListener(SessionModificationListener listener)66     public void addSessionModificationListener(SessionModificationListener listener) {
67         Preconditions.checkNotNull(listener);
68         mSessionModificationListeners.add(listener);
69     }
70 
71     /**
72      * Remove a {@link SessionModificationListener}.
73      *
74      * @param listener The listener.
75      */
removeSessionModificationListener(SessionModificationListener listener)76     public void removeSessionModificationListener(SessionModificationListener listener) {
77         if (listener != null) {
78             mSessionModificationListeners.remove(listener);
79         }
80     }
81 
82     /**
83      * Adds a new {@link VideoEventListener}.
84      *
85      * @param listener The listener.
86      */
addVideoEventListener(VideoEventListener listener)87     public void addVideoEventListener(VideoEventListener listener) {
88         Preconditions.checkNotNull(listener);
89         mVideoEventListeners.add(listener);
90     }
91 
92     /**
93      * Remove a {@link VideoEventListener}.
94      *
95      * @param listener The listener.
96      */
removeVideoEventListener(VideoEventListener listener)97     public void removeVideoEventListener(VideoEventListener listener) {
98         if (listener != null) {
99             mVideoEventListeners.remove(listener);
100         }
101     }
102 
103     /**
104      * Adds a new {@link SurfaceChangeListener}.
105      *
106      * @param listener The listener.
107      */
addSurfaceChangeListener(SurfaceChangeListener listener)108     public void addSurfaceChangeListener(SurfaceChangeListener listener) {
109         Preconditions.checkNotNull(listener);
110         mSurfaceChangeListeners.add(listener);
111     }
112 
113     /**
114      * Remove a {@link SurfaceChangeListener}.
115      *
116      * @param listener The listener.
117      */
removeSurfaceChangeListener(SurfaceChangeListener listener)118     public void removeSurfaceChangeListener(SurfaceChangeListener listener) {
119         if (listener != null) {
120             mSurfaceChangeListeners.remove(listener);
121         }
122     }
123 
124     /**
125      * Inform listeners of an upgrade to video request for a call.
126      *
127      * @param call The call.
128      */
upgradeToVideoRequest(Call call)129     public void upgradeToVideoRequest(Call call) {
130         for (SessionModificationListener listener : mSessionModificationListeners) {
131             listener.onUpgradeToVideoRequest(call);
132         }
133     }
134 
135     /**
136      * Inform listeners of a successful response to a video request for a call.
137      *
138      * @param call The call.
139      */
upgradeToVideoSuccess(Call call)140     public void upgradeToVideoSuccess(Call call) {
141         for (SessionModificationListener listener : mSessionModificationListeners) {
142             listener.onUpgradeToVideoSuccess(call);
143         }
144     }
145 
146     /**
147      * Inform listeners of an unsuccessful response to a video request for a call.
148      *
149      * @param call The call.
150      */
upgradeToVideoFail(Call call)151     public void upgradeToVideoFail(Call call) {
152         for (SessionModificationListener listener : mSessionModificationListeners) {
153             listener.onUpgradeToVideoFail(call);
154         }
155     }
156 
157     /**
158      * Inform listeners of a downgrade to audio.
159      *
160      * @param call The call.
161      */
downgradeToAudio(Call call)162     public void downgradeToAudio(Call call) {
163         for (SessionModificationListener listener : mSessionModificationListeners) {
164             listener.onDowngradeToAudio(call);
165         }
166     }
167 
168     /**
169      * Inform listeners of a downgrade to audio.
170      *
171      * @param call The call.
172      * @param paused The paused state.
173      */
peerPausedStateChanged(Call call, boolean paused)174     public void peerPausedStateChanged(Call call, boolean paused) {
175         for (VideoEventListener listener : mVideoEventListeners) {
176             listener.onPeerPauseStateChanged(call, paused);
177         }
178     }
179 
180     /**
181      * Inform listeners of a change to peer dimensions.
182      *
183      * @param call The call.
184      * @param width New peer width.
185      * @param height New peer height.
186      */
peerDimensionsChanged(Call call, int width, int height)187     public void peerDimensionsChanged(Call call, int width, int height) {
188         for (SurfaceChangeListener listener : mSurfaceChangeListeners) {
189             listener.onUpdatePeerDimensions(call, width, height);
190         }
191     }
192 
193     /**
194      * Inform listeners of a change to camera dimensions.
195      *
196      * @param call The call.
197      * @param width The new camera video width.
198      * @param height The new camera video height.
199      */
cameraDimensionsChanged(Call call, int width, int height)200     public void cameraDimensionsChanged(Call call, int width, int height) {
201         for (SurfaceChangeListener listener : mSurfaceChangeListeners) {
202             listener.onCameraDimensionsChange(call, width, height);
203         }
204     }
205 
206     /**
207      * Listener interface for any class that wants to be notified of upgrade to video and downgrade
208      * to audio session modification requests.
209      */
210     public interface SessionModificationListener {
211         /**
212          * Called when a peer request is received to upgrade an audio-only call to a video call.
213          *
214          * @param call The call the request was received for.
215          */
onUpgradeToVideoRequest(Call call)216         public void onUpgradeToVideoRequest(Call call);
217 
218         /**
219          * Called when a request to a peer to upgrade an audio-only call to a video call is
220          * successful.
221          *
222          * @param call The call the request was successful for.
223          */
onUpgradeToVideoSuccess(Call call)224         public void onUpgradeToVideoSuccess(Call call);
225 
226         /**
227          * Called when a request to a peer to upgrade an audio-only call to a video call is
228          * NOT successful. This can be if the peer chooses rejects the the video call, or if the
229          * peer does not support video calling, or if there is some error in sending the request.
230          *
231          * @param call The call the request was successful for.
232          */
onUpgradeToVideoFail(Call call)233         public void onUpgradeToVideoFail(Call call);
234 
235         /**
236          * Called when a call has been downgraded to audio-only.
237          *
238          * @param call The call which was downgraded to audio-only.
239          */
onDowngradeToAudio(Call call)240         public void onDowngradeToAudio(Call call);
241     }
242 
243     /**
244      * Listener interface for any class that wants to be notified of video events, including pause
245      * and un-pause of peer video.
246      */
247     public interface VideoEventListener {
248         /**
249          * Called when the peer pauses or un-pauses video transmission.
250          *
251          * @param call   The call which paused or un-paused video transmission.
252          * @param paused {@code True} when the video transmission is paused, {@code false}
253          *               otherwise.
254          */
onPeerPauseStateChanged(Call call, boolean paused)255         public void onPeerPauseStateChanged(Call call, boolean paused);
256     }
257 
258     /**
259      * Listener interface for any class that wants to be notified of changes to the video surfaces.
260      */
261     public interface SurfaceChangeListener {
262         /**
263          * Called when the peer video feed changes dimensions. This can occur when the peer rotates
264          * their device, changing the aspect ratio of the video signal.
265          *
266          * @param call The call which experienced a peer video
267          * @param width
268          * @param height
269          */
onUpdatePeerDimensions(Call call, int width, int height)270         public void onUpdatePeerDimensions(Call call, int width, int height);
271 
272         /**
273          * Called when the local camera changes dimensions.  This occurs when a change in camera
274          * occurs.
275          *
276          * @param call The call which experienced the camera dimension change.
277          * @param width The new camera video width.
278          * @param height The new camera video height.
279          */
onCameraDimensionsChange(Call call, int width, int height)280         public void onCameraDimensionsChange(Call call, int width, int height);
281     }
282 }
283