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