diff options
author | Tyler Gunn <tgunn@google.com> | 2014-07-23 13:19:58 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-07-23 13:19:58 +0000 |
commit | 9aef95c3616a4aa80ab9d35941e611b1f10eacbf (patch) | |
tree | d00f67a2a0e20feccff3fca0f3864ac8653b6f6c | |
parent | 49265178a342492ba871c865894ab564c4090543 (diff) | |
parent | 3676fd514ce0844761df8c8098cd2e2c74cf2f1d (diff) |
am 3bb8db11: Merge "InCall UI VT changes" into lmp-dev
* commit '3bb8db11e46d0ce68944a8fecff6818b6e189070':
InCall UI VT changes
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 694eb9839..3d7371088 100644 --- a/InCallUI/src/com/android/incallui/CallCardPresenter.java +++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java @@ -218,7 +218,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 { |