summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--InCallUI/src/com/android/incallui/Call.java2
-rw-r--r--InCallUI/src/com/android/incallui/CallCardPresenter.java2
-rw-r--r--InCallUI/src/com/android/incallui/CallVideoClientNotifier.java207
-rw-r--r--InCallUI/src/com/android/incallui/InCallPresenter.java5
-rw-r--r--InCallUI/src/com/android/incallui/InCallVideoClient.java91
-rw-r--r--InCallUI/src/com/android/incallui/VideoCallFragment.java13
-rw-r--r--InCallUI/src/com/android/incallui/VideoCallPresenter.java103
7 files changed, 399 insertions, 24 deletions
diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java
index f3986a4fa..3887eca5b 100644
--- a/InCallUI/src/com/android/incallui/Call.java
+++ b/InCallUI/src/com/android/incallui/Call.java
@@ -202,7 +202,7 @@ public final class Call {
if (mTelecommCall.getCallVideoProvider() != null) {
if (mCallVideoClient == null) {
- mCallVideoClient = new InCallVideoClient();
+ mCallVideoClient = new InCallVideoClient(this);
}
mTelecommCall.getCallVideoProvider().setCallVideoClient(mCallVideoClient);
}
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index 5a1605090..645879984 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -220,7 +220,7 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi>
}
@Override
- public void onDetailsChanged(android.telecomm.Call.Details details) {
+ public void onDetailsChanged(Call call, android.telecomm.Call.Details details) {
getUi().setCallDetails(details);
if (mPrimary != null) {
diff --git a/InCallUI/src/com/android/incallui/CallVideoClientNotifier.java b/InCallUI/src/com/android/incallui/CallVideoClientNotifier.java
new file mode 100644
index 000000000..2c048997f
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/CallVideoClientNotifier.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui;
+
+import com.google.android.collect.Sets;
+import com.google.common.base.Preconditions;
+
+import java.util.Set;
+
+/**
+ * Class used by {@link InCallVideoClient}s to notify interested parties of incoming events.
+ */
+public class CallVideoClientNotifier {
+ /**
+ * Singleton instance of this class.
+ */
+ private static CallVideoClientNotifier sInstance = new CallVideoClientNotifier();
+
+ private final Set<SessionModificationListener> mSessionModificationListeners =
+ Sets.newHashSet();
+ private final Set<VideoEventListener> mVideoEventListeners = Sets.newHashSet();
+ private final Set<SurfaceChangeListener> mSurfaceChangeListeners = Sets.newHashSet();
+
+ /**
+ * Static singleton accessor method.
+ */
+ public static CallVideoClientNotifier getInstance() {
+ return sInstance;
+ }
+
+ /**
+ * Private constructor. Instance should only be acquired through getInstance().
+ */
+ private CallVideoClientNotifier() {
+ }
+
+ /**
+ * Adds a new {@link SessionModificationListener}.
+ *
+ * @param listener The listener.
+ */
+ public void addSessionModificationListener(SessionModificationListener listener) {
+ Preconditions.checkNotNull(listener);
+ mSessionModificationListeners.add(listener);
+ }
+
+ /**
+ * Remove a {@link SessionModificationListener}.
+ *
+ * @param listener The listener.
+ */
+ public void removeSessionModificationListener(SessionModificationListener listener) {
+ Preconditions.checkNotNull(listener);
+ mSessionModificationListeners.remove(listener);
+ }
+
+ /**
+ * Adds a new {@link VideoEventListener}.
+ *
+ * @param listener The listener.
+ */
+ public void addVideoEventListener(VideoEventListener listener) {
+ Preconditions.checkNotNull(listener);
+ mVideoEventListeners.add(listener);
+ }
+
+ /**
+ * Remove a {@link VideoEventListener}.
+ *
+ * @param listener The listener.
+ */
+ public void removeVideoEventListener(VideoEventListener listener) {
+ Preconditions.checkNotNull(listener);
+ mVideoEventListeners.remove(listener);
+ }
+
+ /**
+ * Adds a new {@link SurfaceChangeListener}.
+ *
+ * @param listener The listener.
+ */
+ public void addSurfaceChangeListener(SurfaceChangeListener listener) {
+ Preconditions.checkNotNull(listener);
+ mSurfaceChangeListeners.add(listener);
+ }
+
+ /**
+ * Remove a {@link SurfaceChangeListener}.
+ *
+ * @param listener The listener.
+ */
+ public void removeSurfaceChangeListener(SurfaceChangeListener listener) {
+ Preconditions.checkNotNull(listener);
+ mSurfaceChangeListeners.remove(listener);
+ }
+
+ /**
+ * Inform listeners of an upgrade to video request for a call.
+ *
+ * @param call The call.
+ */
+ public void upgradeToVideoRequest(Call call) {
+ for (SessionModificationListener listener : mSessionModificationListeners) {
+ listener.onUpgradeToVideoRequest(call);
+ }
+ }
+
+ /**
+ * Inform listeners of a downgrade to audio.
+ *
+ * @param call The call.
+ */
+ public void downgradeToAudio(Call call) {
+ for (SessionModificationListener listener : mSessionModificationListeners) {
+ listener.onDowngradeToAudio(call);
+ }
+ }
+
+ /**
+ * Inform listeners of a downgrade to audio.
+ *
+ * @param call The call.
+ * @param paused The paused state.
+ */
+ public void peerPausedStateChanged(Call call, boolean paused) {
+ for (VideoEventListener listener : mVideoEventListeners) {
+ listener.onPeerPauseStateChanged(call, paused);
+ }
+ }
+
+ /**
+ * Inform listeners of a change to peer dimensions.
+ *
+ * @param call The call.
+ * @param width New peer width.
+ * @param height New peer height.
+ */
+ public void peerDimensionsChanged(Call call, int width, int height) {
+ for (SurfaceChangeListener listener : mSurfaceChangeListeners) {
+ listener.onUpdatePeerDimensions(call, width, height);
+ }
+ }
+
+ /**
+ * Listener interface for any class that wants to be notified of upgrade to video and downgrade
+ * to audio session modification requests.
+ */
+ public interface SessionModificationListener {
+ /**
+ * Called when a peer request is received to upgrade an audio-only call to a video call.
+ *
+ * @param call The call the request was received for.
+ */
+ public void onUpgradeToVideoRequest(Call call);
+
+ /**
+ * Called when a call has been downgraded to audio-only.
+ *
+ * @param call The call which was downgraded to audio-only.
+ */
+ public void onDowngradeToAudio(Call call);
+ }
+
+ /**
+ * Listener interface for any class that wants to be notified of video events, including pause
+ * and un-pause of peer video.
+ */
+ public interface VideoEventListener {
+ /**
+ * Called when the peer pauses or un-pauses video transmission.
+ *
+ * @param call The call which paused or un-paused video transmission.
+ * @param paused {@code True} when the video transmission is paused, {@code false}
+ * otherwise.
+ */
+ public void onPeerPauseStateChanged(Call call, boolean paused);
+ }
+
+ /**
+ * Listener interface for any class that wants to be notified of changes to the video surfaces.
+ */
+ public interface SurfaceChangeListener {
+ /**
+ * Called when the peer video feed changes dimensions. This can occur when the peer rotates
+ * their device, changing the aspect ratio of the video signal.
+ *
+ * @param call The call which experienced a peer video
+ * @param width
+ * @param height
+ */
+ public void onUpdatePeerDimensions(Call call, int width, int height);
+ }
+}
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index cc7f1b9a0..3a8dc43b6 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -88,7 +88,8 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
public void onDetailsChanged(android.telecomm.Call call,
android.telecomm.Call.Details details) {
for (InCallDetailsListener listener : mDetailsListeners) {
- listener.onDetailsChanged(details);
+ listener.onDetailsChanged(CallList.getInstance().getCallByTelecommCall(call),
+ details);
}
}
@@ -876,6 +877,6 @@ public class InCallPresenter implements CallList.Listener, InCallPhoneListener {
}
public interface InCallDetailsListener {
- public void onDetailsChanged(android.telecomm.Call.Details details);
+ public void onDetailsChanged(Call call, android.telecomm.Call.Details details);
}
}
diff --git a/InCallUI/src/com/android/incallui/InCallVideoClient.java b/InCallUI/src/com/android/incallui/InCallVideoClient.java
index 097054dbf..792348b6a 100644
--- a/InCallUI/src/com/android/incallui/InCallVideoClient.java
+++ b/InCallUI/src/com/android/incallui/InCallVideoClient.java
@@ -24,34 +24,117 @@ import android.telecomm.CallVideoClient;
* Implements the InCall-UI Call Video client.
*/
public class InCallVideoClient extends CallVideoClient {
+
+ /**
+ * The call associated with this {@link InCallVideoClient}.
+ */
+ private Call mCall;
+
+ /**
+ * Creates an instance of the call video client, specifying the call it is related to.
+ *
+ * @param call The call.
+ */
+ public InCallVideoClient(Call call) {
+ mCall = call;
+ }
+
+ /**
+ * Handles an incoming session modification request.
+ *
+ * @param videoCallProfile The requested video call profile.
+ */
@Override
public void onReceiveSessionModifyRequest(VideoCallProfile videoCallProfile) {
+ int previousVideoState = mCall.getVideoState();
+ int newVideoState = videoCallProfile.getVideoState();
+
+ boolean wasVideoState = isVideoStateSet(previousVideoState,
+ VideoCallProfile.VIDEO_STATE_BIDIRECTIONAL);
+ boolean isVideoState = isVideoStateSet(newVideoState,
+ VideoCallProfile.VIDEO_STATE_BIDIRECTIONAL);
+
+ boolean wasPaused = isVideoStateSet(previousVideoState, VideoCallProfile.VIDEO_STATE_PAUSED);
+ boolean isPaused = isVideoStateSet(newVideoState, VideoCallProfile.VIDEO_STATE_PAUSED);
+ // Check for upgrades to video and downgrades to audio.
+ if (!wasVideoState && isVideoState) {
+ CallVideoClientNotifier.getInstance().upgradeToVideoRequest(mCall);
+ } else if (wasVideoState && !isVideoState) {
+ CallVideoClientNotifier.getInstance().downgradeToAudio(mCall);
+ }
+
+ // Check for pause/un-pause
+ if (!wasPaused && isPaused) {
+ CallVideoClientNotifier.getInstance().peerPausedStateChanged(mCall, true /* pause */);
+ } else {
+ CallVideoClientNotifier.getInstance().peerPausedStateChanged(mCall, false /* resume */);
+ }
}
+ /**
+ * Handles a session modification response.
+ *
+ * @param status Status of the session modify request. Valid values are
+ * {@link CallVideoClient#SESSION_MODIFY_REQUEST_SUCCESS},
+ * {@link CallVideoClient#SESSION_MODIFY_REQUEST_FAIL},
+ * {@link CallVideoClient#SESSION_MODIFY_REQUEST_INVALID}
+ * @param requestedProfile
+ * @param responseProfile The actual profile changes made by the peer device.
+ */
@Override
public void onReceiveSessionModifyResponse(int status, VideoCallProfile requestedProfile,
VideoCallProfile responseProfile) {
-
}
+ /**
+ * Handles a call session event.
+ *
+ * @param event The event.
+ */
@Override
public void onHandleCallSessionEvent(int event) {
-
}
+ /**
+ * Handles a change to the peer video dimensions.
+ *
+ * @param width The updated peer video width.
+ * @param height The updated peer video height.
+ */
@Override
public void onUpdatePeerDimensions(int width, int height) {
-
+ CallVideoClientNotifier.getInstance().peerDimensionsChanged(mCall, width, height);
}
+ /**
+ * Handles a change to the call data usage. No implementation as the in-call UI does not
+ * display data usage.
+ *
+ * @param dataUsage The updated data usage.
+ */
@Override
public void onUpdateCallDataUsage(int dataUsage) {
-
}
+ /**
+ * Handles changes to the camera capabilities. No implementation as the in-call UI does not
+ * make use of camera capabilities.
+ *
+ * @param callCameraCapabilities The changed camera capabilities.
+ */
@Override
public void onHandleCameraCapabilitiesChange(CallCameraCapabilities callCameraCapabilities) {
+ }
+ /**
+ * Determines if a specified state is set in a videoState bit-mask.
+ *
+ * @param videoState The video state bit-mask.
+ * @param state The state to check.
+ * @return {@code True} if the state is set.
+ */
+ private boolean isVideoStateSet(int videoState, int state) {
+ return (videoState & state) == state;
}
}
diff --git a/InCallUI/src/com/android/incallui/VideoCallFragment.java b/InCallUI/src/com/android/incallui/VideoCallFragment.java
index eee9643f2..969ec01d2 100644
--- a/InCallUI/src/com/android/incallui/VideoCallFragment.java
+++ b/InCallUI/src/com/android/incallui/VideoCallFragment.java
@@ -16,7 +16,6 @@
package com.android.incallui;
-import android.content.res.Configuration;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Surface;
@@ -27,7 +26,6 @@ import android.view.ViewGroup;
import android.view.ViewStub;
import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
/**
* Fragment containing video calling surfaces.
@@ -49,11 +47,6 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
}
/**
- * Listeners to video surface changes.
- */
- private final Set<VideoCallSurfaceListener> mListeners = new CopyOnWriteArraySet<>();
-
- /**
* {@link ViewStub} holding the video call surfaces. This is the parent for the
* {@link VideoCallFragment}. Used to ensure that the video surfaces are only inflated when
* required.
@@ -195,7 +188,6 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- Log.d(this, "surfaceChanged %s", holder.getSurface().toString());
getPresenter().onSurfaceChanged(getSurfaceId(holder), format, width, height);
}
@@ -206,8 +198,6 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
- Log.d(this, "surfaceDestroyed %s", holder.getSurface().toString());
-
int surfaceId = getSurfaceId(holder);
if (surfaceId == SURFACE_DISPLAY) {
@@ -228,10 +218,8 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
private int getSurfaceId(SurfaceHolder holder) {
int surface;
if (holder == mDisplayVideoSurface.getHolder()) {
- Log.d(this, "surfaceCreated: DISPLAY");
surface = SURFACE_DISPLAY;
} else {
- Log.d(this, "surfaceCreated: PREVIEW");
surface = SURFACE_PREVIEW;
}
return surface;
@@ -247,7 +235,6 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
public void showVideoUi(boolean show) {
getView().setVisibility(show ? View.VISIBLE : View.GONE);
- Log.d(this, "Show video call UI: " + show);
if (show) {
inflateVideoCallViews();
}
diff --git a/InCallUI/src/com/android/incallui/VideoCallPresenter.java b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
index 0c8034cb3..3f94995e0 100644
--- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
@@ -16,6 +16,11 @@
package com.android.incallui;
+import com.android.incallui.CallVideoClientNotifier.SurfaceChangeListener;
+import com.android.incallui.CallVideoClientNotifier.VideoEventListener;
+import com.android.incallui.InCallPresenter.InCallDetailsListener;
+import com.android.incallui.InCallPresenter.InCallStateListener;
+import com.android.incallui.InCallPresenter.IncomingCallListener;
import com.android.internal.util.Preconditions;
import android.content.Context;
@@ -30,7 +35,8 @@ import java.util.Objects;
* {@class CallVideoClient}.
*/
public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi> implements
- InCallPresenter.IncomingCallListener, InCallPresenter.InCallStateListener {
+ IncomingCallListener, InCallStateListener,
+ InCallDetailsListener, SurfaceChangeListener, VideoEventListener {
/**
* The current context.
@@ -74,10 +80,29 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
// Register for call state changes last
InCallPresenter.getInstance().addListener(this);
InCallPresenter.getInstance().addIncomingCallListener(this);
+
+ // Register for surface and video events from {@link InCallVideoProvider}s.
+ CallVideoClientNotifier.getInstance().addSurfaceChangeListener(this);
+ CallVideoClientNotifier.getInstance().addVideoEventListener(this);
+
mIsVideoCall = false;
}
/**
+ * Called when the user interface is no longer ready to be used.
+ *
+ * @param ui The Ui implementation that is no longer ready to be used.
+ */
+ public void unUiUnready(VideoCallUi ui) {
+ super.onUiUnready(ui);
+
+ InCallPresenter.getInstance().removeListener(this);
+ InCallPresenter.getInstance().removeIncomingCallListener(this);
+ CallVideoClientNotifier.getInstance().removeSurfaceChangeListener(this);
+ CallVideoClientNotifier.getInstance().removeVideoEventListener(this);
+ }
+
+ /**
* @return The {@link RemoteCallVideoProvider}.
*/
private RemoteCallVideoProvider getCallVideoProvider() {
@@ -166,6 +191,9 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
if (call == null || getUi() == null) {
return;
}
+
+ Log.d(this, "onStateChange "+call);
+
final boolean callChanged = !Objects.equals(mCall, call);
// If the call changed track it now.
@@ -173,13 +201,45 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
mCall = call;
}
+ checkForCallVideoProviderChange();
+ checkForVideoStateChange();
+ }
+
+ /**
+ * Handles changes to the details of the call. The {@link VideoCallPresenter} is interested in
+ * changes to the video state.
+ *
+ * @param call The call for which the details changed.
+ * @param details The new call details.
+ */
+ @Override
+ public void onDetailsChanged(Call call, android.telecomm.Call.Details details) {
+ Log.d(this, "onDetailsChanged "+call);
+
+ // If the details change is not for the currently active call no update is required.
+ if (!call.equals(mCall)) {
+ return;
+ }
+
+ checkForVideoStateChange();
+ }
+
+ /**
+ * Checks for a change to the call video provider and changes it if required.
+ */
+ private void checkForCallVideoProviderChange() {
RemoteCallVideoProvider callVideoProvider =
mCall.getTelecommCall().getCallVideoProvider();
- if (callVideoProvider != mCallVideoProvider) {
+ if (!Objects.equals(callVideoProvider, mCallVideoProvider)) {
changeCallVideoProvider(callVideoProvider);
}
+ }
- boolean newVideoState = call.isVideoCall();
+ /**
+ * Checks to see if the current video state has changed and updates the UI if required.
+ */
+ private void checkForVideoStateChange() {
+ boolean newVideoState = mCall.isVideoCall();
// Check if video state changed
if (mIsVideoCall != newVideoState) {
@@ -200,6 +260,8 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
* @param callVideoProvider The new call video provider.
*/
private void changeCallVideoProvider(RemoteCallVideoProvider callVideoProvider) {
+ Log.d(this, "changeCallVideoProvider");
+
// Null out the surfaces on the previous provider
if (mCallVideoProvider != null) {
mCallVideoProvider.setDisplaySurface(null);
@@ -216,6 +278,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
* TODO(vt): Need to adjust size and orientation of preview surface here.
*/
private void enterVideoState() {
+ Log.d(this, "enterVideoState");
VideoCallUi ui = getUi();
if (ui == null) {
return;
@@ -228,6 +291,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
* Sets the surfaces on the specified {@link RemoteCallVideoProvider}.
*/
private void setSurfaces() {
+ Log.d(this, "setSurfaces");
VideoCallUi ui = getUi();
if (ui == null || mCallVideoProvider == null) {
return;
@@ -246,6 +310,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
* Exits video mode by hiding the video surfaces.
*/
private void exitVideoState() {
+ Log.d(this, "exitVideoState");
VideoCallUi ui = getUi();
if (ui == null) {
return;
@@ -255,6 +320,38 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
}
/**
+ * Handles peer video pause state changes.
+ *
+ * @param call The call which paused or un-pausedvideo transmission.
+ * @param paused {@code True} when the video transmission is paused, {@code false} when video
+ * transmission resumes.
+ */
+ @Override
+ public void onPeerPauseStateChanged(Call call, boolean paused) {
+ if (!call.equals(mCall)) {
+ return;
+ }
+
+ // TODO(vt): Show/hide the peer contact photo.
+ }
+
+ /**
+ * Handles peer video dimension changes.
+ *
+ * @param call The call which experienced a peer video dimension change.
+ * @param width The new peer video width .
+ * @param height The new peer video height.
+ */
+ @Override
+ public void onUpdatePeerDimensions(Call call, int width, int height) {
+ if (!call.equals(mCall)) {
+ return;
+ }
+
+ // TODO(vt): Change display surface aspect ratio.
+ }
+
+ /**
* Defines the VideoCallUI interactions.
*/
public interface VideoCallUi extends Ui {