summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--InCallUI/res/drawable/btn_change_to_voice.xml31
-rw-r--r--InCallUI/res/layout/call_button_fragment.xml9
-rw-r--r--InCallUI/res/layout/video_call_views.xml41
-rw-r--r--InCallUI/res/values/strings.xml26
-rw-r--r--InCallUI/src/com/android/incallui/AnswerPresenter.java12
-rw-r--r--InCallUI/src/com/android/incallui/Call.java8
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonFragment.java105
-rw-r--r--InCallUI/src/com/android/incallui/CallButtonPresenter.java27
-rw-r--r--InCallUI/src/com/android/incallui/CallUtils.java5
-rw-r--r--InCallUI/src/com/android/incallui/VideoCallFragment.java136
-rw-r--r--InCallUI/src/com/android/incallui/VideoCallPresenter.java153
11 files changed, 237 insertions, 316 deletions
diff --git a/InCallUI/res/drawable/btn_change_to_voice.xml b/InCallUI/res/drawable/btn_change_to_voice.xml
deleted file mode 100644
index 86a7f21d5..000000000
--- a/InCallUI/res/drawable/btn_change_to_voice.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ 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
- -->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:id="@+id/backgroundItem"
- android:drawable="@drawable/btn_background" />
-
- <item>
- <bitmap android:src="@drawable/ic_toolbar_audio_phone"
- android:gravity="center"
- android:tint="@color/selectable_icon_tint"
- android:autoMirrored="true" />
- </item>
-
-</layer-list> \ No newline at end of file
diff --git a/InCallUI/res/layout/call_button_fragment.xml b/InCallUI/res/layout/call_button_fragment.xml
index 7f429c76e..17c2d7c78 100644
--- a/InCallUI/res/layout/call_button_fragment.xml
+++ b/InCallUI/res/layout/call_button_fragment.xml
@@ -69,13 +69,6 @@
android:background="@drawable/btn_compound_audio"
android:contentDescription="@string/audio_mode_speaker" />
- <!-- "Change to audio call" for video calls. -->
- <ImageButton android:id="@+id/changeToVoiceButton"
- style="@style/InCallButton"
- android:background="@drawable/btn_change_to_voice"
- android:contentDescription="@string/onscreenChangeToVoiceText"
- android:visibility="gone" />
-
<!-- MIDDLE LEFT SLOT ================================================================== -->
<!-- "Mute" -->
@@ -145,7 +138,7 @@
android:contentDescription="@string/onscreenMergeCallsText"
android:visibility="gone" />
- <!-- "Switch camera" for video calls. -->
+ <!-- "Turn off camera" for video calls. -->
<ToggleButton android:id="@+id/pauseVideoButton"
style="@style/InCallCompoundButton"
android:background="@drawable/btn_compound_video_off"
diff --git a/InCallUI/res/layout/video_call_views.xml b/InCallUI/res/layout/video_call_views.xml
index 8961ea4bf..b0c6ce2ad 100644
--- a/InCallUI/res/layout/video_call_views.xml
+++ b/InCallUI/res/layout/video_call_views.xml
@@ -26,10 +26,41 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The width and height are replaced at runtime based on the selected camera. -->
- <TextureView
- android:id="@+id/previewVideo"
- android:layout_gravity="bottom|right"
- android:layout_margin="@dimen/video_preview_margin"
+ <FrameLayout
+ android:id="@+id/previewVideoContainer"
android:layout_width="70dp"
- android:layout_height="120dp" />
+ android:layout_height="120dp"
+ android:layout_gravity="bottom|right"
+ android:layout_margin="@dimen/video_preview_margin" >
+
+ <!-- The video preview surface, where the user's outgoing video is shown. -->
+ <TextureView
+ android:id="@+id/previewVideo"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <!-- The user's profile photo, shown when the user's camera is shut off. -->
+ <ImageView
+ android:id="@+id/previewProfilePhoto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:adjustViewBounds="false"
+ android:contentDescription="@string/profile_photo_description"
+ android:background="@android:color/black"
+ android:visibility="gone" />
+
+ <!-- The "camera off" icon, shown when the user's camera is shut off. -->
+ <ImageView
+ android:id="@+id/previewCameraOff"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|right"
+ android:layout_marginEnd="10dp"
+ android:layout_marginBottom="10dp"
+ android:scaleType="centerCrop"
+ android:contentDescription="@string/camera_off_description"
+ android:src="@drawable/ic_toolbar_video_off"
+ android:visibility="gone" />
+ </FrameLayout>
</FrameLayout>
diff --git a/InCallUI/res/values/strings.xml b/InCallUI/res/values/strings.xml
index c3ccc141c..f913f68a4 100644
--- a/InCallUI/res/values/strings.xml
+++ b/InCallUI/res/values/strings.xml
@@ -294,13 +294,6 @@
<!-- Text for the onscreen overflow button, to see additional actions which can be done. -->
<string name="onscreenOverflowText">More options</string>
- <!-- STOPSHIP - For test only - In-call screen: Modify Call Options for IMS call -->
- <string name="modify_call_option_title" translatable="false">Which type of call?</string>
- <string name="modify_call_option_vt" translatable="false">Video bidirectional</string>
- <string name="modify_call_option_vt_tx" translatable="false">Video transmit</string>
- <string name="modify_call_option_vt_rx" translatable="false">Video receive</string>
- <string name="modify_call_option_voice" translatable="false">Voice Only</string>
-
<!-- Message indicating that Video Started flowing for IMS-VT calls -->
<string name="player_started">Player Started</string>
<!-- Message indicating that Video Stopped flowing for IMS-VT calls -->
@@ -440,17 +433,6 @@
<!-- This can be used in any application wanting to disable the text "Emergency number" -->
<string name="emergency_call_dialog_number_for_display">Emergency number</string>
- <!-- Video quality changed message -->
- <string name="video_quality_changed" translatable="false">Video quality changed to \u0020</string>
- <!-- Video quality High -->
- <string name="video_quality_high" translatable="false">High</string>
- <!-- Video quality Medium -->
- <string name="video_quality_medium" translatable="false">Medium</string>
- <!-- Video quality Low -->
- <string name="video_quality_low" translatable="false">Low</string>
- <!-- Video quality Unknown -->
- <string name="video_quality_unknown" translatable="false">Unknown</string>
-
<!-- Phrase describing a time duration using seconds [CHAR LIMIT=16] -->
<plurals name="duration_seconds">
<item quantity="one">1 second</item>
@@ -466,4 +448,12 @@
<item quantity="one">1 hour</item>
<item quantity="other"><xliff:g id="count">%d</xliff:g> hours</item>
</plurals>
+
+ <!-- Description of the profile photo shown when the device's camera is disabled udring a video
+ call. [CHAR LIMIT=NONE] -->
+ <string name="profile_photo_description">Profile photo</string>
+
+ <!-- Description of the "camera off" icon displayed when the device's camera is disabled during
+ a video call. [CHAR LIMIT=NONE] -->
+ <string name="camera_off_description">Camera off</string>
</resources>
diff --git a/InCallUI/src/com/android/incallui/AnswerPresenter.java b/InCallUI/src/com/android/incallui/AnswerPresenter.java
index 04cc262fd..ff9356be4 100644
--- a/InCallUI/src/com/android/incallui/AnswerPresenter.java
+++ b/InCallUI/src/com/android/incallui/AnswerPresenter.java
@@ -266,17 +266,13 @@ public class AnswerPresenter extends Presenter<AnswerPresenter.AnswerUi>
}
private void configureAnswerTargetsForSms(Call call, List<String> textMsgs) {
- if (getUi() == null) {
- return;
- }
-
- final Context context = getUi().getContext();
-
- mHasTextMessages = textMsgs != null;
boolean withSms =
call.can(android.telecom.Call.Details.CAPABILITY_RESPOND_VIA_TEXT)
&& mHasTextMessages;
- if (call.isVideoCall(context)) {
+
+ // Only present the user with the option to answer as a video call if the incoming call is
+ // a bi-directional video call.
+ if (VideoProfile.VideoState.isBidirectional((call.getVideoState()))) {
if (withSms) {
getUi().showTargets(AnswerFragment.TARGET_SET_FOR_VIDEO_WITH_SMS);
getUi().configureMessageDialog(textMsgs);
diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java
index 5cf0f9b1a..18eb7471e 100644
--- a/InCallUI/src/com/android/incallui/Call.java
+++ b/InCallUI/src/com/android/incallui/Call.java
@@ -509,9 +509,6 @@ public class Call {
mSessionModificationState = state;
Log.d(this, "setSessionModificationState " + state + " mSessionModificationState="
+ mSessionModificationState);
- if (state != Call.SessionModificationState.WAITING_FOR_RESPONSE) {
- setModifyToVideoState(VideoProfile.VideoState.AUDIO_ONLY);
- }
if (hasChanged) {
update();
}
@@ -549,7 +546,7 @@ public class Call {
}
return String.format(Locale.US, "[%s, %s, %s, children:%s, parent:%s, conferenceable:%s, " +
- "videoState:%d, mSessionModificationState:%d, VideoSettings:%s]",
+ "videoState:%s, mSessionModificationState:%d, VideoSettings:%s]",
mId,
State.toString(getState()),
android.telecom.Call.Details
@@ -557,7 +554,8 @@ public class Call {
mChildCallIds,
getParentId(),
this.mTelecommCall.getConferenceableCalls(),
- mTelecommCall.getDetails().getVideoState(),
+ VideoProfile.VideoState.videoStateToString(
+ mTelecommCall.getDetails().getVideoState()),
mSessionModificationState,
getVideoSettings());
}
diff --git a/InCallUI/src/com/android/incallui/CallButtonFragment.java b/InCallUI/src/com/android/incallui/CallButtonFragment.java
index b3cadcfec..506ca7dcc 100644
--- a/InCallUI/src/com/android/incallui/CallButtonFragment.java
+++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java
@@ -68,24 +68,22 @@ public class CallButtonFragment
public interface Buttons {
public static final int BUTTON_AUDIO = 0;
- public static final int BUTTON_DOWNGRADE_TO_VOICE = 1;
- public static final int BUTTON_MUTE = 2;
- public static final int BUTTON_DIALPAD = 3;
- public static final int BUTTON_HOLD = 4;
- public static final int BUTTON_SWAP = 5;
- public static final int BUTTON_UPGRADE_TO_VIDEO = 6;
- public static final int BUTTON_SWITCH_CAMERA = 7;
- public static final int BUTTON_ADD_CALL = 8;
- public static final int BUTTON_MERGE = 9;
- public static final int BUTTON_PAUSE_VIDEO = 10;
- public static final int BUTTON_MANAGE_VIDEO_CONFERENCE = 11;
- public static final int BUTTON_COUNT = 12;
+ public static final int BUTTON_MUTE = 1;
+ public static final int BUTTON_DIALPAD = 2;
+ public static final int BUTTON_HOLD = 3;
+ public static final int BUTTON_SWAP = 4;
+ public static final int BUTTON_UPGRADE_TO_VIDEO = 5;
+ public static final int BUTTON_SWITCH_CAMERA = 6;
+ public static final int BUTTON_ADD_CALL = 7;
+ public static final int BUTTON_MERGE = 8;
+ public static final int BUTTON_PAUSE_VIDEO = 9;
+ public static final int BUTTON_MANAGE_VIDEO_CONFERENCE = 10;
+ public static final int BUTTON_COUNT = 11;
}
private SparseIntArray mButtonVisibilityMap = new SparseIntArray(BUTTON_COUNT);
private CompoundButton mAudioButton;
- private ImageButton mChangeToVoiceButton;
private CompoundButton mMuteButton;
private CompoundButton mShowDialpadButton;
private CompoundButton mHoldButton;
@@ -138,8 +136,6 @@ public class CallButtonFragment
mAudioButton = (CompoundButton) parent.findViewById(R.id.audioButton);
mAudioButton.setOnClickListener(this);
- mChangeToVoiceButton = (ImageButton) parent.findViewById(R.id.changeToVoiceButton);
- mChangeToVoiceButton. setOnClickListener(this);
mMuteButton = (CompoundButton) parent.findViewById(R.id.muteButton);
mMuteButton.setOnClickListener(this);
mShowDialpadButton = (CompoundButton) parent.findViewById(R.id.dialpadButton);
@@ -196,10 +192,6 @@ public class CallButtonFragment
case R.id.addButton:
getPresenter().addCallClicked();
break;
- case R.id.changeToVoiceButton:
- // STOPSHIP One way video options
- getPresenter().displayModifyCallOptions();
- break;
case R.id.muteButton: {
getPresenter().muteClicked(!mMuteButton.isSelected());
break;
@@ -219,8 +211,7 @@ public class CallButtonFragment
getPresenter().showDialpadClicked(!mShowDialpadButton.isSelected());
break;
case R.id.changeToVideoButton:
- // STOPSHIP One way video options
- getPresenter().displayModifyCallOptions();
+ getPresenter().changeToVideoClicked();
break;
case R.id.switchCameraButton:
getPresenter().switchCameraClicked(
@@ -271,7 +262,6 @@ public class CallButtonFragment
}
ImageButton[] normalButtons = {
- mChangeToVoiceButton,
mSwapButton,
mChangeToVideoButton,
mAddCallButton,
@@ -358,7 +348,6 @@ public class CallButtonFragment
mIsEnabled = isEnabled;
mAudioButton.setEnabled(isEnabled);
- mChangeToVoiceButton.setEnabled(isEnabled);
mMuteButton.setEnabled(isEnabled);
mShowDialpadButton.setEnabled(isEnabled);
mHoldButton.setEnabled(isEnabled);
@@ -389,8 +378,6 @@ public class CallButtonFragment
switch (id) {
case BUTTON_AUDIO:
return mAudioButton;
- case BUTTON_DOWNGRADE_TO_VOICE:
- return mChangeToVoiceButton;
case BUTTON_MUTE:
return mMuteButton;
case BUTTON_DIALPAD:
@@ -444,74 +431,6 @@ public class CallButtonFragment
}
}
- /**The function is called when Modify Call button gets pressed. The function creates and
- * displays modify call options.
- */
- @Override
- public void displayModifyCallOptions() {
- CallButtonPresenter.CallButtonUi ui = getUi();
- if (ui == null) {
- Log.e(this, "Cannot display ModifyCallOptions as ui is null");
- return;
- }
-
- Context context = getContext();
-
- final ArrayList<CharSequence> items = new ArrayList<CharSequence>();
- final ArrayList<Integer> itemToCallType = new ArrayList<Integer>();
- final Resources res = ui.getContext().getResources();
- // Prepare the string array and mapping.
- items.add(res.getText(R.string.modify_call_option_voice));
- itemToCallType.add(VideoProfile.VideoState.AUDIO_ONLY);
-
- items.add(res.getText(R.string.modify_call_option_vt_rx));
- itemToCallType.add(VideoProfile.VideoState.RX_ENABLED);
-
- items.add(res.getText(R.string.modify_call_option_vt_tx));
- itemToCallType.add(VideoProfile.VideoState.TX_ENABLED);
-
- items.add(res.getText(R.string.modify_call_option_vt));
- itemToCallType.add(VideoProfile.VideoState.BIDIRECTIONAL);
-
- AlertDialog.Builder builder = new AlertDialog.Builder(getUi().getContext());
- builder.setTitle(R.string.modify_call_option_title);
- final AlertDialog alert;
-
- DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int item) {
- Toast.makeText(getUi().getContext(), items.get(item), Toast.LENGTH_SHORT).show();
- final int selCallType = itemToCallType.get(item);
- Log.v(this, "Videocall: ModifyCall: upgrade/downgrade to "
- + fromCallType(selCallType));
- VideoProfile videoProfile = new VideoProfile(selCallType);
- getPresenter().changeToVideoClicked(videoProfile);
- dialog.dismiss();
- }
- };
- int currVideoState = getPresenter().getCurrentVideoState();
- int currUnpausedVideoState = CallUtils.getUnPausedVideoState(currVideoState);
- int index = itemToCallType.indexOf(currUnpausedVideoState);
- if (index == INVALID_INDEX) {
- return;
- }
- builder.setSingleChoiceItems(items.toArray(new CharSequence[0]), index, listener);
- alert = builder.create();
- alert.show();
- }
-
- public static String fromCallType(int callType) {
- switch (callType) {
- case VideoProfile.VideoState.BIDIRECTIONAL:
- return "VT";
- case VideoProfile.VideoState.TX_ENABLED:
- return "VT_TX";
- case VideoProfile.VideoState.RX_ENABLED:
- return "VT_RX";
- }
- return "";
- }
-
private void addToOverflowMenu(int id, View button, PopupMenu menu) {
button.setVisibility(View.GONE);
menu.getMenu().add(Menu.NONE, id, Menu.NONE, button.getContentDescription());
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index 82c576f79..43ee3326b 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -79,6 +79,7 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
InCallPresenter.getInstance().removeIncomingCallListener(this);
InCallPresenter.getInstance().removeDetailsListener(this);
InCallPresenter.getInstance().getInCallCameraManager().removeCameraSelectionListener(this);
+ InCallPresenter.getInstance().removeCanAddCallListener(this);
}
@Override
@@ -258,20 +259,16 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
getUi().displayDialpad(checked /* show */, true /* animate */);
}
- public void displayModifyCallOptions() {
- getUi().displayModifyCallOptions();
- }
-
- public int getCurrentVideoState() {
- return mCall.getVideoState();
- }
-
- public void changeToVideoClicked(VideoProfile videoProfile) {
+ public void changeToVideoClicked() {
VideoCall videoCall = mCall.getVideoCall();
if (videoCall == null) {
return;
}
+ int currVideoState = mCall.getVideoState();
+ int currUnpausedVideoState = CallUtils.getUnPausedVideoState(currVideoState);
+ currUnpausedVideoState |= VideoProfile.VideoState.BIDIRECTIONAL;
+ VideoProfile videoProfile = new VideoProfile(currUnpausedVideoState);
videoCall.sendSessionModifyRequest(videoProfile);
mCall.setSessionModificationState(Call.SessionModificationState.WAITING_FOR_RESPONSE);
}
@@ -316,14 +313,14 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
if (pause) {
videoCall.setCamera(null);
VideoProfile videoProfile = new VideoProfile(
- mCall.getVideoState() | VideoProfile.VideoState.PAUSED);
+ mCall.getVideoState() & ~VideoProfile.VideoState.TX_ENABLED);
videoCall.sendSessionModifyRequest(videoProfile);
} else {
InCallCameraManager cameraManager = InCallPresenter.getInstance().
getInCallCameraManager();
videoCall.setCamera(cameraManager.getActiveCameraId());
VideoProfile videoProfile = new VideoProfile(
- mCall.getVideoState() & ~VideoProfile.VideoState.PAUSED);
+ mCall.getVideoState() | VideoProfile.VideoState.TX_ENABLED);
videoCall.sendSessionModifyRequest(videoProfile);
}
getUi().setVideoPaused(pause);
@@ -354,7 +351,7 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
* @param call The active call.
*/
private void updateButtonsState(Call call) {
- Log.v(this, "Showing buttons for voice call.");
+ Log.v(this, "updateButtonsState");
final CallButtonUi ui = getUi();
final boolean isVideo = CallUtils.isVideoCall(call);
@@ -373,9 +370,7 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
final boolean showAddCall = TelecomAdapter.getInstance().canAddCall();
final boolean showMerge = call.can(
android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE);
- // TODO: This button is currently being used for both upgrade and downgrade scenarios.
- // It should be split into BUTTON_DOWNGRADE_TO_VOICE AND BUTTON_UPGRADE_TO_VIDEO
- final boolean showUpgradeToVideo = isVideo ||
+ final boolean showUpgradeToVideo = !isVideo &&
(call.can(android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX)
&& call.can(android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX));
@@ -388,7 +383,6 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
ui.showButton(BUTTON_MUTE, showMute);
ui.showButton(BUTTON_ADD_CALL, showAddCall);
ui.showButton(BUTTON_UPGRADE_TO_VIDEO, showUpgradeToVideo);
- ui.showButton(BUTTON_DOWNGRADE_TO_VOICE, false);
ui.showButton(BUTTON_SWITCH_CAMERA, isVideo);
ui.showButton(BUTTON_PAUSE_VIDEO, isVideo);
ui.showButton(BUTTON_DIALPAD, !isVideo);
@@ -436,7 +430,6 @@ public class CallButtonPresenter extends Presenter<CallButtonPresenter.CallButto
void setAudio(int mode);
void setSupportedAudio(int mask);
void displayDialpad(boolean on, boolean animate);
- void displayModifyCallOptions();
boolean isDialpadVisible();
/**
diff --git a/InCallUI/src/com/android/incallui/CallUtils.java b/InCallUI/src/com/android/incallui/CallUtils.java
index 79cf4c7e7..0e0c4c6f5 100644
--- a/InCallUI/src/com/android/incallui/CallUtils.java
+++ b/InCallUI/src/com/android/incallui/CallUtils.java
@@ -39,9 +39,8 @@ public class CallUtils {
}
public static boolean isVideoCall(int videoState) {
- return VideoProfile.VideoState.isBidirectional(videoState)
- && VideoProfile.VideoState.isTransmissionEnabled(videoState)
- && VideoProfile.VideoState.isReceptionEnabled(videoState);
+ return VideoProfile.VideoState.isTransmissionEnabled(videoState)
+ || VideoProfile.VideoState.isReceptionEnabled(videoState);
}
public static boolean isIncomingVideoCall(Call call) {
diff --git a/InCallUI/src/com/android/incallui/VideoCallFragment.java b/InCallUI/src/com/android/incallui/VideoCallFragment.java
index c285ff3fe..6d70b4271 100644
--- a/InCallUI/src/com/android/incallui/VideoCallFragment.java
+++ b/InCallUI/src/com/android/incallui/VideoCallFragment.java
@@ -16,15 +16,10 @@
package com.android.incallui;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
-import android.telecom.Connection;
-import android.telecom.VideoProfile;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
@@ -33,7 +28,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
-import android.widget.Toast;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
import com.google.common.base.Objects;
@@ -65,12 +61,6 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
*/
public static final int ORIENTATION_UNKNOWN = -1;
- /**
- * Invalid resource id.
- */
- public static final int INVALID_RESOURCE_ID = -1;
-
-
// Static storage used to retain the video surfaces across Activity restart.
// TextureViews are not parcelable, so it is not possible to store them in the saved state.
private static boolean sVideoSurfacesInUse = false;
@@ -91,6 +81,21 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
private View mVideoViews;
/**
+ * The {@link FrameLayout} containing the preview surface.
+ */
+ private View mPreviewVideoContainer;
+
+ /**
+ * Icon shown to indicate that the outgoing camera has been turned off.
+ */
+ private View mCameraOff;
+
+ /**
+ * {@link ImageView} containing the user's profile photo.
+ */
+ private ImageView mPreviewPhoto;
+
+ /**
* {@code True} when the layout of the activity has been completed.
*/
private boolean mIsLayoutComplete = false;
@@ -534,19 +539,21 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
}
/**
- * Show or hide preview and incoming video views
+ * Hides and shows the incoming video view and changes the outgoing video view's state based on
+ * whether outgoing view is enabled or not.
*/
- public void showVideoViews(boolean showPreview, boolean showIncoming) {
+ public void showVideoViews(boolean previewPaused, boolean showIncoming) {
inflateVideoUi(true);
View incomingVideoView = mVideoViews.findViewById(R.id.incomingVideo);
- View previewVideoView = mVideoViews.findViewById(R.id.previewVideo);
-
if (incomingVideoView != null) {
incomingVideoView.setVisibility(showIncoming ? View.VISIBLE : View.INVISIBLE);
}
- if (previewVideoView != null) {
- previewVideoView.setVisibility(showPreview ? View.VISIBLE : View.INVISIBLE);
+ if (mCameraOff != null) {
+ mCameraOff.setVisibility(!previewPaused ? View.VISIBLE : View.INVISIBLE);
+ }
+ if (mPreviewPhoto != null) {
+ mPreviewPhoto.setVisibility(!previewPaused ? View.VISIBLE : View.INVISIBLE);
}
}
@@ -558,43 +565,6 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
}
/**
- * Displays a message on the UI that the video call quality has changed.
- *
- */
- @Override
- public void showVideoQualityChanged(int videoQuality) {
- Log.d(this, "showVideoQualityChanged. Video quality changed to " + videoQuality);
-
- final Context context = getActivity();
- if (context == null) {
- Log.e(this, "showVideoQualityChanged - Activity is null. Return");
- return;
- }
-
- final Resources resources = context.getResources();
-
- int videoQualityResourceId = R.string.video_quality_unknown;
- switch (videoQuality) {
- case VideoProfile.QUALITY_HIGH:
- videoQualityResourceId = R.string.video_quality_high;
- break;
- case VideoProfile.QUALITY_MEDIUM:
- videoQualityResourceId = R.string.video_quality_medium;
- break;
- case VideoProfile.QUALITY_LOW:
- videoQualityResourceId = R.string.video_quality_low;
- break;
- default:
- break;
- }
-
- String videoQualityChangedText = resources.getString(R.string.video_quality_changed) +
- resources.getString(videoQualityResourceId);
-
- Toast.makeText(context, videoQualityChangedText, Toast.LENGTH_SHORT).show();
- }
-
- /**
* Cleans up the video telephony surfaces. Used when the presenter indicates a change to an
* audio-only state. Since the surfaces are static, it is important to ensure they are cleaned
* up promptly.
@@ -613,6 +583,11 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
sVideoSurfacesInUse = false;
}
+ @Override
+ public ImageView getPreviewPhotoView() {
+ return mPreviewPhoto;
+ }
+
private void onPresenterChanged(VideoCallPresenter presenter) {
Log.d(this, "onPresenterChanged: Presenter=" + presenter);
if (sDisplaySurface != null) {
@@ -678,11 +653,17 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
return;
}
+ // Set the dimensions of both the video surface and the FrameLayout containing it.
ViewGroup.LayoutParams params = preview.getLayoutParams();
params.width = width;
params.height = height;
preview.setLayoutParams(params);
+ ViewGroup.LayoutParams containerParams = mPreviewVideoContainer.getLayoutParams();
+ containerParams.width = width;
+ containerParams.height = height;
+ mPreviewVideoContainer.setLayoutParams(containerParams);
+
// The width and height are interchanged outside of this method based on the current
// orientation, so we can transform using "width", which will be either the width or
// the height.
@@ -739,47 +720,6 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
}
/**
- * Sets the call's data usage value
- *
- * @param context the current context
- * @param dataUsage the data usage value
- */
- @Override
- public void setCallDataUsage(Context context, long dataUsage) {
- Log.d(this, "setDataUsage: dataUsage = " + dataUsage);
- Toast.makeText(context, "dataUsage=" + dataUsage, Toast.LENGTH_LONG).show();
- }
-
- private int fromCallSessionEvent(int event) {
- switch (event) {
- case Connection.VideoProvider.SESSION_EVENT_RX_PAUSE:
- return R.string.player_stopped;
- case Connection.VideoProvider.SESSION_EVENT_RX_RESUME:
- return R.string.player_started;
- case Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE:
- return R.string.camera_not_ready;
- case Connection.VideoProvider.SESSION_EVENT_CAMERA_READY:
- return R.string.camera_ready;
- default:
- return R.string.unknown_call_session_event;
- }
- }
-
- /**
- * Sets the call's data usage value
- *
- * @param context the current context
- * @param event the call session event
- */
- @Override
- public void displayCallSessionEvent(int event) {
- Log.d(this, "displayCallSessionEvent: event = " + event);
- Context context = getActivity();
- String msg = context.getResources().getString(fromCallSessionEvent(event));
- Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
- }
-
- /**
* Determines the size of the device screen.
*
* @return {@link Point} specifying the width and height of the screen.
@@ -818,6 +758,10 @@ public class VideoCallFragment extends BaseFragment<VideoCallPresenter,
}
if (mVideoViews != null) {
+ mPreviewVideoContainer = mVideoViews.findViewById(R.id.previewVideoContainer);
+ mCameraOff = mVideoViews.findViewById(R.id.previewCameraOff);
+ mPreviewPhoto = (ImageView) mVideoViews.findViewById(R.id.previewProfilePhoto);
+
TextureView displaySurface = (TextureView) mVideoViews.findViewById(R.id.incomingVideo);
Log.d(this, "inflateVideoCallViews: sVideoSurfacesInUse=" + sVideoSurfacesInUse);
diff --git a/InCallUI/src/com/android/incallui/VideoCallPresenter.java b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
index f11f328e6..f145c24ca 100644
--- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
@@ -18,8 +18,12 @@ package com.android.incallui;
import android.content.Context;
import android.content.res.Configuration;
+import android.database.Cursor;
import android.graphics.Point;
+import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Handler;
+import android.provider.ContactsContract;
import android.telecom.AudioState;
import android.telecom.CameraCapabilities;
import android.telecom.Connection;
@@ -27,15 +31,16 @@ import android.telecom.Connection.VideoProvider;
import android.telecom.InCallService.VideoCall;
import android.telecom.VideoProfile;
import android.view.Surface;
+import android.widget.ImageView;
import com.android.contacts.common.CallUtil;
+import com.android.contacts.common.ContactPhotoManager;
import com.android.incallui.InCallPresenter.InCallDetailsListener;
import com.android.incallui.InCallPresenter.InCallOrientationListener;
import com.android.incallui.InCallPresenter.InCallStateListener;
import com.android.incallui.InCallPresenter.IncomingCallListener;
import com.android.incallui.InCallVideoCallCallbackNotifier.SurfaceChangeListener;
import com.android.incallui.InCallVideoCallCallbackNotifier.VideoEventListener;
-import com.google.common.base.Preconditions;
import java.util.Objects;
@@ -163,12 +168,22 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
private static final long SESSION_MODIFICATION_RESET_DELAY_MS = 3000;
/**
+ * Contact photo manager to retrieve cached contact photo information.
+ */
+ private ContactPhotoManager mContactPhotoManager = null;
+
+ /**
+ * The URI for the user's profile photo, or {@code null} if not specified.
+ */
+ private ContactInfoCache.ContactCacheEntry mProfileInfo = null;
+
+ /**
* Initializes the presenter.
*
* @param context The current context.
*/
public void init(Context context) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = context;
mMinimumVideoDimension = mContext.getResources().getDimension(
R.dimen.video_preview_small_dimension);
mSessionModificationResetHandler = new Handler();
@@ -401,8 +416,10 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
final boolean hasVideoStateChanged = mCurrentVideoState != call.getVideoState();
Log.d(this, "checkForVideoStateChange: isVideoCall= " + isVideoCall
- + " hasVideoStateChanged=" +
- hasVideoStateChanged + " isVideoMode=" + isVideoMode());
+ + " hasVideoStateChanged=" + hasVideoStateChanged + " isVideoMode="
+ + isVideoMode() + " previousVideoState: " +
+ VideoProfile.VideoState.videoStateToString(mCurrentVideoState) + " newVideoState: "
+ + VideoProfile.VideoState.videoStateToString(call.getVideoState()));
if (!hasVideoStateChanged) {
return;
@@ -624,7 +641,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
sPrevVideoAudioMode != AudioModeProvider.AUDIO_MODE_INVALID;
Log.d(this, "Is previous audio mode valid = " + isPrevAudioModeValid + " enableSpeaker is "
- + enableSpeaker);
+ + enableSpeaker);
// Set audio mode to previous mode if enableSpeaker is false.
if (isPrevAudioModeValid && !enableSpeaker) {
@@ -712,6 +729,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
ui.showVideoViews(true, false);
} else if (VideoProfile.VideoState.isReceptionEnabled(videoState)) {
ui.showVideoViews(false, !isPaused && isCallActive);
+ loadProfilePhotoAsync();
} else {
ui.hideVideoUi();
}
@@ -770,18 +788,7 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
*/
@Override
public void onVideoQualityChanged(Call call, int videoQuality) {
- if (!call.equals(mPrimaryCall)) {
- return;
- }
-
- VideoCallUi ui = getUi();
- if (ui == null) {
- Log.e(this, "Error VideoCallUi is null. Return.");
- return;
- }
-
- // Display a video quality changed message on UI.
- ui.showVideoQualityChanged(videoQuality);
+ // No-op
}
/**
@@ -851,13 +858,28 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
*/
@Override
public void onCallSessionEvent(int event) {
- Log.d(this, "onCallSessionEvent event =" + event);
- VideoCallUi ui = getUi();
- if (ui == null) {
- Log.e(this, "onCallSessionEvent: VideoCallUi is null");
- return;
+ StringBuilder sb = new StringBuilder();
+ sb.append("onCallSessionEvent = ");
+
+ switch (event) {
+ case Connection.VideoProvider.SESSION_EVENT_RX_PAUSE:
+ sb.append("rx_pause");
+ break;
+ case Connection.VideoProvider.SESSION_EVENT_RX_RESUME:
+ sb.append("rx_resume");
+ break;
+ case Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE:
+ sb.append("camera_failure");
+ break;
+ case Connection.VideoProvider.SESSION_EVENT_CAMERA_READY:
+ sb.append("camera_ready");
+ break;
+ default:
+ sb.append("unknown event = ");
+ sb.append(event);
+ break;
}
- ui.displayCallSessionEvent(event);
+ Log.d(this, sb.toString());
}
/**
@@ -868,12 +890,6 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
@Override
public void onCallDataUsageChange(long dataUsage) {
Log.d(this, "onCallDataUsageChange dataUsage=" + dataUsage);
- VideoCallUi ui = getUi();
- if (ui == null) {
- Log.e(this, "onCallDataUsageChange: VideoCallUi is null");
- return;
- }
- ui.setCallDataUsage(mContext, dataUsage);
}
/**
@@ -1101,12 +1117,86 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
}
/**
+ * Starts an asynchronous load of the user's profile photo.
+ */
+ public void loadProfilePhotoAsync() {
+ final VideoCallUi ui = getUi();
+ if (ui == null) {
+ return;
+ }
+
+ final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
+ /**
+ * Performs asynchronous load of the user profile information.
+ *
+ * @param params The parameters of the task.
+ *
+ * @return {@code null}.
+ */
+ @Override
+ protected Void doInBackground(Void... params) {
+ if (mProfileInfo == null) {
+ // Try and read the photo URI from the local profile.
+ mProfileInfo = new ContactInfoCache.ContactCacheEntry();
+ final Cursor cursor = mContext.getContentResolver().query(
+ ContactsContract.Profile.CONTENT_URI, new String[]{
+ ContactsContract.CommonDataKinds.Phone._ID,
+ ContactsContract.CommonDataKinds.Phone.PHOTO_URI,
+ ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY,
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
+ }, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ mProfileInfo.lookupKey = cursor.getString(cursor.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY));
+ String photoUri = cursor.getString(cursor.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
+ mProfileInfo.displayPhotoUri = photoUri == null ? null
+ : Uri.parse(photoUri);
+ mProfileInfo.name = cursor.getString(cursor.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+
+ // If user profile information was found, issue an async request to load the user's
+ // profile photo.
+ if (mProfileInfo != null) {
+ if (mContactPhotoManager == null) {
+ mContactPhotoManager = ContactPhotoManager.getInstance(mContext);
+ }
+ ContactPhotoManager.DefaultImageRequest imageRequest = (mProfileInfo != null)
+ ? null :
+ new ContactPhotoManager.DefaultImageRequest(mProfileInfo.name,
+ mProfileInfo.lookupKey, false /* isCircularPhoto */);
+
+ mContactPhotoManager
+ .loadDirectoryPhoto(ui.getPreviewPhotoView(),
+ mProfileInfo.displayPhotoUri,
+ false /* darkTheme */, false /* isCircular */, imageRequest);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ // No-op
+ }
+ };
+
+ task.execute();
+ }
+
+ /**
* Defines the VideoCallUI interactions.
*/
public interface VideoCallUi extends Ui {
void showVideoViews(boolean showPreview, boolean showIncoming);
void hideVideoUi();
- void showVideoQualityChanged(int videoQuality);
boolean isDisplayVideoSurfaceCreated();
boolean isPreviewVideoSurfaceCreated();
Surface getDisplayVideoSurface();
@@ -1115,10 +1205,9 @@ public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi
void setPreviewSize(int width, int height);
void setPreviewSurfaceSize(int width, int height);
void setDisplayVideoSize(int width, int height);
- void setCallDataUsage(Context context, long dataUsage);
- void displayCallSessionEvent(int event);
Point getScreenSize();
Point getPreviewSize();
void cleanupSurfaces();
+ ImageView getPreviewPhotoView();
}
}