Upgrade / downgrade requests

- Remove unnecessary "change to voice" button.
- Remove "modify call option" dialog that showed up in the past when
pressing the "upgrade to video button".
- Cleaned up some unnecessary Toasts for call session events, data
usage, and video quality
- Implemented the camera on/off functionality.
- Change preview to show the user's profile photo when their camera is
turned off, as well as a "camera off" icon.

Bug: 20257400
Change-Id: I6b7bb3d2394467f1345a798557130b2a674337c4
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 86a7f21..0000000
--- 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 81c3f69..73d14eb 100644
--- a/InCallUI/res/layout/call_button_fragment.xml
+++ b/InCallUI/res/layout/call_button_fragment.xml
@@ -70,13 +70,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" -->
@@ -146,7 +139,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 8961ea4..b0c6ce2 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 332576d..628d0bf 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 -->
@@ -444,17 +437,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>
@@ -470,4 +452,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/Call.java b/InCallUI/src/com/android/incallui/Call.java
index 729d87c..3b97b0b 100644
--- a/InCallUI/src/com/android/incallui/Call.java
+++ b/InCallUI/src/com/android/incallui/Call.java
@@ -484,9 +484,6 @@
         mSessionModificationState = state;
         Log.d(this, "setSessionModificationState " + state + " mSessionModificationState="
                 + mSessionModificationState);
-        if (state != Call.SessionModificationState.WAITING_FOR_RESPONSE) {
-            setModifyToVideoState(VideoProfile.VideoState.AUDIO_ONLY);
-        }
         if (hasChanged) {
             update();
         }
@@ -518,7 +515,7 @@
     @Override
     public String toString() {
         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
@@ -526,7 +523,8 @@
                 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 e7cfe2c..6da66ba 100644
--- a/InCallUI/src/com/android/incallui/CallButtonFragment.java
+++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java
@@ -68,24 +68,22 @@
 
     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 @@
 
         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 @@
             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 @@
                 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 @@
         }
 
         ImageButton[] normalButtons = {
-            mChangeToVoiceButton,
             mSwapButton,
             mChangeToVideoButton,
             mAddCallButton,
@@ -362,7 +352,6 @@
         }
 
         mAudioButton.setEnabled(isEnabled);
-        mChangeToVoiceButton.setEnabled(isEnabled);
         mMuteButton.setEnabled(isEnabled);
         mShowDialpadButton.setEnabled(isEnabled);
         mHoldButton.setEnabled(isEnabled);
@@ -393,8 +382,6 @@
         switch (id) {
             case BUTTON_AUDIO:
                 return mAudioButton;
-            case BUTTON_DOWNGRADE_TO_VOICE:
-                return mChangeToVoiceButton;
             case BUTTON_MUTE:
                 return mMuteButton;
             case BUTTON_DIALPAD:
@@ -448,74 +435,6 @@
         }
     }
 
-    /**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 6506494..2544c5f 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -258,20 +258,16 @@
         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 +312,14 @@
         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 +350,7 @@
      * @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,10 +369,7 @@
         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));
 
@@ -389,7 +382,6 @@
         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);
@@ -437,7 +429,6 @@
         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 51913d4..53cc66a 100644
--- a/InCallUI/src/com/android/incallui/CallUtils.java
+++ b/InCallUI/src/com/android/incallui/CallUtils.java
@@ -39,9 +39,8 @@
     }
 
     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 2ce7b89..175c674 100644
--- a/InCallUI/src/com/android/incallui/VideoCallFragment.java
+++ b/InCallUI/src/com/android/incallui/VideoCallFragment.java
@@ -17,13 +17,12 @@
 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.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.telecom.Connection;
 import android.telecom.VideoProfile;
 import android.view.Display;
 import android.view.LayoutInflater;
@@ -33,6 +32,8 @@
 import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
 import android.widget.Toast;
 
 import com.google.common.base.Objects;
@@ -89,6 +90,21 @@
     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;
@@ -538,19 +554,21 @@
     }
 
     /**
-     * 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);
         }
     }
 
@@ -562,43 +580,6 @@
     }
 
     /**
-     * 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.
@@ -617,6 +598,11 @@
         sVideoSurfacesInUse = false;
     }
 
+    @Override
+    public ImageView getPreviewPhotoView() {
+        return mPreviewPhoto;
+    }
+
     private void onPresenterChanged(VideoCallPresenter presenter) {
         Log.d(this, "onPresenterChanged: Presenter=" + presenter);
         if (sDisplaySurface != null) {
@@ -682,11 +668,17 @@
                 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.
@@ -743,47 +735,6 @@
     }
 
     /**
-     * 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.
@@ -822,6 +773,10 @@
         }
 
         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 f871129..881fad9 100644
--- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
@@ -18,8 +18,12 @@
 
 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.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;
 
@@ -161,12 +166,22 @@
     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();
@@ -399,8 +414,10 @@
         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;
@@ -622,7 +639,7 @@
             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) {
@@ -710,6 +727,7 @@
             ui.showVideoViews(true, false);
         } else if (VideoProfile.VideoState.isReceptionEnabled(videoState)) {
             ui.showVideoViews(false, !isPaused && isCallActive);
+            loadProfilePhotoAsync();
         } else {
             ui.hideVideoUi();
         }
@@ -768,18 +786,7 @@
      */
     @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
     }
 
     /**
@@ -849,13 +856,28 @@
      */
     @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());
     }
 
     /**
@@ -866,12 +888,6 @@
     @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);
     }
 
     /**
@@ -1099,12 +1115,86 @@
     }
 
     /**
+     * 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();
@@ -1113,10 +1203,9 @@
         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();
     }
 }