Merge "Add activity-aliases to keep shortcuts from GB and HC working"
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index 1fe6faa..6a03493 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -52,7 +52,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/contact_background"
- android:background="?attr/call_detail_primary_background_color"
+ android:background="?attr/call_log_primary_background_color"
/>
<LinearLayout
android:layout_width="match_parent"
@@ -96,14 +96,14 @@
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:paddingLeft="80dp"
- android:background="?attr/call_detail_secondary_background_color"
+ android:background="?attr/call_log_secondary_background_color"
>
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
- android:textColor="?attr/call_detail_secondary_text_color"
+ android:textColor="?attr/call_log_secondary_text_color"
/>
<TextView
android:id="@+id/duration"
@@ -112,7 +112,7 @@
android:layout_alignParentLeft="true"
android:layout_below="@id/time"
android:layout_alignLeft="@id/time"
- android:textColor="?attr/call_detail_secondary_text_color"
+ android:textColor="?attr/call_log_secondary_text_color"
/>
<ImageView
android:id="@+id/delete"
diff --git a/res/layout/call_log_contact_photo.xml b/res/layout/call_log_contact_photo.xml
index 178c45b..552e9ca 100644
--- a/res/layout/call_log_contact_photo.xml
+++ b/res/layout/call_log_contact_photo.xml
@@ -2,9 +2,9 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<QuickContactBadge
android:id="@+id/contact_photo"
- android:layout_width="?attr/call_log_contact_photo_size"
- android:layout_height="?attr/call_log_contact_photo_size"
- android:layout_margin="?attr/call_log_contact_photo_margin"
+ android:layout_width="?attr/call_log_list_contact_photo_size"
+ android:layout_height="?attr/call_log_list_contact_photo_size"
+ android:layout_margin="?attr/call_log_list_contact_photo_margin"
android:layout_alignParentLeft="true"
android:layout_gravity="center_vertical"
/>
diff --git a/res/layout/call_log_list_group_item.xml b/res/layout/call_log_list_group_item.xml
index 352d7ec..57465a6 100644
--- a/res/layout/call_log_list_group_item.xml
+++ b/res/layout/call_log_list_group_item.xml
@@ -21,75 +21,5 @@
<include layout="@layout/call_log_contact_photo"/>
<include layout="@layout/call_log_action_group"/>
-
- <TextView android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toLeftOf="@id/divider"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="8dip"
- android:layout_marginLeft="10dip"
-
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
- />
-
- <TextView android:id="@+id/label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
- android:layout_marginLeft="86dip"
- android:layout_marginRight="5dip"
- android:layout_alignBaseline="@id/date"
-
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- />
-
- <TextView android:id="@+id/number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/label"
- android:layout_toLeftOf="@id/date"
- android:layout_alignBaseline="@id/label"
- android:layout_alignWithParentIfMissing="true"
-
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
-
- <TextView android:id="@+id/groupSize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/divider"
- android:layout_above="@id/date"
- android:layout_alignWithParentIfMissing="true"
- android:layout_marginBottom="-10dip"
-
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:singleLine="true"
- android:gravity="center_vertical"
- />
-
- <TextView android:id="@+id/line1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@+id/groupSize"
- android:layout_above="@id/date"
- android:layout_alignWithParentIfMissing="true"
- android:layout_marginLeft="86dip"
- android:layout_marginBottom="-10dip"
-
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:gravity="center_vertical"
- />
+ <include layout="@layout/call_log_list_item_layout" />
</RelativeLayout>
diff --git a/res/layout/call_log_list_item_layout.xml b/res/layout/call_log_list_item_layout.xml
index 2128a79..8ea2bf7 100644
--- a/res/layout/call_log_list_item_layout.xml
+++ b/res/layout/call_log_list_item_layout.xml
@@ -15,69 +15,12 @@
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
- <ImageView android:id="@+id/call_type_icon"
+ <RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_marginLeft="54dip"
- />
-
- <TextView android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toLeftOf="@id/divider"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="8dip"
- android:layout_marginLeft="10dip"
-
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
- />
-
- <TextView android:id="@+id/label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
- android:layout_marginLeft="86dip"
- android:layout_marginRight="5dip"
- android:layout_alignBaseline="@id/date"
-
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- />
-
- <TextView android:id="@+id/number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/label"
- android:layout_toLeftOf="@id/date"
- android:layout_alignBaseline="@id/label"
- android:layout_alignWithParentIfMissing="true"
-
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
-
- <TextView android:id="@+id/line1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
+ android:layout_toRightOf="@id/contact_photo"
android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/divider"
- android:layout_above="@id/date"
- android:layout_alignWithParentIfMissing="true"
- android:layout_marginLeft="86dip"
- android:layout_marginBottom="-10dip"
-
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:gravity="center_vertical"
- />
+ >
+ <include layout="@layout/call_log_phone_call_details"/>
+ </RelativeLayout>
</merge>
diff --git a/res/layout/call_log_phone_call_details.xml b/res/layout/call_log_phone_call_details.xml
index 5da2773..f22efba 100644
--- a/res/layout/call_log_phone_call_details.xml
+++ b/res/layout/call_log_phone_call_details.xml
@@ -16,22 +16,42 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
- android:id="@+id/call_types"
+ android:id="@+id/call_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?attr/call_detail_primary_text_color"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
- />
+ >
+ <LinearLayout
+ android:id="@+id/call_type_icons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+ <TextView
+ android:id="@+id/call_type_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?attr/call_log_primary_text_color"
+ />
+ <TextView
+ android:id="@+id/call_type_separator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="?attr/call_log_date_margin"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?attr/call_log_primary_text_color"
+ android:text="@string/call_log_type_date_separator"
+ />
+ </LinearLayout>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?attr/call_detail_primary_text_color"
- android:layout_toRightOf="@id/call_types"
- android:layout_marginLeft="?attr/call_detail_date_margin"
+ android:textColor="?attr/call_log_primary_text_color"
+ android:layout_toRightOf="@id/call_type"
+ android:layout_marginLeft="?attr/call_log_date_margin"
android:layout_alignParentBottom="true"
/>
<TextView
@@ -39,16 +59,16 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?attr/call_detail_primary_text_color"
+ android:textColor="?attr/call_log_primary_text_color"
android:layout_alignParentLeft="true"
- android:layout_above="@id/call_types"
+ android:layout_above="@id/call_type"
/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?attr/call_detail_primary_text_color"
+ android:textColor="?attr/call_log_primary_text_color"
android:layout_alignParentLeft="true"
android:layout_above="@id/number"
android:paddingBottom="2dp"
diff --git a/res/layout/dialpad_fragment.xml b/res/layout/dialpad_fragment.xml
index aee2c25..9f8c0cf 100644
--- a/res/layout/dialpad_fragment.xml
+++ b/res/layout/dialpad_fragment.xml
@@ -22,20 +22,35 @@
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip" >
- <!-- Text field above the keypad where the digits are displayed.
- It's type is set to NULL (to disable the IME keyboard) in the
- java code.
-
- Background drawable can be controlled programatically.
- -->
- <EditText android:id="@+id/digits"
+ <!-- Text field and possibly soft menu button above the keypad where
+ the digits are displayed. -->
+ <RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dialpad_digits_height"
android:layout_marginTop="4dip"
android:gravity="center"
- android:textAppearance="@style/DialtactsDigitsTextAppearance"
- android:background="@drawable/dialpad_background"
- android:textColor="?android:attr/textColorPrimary" />
+ android:background="@drawable/dialpad_background" >
+
+ <!-- Type of this EditText is set to NULL (to disable the IME keyboard)
+ in the java code.
+
+ Background drawable can be controlled programatically. -->
+ <EditText android:id="@+id/digits"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ android:layout_toLeftOf="@+id/moreoverflow"
+ android:gravity="center"
+ android:textAppearance="@style/DialtactsDigitsTextAppearance"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <ImageButton android:id="@+id/overflow_menu"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:src="@drawable/ic_menu_overflow" />
+
+ </RelativeLayout>
<!-- Keypad section -->
<include layout="@layout/dialpad" />
diff --git a/res/menu/call_log_options.xml b/res/menu/call_log_options.xml
index 57d637e..1f8de57 100644
--- a/res/menu/call_log_options.xml
+++ b/res/menu/call_log_options.xml
@@ -19,4 +19,9 @@
android:icon="@android:drawable/ic_menu_close_clear_cancel"
android:title="@string/recentCalls_deleteAll"
android:showAsAction="withText" />
+
+ <item
+ android:id="@+id/menu_call_settings_call_log"
+ android:title="@string/call_settings"
+ android:showAsAction="withText" />
</menu>
diff --git a/res/menu/dialpad_options.xml b/res/menu/dialpad_options.xml
index 77da9cb..c736e34 100644
--- a/res/menu/dialpad_options.xml
+++ b/res/menu/dialpad_options.xml
@@ -30,4 +30,9 @@
android:icon="@drawable/ic_menu_wait"
android:title="@string/add_wait"
android:showAsAction="withText" />
+
+ <item
+ android:id="@+id/menu_call_settings_dialpad"
+ android:title="@string/call_settings"
+ android:showAsAction="withText" />
</menu>
diff --git a/res/menu/dialtacts_options.xml b/res/menu/dialtacts_options.xml
index a5ed153..aa3af3f 100644
--- a/res/menu/dialtacts_options.xml
+++ b/res/menu/dialtacts_options.xml
@@ -15,11 +15,6 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
- android:id="@+id/menu_call_settings"
- android:title="@string/call_settings"
- android:showAsAction="withText" />
-
- <item
android:id="@+id/search_on_action_bar"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="always" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e17648a..9e2e085 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -571,6 +571,9 @@
<!-- Title for missed call details screen -->
<string name="type_missed">Missed call</string>
+ <!-- Title for voicemail details screen -->
+ <string name="type_voicemail">Voicemail</string>
+
<!-- Description for incoming calls going to voice mail vs. not -->
<string name="actionIncomingCall">Incoming calls</string>
@@ -1601,4 +1604,7 @@
<!-- Title of the notification of new voicemail. -->
<string name="notification_voicemail_title">New voicemail</string>
+
+ <!-- The separator between the call type text and the date in the call log [CHAR LIMIT=3] -->
+ <string name="call_log_type_date_separator">/</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 914532c..e4b7a86 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -36,10 +36,16 @@
<item name="list_item_header_text_color">#ffcccccc</item>
<item name="list_item_header_text_size">14sp</item>
<item name="contact_filter_popup_width">320dip</item>
- <!-- CallLogActivity -->
- <item name="call_log_contact_photo_size">50dip</item>
- <item name="call_log_contact_photo_margin">5dip</item>
+ <!-- CallLogList -->
+ <item name="call_log_list_contact_photo_size">50dip</item>
+ <item name="call_log_list_contact_photo_margin">5dip</item>
<item name="call_log_list_item_height">60dip</item>
+ <!-- CallLog -->
+ <item name="call_log_date_margin">5dip</item>
+ <item name="call_log_primary_text_color">#FFFFFF</item>
+ <item name="call_log_primary_background_color">#000000</item>
+ <item name="call_log_secondary_text_color">#FFFFFF</item>
+ <item name="call_log_secondary_background_color">#333333</item>
</style>
<style name="CallDetailActivityTheme" parent="android:Theme.Holo">
@@ -51,11 +57,12 @@
<item name="call_detail_action_bar_height">60dip</item>
<item name="call_detail_action_icon_size">60dip</item>
<item name="call_detail_contact_background_overlay_alpha">0.25</item>
- <item name="call_detail_primary_text_color">#FFFFFF</item>
- <item name="call_detail_date_margin">5dip</item>
- <item name="call_detail_primary_background_color">#000000</item>
- <item name="call_detail_secondary_text_color">#FFFFFF</item>
- <item name="call_detail_secondary_background_color">#333333</item>
+ <!-- CallLog -->
+ <item name="call_log_date_margin">5dip</item>
+ <item name="call_log_primary_text_color">#FFFFFF</item>
+ <item name="call_log_primary_background_color">#000000</item>
+ <item name="call_log_secondary_text_color">#FFFFFF</item>
+ <item name="call_log_secondary_background_color">#333333</item>
</style>
<style name="ContactDetailActivityTheme" parent="android:Theme.Holo.Light">
@@ -138,16 +145,19 @@
<attr name="call_detail_contact_photo_size" format="dimension" />
<attr name="call_detail_action_icon_size" format="dimension" />
<attr name="call_detail_action_bar_height" format="dimension" />
- <attr name="call_detail_primary_text_color" format="color" />
- <attr name="call_detail_primary_background_color" format="color" />
- <attr name="call_detail_secondary_text_color" format="color" />
- <attr name="call_detail_secondary_background_color" format="color" />
- <attr name="call_detail_date_margin" format="dimension" />
</declare-styleable>
- <declare-styleable name="CallLogActivity">
- <attr name="call_log_contact_photo_size" format="dimension" />
- <attr name="call_log_contact_photo_margin" format="dimension" />
+ <declare-styleable name="CallLog">
+ <attr name="call_log_primary_text_color" format="color" />
+ <attr name="call_log_primary_background_color" format="color" />
+ <attr name="call_log_secondary_text_color" format="color" />
+ <attr name="call_log_secondary_background_color" format="color" />
+ <attr name="call_log_date_margin" format="dimension" />
+ </declare-styleable>
+
+ <declare-styleable name="CallLogList">
+ <attr name="call_log_list_contact_photo_size" format="dimension" />
+ <attr name="call_log_list_contact_photo_margin" format="dimension" />
<attr name="call_log_list_item_height" format="dimension" />
</declare-styleable>
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 7f01481..d08b76a 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -214,6 +214,7 @@
Uri.encode(mNumber));
Cursor phonesCursor = resolver.query(
phoneUri, PHONES_PROJECTION, null, null, null);
+ String candidateNumberText = mNumber;
try {
if (phonesCursor != null && phonesCursor.moveToFirst()) {
long personId = phonesCursor.getLong(COLUMN_INDEX_ID);
@@ -221,19 +222,20 @@
Contacts.CONTENT_URI, personId);
nameText = phonesCursor.getString(COLUMN_INDEX_NAME);
photoId = phonesCursor.getLong(COLUMN_INDEX_PHOTO_ID);
- mNumber = PhoneNumberUtils.formatNumber(
+ candidateNumberText = PhoneNumberUtils.formatNumber(
phonesCursor.getString(COLUMN_INDEX_NUMBER),
phonesCursor.getString(COLUMN_INDEX_NORMALIZED_NUMBER),
countryIso);
numberType = phonesCursor.getInt(COLUMN_INDEX_TYPE);
numberLabel = phonesCursor.getString(COLUMN_INDEX_LABEL);
} else {
- mNumber = PhoneNumberUtils.formatNumber(mNumber, countryIso);
+ candidateNumberText =
+ PhoneNumberUtils.formatNumber(mNumber, countryIso);
}
} finally {
- if (phonesCursor != null) phonesCursor.close();
+ if (phonesCursor != null) phonesCursor.close();
+ numberText = candidateNumberText;
}
- numberText = mNumber;
// Let user view contact details if they exist, otherwise add option
// to create new contact from this number.
@@ -301,8 +303,9 @@
ViewAdapter adapter = new ViewAdapter(this, actions);
setListAdapter(adapter);
}
- mPhoneCallDetailsHelper.setPhoneCallDetails(mPhoneCallDetailsViews, date, callType,
- nameText, numberText, numberType, numberLabel);
+ mPhoneCallDetailsHelper.setPhoneCallDetails(mPhoneCallDetailsViews,
+ new PhoneCallDetails(mNumber, numberText, new int[]{ callType }, date,
+ nameText, numberType, numberLabel), false);
loadContactPhotos(photoId);
} else {
diff --git a/src/com/android/contacts/PhoneCallDetails.java b/src/com/android/contacts/PhoneCallDetails.java
new file mode 100644
index 0000000..7b02a88
--- /dev/null
+++ b/src/com/android/contacts/PhoneCallDetails.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package com.android.contacts;
+
+import android.provider.CallLog.Calls;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+
+/**
+ * The details of a phone call to be shown in the UI.
+ */
+public class PhoneCallDetails {
+ /** The number of the other party involved in the call. */
+ public final CharSequence number;
+ /** The formatted version of {@link #number}. */
+ public final CharSequence formattedNumber;
+ /**
+ * The type of calls, as defined in the call log table, e.g., {@link Calls#INCOMING_TYPE}.
+ * <p>
+ * There might be multiple types if this represents a set of entries grouped together.
+ */
+ public final int[] callTypes;
+ /** The date of the call, in milliseconds since the epoch. */
+ public final long date;
+ /** The name of the contact, or the empty string. */
+ public final CharSequence name;
+ /** The type of phone, e.g., {@link Phone#TYPE_HOME}, 0 if not available. */
+ public final int numberType;
+ /** The custom label associated with the phone number in the contact, or the empty string. */
+ public final CharSequence numberLabel;
+
+ /** Create the details for a call with a number not associated with a contact. */
+ public PhoneCallDetails(CharSequence number, CharSequence formattedNumber, int[] callTypes,
+ long date) {
+ this(number, formattedNumber, callTypes, date, "", 0, "");
+ }
+
+ /** Create the details for a call with a number associated with a contact. */
+ public PhoneCallDetails(CharSequence number, CharSequence formattedNumber, int[] callTypes,
+ long date, CharSequence name, int numberType, CharSequence numberLabel) {
+ this.number = number;
+ this.formattedNumber = formattedNumber;
+ this.callTypes = callTypes;
+ this.date = date;
+ this.name = name;
+ this.numberType = numberType;
+ this.numberLabel = numberLabel;
+ }
+}
diff --git a/src/com/android/contacts/PhoneCallDetailsHelper.java b/src/com/android/contacts/PhoneCallDetailsHelper.java
index 78ca252..7f73b04 100644
--- a/src/com/android/contacts/PhoneCallDetailsHelper.java
+++ b/src/com/android/contacts/PhoneCallDetailsHelper.java
@@ -47,6 +47,14 @@
private final Drawable mMissedDrawable;
/** Icon for voicemails. */
private final Drawable mVoicemailDrawable;
+ /** Name used to identify incoming calls. */
+ private final String mIncomingName;
+ /** Name used to identify outgoing calls. */
+ private final String mOutgoingName;
+ /** Name used to identify missed calls. */
+ private final String mMissedName;
+ /** Name used to identify voicemail calls. */
+ private final String mVoicemailName;
/** The injected current time in milliseconds since the epoch. Used only by tests. */
private Long mCurrentTimeMillisForTest;
@@ -67,72 +75,72 @@
mOutgoingDrawable = outgoingDrawable;
mMissedDrawable = missedDrawable;
mVoicemailDrawable = voicemailDrawable;
+ // Cache these values so that we do not need to look them up each time.
+ mIncomingName = mResources.getString(R.string.type_incoming);
+ mOutgoingName = mResources.getString(R.string.type_outgoing);
+ mMissedName = mResources.getString(R.string.type_missed);
+ mVoicemailName = mResources.getString(R.string.type_voicemail);
}
- /**
- * Fills the call details views with content.
- *
- * @param date the date of the call, in milliseconds since the epoch
- * @param callType the type of call, as defined in the call log table
- * @param name the name of the contact, if available
- * @param number the number of the other party involved in the call
- * @param numberType the type of phone, e.g., {@link Phone#TYPE_HOME}, 0 if not available
- * @param numberLabel the custom label associated with the phone number in the contact
- */
- public void setPhoneCallDetails(PhoneCallDetailsViews views, long date,
- int callType, CharSequence name, CharSequence number, int numberType,
- CharSequence numberLabel) {
- Drawable callTypeDrawable = null;
- switch (callType) {
- case Calls.INCOMING_TYPE:
- callTypeDrawable = mIncomingDrawable;
- break;
+ /** Fills the call details views with content. */
+ public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details,
+ boolean useIcons) {
+ if (useIcons) {
+ views.callTypeIcons.removeAllViews();
+ int count = details.callTypes.length;
+ for (int callType : details.callTypes) {
+ ImageView callTypeImage = new ImageView(mContext);
+ callTypeImage.setImageDrawable(getCallTypeDrawable(callType));
+ views.callTypeIcons.addView(callTypeImage);
+ }
+ views.callTypeIcons.setVisibility(View.VISIBLE);
+ views.callTypeText.setVisibility(View.GONE);
+ views.callTypeSeparator.setVisibility(View.GONE);
+ } else {
+ String callTypeName;
+ // Use the name of the first call type.
+ // TODO: We should update this to handle the text for multiple calls as well.
+ int callType = details.callTypes[0];
+ views.callTypeText.setText(getCallTypeText(callType));
+ views.callTypeIcons.removeAllViews();
- case Calls.OUTGOING_TYPE:
- callTypeDrawable = mOutgoingDrawable;
- break;
-
- case Calls.MISSED_TYPE:
- callTypeDrawable = mMissedDrawable;
- break;
-
- case Calls.VOICEMAIL_TYPE:
- callTypeDrawable = mVoicemailDrawable;
- break;
+ views.callTypeText.setVisibility(View.VISIBLE);
+ views.callTypeSeparator.setVisibility(View.VISIBLE);
+ views.callTypeIcons.setVisibility(View.GONE);
}
+
CharSequence shortDateText =
- DateUtils.getRelativeTimeSpanString(date,
+ DateUtils.getRelativeTimeSpanString(details.date,
getCurrentTimeMillis(),
DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_ABBREV_RELATIVE);
CharSequence numberFormattedLabel = null;
// Only show a label if the number is shown and it is not a SIP address.
- if (!TextUtils.isEmpty(number) && !PhoneNumberUtils.isUriNumber(number.toString())) {
- numberFormattedLabel = Phone.getTypeLabel(mResources, numberType, numberLabel);
+ if (!TextUtils.isEmpty(details.number)
+ && !PhoneNumberUtils.isUriNumber(details.number.toString())) {
+ numberFormattedLabel = Phone.getTypeLabel(mResources, details.numberType,
+ details.numberLabel);
}
- CharSequence nameText;
- CharSequence numberText;
- if (TextUtils.isEmpty(name)) {
- nameText = getDisplayNumber(number);
+ final CharSequence nameText;
+ final CharSequence numberText;
+ if (TextUtils.isEmpty(details.name)) {
+ nameText = getDisplayNumber(details.number, details.formattedNumber);
numberText = "";
} else {
- nameText = name;
- numberText = getDisplayNumber(number);
- if (callType != 0 && numberFormattedLabel != null) {
+ nameText = details.name;
+ CharSequence displayNumber = getDisplayNumber(details.number, details.formattedNumber);
+ if (numberFormattedLabel != null) {
numberText = FormatUtils.applyStyleToSpan(Typeface.BOLD,
- numberFormattedLabel + " " + number, 0,
+ numberFormattedLabel + " " + displayNumber, 0,
numberFormattedLabel.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ } else {
+ numberText = displayNumber;
}
}
- ImageView callTypeImage = new ImageView(mContext);
- callTypeImage.setImageDrawable(callTypeDrawable);
- views.callTypesLayout.removeAllViews();
- views.callTypesLayout.addView(callTypeImage);
-
views.dateView.setText(shortDateText);
views.dateView.setVisibility(View.VISIBLE);
views.nameView.setText(nameText);
@@ -147,7 +155,47 @@
}
}
- private CharSequence getDisplayNumber(CharSequence number) {
+ /** Returns the text used to represent the given call type. */
+ private String getCallTypeText(int callType) {
+ switch (callType) {
+ case Calls.INCOMING_TYPE:
+ return mIncomingName;
+
+ case Calls.OUTGOING_TYPE:
+ return mOutgoingName;
+
+ case Calls.MISSED_TYPE:
+ return mMissedName;
+
+ case Calls.VOICEMAIL_TYPE:
+ return mVoicemailName;
+
+ default:
+ throw new IllegalArgumentException("invalid call type: " + callType);
+ }
+ }
+
+ /** Returns the drawable of the icon associated with the given call type. */
+ private Drawable getCallTypeDrawable(int callType) {
+ switch (callType) {
+ case Calls.INCOMING_TYPE:
+ return mIncomingDrawable;
+
+ case Calls.OUTGOING_TYPE:
+ return mOutgoingDrawable;
+
+ case Calls.MISSED_TYPE:
+ return mMissedDrawable;
+
+ case Calls.VOICEMAIL_TYPE:
+ return mVoicemailDrawable;
+
+ default:
+ throw new IllegalArgumentException("invalid call type: " + callType);
+ }
+ }
+
+ private CharSequence getDisplayNumber(CharSequence number, CharSequence formattedNumber) {
if (TextUtils.isEmpty(number)) {
return "";
}
@@ -163,7 +211,11 @@
if (PhoneNumberUtils.extractNetworkPortion(number.toString()).equals(mVoicemailNumber)) {
return mResources.getString(R.string.voicemail);
}
- return number;
+ if (TextUtils.isEmpty(formattedNumber)) {
+ return number;
+ } else {
+ return formattedNumber;
+ }
}
public void setCurrentTimeForTest(long currentTimeMillis) {
diff --git a/src/com/android/contacts/PhoneCallDetailsViews.java b/src/com/android/contacts/PhoneCallDetailsViews.java
index 483ec65..7453af0 100644
--- a/src/com/android/contacts/PhoneCallDetailsViews.java
+++ b/src/com/android/contacts/PhoneCallDetailsViews.java
@@ -25,14 +25,18 @@
*/
public final class PhoneCallDetailsViews {
public final TextView nameView;
- public final LinearLayout callTypesLayout;
+ public final LinearLayout callTypeIcons;
+ public final TextView callTypeText;
+ public final View callTypeSeparator;
public final TextView dateView;
public final TextView numberView;
- private PhoneCallDetailsViews(TextView nameView, LinearLayout callTypesLayout,
- TextView dateView, TextView numberView) {
+ private PhoneCallDetailsViews(TextView nameView, LinearLayout callTypeIcons,
+ TextView callTypeText, View callTypeSeparator, TextView dateView, TextView numberView) {
this.nameView = nameView;
- this.callTypesLayout = callTypesLayout;
+ this.callTypeIcons = callTypeIcons;
+ this.callTypeText = callTypeText;
+ this.callTypeSeparator = callTypeSeparator;
this.dateView = dateView;
this.numberView = numberView;
}
@@ -46,13 +50,17 @@
*/
public static PhoneCallDetailsViews fromView(View view) {
return new PhoneCallDetailsViews((TextView) view.findViewById(R.id.name),
- (LinearLayout) view.findViewById(R.id.call_types),
+ (LinearLayout) view.findViewById(R.id.call_type_icons),
+ (TextView) view.findViewById(R.id.call_type_name),
+ view.findViewById(R.id.call_type_separator),
(TextView) view.findViewById(R.id.date),
(TextView) view.findViewById(R.id.number));
}
public static PhoneCallDetailsViews createForTest(TextView nameView,
- LinearLayout callTypesLayout, TextView dateView, TextView numberView) {
- return new PhoneCallDetailsViews(nameView, callTypesLayout, dateView, numberView);
+ LinearLayout callTypeIcons, TextView callTypeText, View callTypeSeparator,
+ TextView dateView, TextView numberView) {
+ return new PhoneCallDetailsViews(nameView, callTypeIcons, callTypeText, callTypeSeparator,
+ dateView, numberView);
}
}
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 800bfb1..7456967 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -218,7 +218,7 @@
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// First check if the {@link ContactLoaderFragment} can handle the key
- if (mLoaderFragment.handleKeyDown(keyCode)) return true;
+ if (mLoaderFragment != null && mLoaderFragment.handleKeyDown(keyCode)) return true;
// Otherwise find the correct fragment to handle the event
FragmentKeyListener mCurrentFragment;
@@ -232,7 +232,7 @@
default:
throw new IllegalStateException("Invalid current item for ViewPager");
}
- if (mCurrentFragment.handleKeyDown(keyCode)) return true;
+ if (mCurrentFragment != null && mCurrentFragment.handleKeyDown(keyCode)) return true;
// In the last case, give the key event to the superclass.
return super.onKeyDown(keyCode, event);
@@ -323,28 +323,40 @@
mContentView = (ViewGroup) mInflater.inflate(
R.layout.contact_detail_container_with_updates, mRootView, false);
mRootView.addView(mContentView);
+
+ // Make sure all needed views are retrieved. Note that narrow width screens have a
+ // {@link ViewPager} and {@link ContactDetailTabCarousel}, while wide width screens have
+ // a {@link ContactDetailFragmentCarousel}.
+ mViewPager = (ViewPager) findViewById(R.id.pager);
+ if (mViewPager != null) {
+ mViewPager.removeAllViews();
+ mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
+ mViewPager.setOnPageChangeListener(mOnPageChangeListener);
+ }
+
+ mTabCarousel = (ContactDetailTabCarousel) findViewById(R.id.tab_carousel);
+ if (mTabCarousel != null) {
+ mTabCarousel.setListener(mTabCarouselListener);
+ }
+
+ mFragmentCarousel = (ContactDetailFragmentCarousel)
+ findViewById(R.id.fragment_carousel);
}
- // Narrow width screens have a {@link ViewPager} and {@link ContactDetailTabCarousel}
- mViewPager = (ViewPager) findViewById(R.id.pager);
- if (mViewPager != null) {
- mViewPager.removeAllViews();
- mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
- mViewPager.setOnPageChangeListener(mOnPageChangeListener);
- }
-
- mTabCarousel = (ContactDetailTabCarousel) findViewById(R.id.tab_carousel);
+ // Then reset the contact data to the appropriate views
if (mTabCarousel != null) {
- mTabCarousel.setListener(mTabCarouselListener);
mTabCarousel.loadData(mContactData);
}
-
- // Otherwise, wide width screens have a {@link ContactDetailFragmentCarousel}
- mFragmentCarousel = (ContactDetailFragmentCarousel) findViewById(R.id.fragment_carousel);
if (mFragmentCarousel != null) {
if (mDetailFragment != null) mFragmentCarousel.setAboutFragment(mDetailFragment);
if (mUpdatesFragment != null) mFragmentCarousel.setUpdatesFragment(mUpdatesFragment);
}
+ if (mDetailFragment != null) {
+ mDetailFragment.setData(mLookupUri, mContactData);
+ }
+ if (mUpdatesFragment != null) {
+ mUpdatesFragment.setData(mLookupUri, mContactData);
+ }
}
private void setupContactWithoutUpdates() {
@@ -353,6 +365,10 @@
R.layout.contact_detail_container_without_updates, mRootView, false);
mRootView.addView(mContentView);
}
+ // Reset contact data
+ if (mDetailFragment != null) {
+ mDetailFragment.setData(mLookupUri, mContactData);
+ }
}
private final ContactDetailFragment.Listener mFragmentListener =
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index 5dbe87b..e345db7 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -592,16 +592,6 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- final MenuItem callSettingsMenuItem = menu.findItem(R.id.menu_call_settings);
- if (!mInSearchUi) {
- callSettingsMenuItem.setVisible(!mInSearchUi);
- Intent settingsIntent = new Intent(Intent.ACTION_MAIN);
- settingsIntent.setClassName(PHONE_PACKAGE, CALL_SETTINGS_CLASS_NAME);
- callSettingsMenuItem.setIntent(settingsIntent);
- } else {
- callSettingsMenuItem.setVisible(false);
- }
-
final MenuItem searchMenuItem = menu.findItem(R.id.search_on_action_bar);
if (mInSearchUi || getActionBar().getSelectedTab().getPosition() == TAB_INDEX_DIALER) {
searchMenuItem.setVisible(false);
@@ -753,4 +743,11 @@
((ViewPagerVisibilityListener) fragment).onVisibilityChanged(visibility);
}
}
+
+ /** Returns an Intent to launch Call Settings screen */
+ public static Intent getCallSettingsIntent() {
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(PHONE_PACKAGE, CALL_SETTINGS_CLASS_NAME);
+ return intent;
+ }
}
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 3488bed..bf0b256 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -55,6 +55,7 @@
import com.android.contacts.util.AccountSelectionUtil;
import com.android.contacts.util.AccountsListAdapter;
import com.android.contacts.util.DialogManager;
+import com.android.contacts.util.PhoneCapabilityTester;
import com.android.contacts.widget.ContextMenuAdapter;
import android.accounts.Account;
@@ -123,12 +124,6 @@
private boolean mSearchMode;
- /**
- * Whether we have a right-side contact or group detail pane for displaying info on that
- * contact or group while browsing. Generally means "this is a tablet".
- */
- private boolean mContentPaneDisplayed;
-
private ContactDetailFragment mContactDetailFragment;
private ContactDetailUpdatesFragment mContactDetailUpdatesFragment;
private final ContactDetailFragmentListener mContactDetailFragmentListener =
@@ -228,7 +223,6 @@
} else if (fragment instanceof ContactDetailFragment) {
mContactDetailFragment = (ContactDetailFragment) fragment;
mContactDetailFragment.setListener(mContactDetailFragmentListener);
- mContentPaneDisplayed = true;
} else if (fragment instanceof ContactDetailUpdatesFragment) {
mContactDetailUpdatesFragment = (ContactDetailUpdatesFragment) fragment;
} else if (fragment instanceof ContactsUnavailableFragment) {
@@ -239,11 +233,9 @@
} else if (fragment instanceof ContactLoaderFragment) {
mContactDetailLoaderFragment = (ContactLoaderFragment) fragment;
mContactDetailLoaderFragment.setListener(mContactDetailLoaderFragmentListener);
- mContentPaneDisplayed = true;
} else if (fragment instanceof GroupDetailFragment) {
mGroupDetailFragment = (GroupDetailFragment) fragment;
mGroupDetailFragment.setListener(mGroupDetailFragmentListener);
- mContentPaneDisplayed = true;
} else if (fragment instanceof StrequentContactListFragment) {
mFavoritesFragment = (StrequentContactListFragment) fragment;
mFavoritesFragment.setListener(mFavoritesFragmentListener);
@@ -315,7 +307,7 @@
}
if (mRequest.getActionCode() == ContactsRequest.ACTION_VIEW_CONTACT
- && !mContentPaneDisplayed) {
+ && !PhoneCapabilityTester.isUsingTwoPanes(this)) {
redirect = new Intent(this, ContactDetailActivity.class);
redirect.setAction(Intent.ACTION_VIEW);
redirect.setData(mRequest.getContactUri());
@@ -428,7 +420,7 @@
private void setSelectedTab(TabState tab) {
mSelectedTab = tab;
- if (mContentPaneDisplayed) {
+ if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
switch (mSelectedTab) {
case FAVORITES:
mFavoritesView.setVisibility(View.VISIBLE);
@@ -554,7 +546,7 @@
switch (action) {
case START_SEARCH_MODE:
// Checking if multi fragments are being displayed
- if (mContentPaneDisplayed) {
+ if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
mFavoritesView.setVisibility(View.GONE);
mBrowserView.setVisibility(View.VISIBLE);
mDetailsView.setVisibility(View.VISIBLE);
@@ -621,21 +613,23 @@
private void configureContactListFragment() {
mAllFragment.setSearchMode(mSearchMode);
+ final boolean useTwoPane = PhoneCapabilityTester.isUsingTwoPanes(this);
mAllFragment.setVisibleScrollbarEnabled(!mSearchMode);
mAllFragment.setVerticalScrollbarPosition(
- mContentPaneDisplayed
+ useTwoPane
? View.SCROLLBAR_POSITION_LEFT
: View.SCROLLBAR_POSITION_RIGHT);
- mAllFragment.setSelectionVisible(mContentPaneDisplayed);
- mAllFragment.setQuickContactEnabled(!mContentPaneDisplayed);
+ mAllFragment.setSelectionVisible(useTwoPane);
+ mAllFragment.setQuickContactEnabled(!useTwoPane);
}
private void configureGroupListFragment() {
+ final boolean useTwoPane = PhoneCapabilityTester.isUsingTwoPanes(this);
mGroupsFragment.setVerticalScrollbarPosition(
- mContentPaneDisplayed
+ useTwoPane
? View.SCROLLBAR_POSITION_LEFT
: View.SCROLLBAR_POSITION_RIGHT);
- mGroupsFragment.setSelectionVisible(mContentPaneDisplayed);
+ mGroupsFragment.setSelectionVisible(useTwoPane);
}
@Override
@@ -690,14 +684,14 @@
@Override
public void onSelectionChange() {
- if (mContentPaneDisplayed) {
+ if (PhoneCapabilityTester.isUsingTwoPanes(PeopleActivity.this)) {
setupContactDetailFragment(mAllFragment.getSelectedContactUri());
}
}
@Override
public void onViewContactAction(Uri contactLookupUri) {
- if (mContentPaneDisplayed) {
+ if (PhoneCapabilityTester.isUsingTwoPanes(PeopleActivity.this)) {
setupContactDetailFragment(contactLookupUri);
} else {
startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri));
@@ -870,7 +864,7 @@
implements StrequentContactListFragment.Listener {
@Override
public void onContactSelected(Uri contactUri) {
- if (mContentPaneDisplayed) {
+ if (PhoneCapabilityTester.isUsingTwoPanes(PeopleActivity.this)) {
setupContactDetailFragment(contactUri);
} else {
startActivity(new Intent(Intent.ACTION_VIEW, contactUri));
@@ -882,7 +876,7 @@
@Override
public void onViewGroupAction(Uri groupUri) {
- if (mContentPaneDisplayed) {
+ if (PhoneCapabilityTester.isUsingTwoPanes(PeopleActivity.this)) {
setupGroupDetailFragment(groupUri);
} else {
Intent intent = new Intent(PeopleActivity.this, GroupDetailActivity.class);
@@ -1161,7 +1155,7 @@
}
case SUBACTIVITY_EDIT_CONTACT:
case SUBACTIVITY_NEW_CONTACT: {
- if (resultCode == RESULT_OK && mContentPaneDisplayed) {
+ if (resultCode == RESULT_OK && PhoneCapabilityTester.isUsingTwoPanes(this)) {
mRequest.setActionCode(ContactsRequest.ACTION_VIEW_CONTACT);
mAllFragment.reloadDataAndSetSelectedUri(data.getData());
}
@@ -1170,7 +1164,7 @@
case SUBACTIVITY_NEW_GROUP:
case SUBACTIVITY_EDIT_GROUP: {
- if (resultCode == RESULT_OK && mContentPaneDisplayed) {
+ if (resultCode == RESULT_OK && PhoneCapabilityTester.isUsingTwoPanes(this)) {
mRequest.setActionCode(ContactsRequest.ACTION_GROUP);
mGroupsFragment.setSelectedUri(data.getData());
}
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index 84e6a8a..11f8965 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -20,7 +20,10 @@
import com.android.contacts.CallDetailActivity;
import com.android.contacts.ContactPhotoManager;
import com.android.contacts.ContactsUtils;
+import com.android.contacts.PhoneCallDetails;
+import com.android.contacts.PhoneCallDetailsHelper;
import com.android.contacts.R;
+import com.android.contacts.activities.DialtactsActivity;
import com.android.contacts.activities.DialtactsActivity.ViewPagerVisibilityListener;
import com.android.contacts.util.ExpirableCache;
import com.android.internal.telephony.CallerInfo;
@@ -61,13 +64,12 @@
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AdapterView;
-import android.widget.ImageView;
import android.widget.ListView;
import android.widget.QuickContactBadge;
-import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
@@ -92,9 +94,6 @@
Calls.DATE,
Calls.DURATION,
Calls.TYPE,
- Calls.CACHED_NAME,
- Calls.CACHED_NUMBER_TYPE,
- Calls.CACHED_NUMBER_LABEL,
Calls.COUNTRY_ISO};
public static final int ID = 0;
@@ -102,10 +101,7 @@
public static final int DATE = 2;
public static final int DURATION = 3;
public static final int CALL_TYPE = 4;
- public static final int CALLER_NAME = 5;
- public static final int CALLER_NUMBERTYPE = 6;
- public static final int CALLER_NUMBERLABEL = 7;
- public static final int COUNTRY_ISO = 8;
+ public static final int COUNTRY_ISO = 5;
}
/** The query to use for the phones table */
@@ -147,7 +143,7 @@
private String mCurrentCountryIso;
private boolean mScrollToTop;
- private boolean mShowMenu;
+ private boolean mShowOptionsMenu;
public static final class ContactInfo {
public long personId;
@@ -265,23 +261,25 @@
mRequests = new LinkedList<CallerInfoQuery>();
mPreDrawListener = null;
- Drawable drawableIncoming = getResources().getDrawable(
+ Drawable incomingDrawable = getResources().getDrawable(
R.drawable.ic_call_log_list_incoming_call);
- Drawable drawableOutgoing = getResources().getDrawable(
+ Drawable outgoingDrawable = getResources().getDrawable(
R.drawable.ic_call_log_list_outgoing_call);
- Drawable drawableMissed = getResources().getDrawable(
+ Drawable missedDrawable = getResources().getDrawable(
R.drawable.ic_call_log_list_missed_call);
- Drawable drawableVoicemail = getResources().getDrawable(
+ Drawable voicemailDrawable = getResources().getDrawable(
R.drawable.ic_call_log_list_voicemail);
- Drawable drawableCall = getResources().getDrawable(
+ Drawable callDrawable = getResources().getDrawable(
R.drawable.ic_call_log_list_action_call);
- Drawable drawablePlay = getResources().getDrawable(
+ Drawable playDrawable = getResources().getDrawable(
R.drawable.ic_call_log_list_action_play);
mContactPhotoManager = ContactPhotoManager.getInstance(getActivity());
- mCallLogViewsHelper = new CallLogListItemHelper(getResources(), mVoiceMailNumber,
- drawableIncoming, drawableOutgoing, drawableMissed, drawableVoicemail,
- drawableCall, drawablePlay);
+ PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
+ getActivity(), getResources(), mVoiceMailNumber, incomingDrawable,
+ outgoingDrawable, missedDrawable, voicemailDrawable);
+ mCallLogViewsHelper = new CallLogListItemHelper(phoneCallDetailsHelper, callDrawable,
+ playDrawable);
}
/**
@@ -340,32 +338,6 @@
mContactInfoCache.expireAll();
}
- private void updateCallLog(CallerInfoQuery ciq, ContactInfo ci) {
- // Check if they are different. If not, don't update.
- if (TextUtils.equals(ciq.name, ci.name)
- && TextUtils.equals(ciq.numberLabel, ci.label)
- && ciq.numberType == ci.type
- && ciq.photoId == ci.photoId
- && ciq.lookupKey == ci.lookupKey) {
- return;
- }
- ContentValues values = new ContentValues(3);
- values.put(Calls.CACHED_NAME, ci.name);
- values.put(Calls.CACHED_NUMBER_TYPE, ci.type);
- values.put(Calls.CACHED_NUMBER_LABEL, ci.label);
-
- try {
- getActivity().getContentResolver().update(Calls.CONTENT_URI_WITH_VOICEMAIL, values,
- Calls.NUMBER + "='" + ciq.number + "'", null);
- } catch (SQLiteDiskIOException e) {
- Log.w(TAG, "Exception while updating call info", e);
- } catch (SQLiteFullException e) {
- Log.w(TAG, "Exception while updating call info", e);
- } catch (SQLiteDatabaseCorruptException e) {
- Log.w(TAG, "Exception while updating call info", e);
- }
- }
-
private void enqueueRequest(String number, boolean immediate, int position,
String name, int numberType, String numberLabel, long photoId, String lookupKey) {
CallerInfoQuery ciq = new CallerInfoQuery();
@@ -503,9 +475,6 @@
needNotify = true;
}
}
- if (info != null) {
- updateCallLog(ciq, info);
- }
return needNotify;
}
@@ -614,7 +583,7 @@
@VisibleForTesting
@Override
public void bindStandAloneView(View view, Context context, Cursor cursor) {
- bindView(context, view, cursor);
+ bindView(view, cursor, 1);
}
@VisibleForTesting
@@ -630,7 +599,7 @@
@VisibleForTesting
@Override
public void bindChildView(View view, Context context, Cursor cursor) {
- bindView(context, view, cursor);
+ bindView(view, cursor, 1);
}
@VisibleForTesting
@@ -647,42 +616,31 @@
@Override
public void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
boolean expanded) {
- final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
- int groupIndicator = expanded
- ? com.android.internal.R.drawable.expander_ic_maximized
- : com.android.internal.R.drawable.expander_ic_minimized;
- views.groupIndicator.setImageResource(groupIndicator);
- views.groupSize.setText("(" + groupSize + ")");
- bindView(context, view, cursor);
+ bindView(view, cursor, groupSize);
}
private void findAndCacheViews(View view) {
-
- // Get the views to bind to
- CallLogListItemViews views = new CallLogListItemViews();
- views.line1View = (TextView) view.findViewById(R.id.line1);
- views.labelView = (TextView) view.findViewById(R.id.label);
- views.numberView = (TextView) view.findViewById(R.id.number);
- views.dateView = (TextView) view.findViewById(R.id.date);
- views.iconView = (ImageView) view.findViewById(R.id.call_type_icon);
- views.callView = (ImageView) view.findViewById(R.id.call_icon);
+ // Get the views to bind to.
+ CallLogListItemViews views = CallLogListItemViews.fromView(view);
if (views.callView != null) {
views.callView.setOnClickListener(this);
}
- views.groupIndicator = (ImageView) view.findViewById(R.id.groupIndicator);
- views.groupSize = (TextView) view.findViewById(R.id.groupSize);
- views.photoView = (QuickContactBadge) view.findViewById(R.id.contact_photo);
view.setTag(views);
}
- public void bindView(Context context, View view, Cursor c) {
+ /**
+ * Binds the views in the entry to the data in the call log.
+ *
+ * @param view the view corresponding to this entry
+ * @param c the cursor pointing to the entry in the call log
+ * @param count the number of entries in the current item, greater than 1 if it is a group
+ */
+ private void bindView(View view, Cursor c, int count) {
final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
String number = c.getString(CallLogQuery.NUMBER);
- String formattedNumber = null;
- String callerName = c.getString(CallLogQuery.CALLER_NAME);
- int callerNumberType = c.getInt(CallLogQuery.CALLER_NUMBERTYPE);
- String callerNumberLabel = c.getString(CallLogQuery.CALLER_NUMBERLABEL);
+ long date = c.getLong(CallLogQuery.DATE);
+ final String formattedNumber;
String countryIso = c.getString(CallLogQuery.COUNTRY_ISO);
// Store away the number so we can call it directly if you click on the call icon
if (views.callView != null) {
@@ -697,25 +655,14 @@
// Mark it as empty and queue up a request to find the name
// The db request should happen on a non-UI thread
info = ContactInfo.EMPTY;
+ // Format the cached call_log phone number
+ formattedNumber = formatPhoneNumber(number, null, countryIso);
mContactInfoCache.put(number, info);
Log.d(TAG, "Contact info missing: " + number);
// Request the contact details immediately since they are currently missing.
- enqueueRequest(number, true, c.getPosition(),
- callerName, callerNumberType, callerNumberLabel, 0L, "");
+ enqueueRequest(number, true, c.getPosition(), "", 0, "", 0L, "");
} else if (info != ContactInfo.EMPTY) { // Has been queried
- // Check if any data is different from the data cached in the
- // calls db. If so, queue the request so that we can update
- // the calls db.
- if (!TextUtils.equals(info.name, callerName)
- || info.type != callerNumberType
- || !TextUtils.equals(info.label, callerNumberLabel)) {
- // Something is amiss, so sync up.
- Log.w(TAG, "Contact info inconsistent: " + number);
- // Request the contact details immediately since they are probably wrong.
- enqueueRequest(number, true, c.getPosition(),
- callerName, callerNumberType, callerNumberLabel, info.photoId,
- info.lookupKey);
- } else if (cachedInfo.isExpired()) {
+ if (cachedInfo.isExpired()) {
Log.d(TAG, "Contact info expired: " + number);
// Put it back in the cache, therefore marking it as not expired, so that other
// entries with the same number will not re-request it.
@@ -732,6 +679,9 @@
formatPhoneNumber(info.number, info.normalizedNumber, countryIso);
}
formattedNumber = info.formattedNumber;
+ } else {
+ // Format the cached call_log phone number
+ formattedNumber = formatPhoneNumber(number, null, countryIso);
}
long contactId = info.personId;
@@ -740,36 +690,21 @@
String label = info.label;
long photoId = info.photoId;
String lookupKey = info.lookupKey;
- // If there's no name cached in our hashmap, but there's one in the
- // calls db, use the one in the calls db. Otherwise the name in our
- // hashmap is more recent, so it has precedence.
- if (TextUtils.isEmpty(name) && !TextUtils.isEmpty(callerName)) {
- name = callerName;
- ntype = callerNumberType;
- label = callerNumberLabel;
-
- // Format the cached call_log phone number
- formattedNumber = formatPhoneNumber(number, null, countryIso);
- }
-
// Assumes the call back feature is on most of the
// time. For private and unknown numbers: hide it.
if (views.callView != null) {
views.callView.setVisibility(View.VISIBLE);
}
- if (!TextUtils.isEmpty(name)) {
- mCallLogViewsHelper.setContactNameLabelAndNumber(views, name, number, ntype, label,
- formattedNumber);
+ int[] callTypes = getCallTypes(c, count);
+ final PhoneCallDetails details;
+ if (TextUtils.isEmpty(name)) {
+ details = new PhoneCallDetails(number, formattedNumber, callTypes, date);
} else {
- // TODO: Do we need to format the number again? Is formattedNumber already storing
- // this value?
- mCallLogViewsHelper.setContactNumberOnly(views, number,
- formatPhoneNumber(number, null, countryIso));
+ details = new PhoneCallDetails(number, formattedNumber, callTypes, date, name,
+ ntype, label);
}
- mCallLogViewsHelper.setDate(views, c.getLong(CallLogQuery.DATE),
- System.currentTimeMillis());
- mCallLogViewsHelper.setCallType(views, c.getInt(CallLogQuery.CALL_TYPE));
+ mCallLogViewsHelper.setPhoneCallDetails(views, details , true);
if (views.photoView != null) {
bindQuickContact(views.photoView, photoId, contactId, lookupKey);
}
@@ -783,6 +718,24 @@
}
}
+ /**
+ * Returns the call types for the given number of items in the cursor.
+ * <p>
+ * It uses the next {@code count} rows in the cursor to extract the types.
+ * <p>
+ * It position in the cursor is unchanged by this function.
+ */
+ private int[] getCallTypes(Cursor cursor, int count) {
+ int position = cursor.getPosition();
+ int[] callTypes = new int[count];
+ for (int index = 0; index < count; ++index) {
+ callTypes[index] = cursor.getInt(CallLogQuery.CALL_TYPE);
+ cursor.moveToNext();
+ }
+ cursor.moveToPosition(position);
+ return callTypes;
+ }
+
private void bindQuickContact(QuickContactBadge view, long photoId, long contactId,
String lookupKey) {
view.assignContactUri(getContactUri(contactId, lookupKey));
@@ -802,6 +755,10 @@
public void disableRequestProcessingForTest() {
mRequestProcessingDisabled = true;
}
+
+ public void injectContactInfoForTest(String number, ContactInfo contactInfo) {
+ mContactInfoCache.put(number, contactInfo);
+ }
}
private static final class QueryHandler extends AsyncQueryHandler {
@@ -981,7 +938,14 @@
@Override
public void onPrepareOptionsMenu(Menu menu) {
- menu.findItem(R.id.delete_all).setVisible(mShowMenu);
+ menu.findItem(R.id.delete_all).setVisible(mShowOptionsMenu);
+ final MenuItem callSettingsMenuItem = menu.findItem(R.id.menu_call_settings_call_log);
+ if (mShowOptionsMenu) {
+ callSettingsMenuItem.setVisible(true);
+ callSettingsMenuItem.setIntent(DialtactsActivity.getCallSettingsIntent());
+ } else {
+ callSettingsMenuItem.setVisible(false);
+ }
}
@Override
@@ -1216,6 +1180,6 @@
@Override
public void onVisibilityChanged(boolean visible) {
- mShowMenu = visible;
+ mShowOptionsMenu = visible;
}
}
diff --git a/src/com/android/contacts/calllog/CallLogListItemHelper.java b/src/com/android/contacts/calllog/CallLogListItemHelper.java
index 56399c0..e4630e9 100644
--- a/src/com/android/contacts/calllog/CallLogListItemHelper.java
+++ b/src/com/android/contacts/calllog/CallLogListItemHelper.java
@@ -16,220 +16,64 @@
package com.android.contacts.calllog;
-import com.android.contacts.R;
+import com.android.contacts.PhoneCallDetails;
+import com.android.contacts.PhoneCallDetailsHelper;
import com.android.internal.telephony.CallerInfo;
-import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.provider.CallLog.Calls;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
-import android.text.format.DateUtils;
import android.view.View;
-import android.view.ViewGroup;
/**
* Helper class to fill in the views of a call log entry.
*/
/*package*/ class CallLogListItemHelper {
- /** The resources used to look up strings. */
- private final Resources mResources;
- /** The voicemail number. */
- private final String mVoiceMailNumber;
- /** Icon for incoming calls. */
- private final Drawable mDrawableIncoming;
- /** Icon for outgoing calls. */
- private final Drawable mDrawableOutgoing;
- /** Icon for missed calls. */
- private final Drawable mDrawableMissed;
- /** Icon for voicemails. */
- private final Drawable mDrawableVoicemail;
+ /** Helper for populating the details of a phone call. */
+ private final PhoneCallDetailsHelper mPhoneCallDetailsHelper;
/** Icon for the call action. */
- private final Drawable mDrawableCall;
+ private final Drawable mCallDrawable;
/** Icon for the play action. */
- private final Drawable mDrawablePlay;
+ private final Drawable mPlayDrawable;
/**
* Creates a new helper instance.
*
- * @param resources used to look up strings
- * @param voicemailNumber the voicemail number, used to determine if a call was to voicemail
- * @param drawableIncoming the icon drawn besides an incoming call entry
- * @param drawableOutgoing the icon drawn besides an outgoing call entry
- * @param drawableMissed the icon drawn besides a missed call entry
+ * @param phoneCallDetailsHelper used to set the details of a phone call
+ * @param callDrawable used to render the call button, for calling back a person
+ * @param playDrawable used to render the play button, for playing a voicemail
*/
- public CallLogListItemHelper(Resources resources, String voicemailNumber,
- Drawable drawableIncoming, Drawable drawableOutgoing, Drawable drawableMissed,
- Drawable drawableVoicemail, Drawable drawableCall, Drawable drawablePlay) {
- mResources = resources;
- mVoiceMailNumber = voicemailNumber;
- mDrawableIncoming = drawableIncoming;
- mDrawableOutgoing = drawableOutgoing;
- mDrawableMissed = drawableMissed;
- mDrawableVoicemail = drawableVoicemail;
- mDrawableCall = drawableCall;
- mDrawablePlay = drawablePlay;
+ public CallLogListItemHelper(PhoneCallDetailsHelper phoneCallDetailsHelper,
+ Drawable callDrawable, Drawable playDrawable) {
+ mPhoneCallDetailsHelper = phoneCallDetailsHelper;
+ mCallDrawable = callDrawable;
+ mPlayDrawable = playDrawable;
}
/**
* Sets the name, label, and number for a contact.
*
* @param views the views to populate
- * @param name the name of the contact
- * @param number the number of the contact
- * @param numberType the type of the number as it appears in the contact, e.g.,
- * {@link Phone#TYPE_HOME}
- * @param label the label of the number, only used if numberType is {@link Phone#TYPE_CUSTOM}
- * @param formattedNumber the formatted version of the number above
+ * @param details the details of a phone call needed to fill in the data
+ * @param useIcons whether to use icons to show the type of the call
*/
- public void setContactNameLabelAndNumber(CallLogListItemViews views, String name, String number,
- int numberType, String label, String formattedNumber) {
- views.line1View.setText(name);
- views.labelView.setVisibility(View.VISIBLE);
-
- // "type" and "label" are currently unused for SIP addresses.
- CharSequence numberLabel = null;
- if (!PhoneNumberUtils.isUriNumber(number)) {
- numberLabel = Phone.getTypeLabel(mResources, numberType, label);
- }
- views.numberView.setVisibility(View.VISIBLE);
- views.numberView.setText(formattedNumber);
- if (!TextUtils.isEmpty(numberLabel)) {
- views.labelView.setText(numberLabel);
- views.labelView.setVisibility(View.VISIBLE);
-
- // Zero out the numberView's left margin (see below)
- ViewGroup.MarginLayoutParams numberLP =
- (ViewGroup.MarginLayoutParams) views.numberView.getLayoutParams();
- numberLP.leftMargin = 0;
- views.numberView.setLayoutParams(numberLP);
- } else {
- // There's nothing to display in views.labelView, so hide it.
- // We can't set it to View.GONE, since it's the anchor for
- // numberView in the RelativeLayout, so make it INVISIBLE.
- // Also, we need to manually *subtract* some left margin from
- // numberView to compensate for the right margin built in to
- // labelView (otherwise the number will be indented by a very
- // slight amount).
- // TODO: a cleaner fix would be to contain both the label and
- // number inside a LinearLayout, and then set labelView *and*
- // its padding to GONE when there's no label to display.
- views.labelView.setText(null);
- views.labelView.setVisibility(View.INVISIBLE);
-
- ViewGroup.MarginLayoutParams labelLP =
- (ViewGroup.MarginLayoutParams) views.labelView.getLayoutParams();
- ViewGroup.MarginLayoutParams numberLP =
- (ViewGroup.MarginLayoutParams) views.numberView.getLayoutParams();
- // Equivalent to setting android:layout_marginLeft in XML
- numberLP.leftMargin = -labelLP.rightMargin;
- views.numberView.setLayoutParams(numberLP);
- }
- }
-
- /**
- * Sets the number in a call log entry.
- * <p>
- * To be used if we do not have a contact with this number.
- *
- * @param views the views to populate
- * @param number the number of the contact
- * @param formattedNumber the formatted version of the number above
- */
- public void setContactNumberOnly(final CallLogListItemViews views, String number,
- String formattedNumber) {
- if (number.equals(CallerInfo.UNKNOWN_NUMBER)) {
- number = mResources.getString(R.string.unknown);
- if (views.callView != null) {
- views.callView.setVisibility(View.INVISIBLE);
- }
- } else if (number.equals(CallerInfo.PRIVATE_NUMBER)) {
- number = mResources.getString(R.string.private_num);
- if (views.callView != null) {
- views.callView.setVisibility(View.INVISIBLE);
- }
- } else if (number.equals(CallerInfo.PAYPHONE_NUMBER)) {
- number = mResources.getString(R.string.payphone);
- if (views.callView != null) {
- views.callView.setVisibility(View.INVISIBLE);
- }
- } else if (PhoneNumberUtils.extractNetworkPortion(number)
- .equals(mVoiceMailNumber)) {
- number = mResources.getString(R.string.voicemail);
- } else {
- // Just a phone number, so use the formatted version of the number.
- number = formattedNumber;
- }
-
- views.line1View.setText(number);
- views.numberView.setVisibility(View.GONE);
- views.labelView.setVisibility(View.GONE);
- }
-
- /**
- * Sets the date in the views.
- *
- * @param views the views to populate
- * @param date the date of the call log entry
- * @param now the current time relative to which the date should be formatted
- */
- public void setDate(final CallLogListItemViews views, long date, long now) {
- views.dateView.setText(
- DateUtils.getRelativeTimeSpanString(
- date, now, DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE));
- }
-
- /**
- * Sets the type of the call in the views.
- *
- * @param views the views to populate
- * @param type the type of call log entry, e.g., {@link Calls#INCOMING_TYPE}
- */
- public void setCallType(final CallLogListItemViews views, int type) {
- if (views.iconView != null) {
- // Set the call type icon.
- Drawable drawable = null;
- switch (type) {
- case Calls.INCOMING_TYPE:
- drawable = mDrawableIncoming;
- break;
-
- case Calls.OUTGOING_TYPE:
- drawable = mDrawableOutgoing;
- break;
-
- case Calls.MISSED_TYPE:
- drawable = mDrawableMissed;
- break;
-
- case Calls.VOICEMAIL_TYPE:
- drawable = mDrawableVoicemail;
- break;
-
- default:
- throw new IllegalArgumentException("invalid call type: " + type);
- }
- views.iconView.setImageDrawable(drawable);
- }
+ public void setPhoneCallDetails(CallLogListItemViews views, PhoneCallDetails details,
+ boolean useIcons) {
+ mPhoneCallDetailsHelper.setPhoneCallDetails(views.phoneCallDetailsViews, details, useIcons);
if (views.callView != null) {
- // Set the action icon.
- Drawable drawable = null;
- switch (type) {
- case Calls.INCOMING_TYPE:
- case Calls.OUTGOING_TYPE:
- case Calls.MISSED_TYPE:
- drawable = mDrawableCall;
- break;
-
- case Calls.VOICEMAIL_TYPE:
- drawable = mDrawablePlay;
- break;
-
- default:
- throw new IllegalArgumentException("invalid call type: " + type);
- }
- views.callView.setImageDrawable(drawable);
+ // The type of icon, call or play, is determined by the first call in the group.
+ views.callView.setImageDrawable(
+ details.callTypes[0] == Calls.VOICEMAIL_TYPE ? mPlayDrawable : mCallDrawable);
+ views.callView.setVisibility(
+ canPlaceCallsTo(details.number) ? View.VISIBLE : View.INVISIBLE);
}
}
+
+ /** Returns true if it is possible to place a call to the given number. */
+ public boolean canPlaceCallsTo(CharSequence number) {
+ return !(TextUtils.isEmpty(number)
+ || number.equals(CallerInfo.UNKNOWN_NUMBER)
+ || number.equals(CallerInfo.PRIVATE_NUMBER)
+ || number.equals(CallerInfo.PAYPHONE_NUMBER));
+ }
}
diff --git a/src/com/android/contacts/calllog/CallLogListItemViews.java b/src/com/android/contacts/calllog/CallLogListItemViews.java
index 7264c96..0cf15cc 100644
--- a/src/com/android/contacts/calllog/CallLogListItemViews.java
+++ b/src/com/android/contacts/calllog/CallLogListItemViews.java
@@ -16,37 +16,39 @@
package com.android.contacts.calllog;
+import com.android.contacts.PhoneCallDetailsViews;
+import com.android.contacts.R;
+
+import android.view.View;
import android.widget.ImageView;
import android.widget.QuickContactBadge;
-import android.widget.TextView;
/**
* Simple value object containing the various views within a call log entry.
*/
public final class CallLogListItemViews {
- /** The first line in the call log entry, containing either the name or the number. */
- public TextView line1View;
- /** The label associated with the phone number. */
- public TextView labelView;
- /**
- * The number the call was from or to.
- * <p>
- * Only filled in if the number is not already in the first line, i.e., {@link #line1View}.
- */
- public TextView numberView;
- /** The date of the call. */
- public TextView dateView;
- /** The icon indicating the type of call. */
- public ImageView iconView;
- /** The icon used to place a call to the contact. Only present for non-group entries. */
- public ImageView callView;
- /** The icon used to expand and collapse an entry. Only present for group entries. */
- public ImageView groupIndicator;
- /**
- * The text view containing the number of items in the group. Only present for group
- * entries.
- */
- public TextView groupSize;
/** The quick contact badge for the contact. Only present for group and stand alone entries. */
- public QuickContactBadge photoView;
+ public final QuickContactBadge photoView;
+ /** The main action button on the entry. */
+ public final ImageView callView;
+ /** The details of the phone call. */
+ public final PhoneCallDetailsViews phoneCallDetailsViews;
+
+ private CallLogListItemViews(QuickContactBadge photoView, ImageView callView,
+ PhoneCallDetailsViews phoneCallDetailsViews) {
+ this.photoView = photoView;
+ this.callView = callView;
+ this.phoneCallDetailsViews = phoneCallDetailsViews;
+ }
+
+ public static CallLogListItemViews fromView(View view) {
+ return new CallLogListItemViews((QuickContactBadge) view.findViewById(R.id.contact_photo),
+ (ImageView) view.findViewById(R.id.call_icon),
+ PhoneCallDetailsViews.fromView(view));
+ }
+
+ public static CallLogListItemViews createForTest(QuickContactBadge photoView,
+ ImageView callView, PhoneCallDetailsViews phoneCallDetailsViews) {
+ return new CallLogListItemViews(photoView, callView, phoneCallDetailsViews);
+ }
}
diff --git a/src/com/android/contacts/dialpad/DialpadFragment.java b/src/com/android/contacts/dialpad/DialpadFragment.java
index af706b8..be873c6 100644
--- a/src/com/android/contacts/dialpad/DialpadFragment.java
+++ b/src/com/android/contacts/dialpad/DialpadFragment.java
@@ -24,7 +24,6 @@
import com.android.internal.telephony.ITelephony;
import com.android.phone.CallLogAsync;
import com.android.phone.HapticFeedback;
-import com.google.i18n.phonenumbers.PhoneNumberUtil;
import android.app.Activity;
import android.app.Fragment;
@@ -62,12 +61,14 @@
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
+import android.widget.PopupMenu;
import android.widget.TextView;
/**
@@ -77,6 +78,7 @@
implements View.OnClickListener,
View.OnLongClickListener, View.OnKeyListener,
AdapterView.OnItemClickListener, TextWatcher,
+ PopupMenu.OnMenuItemClickListener,
ViewPagerVisibilityListener {
private static final String TAG = DialpadFragment.class.getSimpleName();
@@ -111,7 +113,7 @@
private ListView mDialpadChooser;
private DialpadChooserAdapter mDialpadChooserAdapter;
- private boolean mShowMenu;
+ private boolean mShowOptionsMenu;
private boolean mHasVoicemail = false;
@@ -266,6 +268,16 @@
mDigits.addTextChangedListener(mTextWatcher);
}
+ // Soft menu button should appear only when there's no hardware menu button.
+ final View overflowMenuButton = fragmentView.findViewById(R.id.overflow_menu);
+ if (overflowMenuButton != null) {
+ if (ViewConfiguration.get(getActivity()).hasPermanentMenuKey()) {
+ overflowMenuButton.setVisibility(View.GONE);
+ } else {
+ overflowMenuButton.setOnClickListener(this);
+ }
+ }
+
// Check for the presence of the keypad
View oneButton = fragmentView.findViewById(R.id.one);
if (oneButton != null) {
@@ -535,35 +547,51 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
- inflater.inflate(R.menu.dialpad_options, menu);
+
+ // If the hardware doesn't have a hardware menu key, we'll show soft menu button on the
+ // right side of digits EditText.
+ if (ViewConfiguration.get(getActivity()).hasPermanentMenuKey()) {
+ inflater.inflate(R.menu.dialpad_options, menu);
+ }
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
- if (mDialpadChooser == null || mDigits == null) {
- // The layout itself isn't ready yet. Let's ignore this call.
- return;
+ // Hardware menu key should be available and Views should already be ready.
+ if (ViewConfiguration.get(getActivity()).hasPermanentMenuKey() &&
+ mDialpadChooser != null && mDigits != null) {
+ if (mShowOptionsMenu) {
+ setupMenuItems(menu);
+ } else {
+ menu.findItem(R.id.menu_call_settings_dialpad).setVisible(false);
+ menu.findItem(R.id.menu_add_contacts).setVisible(false);
+ menu.findItem(R.id.menu_2s_pause).setVisible(false);
+ menu.findItem(R.id.menu_add_wait).setVisible(false);
+ }
}
+ }
+ private void setupMenuItems(Menu menu) {
+ final MenuItem callSettingsMenuItem = menu.findItem(R.id.menu_call_settings_dialpad);
final MenuItem addToContactMenuItem = menu.findItem(R.id.menu_add_contacts);
- final MenuItem m2SecPauseMenuItem = menu.findItem(R.id.menu_2s_pause);
- final MenuItem mWaitMenuItem = menu.findItem(R.id.menu_add_wait);
+ final MenuItem twoSecPauseMenuItem = menu.findItem(R.id.menu_2s_pause);
+ final MenuItem waitMenuItem = menu.findItem(R.id.menu_add_wait);
+
+ callSettingsMenuItem.setVisible(true);
+ callSettingsMenuItem.setIntent(DialtactsActivity.getCallSettingsIntent());
// We show "add to contacts", "2sec pause", and "add wait" menus only when the user is
// seeing usual dialpads and has typed at least one digit.
// We never show a menu if the "choose dialpad" UI is up.
- if (!mShowMenu || dialpadChooserVisible() || isDigitsEmpty()) {
+ if (dialpadChooserVisible() || isDigitsEmpty()) {
addToContactMenuItem.setVisible(false);
- m2SecPauseMenuItem.setVisible(false);
- mWaitMenuItem.setVisible(false);
+ twoSecPauseMenuItem.setVisible(false);
+ waitMenuItem.setVisible(false);
} else {
- CharSequence digits = mDigits.getText();
+ final CharSequence digits = mDigits.getText();
// Put the current digits string into an intent
- Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.putExtra(Insert.PHONE, digits);
- intent.setType(People.CONTENT_ITEM_TYPE);
- addToContactMenuItem.setIntent(intent);
+ addToContactMenuItem.setIntent(getAddToContactIntent(digits));
addToContactMenuItem.setVisible(true);
// Check out whether to show Pause & Wait option menu items
@@ -584,25 +612,32 @@
if (selectionStart != 0) {
// Pause can be visible if cursor is not in the begining
- m2SecPauseMenuItem.setVisible(true);
+ twoSecPauseMenuItem.setVisible(true);
// For Wait to be visible set of condition to meet
- mWaitMenuItem.setVisible(showWait(selectionStart,
- selectionEnd, strDigits));
+ waitMenuItem.setVisible(showWait(selectionStart, selectionEnd, strDigits));
} else {
// cursor in the beginning both pause and wait to be invisible
- m2SecPauseMenuItem.setVisible(false);
- mWaitMenuItem.setVisible(false);
+ twoSecPauseMenuItem.setVisible(false);
+ waitMenuItem.setVisible(false);
}
} else {
+ twoSecPauseMenuItem.setVisible(true);
+
// cursor is not selected so assume new digit is added to the end
int strLength = strDigits.length();
- mWaitMenuItem.setVisible(showWait(strLength,
- strLength, strDigits));
+ waitMenuItem.setVisible(showWait(strLength, strLength, strDigits));
}
}
}
+ private static Intent getAddToContactIntent(CharSequence digits) {
+ final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ intent.putExtra(Insert.PHONE, digits);
+ intent.setType(People.CONTENT_ITEM_TYPE);
+ return intent;
+ }
+
private void keyPressed(int keyCode) {
mHaptic.vibrate();
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
@@ -706,9 +741,28 @@
}
return;
}
+ case R.id.overflow_menu: {
+ PopupMenu popup = constructPopupMenu(view);
+ if (popup != null) {
+ popup.show();
+ }
+ }
}
}
+ private PopupMenu constructPopupMenu(View anchorView) {
+ final Context context = getActivity();
+ if (context == null) {
+ return null;
+ }
+ final PopupMenu popupMenu = new PopupMenu(context, anchorView);
+ final Menu menu = popupMenu.getMenu();
+ popupMenu.inflate(R.menu.dialpad_options);
+ popupMenu.setOnMenuItemClickListener(this);
+ setupMenuItems(menu);
+ return popupMenu;
+ }
+
public boolean onLongClick(View view) {
final Editable digits = mDigits.getText();
int id = view.getId();
@@ -1091,6 +1145,11 @@
return false;
}
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ return onOptionsItemSelected(item);
+ }
+
/**
* Updates the dial string (mDigits) after inserting a Pause character (,)
* or Wait character (;).
@@ -1163,7 +1222,7 @@
* otherwise returns false. Assumes the passed string is non-empty
* and the 0th index check is not required.
*/
- private boolean showWait(int start, int end, String digits) {
+ private static boolean showWait(int start, int end, String digits) {
if (start == end) {
// visible false in this case
if (start > digits.length()) return false;
@@ -1241,6 +1300,6 @@
@Override
public void onVisibilityChanged(boolean visible) {
- mShowMenu = visible;
+ mShowOptionsMenu = visible;
}
}
diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java
index 4443a53..0b53acf 100644
--- a/src/com/android/contacts/group/GroupBrowseListFragment.java
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -32,6 +32,7 @@
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Parcelable;
import android.provider.ContactsContract.Groups;
import android.text.TextUtils;
import android.view.LayoutInflater;
@@ -229,6 +230,7 @@
mAdapter.setSelectionVisible(mSelectionVisible);
mAdapter.setSelectedGroup(mSelectedGroupUri);
+ Parcelable listState = mListView.onSaveInstanceState();
mListView.setAdapter(mAdapter);
mListView.setEmptyView(mEmptyView);
mListView.setOnItemClickListener(new OnItemClickListener() {
@@ -241,6 +243,9 @@
if (mSelectionToScreenRequested) {
requestSelectionToScreen();
+ } else {
+ // Restore the scroll position.
+ mListView.onRestoreInstanceState(listState);
}
if (mSelectionVisible && mSelectedGroupUri != null) {
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
index 5c02959..353c2ec 100644
--- a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -25,6 +25,7 @@
import android.graphics.drawable.Drawable;
import android.provider.CallLog.Calls;
import android.test.AndroidTestCase;
+import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -41,7 +42,9 @@
/** The date of the call log entry. */
private static final long TEST_DATE = 1300000000;
/** The number of the caller/callee in the log entry. */
- private static final String TEST_NUMBER = "1-412-555-5555";
+ private static final String TEST_NUMBER = "14125555555";
+ /** The formatted version of {@link #TEST_NUMBER}. */
+ private static final String TEST_FORMATTED_NUMBER = "1-412-255-5555";
/** A drawable to be used for incoming calls. */
private static final Drawable TEST_INCOMING_DRAWABLE = new ColorDrawable(Color.BLACK);
/** A drawable to be used for outgoing calls. */
@@ -64,7 +67,8 @@
TEST_VOICEMAIL_NUMBER, TEST_INCOMING_DRAWABLE, TEST_OUTGOING_DRAWABLE,
TEST_MISSED_DRAWABLE, TEST_VOICEMAIL_DRAWABLE);
mViews = PhoneCallDetailsViews.createForTest(new TextView(context),
- new LinearLayout(context), new TextView(context), new TextView(context));
+ new LinearLayout(context), new TextView(context), new View(context),
+ new TextView(context), new TextView(context));
}
@Override
@@ -75,27 +79,27 @@
}
public void testSetPhoneCallDetails_Unknown() {
- setPhoneCallDetailsWithNumber(CallerInfo.UNKNOWN_NUMBER);
+ setPhoneCallDetailsWithNumber(CallerInfo.UNKNOWN_NUMBER, CallerInfo.UNKNOWN_NUMBER);
assertNameEqualsResource(R.string.unknown);
}
public void testSetPhoneCallDetails_Private() {
- setPhoneCallDetailsWithNumber(CallerInfo.PRIVATE_NUMBER);
+ setPhoneCallDetailsWithNumber(CallerInfo.PRIVATE_NUMBER, CallerInfo.PRIVATE_NUMBER);
assertNameEqualsResource(R.string.private_num);
}
public void testSetPhoneCallDetails_Payphone() {
- setPhoneCallDetailsWithNumber(CallerInfo.PAYPHONE_NUMBER);
+ setPhoneCallDetailsWithNumber(CallerInfo.PAYPHONE_NUMBER, CallerInfo.PAYPHONE_NUMBER);
assertNameEqualsResource(R.string.payphone);
}
public void testSetPhoneCallDetails_Voicemail() {
- setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER);
+ setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, TEST_VOICEMAIL_NUMBER);
assertNameEqualsResource(R.string.voicemail);
}
public void testSetPhoneCallDetails_Normal() {
- setPhoneCallDetailsWithNumber("1-412-555-1212");
+ setPhoneCallDetailsWithNumber("14125551212", "1-412-555-1212");
assertNameEquals("1-412-555-1212");
}
@@ -126,20 +130,40 @@
}
}
- public void testSetPhoneCallDetails_CallType() {
- setPhoneCallDetailsWithCallType(Calls.INCOMING_TYPE);
+ public void testSetPhoneCallDetails_CallTypeIcons() {
+ setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE);
assertCallTypeIconsEquals(TEST_INCOMING_DRAWABLE);
- setPhoneCallDetailsWithCallType(Calls.OUTGOING_TYPE);
+ setPhoneCallDetailsWithCallTypeIcons(Calls.OUTGOING_TYPE);
assertCallTypeIconsEquals(TEST_OUTGOING_DRAWABLE);
- setPhoneCallDetailsWithCallType(Calls.MISSED_TYPE);
+ setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE);
assertCallTypeIconsEquals(TEST_MISSED_DRAWABLE);
- setPhoneCallDetailsWithCallType(Calls.VOICEMAIL_TYPE);
+ setPhoneCallDetailsWithCallTypeIcons(Calls.VOICEMAIL_TYPE);
assertCallTypeIconsEquals(TEST_VOICEMAIL_DRAWABLE);
}
+ public void testSetPhoneCallDetails_CallTypeText() {
+ LocaleTestUtils localeTestUtils = new LocaleTestUtils(getContext());
+ localeTestUtils.setLocale(Locale.US);
+ try {
+ setPhoneCallDetailsWithCallTypeText(Calls.INCOMING_TYPE);
+ assertCallTypeTextEquals("Incoming call");
+
+ setPhoneCallDetailsWithCallTypeText(Calls.OUTGOING_TYPE);
+ assertCallTypeTextEquals("Outgoing call");
+
+ setPhoneCallDetailsWithCallTypeText(Calls.MISSED_TYPE);
+ assertCallTypeTextEquals("Missed call");
+
+ setPhoneCallDetailsWithCallTypeText(Calls.VOICEMAIL_TYPE);
+ assertCallTypeTextEquals("Voicemail");
+ } finally {
+ localeTestUtils.restoreLocale();
+ }
+ }
+
/** Asserts that the name text field contains the value of the given string resource. */
private void assertNameEqualsResource(int resId) {
assertNameEquals(getContext().getString(resId));
@@ -155,28 +179,56 @@
assertEquals(text, mViews.dateView.getText().toString());
}
- /** Asserts that the call type linear layout contains the images with the given drawables. */
+ /** Asserts that the call type contains the images with the given drawables. */
private void assertCallTypeIconsEquals(Drawable... drawables) {
- assertEquals(drawables.length, mViews.callTypesLayout.getChildCount());
+ assertEquals(drawables.length, mViews.callTypeIcons.getChildCount());
for (int index = 0; index < drawables.length; ++index) {
Drawable drawable = drawables[index];
- ImageView imageView = (ImageView) mViews.callTypesLayout.getChildAt(index);
+ ImageView imageView = (ImageView) mViews.callTypeIcons.getChildAt(index);
assertEquals(drawable, imageView.getDrawable());
}
+ assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility());
+ assertEquals(View.GONE, mViews.callTypeText.getVisibility());
+ assertEquals(View.GONE, mViews.callTypeSeparator.getVisibility());
+ }
+
+ /** Asserts that the call type contains the given text. */
+ private void assertCallTypeTextEquals(String text) {
+ assertEquals(text, mViews.callTypeText.getText().toString());
+ assertEquals(View.GONE, mViews.callTypeIcons.getVisibility());
+ assertEquals(View.VISIBLE, mViews.callTypeText.getVisibility());
+ assertEquals(View.VISIBLE, mViews.callTypeSeparator.getVisibility());
}
/** Sets the phone call details with default values and the given number. */
- private void setPhoneCallDetailsWithNumber(String number) {
- mHelper.setPhoneCallDetails(mViews, TEST_DATE, Calls.INCOMING_TYPE, "", number, 0, "");
+ private void setPhoneCallDetailsWithNumber(String number, String formattedNumber) {
+ mHelper.setPhoneCallDetails(mViews,
+ new PhoneCallDetails(number, formattedNumber, new int[]{ Calls.INCOMING_TYPE },
+ TEST_DATE),
+ false);
}
/** Sets the phone call details with default values and the given date. */
private void setPhoneCallDetailsWithDate(long date) {
- mHelper.setPhoneCallDetails(mViews, date, Calls.INCOMING_TYPE, "", TEST_NUMBER, 0, "");
+ mHelper.setPhoneCallDetails(mViews,
+ new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER,
+ new int[]{ Calls.INCOMING_TYPE }, date),
+ false);
}
- /** Sets the phone call details with default values and the given call type. */
- private void setPhoneCallDetailsWithCallType(int callType) {
- mHelper.setPhoneCallDetails(mViews, TEST_DATE, callType, "", TEST_NUMBER, 0, "");
+ /** Sets the phone call details with default values and the given call types using icons. */
+ private void setPhoneCallDetailsWithCallTypeIcons(int... callTypes) {
+ setPhoneCallDetailsWithCallTypes(true, callTypes);
+ }
+
+ /** Sets the phone call details with default values and the given call types using text. */
+ private void setPhoneCallDetailsWithCallTypeText(int... callTypes) {
+ setPhoneCallDetailsWithCallTypes(false, callTypes);
+ }
+
+ private void setPhoneCallDetailsWithCallTypes(boolean useIcons, int... callTypes) {
+ mHelper.setPhoneCallDetails(mViews,
+ new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, callTypes, TEST_DATE),
+ useIcons);
}
}
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
index 6421a9e..8db291d 100644
--- a/tests/src/com/android/contacts/activities/CallLogActivityTests.java
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -18,6 +18,7 @@
import com.android.contacts.R;
import com.android.contacts.calllog.CallLogFragment;
+import com.android.contacts.calllog.CallLogFragment.ContactInfo;
import com.android.contacts.calllog.CallLogListItemViews;
import com.android.internal.telephony.CallerInfo;
@@ -27,6 +28,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.telephony.PhoneNumberUtils;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
@@ -51,25 +53,31 @@
@LargeTest
public class CallLogActivityTests
extends ActivityInstrumentationTestCase2<CallLogActivity> {
- static private final String TAG = "CallLogActivityTests";
- static private final String[] CALL_LOG_PROJECTION = new String[] {
+ private static final String TAG = "CallLogActivityTests";
+
+ private static final String[] CALL_LOG_PROJECTION = new String[] {
Calls._ID,
Calls.NUMBER,
Calls.DATE,
Calls.DURATION,
Calls.TYPE,
- Calls.CACHED_NAME,
- Calls.CACHED_NUMBER_TYPE,
- Calls.CACHED_NUMBER_LABEL,
Calls.COUNTRY_ISO,
};
- static private final int RAND_DURATION = -1;
- static private final long NOW = -1L;
+ private static final int RAND_DURATION = -1;
+ private static final long NOW = -1L;
+ /** A test value for the person id of a contact. */
+ private static final long TEST_PERSON_ID = 1;
+ /** A test value for the photo id of a contact. */
+ private static final long TEST_PHOTO_ID = 2;
+ /** A test value for the lookup key for contacts. */
+ private static final String TEST_LOOKUP_KEY = "contact_id";
+ /** A test value for the country ISO of the phone number in the call log. */
+ private static final String TEST_COUNTRY_ISO = "US";
/** A phone number to be used in tests. */
- private static final String TEST_PHONE_NUMBER = "12125551000";
- /** The formatted version of {@link #TEST_PHONE_NUMBER}. */
- private static final String TEST_FORMATTED_PHONE_NUMBER = "1 212-555-1000";
+ private static final String TEST_NUMBER = "12125551000";
+ /** The formatted version of {@link #TEST_NUMBER}. */
+ private static final String TEST_FORMATTED_NUMBER = "1 212-555-1000";
// We get the call list activity and assign is a frame to build
// its list. mAdapter is an inner class of
@@ -185,28 +193,26 @@
@MediumTest
public void testBindView_NumberOnly() {
mCursor.moveToFirst();
- insert(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+ insert(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
View view = mAdapter.newStandAloneView(getActivity(), mParentView);
mAdapter.bindStandAloneView(view, getActivity(), mCursor);
CallLogListItemViews views = (CallLogListItemViews) view.getTag();
- assertNameIs(views, TEST_FORMATTED_PHONE_NUMBER);
- assertNumberLabelIsGone(views);
- assertNumberIsGone(views);
+ assertNameIs(views, TEST_FORMATTED_NUMBER);
+ assertNumberAndLabelAreGone(views);
}
@MediumTest
public void testBindView_WithCachedName() {
mCursor.moveToFirst();
- insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
"John Doe", Phone.TYPE_HOME, "");
View view = mAdapter.newStandAloneView(getActivity(), mParentView);
mAdapter.bindStandAloneView(view, getActivity(), mCursor);
CallLogListItemViews views = (CallLogListItemViews) view.getTag();
assertNameIs(views, "John Doe");
- assertNumberLabelIsVisible(views);
- assertNumberIs(views, TEST_FORMATTED_PHONE_NUMBER);
+ assertNumberAndLabelAre(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
}
@MediumTest
@@ -219,51 +225,47 @@
CallLogListItemViews views = (CallLogListItemViews) view.getTag();
assertNameIs(views, "John Doe");
- assertNumberLabelIsInvisible(views);
- assertNumberIs(views, "sip:johndoe@gmail.com");
+ assertNumberAndLabelAre(views, "sip:johndoe@gmail.com", null);
}
@MediumTest
public void testBindView_HomeLabel() {
mCursor.moveToFirst();
- insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
"John Doe", Phone.TYPE_HOME, "");
View view = mAdapter.newStandAloneView(getActivity(), mParentView);
mAdapter.bindStandAloneView(view, getActivity(), mCursor);
CallLogListItemViews views = (CallLogListItemViews) view.getTag();
assertNameIs(views, "John Doe");
- assertNumberLabelIs(views, getTypeLabel(Phone.TYPE_HOME));
- assertNumberIsVisible(views);
+ assertNumberAndLabelAre(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_HOME));
}
@MediumTest
public void testBindView_WorkLabel() {
mCursor.moveToFirst();
- insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
"John Doe", Phone.TYPE_WORK, "");
View view = mAdapter.newStandAloneView(getActivity(), mParentView);
mAdapter.bindStandAloneView(view, getActivity(), mCursor);
CallLogListItemViews views = (CallLogListItemViews) view.getTag();
assertNameIs(views, "John Doe");
- assertNumberLabelIs(views, getTypeLabel(Phone.TYPE_WORK));
- assertNumberIsVisible(views);
+ assertNumberAndLabelAre(views, TEST_FORMATTED_NUMBER, getTypeLabel(Phone.TYPE_WORK));
}
@MediumTest
public void testBindView_CustomLabel() {
mCursor.moveToFirst();
String numberLabel = "My label";
- insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ insertWithCachedValues(TEST_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
"John Doe", Phone.TYPE_CUSTOM, numberLabel);
View view = mAdapter.newStandAloneView(getActivity(), mParentView);
mAdapter.bindStandAloneView(view, getActivity(), mCursor);
CallLogListItemViews views = (CallLogListItemViews) view.getTag();
assertNameIs(views, "John Doe");
- assertNumberLabelIs(views, numberLabel);
- assertNumberIsVisible(views);
+ assertNumberAndLabelAre(views, TEST_FORMATTED_NUMBER, numberLabel);
}
/** Returns the label associated with a given phone type. */
@@ -275,27 +277,6 @@
// HELPERS to check conditions on the DB/views
//
/**
- * Check the date of the current list item.
- * @param date That should be present in the call log list
- * item. Only NOW is supported.
- */
- private void checkDate(long date) {
- if (NOW == date) {
- assertEquals("0 mins ago", mItem.dateView.getText());
- }
- throw new UnsupportedOperationException();
- }
-
- /**
- * Checks the right icon is used to represent the call type
- * (missed, incoming, outgoing.) in the current item.
- */
- private void checkCallType(int type) {
- Bitmap icon = ((BitmapDrawable) mItem.iconView.getDrawable()).getBitmap();
- assertEquals(mCallTypeIcons.get(type), icon);
- }
-
- /**
* Go over all the views in the list and check that the Call
* icon's visibility matches the nature of the number.
*/
@@ -407,6 +388,32 @@
*/
private void insertWithCachedValues(String number, long date, int duration, int type,
String cachedName, int cachedNumberType, String cachedNumberLabel) {
+ insert(number, date, duration, type);
+ ContactInfo contactInfo = new ContactInfo();
+ contactInfo.personId = TEST_PERSON_ID;
+ contactInfo.name = cachedName;
+ contactInfo.type = cachedNumberType;
+ contactInfo.label = cachedNumberLabel;
+ String formattedNumber = PhoneNumberUtils.formatNumber(number, TEST_COUNTRY_ISO);
+ if (formattedNumber == null) {
+ formattedNumber = number;
+ }
+ contactInfo.formattedNumber = formattedNumber;
+ contactInfo.normalizedNumber = number;
+ contactInfo.photoId = TEST_PHOTO_ID;
+ contactInfo.lookupKey = TEST_LOOKUP_KEY;
+ mAdapter.injectContactInfoForTest(number, contactInfo);
+ }
+
+ /**
+ * Insert a new call entry in the test DB.
+ * @param number The phone number. For unknown and private numbers,
+ * use CallerInfo.UNKNOWN_NUMBER or CallerInfo.PRIVATE_NUMBER.
+ * @param date In millisec since epoch. Use NOW to use the current time.
+ * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
+ * @param type Either Call.OUTGOING_TYPE or Call.INCOMING_TYPE or Call.MISSED_TYPE.
+ */
+ private void insert(String number, long date, int duration, int type) {
MatrixCursor.RowBuilder row = mCursor.newRow();
row.add(mIndex);
mIndex ++;
@@ -424,22 +431,7 @@
assertEquals(Calls.OUTGOING_TYPE, type);
}
row.add(type); // type
- row.add(cachedName); // cached name
- row.add(cachedNumberType); // cached number type
- row.add(cachedNumberLabel); // cached number label
- row.add("US"); // country ISO
- }
-
- /**
- * Insert a new call entry in the test DB.
- * @param number The phone number. For unknown and private numbers,
- * use CallerInfo.UNKNOWN_NUMBER or CallerInfo.PRIVATE_NUMBER.
- * @param date In millisec since epoch. Use NOW to use the current time.
- * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
- * @param type Either Call.OUTGOING_TYPE or Call.INCOMING_TYPE or Call.MISSED_TYPE.
- */
- private void insert(String number, long date, int duration, int type) {
- insertWithCachedValues(number, date, duration, type, "", Phone.TYPE_HOME, "");
+ row.add(TEST_COUNTRY_ISO); // country ISO
}
/**
@@ -513,44 +505,25 @@
/** Asserts that the name text view is shown and contains the given text. */
private void assertNameIs(CallLogListItemViews views, String name) {
- assertEquals(View.VISIBLE, views.line1View.getVisibility());
- assertEquals(name, views.line1View.getText());
+ assertEquals(View.VISIBLE, views.phoneCallDetailsViews.nameView.getVisibility());
+ assertEquals(name, views.phoneCallDetailsViews.nameView.getText());
}
- /** Asserts that the number label text view is shown and contains the given text. */
- private void assertNumberLabelIs(CallLogListItemViews views, CharSequence numberLabel) {
- assertNumberLabelIsVisible(views);
- assertEquals(numberLabel, views.labelView.getText());
+ /** Asserts that the number and label text view contains the given text. */
+ private void assertNumberAndLabelAre(CallLogListItemViews views, CharSequence number,
+ CharSequence numberLabel) {
+ assertEquals(View.VISIBLE, views.phoneCallDetailsViews.numberView.getVisibility());
+ final CharSequence expectedText;
+ if (numberLabel == null) {
+ expectedText = number;
+ } else {
+ expectedText = numberLabel + " " + number;
+ }
+ assertEquals(expectedText, views.phoneCallDetailsViews.numberView.getText().toString());
}
- /** Asserts that the number label text view is shown. */
- private void assertNumberLabelIsVisible(CallLogListItemViews views) {
- assertEquals(View.VISIBLE, views.labelView.getVisibility());
- }
-
- /** Asserts that the number label text view is invisible. */
- private void assertNumberLabelIsInvisible(CallLogListItemViews views) {
- assertEquals(View.INVISIBLE, views.labelView.getVisibility());
- }
-
- /** Asserts that the number label text view is gone. */
- private void assertNumberLabelIsGone(CallLogListItemViews views) {
- assertEquals(View.GONE, views.labelView.getVisibility());
- }
-
- /** Asserts that the number text view is shown and contains the given text. */
- private void assertNumberIs(CallLogListItemViews views, String number) {
- assertNumberIsVisible(views);
- assertEquals(number, views.numberView.getText());
- }
-
- /** Asserts that the number text view is shown. */
- private void assertNumberIsVisible(CallLogListItemViews views) {
- assertEquals(View.VISIBLE, views.numberView.getVisibility());
- }
-
- /** Asserts that the number text view is gone. */
- private void assertNumberIsGone(CallLogListItemViews views) {
- assertEquals(View.GONE, views.numberView.getVisibility());
+ /** Asserts that the number and label text view is gone. */
+ private void assertNumberAndLabelAreGone(CallLogListItemViews views) {
+ assertEquals(View.GONE, views.phoneCallDetailsViews.numberView.getVisibility());
}
}
diff --git a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
index a33b710..a8714b4 100644
--- a/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogListItemHelperTest.java
@@ -16,8 +16,9 @@
package com.android.contacts.calllog;
-import com.android.contacts.R;
-import com.android.contacts.util.LocaleTestUtils;
+import com.android.contacts.PhoneCallDetails;
+import com.android.contacts.PhoneCallDetailsHelper;
+import com.android.contacts.PhoneCallDetailsViews;
import com.android.internal.telephony.CallerInfo;
import android.content.Context;
@@ -28,15 +29,20 @@
import android.test.AndroidTestCase;
import android.view.View;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.QuickContactBadge;
import android.widget.TextView;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-
/**
* Unit tests for {@link CallLogListItemHelper}.
*/
public class CallLogListItemHelperTest extends AndroidTestCase {
+ /** A test phone number for phone calls. */
+ private static final String TEST_NUMBER = "14125555555";
+ /** The formatted version of {@link #TEST_NUMBER}. */
+ private static final String TEST_FORMATTED_NUMBER = "1-412-255-5555";
+ /** A test date value for phone calls. */
+ private static final long TEST_DATE = 1300000000;
/** A test voicemail number. */
private static final String TEST_VOICEMAIL_NUMBER = "123";
/** A drawable to be used for incoming calls. */
@@ -62,17 +68,15 @@
protected void setUp() throws Exception {
super.setUp();
Context context = getContext();
- mHelper = new CallLogListItemHelper(context.getResources(), TEST_VOICEMAIL_NUMBER,
- TEST_INCOMING_DRAWABLE, TEST_OUTGOING_DRAWABLE, TEST_MISSED_DRAWABLE,
- TEST_VOICEMAIL_DRAWABLE, TEST_CALL_DRAWABLE, TEST_PLAY_DRAWABLE);
- mViews = new CallLogListItemViews();
- // Only set the views that are needed in the tests.
- mViews.iconView = new ImageView(context);
- mViews.dateView = new TextView(context);
- mViews.callView = new ImageView(context);
- mViews.line1View = new TextView(context);
- mViews.labelView = new TextView(context);
- mViews.numberView = new TextView(context);
+ PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(context,
+ context.getResources(), TEST_VOICEMAIL_NUMBER, TEST_INCOMING_DRAWABLE,
+ TEST_OUTGOING_DRAWABLE, TEST_MISSED_DRAWABLE, TEST_VOICEMAIL_DRAWABLE);
+ mHelper = new CallLogListItemHelper(phoneCallDetailsHelper, TEST_CALL_DRAWABLE,
+ TEST_PLAY_DRAWABLE);
+ mViews = CallLogListItemViews.createForTest(new QuickContactBadge(context),
+ new ImageView(context), PhoneCallDetailsViews.createForTest(new TextView(context),
+ new LinearLayout(context), new TextView(context), new TextView(context),
+ new TextView(context), new TextView(context)));
}
@Override
@@ -82,70 +86,50 @@
super.tearDown();
}
- public void testSetContactNumberOnly() {
- mHelper.setContactNumberOnly(mViews, "12125551234", "1-212-555-1234");
- assertEquals("1-212-555-1234", mViews.line1View.getText());
- assertEquals(View.GONE, mViews.labelView.getVisibility());
- assertEquals(View.GONE, mViews.numberView.getVisibility());
+ public void testSetPhoneCallDetails() {
+ setPhoneCallDetailsWithNumber("12125551234", "1-212-555-1234");
assertEquals(View.VISIBLE, mViews.callView.getVisibility());
+ assertEquals(TEST_CALL_DRAWABLE, mViews.callView.getDrawable());
}
- public void testSetContactNumberOnly_Unknown() {
- mHelper.setContactNumberOnly(mViews, CallerInfo.UNKNOWN_NUMBER, "");
- assertEquals(getContext().getString(R.string.unknown), mViews.line1View.getText());
- assertEquals(View.GONE, mViews.labelView.getVisibility());
- assertEquals(View.GONE, mViews.numberView.getVisibility());
+ public void testSetPhoneCallDetails_Unknown() {
+ setPhoneCallDetailsWithNumber(CallerInfo.UNKNOWN_NUMBER, CallerInfo.UNKNOWN_NUMBER);
assertEquals(View.INVISIBLE, mViews.callView.getVisibility());
}
- public void testSetContactNumberOnly_Private() {
- mHelper.setContactNumberOnly(mViews, CallerInfo.PRIVATE_NUMBER, "");
- assertEquals(getContext().getString(R.string.private_num), mViews.line1View.getText());
- assertEquals(View.GONE, mViews.labelView.getVisibility());
- assertEquals(View.GONE, mViews.numberView.getVisibility());
+ public void testSetPhoneCallDetails_Private() {
+ setPhoneCallDetailsWithNumber(CallerInfo.PRIVATE_NUMBER, CallerInfo.PRIVATE_NUMBER);
assertEquals(View.INVISIBLE, mViews.callView.getVisibility());
}
- public void testSetContactNumberOnly_Payphone() {
- mHelper.setContactNumberOnly(mViews, CallerInfo.PAYPHONE_NUMBER, "");
- assertEquals(getContext().getString(R.string.payphone), mViews.line1View.getText());
- assertEquals(View.GONE, mViews.labelView.getVisibility());
- assertEquals(View.GONE, mViews.numberView.getVisibility());
+ public void testSetPhoneCallDetails_Payphone() {
+ setPhoneCallDetailsWithNumber(CallerInfo.PAYPHONE_NUMBER, CallerInfo.PAYPHONE_NUMBER);
assertEquals(View.INVISIBLE, mViews.callView.getVisibility());
}
- public void testSetContactNumberOnly_Voicemail() {
- mHelper.setContactNumberOnly(mViews, TEST_VOICEMAIL_NUMBER, "");
- assertEquals(getContext().getString(R.string.voicemail), mViews.line1View.getText());
- assertEquals(View.GONE, mViews.labelView.getVisibility());
- assertEquals(View.GONE, mViews.numberView.getVisibility());
+ public void testSetPhoneCallDetails_VoicemailNumber() {
+ setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, TEST_VOICEMAIL_NUMBER);
assertEquals(View.VISIBLE, mViews.callView.getVisibility());
+ assertEquals(TEST_CALL_DRAWABLE, mViews.callView.getDrawable());
}
- public void testSetDate() {
- // This test requires the locale to be set to US.
- LocaleTestUtils localeTestUtils = new LocaleTestUtils(getContext());
- localeTestUtils.setLocale(Locale.US);
- try {
- mHelper.setDate(mViews,
- new GregorianCalendar(2011, 5, 1, 12, 0, 0).getTimeInMillis(),
- new GregorianCalendar(2011, 5, 1, 13, 0, 0).getTimeInMillis());
- assertEquals("1 hour ago", mViews.dateView.getText());
- mHelper.setDate(mViews,
- new GregorianCalendar(2010, 5, 1, 12, 0, 0).getTimeInMillis(),
- new GregorianCalendar(2011, 5, 1, 13, 0, 0).getTimeInMillis());
- assertEquals("June 1, 2010", mViews.dateView.getText());
- } finally {
- localeTestUtils.restoreLocale();
- }
+ public void testSetPhoneCallDetails_Voicemail() {
+ setPhoneCallDetailsWithTypes(Calls.VOICEMAIL_TYPE);
+ assertEquals(View.VISIBLE, mViews.callView.getVisibility());
+ assertEquals(TEST_PLAY_DRAWABLE, mViews.callView.getDrawable());
}
- public void testSetCallType_Icon() {
- mHelper.setCallType(mViews, Calls.INCOMING_TYPE);
- assertEquals(TEST_INCOMING_DRAWABLE, mViews.iconView.getDrawable());
- mHelper.setCallType(mViews, Calls.OUTGOING_TYPE);
- assertEquals(TEST_OUTGOING_DRAWABLE, mViews.iconView.getDrawable());
- mHelper.setCallType(mViews, Calls.MISSED_TYPE);
- assertEquals(TEST_MISSED_DRAWABLE, mViews.iconView.getDrawable());
+ /** Sets the details of a phone call using the specified phone number. */
+ private void setPhoneCallDetailsWithNumber(String number, String formattedNumber) {
+ mHelper.setPhoneCallDetails(mViews,
+ new PhoneCallDetails(number, formattedNumber, new int[]{ Calls.INCOMING_TYPE },
+ TEST_DATE),
+ true);
+ }
+
+ /** Sets the details of a phone call using the specified call type. */
+ private void setPhoneCallDetailsWithTypes(int... types) {
+ mHelper.setPhoneCallDetails(mViews,
+ new PhoneCallDetails(TEST_NUMBER, TEST_FORMATTED_NUMBER, types, TEST_DATE), true);
}
}