Add volume boost and volume enhancement UI

 - Add volume boost UI in calling screen to enable volume boost and
   volume enhancement function during calling

 - Apply volume boost UI with new icon.

 - Update the volume boost UI by phone/audio status change

 - Enable volume boost icon in TTY HCO(TTY + Earpiece) in UI layer.

 - Restrict volume boost function with earpiece and speaker audio mode.

(cherry-picked from commit266994342829b00452462176ab17e691edde5ec5)

Change-Id: Ic42d8a24602939038c60e6a1a2812a4125200c99
CRs-Fixed: 955705
diff --git a/InCallUI/res/drawable-hdpi/vb_active.png b/InCallUI/res/drawable-hdpi/vb_active.png
new file mode 100644
index 0000000..2a82ca8
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/vb_active.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/vb_disable.png b/InCallUI/res/drawable-hdpi/vb_disable.png
new file mode 100644
index 0000000..c2710b0
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/vb_disable.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/vb_normal.png b/InCallUI/res/drawable-hdpi/vb_normal.png
new file mode 100644
index 0000000..b78c30e
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/vb_normal.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/vb_active.png b/InCallUI/res/drawable-mdpi/vb_active.png
new file mode 100644
index 0000000..a4d5261
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/vb_active.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/vb_disable.png b/InCallUI/res/drawable-mdpi/vb_disable.png
new file mode 100644
index 0000000..e2e4a7d
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/vb_disable.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/vb_normal.png b/InCallUI/res/drawable-mdpi/vb_normal.png
new file mode 100644
index 0000000..702f619
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/vb_normal.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/vb_active.png b/InCallUI/res/drawable-xhdpi/vb_active.png
new file mode 100644
index 0000000..78f80b9
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/vb_active.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/vb_disable.png b/InCallUI/res/drawable-xhdpi/vb_disable.png
new file mode 100644
index 0000000..777b36f
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/vb_disable.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/vb_normal.png b/InCallUI/res/drawable-xhdpi/vb_normal.png
new file mode 100644
index 0000000..7b5468c
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/vb_normal.png
Binary files differ
diff --git a/InCallUI/res/layout-h400dp/call_card_fragment.xml b/InCallUI/res/layout-h400dp/call_card_fragment.xml
index 2ef6e52..a7bf7ac 100644
--- a/InCallUI/res/layout-h400dp/call_card_fragment.xml
+++ b/InCallUI/res/layout-h400dp/call_card_fragment.xml
@@ -123,6 +123,14 @@
 
             </FrameLayout>
 
+            <!-- Volume boost and Volume enhancements in-call UI -->
+            <ImageButton android:id="@+id/volumeBoost"
+                android:layout_below="@+id/primary_call_info_container"
+                android:layout_width="80dp"
+                android:layout_height="80dp"
+                android:visibility="gone"
+                android:soundEffectsEnabled="false"
+                android:background="@drawable/vb_normal"/>
 
             <include layout="@layout/manage_conference_call_button"
                 android:layout_width="match_parent"
@@ -169,4 +177,4 @@
     </LinearLayout>
     <!-- Secondary "Call info" block, for the background ("on hold") call. -->
     <include layout="@layout/secondary_call_info" />
-</RelativeLayout>
\ No newline at end of file
+</RelativeLayout>
diff --git a/InCallUI/res/layout-w500dp-land/call_card_fragment.xml b/InCallUI/res/layout-w500dp-land/call_card_fragment.xml
index c71cf07..f1f8067 100644
--- a/InCallUI/res/layout-w500dp-land/call_card_fragment.xml
+++ b/InCallUI/res/layout-w500dp-land/call_card_fragment.xml
@@ -121,6 +121,15 @@
 
         </FrameLayout>
 
+        <!-- Volume boost and Volume enhancements in-call UI -->
+        <ImageButton android:id="@+id/volumeBoost"
+            android:layout_below="@+id/primary_call_info_container"
+            android:layout_width="80dp"
+            android:layout_height="80dp"
+            android:visibility="gone"
+            android:soundEffectsEnabled="false"
+            android:background="@drawable/vb_normal"/>
+
         <fragment android:name="com.android.incallui.VideoCallFragment"
             android:layout_alignParentStart="true"
             android:layout_gravity="start|center_vertical"
diff --git a/InCallUI/res/layout/call_card_fragment.xml b/InCallUI/res/layout/call_card_fragment.xml
index fabde37..3f45c0a 100644
--- a/InCallUI/res/layout/call_card_fragment.xml
+++ b/InCallUI/res/layout/call_card_fragment.xml
@@ -104,6 +104,15 @@
 
     </FrameLayout>
 
+    <!-- Volume boost and Volume enhancements in-call UI -->
+    <ImageButton android:id="@+id/volumeBoost"
+        android:layout_below="@+id/primary_call_info_container"
+        android:layout_width="80dp"
+        android:layout_height="80dp"
+        android:visibility="gone"
+        android:soundEffectsEnabled="false"
+        android:background="@drawable/vb_normal"/>
+
     <fragment android:name="com.android.incallui.VideoCallFragment"
               android:layout_alignParentStart="true"
               android:layout_gravity="start|center_vertical"
diff --git a/InCallUI/res/values-zh-rCN/strings.xml b/InCallUI/res/values-zh-rCN/strings.xml
index 4ff11f1..881f2b1 100644
--- a/InCallUI/res/values-zh-rCN/strings.xml
+++ b/InCallUI/res/values-zh-rCN/strings.xml
@@ -164,6 +164,9 @@
     <string name="preference_category_ringtone" msgid="6246687516643676729">"铃声和振动"</string>
     <string name="manageConferenceLabel" msgid="7237614418556336108">"管理电话会议"</string>
     <string name="emergency_call_dialog_number_for_display" msgid="7244995877625769187">"紧急呼救号码"</string>
+    <string name="volume_boost_notify_enabled">"开启音量增强"</string>
+    <string name="volume_boost_notify_disabled">"关闭音量增强"</string>
+    <string name="volume_boost_notify_unavailable">"有线/蓝牙耳机连接时,音效增强不可用。"</string>
     <plurals name="duration_seconds" formatted="false" msgid="2544699588744957418">
       <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 秒</item>
       <item quantity="one">1 秒</item>
diff --git a/InCallUI/res/values/strings.xml b/InCallUI/res/values/strings.xml
index 57a1b53..190f576 100644
--- a/InCallUI/res/values/strings.xml
+++ b/InCallUI/res/values/strings.xml
@@ -438,6 +438,9 @@
         <item>never</item>
     </string-array>
 
+    <string name="volume_boost_notify_enabled">"Volume boost ON."</string>
+    <string name="volume_boost_notify_disabled">"Volume boost OFF."</string>
+    <string name="volume_boost_notify_unavailable">"Extra volume is not available when Wired/Bluetooth headset is used."</string>
     <!-- Setting option name to pick ringtone (a list dialog comes up). [CHAR LIMIT=30] -->
     <string name="ringtone_title" msgid="5379026328015343686">Phone ringtone</string>
 
diff --git a/InCallUI/src/com/android/incallui/AudioModeProvider.java b/InCallUI/src/com/android/incallui/AudioModeProvider.java
index ea56dd6..a27371b 100644
--- a/InCallUI/src/com/android/incallui/AudioModeProvider.java
+++ b/InCallUI/src/com/android/incallui/AudioModeProvider.java
@@ -49,6 +49,10 @@
     public void onAudioModeChange(int newMode, boolean muted) {
         if (mAudioMode != newMode) {
             mAudioMode = newMode;
+            InCallActivity inCallActivity = InCallPresenter.getInstance().getActivity();
+            if (inCallActivity != null && inCallActivity.getCallCardFragment() != null) {
+                inCallActivity.getCallCardFragment().updateVbByAudioMode(newMode);
+            }
             for (AudioModeListener l : mListeners) {
                 l.onAudioMode(mAudioMode);
             }
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 9830af1..8a46bf0 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
+import android.app.Activity;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
@@ -35,12 +36,17 @@
 import android.os.Trace;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
+import android.content.ContentResolver;
+import android.media.AudioManager;
+import android.provider.Settings;
 import android.telecom.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.View.OnLayoutChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewPropertyAnimator;
@@ -59,6 +65,8 @@
 import android.widget.Toast;
 
 import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
+import android.telecom.CallAudioState;
+
 import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
 import com.android.contacts.common.widget.FloatingActionButtonController;
 import com.android.dialer.R;
@@ -145,6 +153,8 @@
     private ViewGroup mPrimaryCallInfo;
     private View mCallButtonsContainer;
     private ImageView mPhotoSmall;
+    private ImageButton mVbButton;
+    private AudioManager mAudioManager;
 
     // Secondary caller info
     private View mSecondaryCallInfo;
@@ -194,6 +204,11 @@
      */
     private boolean mHasSecondaryCallInfo = false;
 
+    private static final int TTY_MODE_OFF = 0;
+    private static final int TTY_MODE_HCO = 2;
+
+    private static final String VOLUME_BOOST = "volume_boost";
+
     @Override
     public CallCardPresenter.CallCardUi getUi() {
         return this;
@@ -221,6 +236,7 @@
         if (savedInstanceState != null) {
             mIsDialpadShowing = savedInstanceState.getBoolean(IS_DIALPAD_SHOWING_KEY, false);
         }
+        mAudioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
     }
 
     @Override
@@ -336,6 +352,11 @@
         mPrimaryName.setElegantTextHeight(false);
         mCallStateLabel.setElegantTextHeight(false);
         mCallSubject = (TextView) view.findViewById(R.id.callSubject);
+
+        mVbButton = (ImageButton) view.findViewById(R.id.volumeBoost);
+        if (null != mVbButton) {
+            mVbButton.setOnClickListener(mVbListener);
+        }
     }
 
     @Override
@@ -730,6 +751,8 @@
                 sessionModificationState, disconnectCause, connectionLabel, isGatewayCall, isWifi,
                 isConference, isWorkCall);
 
+        updateVbByCall(state);
+
         Log.v(this, "setCallState " + callStateLabel.getCallStateLabel());
         Log.v(this, "AutoDismiss " + callStateLabel.isAutoDismissing());
         Log.v(this, "DisconnectCause " + disconnectCause.toString());
@@ -1510,4 +1533,100 @@
             v.setBottom(oldBottom);
         }
     }
+
+    private OnClickListener mVbListener = new OnClickListener() {
+        @Override
+        public void onClick(View arg0) {
+            if (isVbAvailable()) {
+                // Switch Volume Boost status
+                setVolumeBoost(!isVolumeBoostOn());
+            }
+
+            updateVbButton();
+            showVbNotify();
+        }
+    };
+
+    private boolean isVbAvailable() {
+        int mode = AudioModeProvider.getInstance().getAudioMode();
+        final Context context = getContext();
+        int settingsTtyMode = Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.PREFERRED_TTY_MODE,
+                TTY_MODE_OFF);
+
+        return (mode == CallAudioState.ROUTE_EARPIECE || mode == CallAudioState.ROUTE_SPEAKER
+                || settingsTtyMode == TTY_MODE_HCO);
+    }
+
+    private void updateVbButton() {
+        if (isVbAvailable()) {
+           if (isVolumeBoostOn()) {
+               mVbButton.setBackgroundResource(R.drawable.vb_active);
+           } else {
+               mVbButton.setBackgroundResource(R.drawable.vb_normal);
+           }
+        } else {
+            mVbButton.setBackgroundResource(R.drawable.vb_disable);
+        }
+    }
+
+    private void showVbNotify() {
+        Toast vbnotify;
+        int resId = R.string.volume_boost_notify_unavailable;
+
+        if (isVbAvailable()) {
+            if (isVolumeBoostOn()) {
+                resId = R.string.volume_boost_notify_enabled;
+            } else {
+                resId = R.string.volume_boost_notify_disabled;
+            }
+        }
+
+        vbnotify = Toast.makeText(getView().getContext(), resId, Toast.LENGTH_SHORT);
+        vbnotify.setGravity(Gravity.CENTER, 0, 0);
+        vbnotify.show();
+    }
+
+    private void updateVbByCall(int state) {
+        updateVbButton();
+
+        if (Call.State.ACTIVE == state) {
+            mVbButton.setVisibility(View.VISIBLE);
+        } else if (Call.State.DISCONNECTED == state) {
+            if (!CallList.getInstance().hasLiveCall()
+                    && isVolumeBoostOn()) {
+                mVbButton.setVisibility(View.GONE);
+
+                setVolumeBoost(false);
+            }
+        }
+    }
+
+    public void updateVbByAudioMode(int newMode) {
+        if (!(newMode == CallAudioState.ROUTE_EARPIECE
+                || newMode == CallAudioState.ROUTE_BLUETOOTH
+                || newMode == CallAudioState.ROUTE_WIRED_HEADSET
+                || newMode == CallAudioState.ROUTE_SPEAKER)) {
+            return;
+        }
+
+        if (mAudioManager != null && isVolumeBoostOn()) {
+            setVolumeBoost(false);
+        }
+
+        updateVbButton();
+    }
+
+    private void setVolumeBoost(boolean on){
+        if (on)
+            mAudioManager.setParameters(VOLUME_BOOST + "=on");
+        else
+            mAudioManager.setParameters(VOLUME_BOOST + "=off");
+    }
+
+    private boolean isVolumeBoostOn(){
+
+        return mAudioManager.getParameters(VOLUME_BOOST).contains("=on");
+    }
+
 }