Merge "Fix bug where keyboard jumps in landscape."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8f083c8..bd23506 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>
 </resources>
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/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));
+
+    }
 }