Moving FAB logic to ContactsCommon.

Moved FAB to ContactsCommon.
Cleaned up FAB Controller.
Replaced implementation of FAB in InCallUI with controller.
Prevented animations from happening again in InCallUI on
orientaton change. FAB also repositions correctly on
orientation change in InCallUI.

Bug: 15386162

Change-Id: I8ea4ef8acb49a83dabe5c18223ce5bac28260824
diff --git a/InCallUI/res/layout-land/call_card_content.xml b/InCallUI/res/layout-land/call_card_content.xml
new file mode 100644
index 0000000..b084e4a
--- /dev/null
+++ b/InCallUI/res/layout-land/call_card_content.xml
@@ -0,0 +1,78 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal" >
+
+    <LinearLayout
+        android:id="@+id/primary_call_info_container"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:elevation="@dimen/primary_call_elevation"
+        android:background="@color/incall_call_banner_background_color"
+        android:paddingTop="@dimen/call_banner_primary_call_container_top_padding"
+        android:clipChildren="false"
+        android:clipToPadding="false" >
+
+        <include layout="@layout/primary_call_info" />
+
+        <fragment android:name="com.android.incallui.CallButtonFragment"
+            android:id="@+id/callButtonFragment"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+    <FrameLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1" >
+
+        <!-- Contact photo for primary call info -->
+        <ImageView android:id="@+id/photo"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="top|center_horizontal"
+            android:scaleType="centerCrop"
+            android:contentDescription="@string/contactPhoto"
+            android:src="@drawable/picture_unknown" />
+
+        <!-- Secondary "Call info" block, for the background ("on hold") call. -->
+        <include layout="@layout/secondary_call_info" />
+
+        <fragment android:name="com.android.incallui.DialpadFragment"
+            android:id="@+id/dialpadFragment"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <fragment android:name="com.android.incallui.AnswerFragment"
+            android:id="@+id/answerFragment"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="top"
+            android:layout_gravity="bottom|center_horizontal"
+            android:layout_marginBottom="@dimen/glowpadview_margin_bottom"
+            android:visibility="gone" />
+
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/InCallUI/res/layout/call_card.xml b/InCallUI/res/layout/call_card.xml
index 658cc49..820397d 100644
--- a/InCallUI/res/layout/call_card.xml
+++ b/InCallUI/res/layout/call_card.xml
@@ -36,77 +36,18 @@
         android:layout_height="0dp"
         android:layout_weight="5" >
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="vertical" >
-
-            <LinearLayout
-                android:id="@+id/primary_call_info_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                android:elevation="@dimen/primary_call_elevation"
-                android:background="@color/incall_call_banner_background_color"
-                android:paddingTop="@dimen/call_banner_primary_call_container_top_padding"
-                android:clipChildren="false"
-                android:clipToPadding="false" >
-
-                <include layout="@layout/primary_call_info" />
-
-                <fragment android:name="com.android.incallui.CallButtonFragment"
-                    android:id="@+id/callButtonFragment"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content" />
-
-            </LinearLayout>
-
-            <FrameLayout
-                android:layout_width="match_parent"
-                android:layout_height="0dp"
-                android:layout_weight="1">
-
-                <!-- Contact photo for primary call info -->
-                <ImageView android:id="@+id/photo"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:gravity="top|center_horizontal"
-                    android:scaleType="centerCrop"
-                    android:contentDescription="@string/contactPhoto"
-                    android:src="@drawable/picture_unknown"/>
-
-                <!-- Secondary "Call info" block, for the background ("on hold") call. -->
-                <include layout="@layout/secondary_call_info" />
-
-                <fragment android:name="com.android.incallui.DialpadFragment"
-                    android:id="@+id/dialpadFragment"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent" />
-
-                <fragment android:name="com.android.incallui.AnswerFragment"
-                    android:id="@+id/answerFragment"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:layout_alignParentBottom="true"
-                    android:layout_centerHorizontal="true"
-                    android:gravity="top"
-                    android:layout_gravity="bottom|center_horizontal"
-                    android:layout_marginBottom="@dimen/glowpadview_margin_bottom"
-                    android:visibility="gone" />
-
-            </FrameLayout>
-
-        </LinearLayout>
+        <include layout="@layout/call_card_content" />
 
         <FrameLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:id="@+id/floating_end_call_action_button_container"
+            android:layout_width="@dimen/floating_action_button_width"
+            android:layout_height="@dimen/floating_action_button_height"
+            android:layout_marginBottom="@dimen/end_call_button_margin_bottom"
             android:layout_gravity="bottom|center">
 
-            <ImageButton android:id="@+id/endButton"
-                android:layout_width="@dimen/floating_action_button_width"
-                android:layout_height="@dimen/floating_action_button_height"
-                android:layout_marginBottom="@dimen/end_call_button_margin_bottom"
+            <ImageButton android:id="@+id/floating_end_call_action_button"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:background="@drawable/end_call_background"
                 android:src="@drawable/fab_ic_end_call"
                 android:contentDescription="@string/onscreenEndCallText" />
@@ -117,13 +58,13 @@
         <FrameLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/end_call_button_margin_bottom"
             android:layout_gravity="bottom|right">
 
             <ImageButton android:id="@+id/handoffButton"
                 android:enabled="false"
                 android:layout_width="@dimen/floating_action_button_width"
                 android:layout_height="@dimen/floating_action_button_height"
-                android:layout_marginBottom="@dimen/end_call_button_margin_bottom"
                 android:background="@drawable/floating_handoff_button_compound_background"
                 android:src="@drawable/ic_in_call_pstn" />
         </FrameLayout>
diff --git a/InCallUI/res/layout/call_card_content.xml b/InCallUI/res/layout/call_card_content.xml
new file mode 100644
index 0000000..cb6f533
--- /dev/null
+++ b/InCallUI/res/layout/call_card_content.xml
@@ -0,0 +1,77 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:id="@+id/primary_call_info_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:elevation="@dimen/primary_call_elevation"
+        android:background="@color/incall_call_banner_background_color"
+        android:paddingTop="@dimen/call_banner_primary_call_container_top_padding"
+        android:clipChildren="false"
+        android:clipToPadding="false" >
+
+        <include layout="@layout/primary_call_info" />
+
+        <fragment android:name="com.android.incallui.CallButtonFragment"
+            android:id="@+id/callButtonFragment"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" >
+
+        <!-- Contact photo for primary call info -->
+        <ImageView android:id="@+id/photo"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="top|center_horizontal"
+            android:scaleType="centerCrop"
+            android:contentDescription="@string/contactPhoto"
+            android:src="@drawable/picture_unknown" />
+
+        <!-- Secondary "Call info" block, for the background ("on hold") call. -->
+        <include layout="@layout/secondary_call_info" />
+
+        <fragment android:name="com.android.incallui.DialpadFragment"
+            android:id="@+id/dialpadFragment"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <fragment android:name="com.android.incallui.AnswerFragment"
+            android:id="@+id/answerFragment"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="top"
+            android:layout_gravity="bottom|center_horizontal"
+            android:layout_marginBottom="@dimen/glowpadview_margin_bottom"
+            android:visibility="gone" />
+
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/InCallUI/res/values/animation_constants.xml b/InCallUI/res/values/animation_constants.xml
new file mode 100644
index 0000000..f3b2c66
--- /dev/null
+++ b/InCallUI/res/values/animation_constants.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+<resources>
+    <!-- Duration of the InCallUI reveal and shrink animations after a call is placed -->
+    <integer name="reveal_animation_duration">333</integer>
+    <integer name="shrink_animation_duration">333</integer>
+</resources>
diff --git a/InCallUI/res/values/dimens.xml b/InCallUI/res/values/dimens.xml
index 95f1101..a60b392 100644
--- a/InCallUI/res/values/dimens.xml
+++ b/InCallUI/res/values/dimens.xml
@@ -101,6 +101,7 @@
     <dimen name="translucent_shadow_height">2dp</dimen>
 
     <dimen name="end_call_button_margin_bottom">8dp</dimen>
+    <dimen name="end_call_button_hide_offset">70dp</dimen>
 
     <dimen name="call_card_anim_translate_y_offset">50dp</dimen>
 </resources>
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 5adb052..3be517b 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -23,6 +23,7 @@
 import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -44,6 +45,7 @@
 
 import com.android.contacts.common.animation.AnimUtils;
 import com.android.contacts.common.util.ViewUtil;
+import com.android.contacts.common.widget.FloatingActionButtonController;
 
 import java.util.List;
 
@@ -53,8 +55,9 @@
 public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPresenter.CallCardUi>
         implements CallCardPresenter.CallCardUi {
 
-    private static final int REVEAL_ANIMATION_DURATION = 333;
-    private static final int SHRINK_ANIMATION_DURATION = 333;
+    private int mRevealAnimationDuration;
+    private int mShrinkAnimationDuration;
+    private boolean mIsLandscape;
 
     // Primary caller info
     private TextView mPhoneNumber;
@@ -76,8 +79,10 @@
     private View mSecondaryCallInfo;
     private TextView mSecondaryCallName;
 
-    private View mEndCallButton;
+    private FloatingActionButtonController mFloatingActionButtonController;
+    private View mFloatingActionButtonContainer;
     private ImageButton mHandoffButton;
+    private int mFloatingActionButtonHideOffset;
 
     // Cached DisplayMetrics density.
     private float mDensity;
@@ -98,6 +103,13 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        mRevealAnimationDuration = getResources().getInteger(R.integer.reveal_animation_duration);
+        mShrinkAnimationDuration = getResources().getInteger(R.integer.shrink_animation_duration);
+        mFloatingActionButtonHideOffset = getResources().getDimensionPixelOffset(
+                R.dimen.end_call_button_hide_offset);
+        mIsLandscape = getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE;
     }
 
 
@@ -142,14 +154,41 @@
         mPrimaryCallInfo = view.findViewById(R.id.primary_call_banner);
         mCallButtonsContainer = view.findViewById(R.id.callButtonFragment);
 
-        mEndCallButton = view.findViewById(R.id.endButton);
-        mEndCallButton.setOnClickListener(new View.OnClickListener() {
+        mFloatingActionButtonContainer = view.findViewById(
+                R.id.floating_end_call_action_button_container);
+        ImageButton floatingActionButton = (ImageButton) view.findViewById(
+                R.id.floating_end_call_action_button);
+        floatingActionButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 getPresenter().endCallClicked();
             }
         });
-        ViewUtil.setupFloatingActionButton(mEndCallButton, getResources());
+        int floatingActionButtonWidth = getResources().getDimensionPixelSize(
+                R.dimen.floating_action_button_width);
+        mFloatingActionButtonController = new FloatingActionButtonController(getActivity(),
+                mFloatingActionButtonContainer);
+        if (savedInstanceState != null) {
+            final ViewGroup parent = (ViewGroup) mPrimaryCallCardContainer.getParent();
+            final ViewTreeObserver observer = getView().getViewTreeObserver();
+            observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+                @Override
+                public void onGlobalLayout() {
+                    final ViewTreeObserver observer = getView().getViewTreeObserver();
+                    if (!observer.isAlive()) {
+                        return;
+                    }
+                    observer.removeOnGlobalLayoutListener(this);
+                    mFloatingActionButtonController.setScreenWidth(parent.getWidth());
+                    mFloatingActionButtonController.align(
+                            mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_RIGHT
+                                : FloatingActionButtonController.ALIGN_MIDDLE,
+                            0 /* offsetX */,
+                            0 /* offsetY */,
+                            false);
+                }
+            });
+        }
 
         mHandoffButton = (ImageButton) view.findViewById(R.id.handoffButton);
         mHandoffButton.setOnClickListener(new View.OnClickListener() {
@@ -544,7 +583,7 @@
 
     @Override
     public void setEndCallButtonEnabled(boolean enabled) {
-        mEndCallButton.setVisibility(enabled ? View.VISIBLE : View.GONE);
+        mFloatingActionButtonController.setVisible(enabled);
     }
 
     private void dispatchPopulateAccessibilityEvent(AccessibilityEvent event, View view) {
@@ -577,7 +616,15 @@
 
                 // Prepare the state of views before the circular reveal animation
                 mPrimaryCallCardContainer.setBottom(parent.getHeight());
-                mEndCallButton.setTranslationY(200);
+
+                // Set up FAB.
+                mFloatingActionButtonController.setScreenWidth(parent.getWidth());
+                // Move it below the screen.
+                mFloatingActionButtonController.manuallyTranslate(
+                        mFloatingActionButtonController.getTranslationXForAlignment(
+                                mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_RIGHT
+                                        : FloatingActionButtonController.ALIGN_MIDDLE),
+                        mFloatingActionButtonHideOffset);
                 mCallButtonsContainer.setAlpha(0);
                 mCallStateLabel.setAlpha(0);
                 mPrimaryName.setAlpha(0);
@@ -615,7 +662,7 @@
         final Animator shrinkAnimator =
                 ObjectAnimator.ofInt(mPrimaryCallCardContainer, "bottom",
                         startHeight, endHeight);
-        shrinkAnimator.setDuration(SHRINK_ANIMATION_DURATION);
+        shrinkAnimator.setDuration(mShrinkAnimationDuration);
         shrinkAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
@@ -625,8 +672,12 @@
                 assignTranslateAnimation(mCallTypeLabel, 4);
                 assignTranslateAnimation(mCallButtonsContainer, 5);
 
-                mEndCallButton.animate().translationY(0)
-                        .setDuration(SHRINK_ANIMATION_DURATION);
+                mFloatingActionButtonController.align(
+                        mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_RIGHT
+                            : FloatingActionButtonController.ALIGN_MIDDLE,
+                        0 /* offsetX */,
+                        0 /* offsetY */,
+                        true);
             }
         });
         shrinkAnimator.setInterpolator(AnimUtils.EASE_IN);
@@ -642,14 +693,14 @@
 
         final ValueAnimator valueAnimator = ViewAnimationUtils.createCircularReveal(view,
                 size.x / 2, size.y / 2, 0, Math.max(size.x, size.y));
-        valueAnimator.setDuration(REVEAL_ANIMATION_DURATION);
+        valueAnimator.setDuration(mRevealAnimationDuration);
         return valueAnimator;
     }
 
     private void assignTranslateAnimation(View view, int offset) {
         view.setTranslationY(mTranslationOffset * offset);
         view.animate().translationY(0).alpha(1).withLayer()
-                .setDuration(SHRINK_ANIMATION_DURATION).setInterpolator(AnimUtils.EASE_IN);
+                .setDuration(mShrinkAnimationDuration).setInterpolator(AnimUtils.EASE_IN);
     }
 
     private final class LayoutIgnoringListener implements View.OnLayoutChangeListener {
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index 6deae1f..c699126 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -346,6 +346,7 @@
             }
 
             if (intent.getBooleanExtra(NEW_OUTGOING_CALL, false)) {
+                intent.removeExtra(NEW_OUTGOING_CALL);
                 mCallCardFragment.animateForNewOutgoingCall();
             }