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.VideoCallCallback} to notify interested parties of incoming 27 * events. 28 */ 29 public 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 call session event. 139 * 140 * @param event The call session event. 141 */ 142 public void callSessionEvent(int event) { 143 for (VideoEventListener listener : mVideoEventListeners) { 144 listener.onCallSessionEvent(event); 145 } 146 } 147 148 /** 149 * Inform listeners of a downgrade to audio. 150 * 151 * @param call The call. 152 * @param paused The paused state. 153 */ 154 public void peerPausedStateChanged(Call call, boolean paused) { 155 for (VideoEventListener listener : mVideoEventListeners) { 156 listener.onPeerPauseStateChanged(call, paused); 157 } 158 } 159 160 /** 161 * Inform listeners of any change in the video quality of the call 162 * 163 * @param call The call. 164 * @param videoQuality The updated video quality of the call. 165 */ 166 public void videoQualityChanged(Call call, int videoQuality) { 167 for (VideoEventListener listener : mVideoEventListeners) { 168 listener.onVideoQualityChanged(call, videoQuality); 169 } 170 } 171 172 /** 173 * Inform listeners of a change to peer dimensions. 174 * 175 * @param call The call. 176 * @param width New peer width. 177 * @param height New peer height. 178 */ 179 public void peerDimensionsChanged(Call call, int width, int height) { 180 for (SurfaceChangeListener listener : mSurfaceChangeListeners) { 181 listener.onUpdatePeerDimensions(call, width, height); 182 } 183 } 184 185 /** 186 * Inform listeners of a change to camera dimensions. 187 * 188 * @param call The call. 189 * @param width The new camera video width. 190 * @param height The new camera video height. 191 */ 192 public void cameraDimensionsChanged(Call call, int width, int height) { 193 for (SurfaceChangeListener listener : mSurfaceChangeListeners) { 194 listener.onCameraDimensionsChange(call, width, height); 195 } 196 } 197 198 /** 199 * Inform listeners of a change to call data usage. 200 * 201 * @param dataUsage data usage value 202 */ 203 public void callDataUsageChanged(long dataUsage) { 204 for (VideoEventListener listener : mVideoEventListeners) { 205 listener.onCallDataUsageChange(dataUsage); 206 } 207 } 208 209 /** 210 * Listener interface for any class that wants to be notified of upgrade to video request. 211 */ 212 public interface SessionModificationListener { 213 /** 214 * Called when a peer request is received to upgrade an audio-only call to a video call. 215 * 216 * @param call The call the request was received for. 217 * @param videoState The requested video state. 218 */ 219 public void onUpgradeToVideoRequest(Call call, int videoState); 220 } 221 222 /** 223 * Listener interface for any class that wants to be notified of video events, including pause 224 * and un-pause of peer video, video quality changes. 225 */ 226 public interface VideoEventListener { 227 /** 228 * Called when the peer pauses or un-pauses video transmission. 229 * 230 * @param call The call which paused or un-paused video transmission. 231 * @param paused {@code True} when the video transmission is paused, {@code false} 232 * otherwise. 233 */ 234 public void onPeerPauseStateChanged(Call call, boolean paused); 235 236 /** 237 * Called when the video quality changes. 238 * 239 * @param call The call whose video quality changes. 240 * @param videoCallQuality - values are QUALITY_HIGH, MEDIUM, LOW and UNKNOWN. 241 */ 242 public void onVideoQualityChanged(Call call, int videoCallQuality); 243 244 /* 245 * Called when call data usage value is requested or when call data usage value is updated 246 * because of a call state change 247 * 248 * @param dataUsage call data usage value 249 */ 250 public void onCallDataUsageChange(long dataUsage); 251 252 /** 253 * Called when call session event is raised. 254 * 255 * @param event The call session event. 256 */ 257 public void onCallSessionEvent(int event); 258 } 259 260 /** 261 * Listener interface for any class that wants to be notified of changes to the video surfaces. 262 */ 263 public interface SurfaceChangeListener { 264 /** 265 * Called when the peer video feed changes dimensions. This can occur when the peer rotates 266 * their device, changing the aspect ratio of the video signal. 267 * 268 * @param call The call which experienced a peer video 269 * @param width 270 * @param height 271 */ 272 public void onUpdatePeerDimensions(Call call, int width, int height); 273 274 /** 275 * Called when the local camera changes dimensions. This occurs when a change in camera 276 * occurs. 277 * 278 * @param call The call which experienced the camera dimension change. 279 * @param width The new camera video width. 280 * @param height The new camera video height. 281 */ 282 public void onCameraDimensionsChange(Call call, int width, int height); 283 } 284 } 285