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