Merge "Applying call details red-lines."
diff --git a/res/anim/slide_in.xml b/res/anim/slide_in.xml
deleted file mode 100644
index fa0bda0..0000000
--- a/res/anim/slide_in.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<translate xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@interpolator/ease_in_interpolator"
-    android:duration="@integer/dialpad_slide_in_duration"
-    android:fromYDelta="67%p"
-    android:toYDelta="0" />
diff --git a/res/anim/slide_in_right.xml b/res/anim/slide_in_right.xml
deleted file mode 100644
index 11b764a..0000000
--- a/res/anim/slide_in_right.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<translate xmlns:android="http://schemas.android.com/apk/res/android"
-           android:fromXDelta="67%p"
-           android:toXDelta="0"
-           android:interpolator="@android:anim/decelerate_interpolator"
-           android:duration="@integer/dialpad_slide_in_duration"/>
diff --git a/res/anim/slide_out.xml b/res/anim/slide_out.xml
deleted file mode 100644
index e5d7ed4..0000000
--- a/res/anim/slide_out.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<translate xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@interpolator/ease_out_interpolator"
-    android:duration="@integer/dialpad_slide_out_duration"
-    android:fromYDelta="0"
-    android:toYDelta="80%p" />
diff --git a/res/anim/slide_out_right.xml b/res/anim/slide_out_right.xml
deleted file mode 100644
index 72304a4..0000000
--- a/res/anim/slide_out_right.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<translate xmlns:android="http://schemas.android.com/apk/res/android"
-           android:fromXDelta="0"
-           android:toXDelta="80%"
-           android:interpolator="@android:anim/decelerate_interpolator"
-           android:duration="@integer/dialpad_slide_out_duration"/>
diff --git a/res/values/animation_constants.xml b/res/values/animation_constants.xml
index 05b8e21..7863060 100644
--- a/res/values/animation_constants.xml
+++ b/res/values/animation_constants.xml
@@ -16,8 +16,6 @@
   -->
 <resources>
     <integer name="fade_duration">300</integer>
-    <integer name="dialpad_slide_in_duration">532</integer>
-    <integer name="dialpad_slide_out_duration">257</integer>
 
     <!-- Swipe constants -->
     <integer name="swipe_escape_velocity">100</integer>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5c7eb68..6d9c77a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -687,11 +687,19 @@
          [CHAR LIMIT=NONE] -->
     <string name="toast_entry_removed">Call log entry deleted.</string>
 
+    <!-- String used as a header in the call log above calls which occurred today.
+         [CHAR LIMIT=65] -->
+    <string name="call_log_header_today">Today</string>
+
+    <!-- String used as a header in the call log above calls which occurred yesterday.
+         [CHAR LIMIT=65] -->
+    <string name="call_log_header_yesterday">Yesterday</string>
+
     <!-- String used as a header in the call log above calls which occurred last week.
          [CHAR LIMIT=65] -->
     <string name="call_log_header_last_week">Last week</string>
 
-    <!-- String used as a header in the call log above calls which ocurred more than a week ago.
+    <!-- String used as a header in the call log above calls which occurred more than a week ago.
          [CHAR LIMIT=65] -->
     <string name="call_log_header_other">Other</string>
 
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 53e438d..baacc15 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -427,9 +427,9 @@
         }
 
         mSlideIn = AnimationUtils.loadAnimation(this,
-                mIsLandscape ? R.anim.slide_in_right : R.anim.slide_in);
+                mIsLandscape ? R.anim.dialpad_slide_in_right : R.anim.dialpad_slide_in_bottom);
         mSlideOut = AnimationUtils.loadAnimation(this,
-                mIsLandscape ? R.anim.slide_out_right : R.anim.slide_out);
+                mIsLandscape ? R.anim.dialpad_slide_out_right : R.anim.dialpad_slide_out_bottom);
 
         mSlideOut.setAnimationListener(mSlideOutListener);
 
@@ -1128,7 +1128,7 @@
         // Only scroll the button when the first tab is selected. The button should scroll from
         // the middle to right position only on the transition from the first tab to the second
         // tab.
-        if (position == ListsFragment.TAB_INDEX_SPEED_DIAL) {
+        if (position == ListsFragment.TAB_INDEX_SPEED_DIAL && !mIsLandscape) {
             mFloatingActionButtonController.onPageScrolled(positionOffset);
         }
     }
@@ -1187,9 +1187,13 @@
             align = mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_RIGHT
                     : FloatingActionButtonController.ALIGN_MIDDLE;
         } else {
-            align = mCurrentTabPosition == ListsFragment.TAB_INDEX_SPEED_DIAL
-                    ? FloatingActionButtonController.ALIGN_MIDDLE
-                        : FloatingActionButtonController.ALIGN_RIGHT;
+            if (!mIsLandscape) {
+                align = mCurrentTabPosition == ListsFragment.TAB_INDEX_SPEED_DIAL
+                        ? FloatingActionButtonController.ALIGN_MIDDLE
+                            : FloatingActionButtonController.ALIGN_RIGHT;
+            } else {
+                align = FloatingActionButtonController.ALIGN_RIGHT;
+            }
         }
         mFloatingActionButtonController.align(align,
                 0 /* offsetX */,
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 924a17f..12edaa0 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -122,12 +122,6 @@
     /** The size of the cache of contact info. */
     private static final int CONTACT_INFO_CACHE_SIZE = 100;
 
-    /** Localized string representing the word "Today". */
-    private final CharSequence mTodayLabel = DateUtils.getTodayString();
-
-    /** Localized string representing the word "Yesterday". */
-    private final CharSequence mYesterdayLabel = DateUtils.getYesterdayString();
-
     /** Constant used to indicate no row is expanded. */
     private static final long NONE_EXPANDED = -1;
 
@@ -1318,9 +1312,9 @@
      */
     private CharSequence getGroupDescription(int group) {
        if (group == CallLogGroupBuilder.DAY_GROUP_TODAY) {
-           return mTodayLabel;
+           return mContext.getResources().getString(R.string.call_log_header_today);
        } else if (group == CallLogGroupBuilder.DAY_GROUP_YESTERDAY) {
-           return mYesterdayLabel;
+           return mContext.getResources().getString(R.string.call_log_header_yesterday);
        } else if (group == CallLogGroupBuilder.DAY_GROUP_LAST_WEEK) {
            return mContext.getResources().getString(R.string.call_log_header_last_week);
        } else {
diff --git a/src/com/android/dialer/widget/SearchEditTextLayout.java b/src/com/android/dialer/widget/SearchEditTextLayout.java
index f3e355d..3dcbc4b 100644
--- a/src/com/android/dialer/widget/SearchEditTextLayout.java
+++ b/src/com/android/dialer/widget/SearchEditTextLayout.java
@@ -230,7 +230,9 @@
         mVoiceSearchButtonView.setVisibility(collapsedViewVisibility);
         mOverflowButtonView.setVisibility(collapsedViewVisibility);
         mBackButtonView.setVisibility(expandedViewVisibility);
-        mExpandedSearchBox.setVisibility(expandedViewVisibility);
+        // TODO: Prevents keyboard from jumping up in landscape mode after exiting the
+        // SearchFragment when the query string is empty. More elegant fix?
+        //mExpandedSearchBox.setVisibility(expandedViewVisibility);
         mClearButtonView.setVisibility(expandedViewVisibility);
     }
 
diff --git a/tests/res/layout/fill_call_log_test.xml b/tests/res/layout/fill_call_log_test.xml
index 704b9c6..6de9b91 100644
--- a/tests/res/layout/fill_call_log_test.xml
+++ b/tests/res/layout/fill_call_log_test.xml
@@ -20,7 +20,7 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:gravity="center_horizontal"
+    android:gravity="left"
 >
     <TextView
         android:layout_width="match_parent"
@@ -53,4 +53,134 @@
         android:indeterminate="false"
         android:visibility="gone"
     />
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/add_custom_entry"
+        />
+    <RadioGroup
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <RadioButton
+            android:id="@+id/call_type_incoming"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/call_type_incoming" />
+        <RadioButton
+            android:id="@+id/call_type_missed"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/call_type_missed" />
+        <RadioButton
+            android:id="@+id/call_type_outgoing"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/call_type_outgoing" />
+    </RadioGroup>
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="left"
+        >
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/call_date"
+            />
+        <TextView
+            android:id="@+id/call_date"
+            android:paddingStart="16dp"
+            android:layout_width="120dp"
+            android:layout_height="wrap_content"
+            />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/edit"
+            android:onClick="showDatePickerDialog" />
+    </LinearLayout>
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="left"
+        >
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/call_time"
+            />
+        <TextView
+            android:id="@+id/call_time"
+            android:paddingStart="16dp"
+            android:layout_width="120dp"
+            android:layout_height="wrap_content"
+            />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/edit"
+            android:onClick="showTimePickerDialog" />
+    </LinearLayout>
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/call_presentation"
+        />
+    <RadioGroup
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <RadioButton
+            android:id="@+id/presentation_allowed"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/presentation_allowed"
+            android:textSize="9sp" />
+        <RadioButton
+            android:id="@+id/presentation_restricted"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/presentation_restricted"
+            android:textSize="9sp" />
+        <RadioButton
+            android:id="@+id/presentation_unknown"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/presentation_unknown"
+            android:textSize="9sp" />
+        <RadioButton
+            android:id="@+id/presentation_payphone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/presentation_payphone"
+            android:textSize="9sp" />
+    </RadioGroup>
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="left"
+        >
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/number"
+            />
+        <EditText
+            android:id="@+id/phone_number"
+            android:layout_width="180dp"
+            android:layout_height="wrap_content"
+            android:inputType="phone"
+            />
+    </LinearLayout>
+    <Button
+        android:id="@+id/add_custom"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/addToCallLogButton"
+        android:onClick="addManualEntry"
+        />
 </LinearLayout>
diff --git a/tests/res/values/donottranslate_strings.xml b/tests/res/values/donottranslate_strings.xml
index ceba5ea..bdeb304 100644
--- a/tests/res/values/donottranslate_strings.xml
+++ b/tests/res/values/donottranslate_strings.xml
@@ -37,5 +37,17 @@
     <string name="numberOfCallLogEntries">Number of call log entries to add:</string>
     <string name="addedLogEntriesToast">Added %1$d call log entries.</string>
     <string name="noLogEntriesToast">No entries in the call log yet.  Need at least one record for the template.  Or use random numbers.</string>
-
+    <string name="add_custom_entry">Add custom call log entry:</string>
+    <string name="call_type_incoming">Incoming</string>
+    <string name="call_type_missed">Missed</string>
+    <string name="call_type_outgoing">Outgoing</string>
+    <string name="call_date">Call date</string>
+    <string name="call_time">Call time</string>
+    <string name="edit">Edit</string>
+    <string name="number">Number</string>
+    <string name="call_presentation">Presentation</string>
+    <string name="presentation_allowed">Allowed</string>
+    <string name="presentation_restricted">Restricted</string>
+    <string name="presentation_unknown">Unknown</string>
+    <string name="presentation_payphone">Payphone</string>
 </resources>
diff --git a/tests/src/com/android/dialer/tests/calllog/FillCallLogTestActivity.java b/tests/src/com/android/dialer/tests/calllog/FillCallLogTestActivity.java
index b1b8e2f..3a1682e 100644
--- a/tests/src/com/android/dialer/tests/calllog/FillCallLogTestActivity.java
+++ b/tests/src/com/android/dialer/tests/calllog/FillCallLogTestActivity.java
@@ -17,7 +17,11 @@
 package com.android.dialer.tests.calllog;
 
 import android.app.Activity;
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
 import android.app.LoaderManager;
+import android.app.TimePickerDialog;
 import android.content.ContentProviderClient;
 import android.content.ContentValues;
 import android.content.CursorLoader;
@@ -27,16 +31,21 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.provider.CallLog.Calls;
+import android.text.format.DateFormat;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 import android.widget.CheckBox;
+import android.widget.DatePicker;
 import android.widget.ProgressBar;
+import android.widget.RadioButton;
 import android.widget.TextView;
+import android.widget.TimePicker;
 import android.widget.Toast;
 
 import com.android.dialer.tests.R;
 
+import java.util.Calendar;
 import java.util.Random;
 
 /**
@@ -56,6 +65,22 @@
     private Button mAddButton;
     private ProgressBar mProgressBar;
     private CheckBox mUseRandomNumbers;
+    private RadioButton mCallTypeIncoming;
+    private RadioButton mCallTypeMissed;
+    private RadioButton mCallTypeOutgoing;
+    private RadioButton mPresentationAllowed;
+    private RadioButton mPresentationRestricted;
+    private RadioButton mPresentationUnknown;
+    private RadioButton mPresentationPayphone;
+    private TextView mCallDate;
+    private TextView mCallTime;
+    private TextView mPhoneNumber;
+
+    private int mCallTimeHour;
+    private int mCallTimeMinute;
+    private int mCallDateYear;
+    private int mCallDateMonth;
+    private int mCallDateDay;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -88,6 +113,27 @@
                 mProgressBar.setVisibility(View.VISIBLE);
             }
         });
+
+        mCallTypeIncoming = (RadioButton) findViewById(R.id.call_type_incoming);
+        mCallTypeMissed = (RadioButton) findViewById(R.id.call_type_missed);
+        mCallTypeOutgoing = (RadioButton) findViewById(R.id.call_type_outgoing);
+        mPresentationAllowed = (RadioButton) findViewById(R.id.presentation_allowed);
+        mPresentationPayphone = (RadioButton) findViewById(R.id.presentation_payphone);
+        mPresentationUnknown = (RadioButton) findViewById(R.id.presentation_unknown);
+        mPresentationRestricted = (RadioButton) findViewById(R.id.presentation_restricted);
+        mCallTime = (TextView) findViewById(R.id.call_time);
+        mCallDate = (TextView) findViewById(R.id.call_date);
+        mPhoneNumber = (TextView) findViewById(R.id.phone_number);
+
+        // Use the current time as the default values for the picker
+        final Calendar c = Calendar.getInstance();
+        mCallTimeHour = c.get(Calendar.HOUR_OF_DAY);
+        mCallTimeMinute = c.get(Calendar.MINUTE);
+        mCallDateYear = c.get(Calendar.YEAR);
+        mCallDateMonth = c.get(Calendar.MONTH);
+        mCallDateDay = c.get(Calendar.DAY_OF_MONTH);
+        setDisplayDate();
+        setDisplayTime();
     }
 
     /**
@@ -306,4 +352,122 @@
     public void updateCount(Integer count) {
         mProgressBar.setProgress(count);
     }
+
+    /**
+     * Determines the call type for a manually entered call.
+     *
+     * @return Call type.
+     */
+    private int getManualCallType() {
+        if (mCallTypeIncoming.isChecked()) {
+            return Calls.INCOMING_TYPE;
+        } else if (mCallTypeOutgoing.isChecked()) {
+            return Calls.OUTGOING_TYPE;
+        } else {
+            return Calls.MISSED_TYPE;
+        }
+    }
+
+    /**
+     * Determines the presentation for a manually entered call.
+     *
+     * @return Presentation.
+     */
+    private int getManualPresentation() {
+        if (mPresentationAllowed.isChecked()) {
+            return Calls.PRESENTATION_ALLOWED;
+        } else if (mPresentationPayphone.isChecked()) {
+            return Calls.PRESENTATION_PAYPHONE;
+        } else if (mPresentationRestricted.isChecked()) {
+            return Calls.PRESENTATION_RESTRICTED;
+        } else {
+            return Calls.PRESENTATION_UNKNOWN;
+        }
+    }
+
+    /**
+     * Shows a time picker dialog, storing the results in the time field.
+     */
+    public void showTimePickerDialog(View v) {
+        DialogFragment newFragment = new TimePickerFragment();
+        newFragment.show(getFragmentManager(),"timePicker");
+    }
+
+    /**
+     * Helper class to display time picker and store the hour/minute.
+     */
+    public class TimePickerFragment extends DialogFragment
+            implements TimePickerDialog.OnTimeSetListener {
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            // Create a new instance of TimePickerDialog and return it
+            return new TimePickerDialog(getActivity(), this, mCallTimeHour, mCallTimeMinute,
+                    DateFormat.is24HourFormat(getActivity()));
+        }
+
+        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+            mCallTimeHour = hourOfDay;
+            mCallTimeMinute = minute;
+            setDisplayTime();
+        }
+    }
+
+    /**
+     * Sets the call time TextView to the current selected time.
+     */
+    private void setDisplayTime() {
+        mCallTime.setText(String.format("%02d:%02d", mCallTimeHour, mCallTimeMinute));
+    }
+
+    /**
+     * Sets the call date Textview to the current selected date
+     */
+    private void setDisplayDate() {
+        mCallDate.setText(String.format("%04d-%02d-%02d", mCallDateYear, mCallDateMonth,
+                mCallDateDay));
+    }
+
+    /**
+     * Shows a date picker dialog.
+     */
+    public void showDatePickerDialog(View v) {
+        DialogFragment newFragment = new DatePickerFragment();
+        newFragment.show(getFragmentManager(),"datePicker");
+    }
+
+    /**
+     * Helper class to show a date picker.
+     */
+    public class DatePickerFragment extends DialogFragment
+            implements DatePickerDialog.OnDateSetListener {
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            // Create a new instance of DatePickerDialog and return it
+            return new DatePickerDialog(getActivity(), this, mCallDateYear, mCallDateMonth,
+                    mCallDateDay);
+        }
+
+        public void onDateSet(DatePicker view, int year, int month, int day) {
+            mCallDateYear = year;
+            mCallDateMonth = month;
+            mCallDateDay = day;
+            setDisplayDate();
+        }
+    }
+
+    /**
+     * OnClick handler for the button that adds a manual call log entry to the call log.
+     *
+     * @param v Calling view.
+     */
+    public void addManualEntry(View v) {
+        Calendar dateTime = Calendar.getInstance();
+        dateTime.set(mCallDateYear, mCallDateMonth, mCallDateDay, mCallTimeHour, mCallTimeMinute);
+
+        Calls.addCall(null, this, mPhoneNumber.getText().toString(), getManualPresentation(),
+                getManualCallType(), dateTime.getTimeInMillis(), RNG.nextInt(60 * 60));
+
+    }
 }