Merge "Two fixes for custom filter activity."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9640536..fc0036c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -492,7 +492,6 @@
<activity
android:name=".activities.ContactEditorActivity"
android:theme="@style/EditorActivityTheme"
- android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustResize">
<intent-filter android:label="@string/editContactDescription">
diff --git a/res/layout-sw580dp/group_editor_view.xml b/res/layout-sw580dp/group_editor_view.xml
index 7874c8c..a31a36a 100644
--- a/res/layout-sw580dp/group_editor_view.xml
+++ b/res/layout-sw580dp/group_editor_view.xml
@@ -19,8 +19,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="50dip"
- android:paddingLeft="50dip"
- android:paddingRight="100dip"
+ android:paddingLeft="64dip"
+ android:paddingRight="64dip"
android:orientation="horizontal"
android:background="@color/background_primary">
@@ -39,11 +39,12 @@
android:id="@+id/group_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:minHeight="48dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:inputType="textCapWords"
android:hint="@string/group_name_hint"
- android:layout_marginBottom="5dip"/>
+ android:paddingLeft="16dip"/>
</LinearLayout>
@@ -55,6 +56,11 @@
android:orientation="vertical">
<include
+ android:id="@+id/spacer"
+ layout="@layout/editor_account_header"
+ android:visibility="invisible"/>
+
+ <include
layout="@layout/group_editor_autocomplete_view"
android:id="@+id/add_member_field"/>
diff --git a/res/layout/contact_picker_content.xml b/res/layout/contact_picker_content.xml
index c30add7..14eaf15 100644
--- a/res/layout/contact_picker_content.xml
+++ b/res/layout/contact_picker_content.xml
@@ -22,7 +22,7 @@
android:orientation="vertical">
<view
- class="com.android.contacts.list.ContactEntryListView"
+ class="com.android.contacts.widget.PinnedHeaderListView"
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0dip"
diff --git a/res/layout/contacts_list_content.xml b/res/layout/contacts_list_content.xml
index 4223f54..8e1289f 100644
--- a/res/layout/contacts_list_content.xml
+++ b/res/layout/contacts_list_content.xml
@@ -57,7 +57,7 @@
</LinearLayout>
<view
- class="com.android.contacts.list.ContactEntryListView"
+ class="com.android.contacts.widget.PinnedHeaderListView"
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0dip"
diff --git a/res/layout/editor_account_header.xml b/res/layout/editor_account_header.xml
index 5181708..dd4bc30 100644
--- a/res/layout/editor_account_header.xml
+++ b/res/layout/editor_account_header.xml
@@ -24,7 +24,7 @@
android:orientation="horizontal"
android:paddingTop="8dip"
android:paddingBottom="8dip"
- android:paddingLeft="16dip"
+ android:paddingLeft="@dimen/account_container_left_padding"
android:paddingRight="16dip">
<LinearLayout
diff --git a/res/layout/external_group_member_item.xml b/res/layout/external_group_member_item.xml
index 5fa81d0..1fba205 100644
--- a/res/layout/external_group_member_item.xml
+++ b/res/layout/external_group_member_item.xml
@@ -18,9 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:minHeight="58dip"
- android:paddingLeft="10dip">
+ android:orientation="horizontal">
<TextView
android:id="@+id/name"
@@ -31,7 +29,8 @@
android:gravity="center_vertical"
android:paddingRight="3dip"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:focusable="true" />
+ android:focusable="true"
+ android:paddingLeft="@dimen/group_member_item_left_padding" />
<QuickContactBadge
android:id="@+id/badge"
diff --git a/res/layout/group_editor_autocomplete_view.xml b/res/layout/group_editor_autocomplete_view.xml
index 6b35cae..46539de 100644
--- a/res/layout/group_editor_autocomplete_view.xml
+++ b/res/layout/group_editor_autocomplete_view.xml
@@ -22,4 +22,6 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary"
- android:hint="@string/enter_contact_name"/>
\ No newline at end of file
+ android:hint="@string/enter_contact_name"
+ android:minHeight="48dip"
+ android:paddingLeft="@dimen/group_editor_autocomplete_left_padding"/>
\ No newline at end of file
diff --git a/res/layout/group_editor_existing_member_list.xml b/res/layout/group_editor_existing_member_list.xml
index 9765de1..3933670 100644
--- a/res/layout/group_editor_existing_member_list.xml
+++ b/res/layout/group_editor_existing_member_list.xml
@@ -21,5 +21,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dip"
- android:cacheColorHint="@android:color/transparent"
- android:divider="@null" />
\ No newline at end of file
+ android:layout_marginLeft="@dimen/group_editor_member_list_left_margin"
+ android:layout_marginRight="@dimen/group_editor_member_list_right_margin"
+ android:cacheColorHint="@android:color/transparent" />
\ No newline at end of file
diff --git a/res/layout/group_editor_fragment.xml b/res/layout/group_editor_fragment.xml
index 3d72384..3a69e05 100644
--- a/res/layout/group_editor_fragment.xml
+++ b/res/layout/group_editor_fragment.xml
@@ -22,7 +22,4 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/background_primary"
- android:paddingTop="5dip"
- android:paddingLeft="5dip"
- android:paddingRight="5dip" />
+ android:background="@color/background_primary" />
diff --git a/res/layout/group_editor_view.xml b/res/layout/group_editor_view.xml
index 59f2986..e94b387 100644
--- a/res/layout/group_editor_view.xml
+++ b/res/layout/group_editor_view.xml
@@ -24,22 +24,30 @@
android:id="@+id/account_header"
layout="@layout/editor_account_header"/>
- <EditText
- android:id="@+id/group_name"
- android:layout_width="match_parent"
+ <LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textStyle="bold"
- android:inputType="textCapWords"
- android:hint="@string/group_name_hint"
- android:layout_marginBottom="5dip"/>
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip"
+ android:orientation="vertical">
- <include
- layout="@layout/group_editor_autocomplete_view"
- android:id="@+id/add_member_field"/>
+ <EditText
+ android:id="@+id/group_name"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:inputType="textCapWords"
+ android:hint="@string/group_name_hint"
+ android:minHeight="48dip"
+ android:paddingLeft="8dip"/>
- <include
- layout="@layout/group_editor_existing_member_list"
- android:id="@android:id/list"/>
+ <include
+ layout="@layout/group_editor_autocomplete_view"
+ android:id="@+id/add_member_field"/>
+
+ <include
+ layout="@layout/group_editor_existing_member_list"
+ android:id="@android:id/list"/>
+ </LinearLayout>
</LinearLayout>
diff --git a/res/layout/group_member_item.xml b/res/layout/group_member_item.xml
index 23f02e0..518e26f 100644
--- a/res/layout/group_member_item.xml
+++ b/res/layout/group_member_item.xml
@@ -18,9 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:minHeight="58dip"
- android:paddingLeft="10dip">
+ android:orientation="horizontal">
<TextView
android:id="@+id/name"
@@ -31,7 +29,8 @@
android:gravity="center_vertical"
android:paddingRight="3dip"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:focusable="true" />
+ android:focusable="true"
+ android:paddingLeft="@dimen/group_member_item_left_padding" />
<QuickContactBadge
android:id="@+id/badge"
diff --git a/res/layout/join_contact_picker_list_content.xml b/res/layout/join_contact_picker_list_content.xml
index 9e72c31..1535539 100644
--- a/res/layout/join_contact_picker_list_content.xml
+++ b/res/layout/join_contact_picker_list_content.xml
@@ -36,7 +36,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<view
- class="com.android.contacts.list.ContactEntryListView"
+ class="com.android.contacts.widget.PinnedHeaderListView"
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/res/values-sw580dp/dimens.xml b/res/values-sw580dp/dimens.xml
index c75ba6e..0a7bb6b 100644
--- a/res/values-sw580dp/dimens.xml
+++ b/res/values-sw580dp/dimens.xml
@@ -52,4 +52,15 @@
<dimen name="widget_snippet_bottom_margin">6dip</dimen>
<dimen name="widget_snippet_top_padding">6dip</dimen>
<dimen name="widget_snippet_bottom_padding">3dip</dimen>
+
+ <!-- Left padding for a group member list item -->
+ <dimen name="group_member_item_left_padding">12dip</dimen>
+ <!-- Left margin for the group member list to match the built in margin in the autocomplete asset -->
+ <dimen name="group_editor_member_list_left_margin">4dip</dimen>
+ <!-- Right margin for the group member list to match the built in margin in the autocomplete asset -->
+ <dimen name="group_editor_member_list_right_margin">4dip</dimen>
+ <!-- Account title left padding -->
+ <dimen name="account_container_left_padding">16dip</dimen>
+ <!-- Left padding of the auto complete field to line hint text up with member list -->
+ <dimen name="group_editor_autocomplete_left_padding">16dip</dimen>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f5fd3bf..419e9ce 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -190,6 +190,21 @@
<!-- Border padding for the group list header for each account -->
<dimen name="group_list_header_padding">5dip</dimen>
+ <!-- Account title left padding -->
+ <dimen name="account_container_left_padding">16dip</dimen>
+
+ <!-- Left padding for a group member list item -->
+ <dimen name="group_member_item_left_padding">4dip</dimen>
+
+ <!-- Left margin for the group member list to match the built in margin in the autocomplete asset -->
+ <dimen name="group_editor_member_list_left_margin">4dip</dimen>
+
+ <!-- Right margin for the group member list to match the built in margin in the autocomplete asset -->
+ <dimen name="group_editor_member_list_right_margin">4dip</dimen>
+
+ <!-- Left padding of the auto complete field to line hint text up with member list -->
+ <dimen name="group_editor_autocomplete_left_padding">8dip</dimen>
+
<!-- Size of group list icons -->
<dimen name="group_list_icon_size">32dip</dimen>
diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java
index 1164069..f54dbd6 100644
--- a/src/com/android/contacts/group/GroupDetailFragment.java
+++ b/src/com/android/contacts/group/GroupDetailFragment.java
@@ -403,10 +403,9 @@
mOptionsMenuEditable = isGroupEditable() && isVisible();
mOptionsMenuGroupPresent = isGroupPresent() && isVisible();
- // Editing a group is always possible if a group is selected
- // TODO: check for external group (member editable) buganizer #5049046
+ // Editing is not possible for read only groups
final MenuItem editMenu = menu.findItem(R.id.menu_edit_group);
- editMenu.setVisible(mOptionsMenuGroupPresent);
+ editMenu.setVisible(mOptionsMenuGroupPresent && mOptionsMenuEditable);
final MenuItem deleteMenu = menu.findItem(R.id.menu_delete_group);
deleteMenu.setVisible(mOptionsMenuEditable);
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index ba16c17..9b968f7 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -242,22 +242,6 @@
mSortOrder = sortOrder;
}
- public void setNameHighlightingEnabled(boolean flag) {
- mNameHighlightingEnabled = flag;
- }
-
- public boolean isNameHighlightingEnabled() {
- return mNameHighlightingEnabled;
- }
-
- public void setTextWithHighlightingFactory(TextWithHighlightingFactory factory) {
- mTextWithHighlightingFactory = factory;
- }
-
- protected TextWithHighlightingFactory getTextWithHighlightingFactory() {
- return mTextWithHighlightingFactory;
- }
-
public void setPhotoLoader(ContactPhotoManager photoLoader) {
mPhotoLoader = photoLoader;
}
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index 4ddba75..a4163fd 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -717,11 +717,6 @@
changed = true;
}
- if (mListView instanceof ContactEntryListView) {
- ContactEntryListView listView = (ContactEntryListView)mListView;
- listView.setHighlightNamesWhenScrolling(isNameHighlightingEnabled());
- }
-
return changed;
}
@@ -756,6 +751,8 @@
"'android.R.id.list'");
}
+ mListView.setSelector(getContext().getResources().getDrawable(R.drawable.list_selector));
+
View emptyView = mView.findViewById(com.android.internal.R.id.empty);
if (emptyView != null) {
mListView.setEmptyView(emptyView);
@@ -810,30 +807,11 @@
mAdapter.setPinnedPartitionHeadersEnabled(mSearchMode);
mAdapter.setContactNameDisplayOrder(mDisplayOrder);
mAdapter.setSortOrder(mSortOrder);
- mAdapter.setNameHighlightingEnabled(isNameHighlightingEnabled());
mAdapter.setSectionHeaderDisplayEnabled(mSectionHeaderDisplayEnabled);
mAdapter.setSelectionVisible(mSelectionVisible);
mAdapter.setDirectoryResultLimit(mDirectoryResultLimit);
}
- protected boolean isNameHighlightingEnabled() {
- if (mAdapter.isNameHighlightingEnabled()) {
- return true;
- }
-
- // When sort order and display order contradict each other, we want to
- // highlight the part of the name used for sorting.
- if (mSortOrder == ContactsContract.Preferences.SORT_ORDER_PRIMARY &&
- mDisplayOrder == ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE) {
- return true;
- } else if (mSortOrder == ContactsContract.Preferences.SORT_ORDER_ALTERNATIVE &&
- mDisplayOrder == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
- return true;
- } else {
- return false;
- }
- }
-
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
diff --git a/src/com/android/contacts/list/ContactEntryListView.java b/src/com/android/contacts/list/ContactEntryListView.java
deleted file mode 100644
index 86e33fe..0000000
--- a/src/com/android/contacts/list/ContactEntryListView.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2010 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.list;
-
-import com.android.contacts.R;
-import com.android.contacts.widget.PinnedHeaderListView;
-import com.android.contacts.widget.TextHighlightingAnimation;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.AbsListView;
-import android.widget.ListAdapter;
-
-/**
- * A custom list view for a list of contacts or contact-related entries. It handles
- * animation of names on scroll.
- */
-public class ContactEntryListView extends PinnedHeaderListView {
-
- private static final int TEXT_HIGHLIGHTING_ANIMATION_DURATION = 350;
-
- private final TextHighlightingAnimation mHighlightingAnimation =
- new ContactNameHighlightingAnimation(this, TEXT_HIGHLIGHTING_ANIMATION_DURATION);
-
- private boolean mHighlightNamesWhenScrolling;
-
- public ContactEntryListView(Context context) {
- this(context, null);
- }
-
- public ContactEntryListView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.listViewStyle);
- }
-
- public ContactEntryListView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- setSelector(getContext().getResources().getDrawable(R.drawable.list_selector));
- }
-
- public TextHighlightingAnimation getTextHighlightingAnimation() {
- return mHighlightingAnimation;
- }
-
- public boolean getHighlightNamesWhenScrolling() {
- return mHighlightNamesWhenScrolling;
- }
-
- public void setHighlightNamesWhenScrolling(boolean flag) {
- mHighlightNamesWhenScrolling = flag;
- }
-
- @Override
- public void setAdapter(ListAdapter adapter) {
- super.setAdapter(adapter);
- if (adapter instanceof ContactEntryListAdapter) {
- ((ContactEntryListAdapter)adapter)
- .setTextWithHighlightingFactory(mHighlightingAnimation);
- }
- }
-
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- super.onScrollStateChanged(view, scrollState);
- if (mHighlightNamesWhenScrolling) {
- if (scrollState != OnScrollListener.SCROLL_STATE_IDLE) {
- mHighlightingAnimation.startHighlighting();
- } else {
- mHighlightingAnimation.stopHighlighting();
- }
- }
- }
-}
diff --git a/src/com/android/contacts/list/ContactListAdapter.java b/src/com/android/contacts/list/ContactListAdapter.java
index 2e511bc..c057a48 100644
--- a/src/com/android/contacts/list/ContactListAdapter.java
+++ b/src/com/android/contacts/list/ContactListAdapter.java
@@ -222,7 +222,6 @@
ViewGroup parent) {
ContactListItemView view = new ContactListItemView(context, null);
view.setUnknownNameText(mUnknownNameText);
- view.setTextWithHighlightingFactory(getTextWithHighlightingFactory());
view.setQuickContactEnabled(isQuickContactEnabled());
view.setActivatedStateSupported(isSelectionVisible());
return view;
@@ -271,7 +270,7 @@
protected void bindName(final ContactListItemView view, Cursor cursor) {
view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
- isNameHighlightingEnabled(), getContactNameDisplayOrder());
+ false, getContactNameDisplayOrder());
view.showPhoneticName(cursor, CONTACT_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/EmailAddressListAdapter.java b/src/com/android/contacts/list/EmailAddressListAdapter.java
index e1c8ea2..5f96297 100644
--- a/src/com/android/contacts/list/EmailAddressListAdapter.java
+++ b/src/com/android/contacts/list/EmailAddressListAdapter.java
@@ -120,7 +120,6 @@
ViewGroup parent) {
final ContactListItemView view = new ContactListItemView(context, null);
view.setUnknownNameText(mUnknownNameText);
- view.setTextWithHighlightingFactory(getTextWithHighlightingFactory());
view.setQuickContactEnabled(isQuickContactEnabled());
return view;
}
@@ -167,8 +166,7 @@
protected void bindName(final ContactListItemView view, Cursor cursor) {
view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
- isNameHighlightingEnabled(), getContactNameDisplayOrder());
-// view.showPhoneticName(cursor, PHONE_PHONETIC_NAME_COLUMN_INDEX);
+ false, getContactNameDisplayOrder());
}
protected void bindPhoto(final ContactListItemView view, Cursor cursor) {
diff --git a/src/com/android/contacts/list/PhoneNumberListAdapter.java b/src/com/android/contacts/list/PhoneNumberListAdapter.java
index 87fb60f..cac89b1 100644
--- a/src/com/android/contacts/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/list/PhoneNumberListAdapter.java
@@ -231,7 +231,6 @@
ViewGroup parent) {
final ContactListItemView view = new ContactListItemView(context, null);
view.setUnknownNameText(mUnknownNameText);
- view.setTextWithHighlightingFactory(getTextWithHighlightingFactory());
view.setQuickContactEnabled(isQuickContactEnabled());
return view;
}
@@ -240,9 +239,6 @@
protected void bindView(View itemView, int partition, Cursor cursor, int position) {
ContactListItemView view = (ContactListItemView)itemView;
- view.setHighlightedPrefix(isNameHighlightingEnabled() && isSearchMode() ?
- getUpperCaseQueryString() : null);
-
// Look at elements before and after this position, checking if contact IDs are same.
// If they have one same contact ID, it means they can be grouped.
//
@@ -317,7 +313,7 @@
protected void bindName(final ContactListItemView view, Cursor cursor) {
view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
- isNameHighlightingEnabled(), getContactNameDisplayOrder());
+ false, getContactNameDisplayOrder());
view.showPhoneticName(cursor, PHONE_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
index 5986b9c..2798905 100644
--- a/src/com/android/contacts/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/list/PhoneNumberPickerFragment.java
@@ -56,16 +56,6 @@
private static final String KEY_FILTER = "filter";
- /**
- * Used to remember the result of {@link #setNameHighlightingEnabled(boolean)} when it is called
- * before this Fragment is attached to its parent Activity. The value will be used after
- * an actual Adapter is ready.
- *
- * Null if the Adapter is already available and thus we don't need to remember the user's
- * decision.
- */
- private Boolean mDelayedNameHighlightingEnabled;
-
public PhoneNumberPickerFragment() {
setQuickContactEnabled(false);
setPhotoLoaderEnabled(true);
@@ -191,16 +181,10 @@
if (!isLegacyCompatibilityMode()) {
PhoneNumberListAdapter adapter = new PhoneNumberListAdapter(getActivity());
adapter.setDisplayPhotos(true);
- if (mDelayedNameHighlightingEnabled != null) {
- adapter.setNameHighlightingEnabled(mDelayedNameHighlightingEnabled);
- }
return adapter;
} else {
LegacyPhoneNumberListAdapter adapter = new LegacyPhoneNumberListAdapter(getActivity());
adapter.setDisplayPhotos(true);
- if (mDelayedNameHighlightingEnabled != null) {
- adapter.setNameHighlightingEnabled(mDelayedNameHighlightingEnabled);
- }
return adapter;
}
}
@@ -251,25 +235,6 @@
mListener.onPickPhoneNumberAction(data.getData());
}
- public void setNameHighlightingEnabled(boolean highlight) {
- final Adapter adapter = getAdapter();
- // This may happen when the Fragment is not attached to its parent Activity and thus
- // parent's onCreateView() isn't called yet (where adapter will be prepared).
- // See also ContactEntryListFragment#onCreateView()
- if (adapter == null) {
- mDelayedNameHighlightingEnabled = highlight;
- } else {
- if (!isLegacyCompatibilityMode()) {
- ((PhoneNumberListAdapter) adapter).setNameHighlightingEnabled(highlight);
- } else {
- ((LegacyPhoneNumberListAdapter) adapter).setNameHighlightingEnabled(highlight);
- }
-
- // We don't want to remember the choice if the adapter is already available.
- mDelayedNameHighlightingEnabled = null;
- }
- }
-
public ContactListFilter getFilter() {
return mFilter;
}
diff --git a/src/com/android/contacts/list/PostalAddressListAdapter.java b/src/com/android/contacts/list/PostalAddressListAdapter.java
index 5642045..c9da281 100644
--- a/src/com/android/contacts/list/PostalAddressListAdapter.java
+++ b/src/com/android/contacts/list/PostalAddressListAdapter.java
@@ -109,7 +109,6 @@
ViewGroup parent) {
final ContactListItemView view = new ContactListItemView(context, null);
view.setUnknownNameText(mUnknownNameText);
- view.setTextWithHighlightingFactory(getTextWithHighlightingFactory());
view.setQuickContactEnabled(isQuickContactEnabled());
return view;
}
@@ -156,8 +155,7 @@
protected void bindName(final ContactListItemView view, Cursor cursor) {
view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
- isNameHighlightingEnabled(), getContactNameDisplayOrder());
-// view.showPhoneticName(cursor, PHONE_PHONETIC_NAME_COLUMN_INDEX);
+ false, getContactNameDisplayOrder());
}
protected void bindPhoto(final ContactListItemView view, Cursor cursor) {
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
index 5eb0ddf..7d29406 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
@@ -111,6 +111,12 @@
super.onDestroy();
}
+ @Override
+ public void onPause() {
+ mPresenter.onPause();
+ super.onPause();
+ }
+
private PlaybackViewImpl createPlaybackViewImpl() {
return new PlaybackViewImpl(new ActivityReference(), getActivity().getApplicationContext(),
mPlaybackLayout);
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
index d3e4bef..d54cddc 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
@@ -555,4 +555,10 @@
}
}
}
+
+ public void onPause() {
+ if (mPlayer.isPlaying()) {
+ stopPlaybackAtPosition(mPlayer.getCurrentPosition(), mDuration.get());
+ }
+ }
}
diff --git a/tests/assets/README.txt b/tests/assets/README.txt
new file mode 100644
index 0000000..53bb0bd
--- /dev/null
+++ b/tests/assets/README.txt
@@ -0,0 +1,4 @@
+File quick_test_recording.mp3 is copyright 2011 by
+Hugo Hudson and is licensed under a
+Creative Commons Attribution 3.0 Unported License:
+ http://creativecommons.org/licenses/by/3.0/
diff --git a/tests/assets/quick_test_recording.mp3 b/tests/assets/quick_test_recording.mp3
new file mode 100644
index 0000000..ad7cb9c
--- /dev/null
+++ b/tests/assets/quick_test_recording.mp3
Binary files differ
diff --git a/tests/src/com/android/contacts/CallDetailActivityTest.java b/tests/src/com/android/contacts/CallDetailActivityTest.java
index 6a8fcb3..ac02588 100644
--- a/tests/src/com/android/contacts/CallDetailActivityTest.java
+++ b/tests/src/com/android/contacts/CallDetailActivityTest.java
@@ -26,11 +26,13 @@
import com.android.contacts.util.LocaleTestUtils;
import com.android.internal.view.menu.ContextMenuBuilder;
import com.google.common.base.Preconditions;
+import com.google.common.io.Closeables;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
+import android.content.res.AssetManager;
import android.net.Uri;
import android.provider.CallLog;
import android.provider.VoicemailContract;
@@ -40,6 +42,9 @@
import android.view.Menu;
import android.widget.TextView;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.List;
import java.util.Locale;
@@ -48,6 +53,11 @@
*/
@LargeTest
public class CallDetailActivityTest extends ActivityInstrumentationTestCase2<CallDetailActivity> {
+ private static final String TEST_ASSET_NAME = "quick_test_recording.mp3";
+ private static final String MIME_TYPE = "audio/mp3";
+ private static final String CONTACT_NUMBER = "+1412555555";
+ private static final String VOICEMAIL_FILE_LOCATION = "/sdcard/sadlfj893w4j23o9sfu.mp3";
+
private Uri mCallLogUri;
private Uri mVoicemailUri;
private IntegrationTestUtils mTestUtils;
@@ -202,11 +212,25 @@
assertEquals("00:00", mTestUtils.getText(timeDisplay));
}
+ @Suppress
+ public void testClickingCallStopsPlayback() throws Throwable {
+ setActivityIntentForRealFileVoicemailEntry();
+ startActivityUnderTest();
+ mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
+ mFakeAsyncTaskExecutor.runTask(PREPARE_MEDIA_PLAYER);
+ mTestUtils.clickButton(mActivityUnderTest, R.id.playback_speakerphone);
+ mTestUtils.clickButton(mActivityUnderTest, R.id.playback_start_stop);
+ mTestUtils.clickButton(mActivityUnderTest, R.id.call_and_sms_main_action);
+ Thread.sleep(2000);
+ // TODO: Suppressed the test for now, because I'm looking for an easy way to say "the audio
+ // is not playing at this point", and I can't find it without doing dirty things.
+ }
+
private void setActivityIntentForTestCallEntry() {
Preconditions.checkState(mCallLogUri == null, "mUri should be null");
ContentResolver contentResolver = getContentResolver();
ContentValues values = new ContentValues();
- values.put(CallLog.Calls.NUMBER, "01234567890");
+ values.put(CallLog.Calls.NUMBER, CONTACT_NUMBER);
values.put(CallLog.Calls.TYPE, CallLog.Calls.INCOMING_TYPE);
mCallLogUri = contentResolver.insert(CallLog.Calls.CONTENT_URI, values);
setActivityIntent(new Intent(Intent.ACTION_VIEW, mCallLogUri));
@@ -216,8 +240,9 @@
Preconditions.checkState(mVoicemailUri == null, "mUri should be null");
ContentResolver contentResolver = getContentResolver();
ContentValues values = new ContentValues();
- values.put(VoicemailContract.Voicemails.NUMBER, "01234567890");
+ values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
+ values.put(VoicemailContract.Voicemails._DATA, VOICEMAIL_FILE_LOCATION);
mVoicemailUri = contentResolver.insert(VoicemailContract.Voicemails.CONTENT_URI, values);
Uri callLogUri = ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
ContentUris.parseId(mVoicemailUri));
@@ -226,6 +251,44 @@
setActivityIntent(intent);
}
+ private void setActivityIntentForRealFileVoicemailEntry() throws IOException {
+ Preconditions.checkState(mVoicemailUri == null, "mUri should be null");
+ ContentValues values = new ContentValues();
+ values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis()));
+ values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
+ values.put(VoicemailContract.Voicemails.MIME_TYPE, MIME_TYPE);
+ values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
+ String packageName = getInstrumentation().getTargetContext().getPackageName();
+ mVoicemailUri = getContentResolver().insert(
+ VoicemailContract.Voicemails.buildSourceUri(packageName), values);
+ AssetManager assets = getAssets();
+ OutputStream outputStream = null;
+ InputStream inputStream = null;
+ try {
+ inputStream = assets.open(TEST_ASSET_NAME);
+ outputStream = getContentResolver().openOutputStream(mVoicemailUri);
+ copyBetweenStreams(inputStream, outputStream);
+ } finally {
+ Closeables.closeQuietly(outputStream);
+ Closeables.closeQuietly(inputStream);
+ }
+ Uri callLogUri = ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
+ ContentUris.parseId(mVoicemailUri));
+ Intent intent = new Intent(Intent.ACTION_VIEW, callLogUri);
+ intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI, mVoicemailUri);
+ setActivityIntent(intent);
+ }
+
+ public void copyBetweenStreams(InputStream in, OutputStream out) throws IOException {
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ int total = 0;
+ while ((bytesRead = in.read(buffer)) != -1) {
+ total += bytesRead;
+ out.write(buffer, 0, bytesRead);
+ }
+ }
+
private void cleanUpUri() {
if (mVoicemailUri != null) {
getContentResolver().delete(VoicemailContract.Voicemails.CONTENT_URI,
@@ -267,4 +330,8 @@
// of a single unit test.
mFakeAsyncTaskExecutor.runAllTasks(UPDATE_PHONE_CALL_DETAILS);
}
+
+ private AssetManager getAssets() {
+ return getInstrumentation().getContext().getAssets();
+ }
}
diff --git a/tests/src/com/android/contacts/list/ContactListItemViewTest.java b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
index ccd2fb5..8372f96 100644
--- a/tests/src/com/android/contacts/list/ContactListItemViewTest.java
+++ b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
@@ -19,6 +19,7 @@
import com.android.contacts.activities.PeopleActivity;
import com.android.contacts.format.SpannedTestUtils;
import com.android.contacts.format.TestTextWithHighlightingFactory;
+import com.android.contacts.util.IntegrationTestUtils;
import android.database.Cursor;
import android.database.MatrixCursor;
@@ -40,10 +41,26 @@
/** The HTML code used to mark the end of the highlighted part. */
private static final String END = "</font>";
+ private IntegrationTestUtils mUtils;
+
public ContactListItemViewTest() {
super(PeopleActivity.class);
}
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // This test requires that the screen be turned on.
+ mUtils = new IntegrationTestUtils(getInstrumentation());
+ mUtils.acquireScreenWakeLock(getInstrumentation().getTargetContext());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mUtils.releaseScreenWakeLock();
+ super.tearDown();
+ }
+
public void testShowDisplayName_Simple() {
Cursor cursor = createCursor("John Doe", "Doe John");
ContactListItemView view = createView();
diff --git a/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java b/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java
index e27c6fb..960f0bf 100644
--- a/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java
+++ b/tests/src/com/android/contacts/util/FakeAsyncTaskExecutor.java
@@ -16,9 +16,11 @@
package com.android.contacts.util;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Executors;
import android.app.Instrumentation;
import android.os.AsyncTask;
@@ -28,10 +30,8 @@
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
@@ -46,43 +46,45 @@
* Tasks submitted to this executor will not be run immediately. Rather they will be stored in a
* list of submitted tasks, where they can be examined. They can also be run on-demand using the run
* methods, so that different ordering of AsyncTask execution can be simulated.
+ * <p>
+ * The onPreExecute method of the submitted AsyncTask will be called synchronously during the
+ * call to {@link #submit(Object, AsyncTask, Object...)}.
*/
@ThreadSafe
public class FakeAsyncTaskExecutor implements AsyncTaskExecutor {
private static final long DEFAULT_TIMEOUT_MS = 10000;
- private static final Executor DEFAULT_EXECUTOR = Executors.sameThreadExecutor();
/** The maximum length of time in ms to wait for tasks to execute during tests. */
private final long mTimeoutMs = DEFAULT_TIMEOUT_MS;
- /** The executor for the background part of our test tasks. */
- private final Executor mExecutor = DEFAULT_EXECUTOR;
private final Object mLock = new Object();
- @GuardedBy("mLock") private final List<SubmittedTask<?>> mSubmittedTasks = Lists.newArrayList();
+ @GuardedBy("mLock") private final List<SubmittedTask> mSubmittedTasks = Lists.newArrayList();
+ private final DelayedExecutor mBlockingExecutor = new DelayedExecutor();
private final Instrumentation mInstrumentation;
/** Create a fake AsyncTaskExecutor for use in unit tests. */
public FakeAsyncTaskExecutor(Instrumentation instrumentation) {
- mInstrumentation = Preconditions.checkNotNull(instrumentation);
+ mInstrumentation = checkNotNull(instrumentation);
}
/** Encapsulates an async task with the params and identifier it was submitted with. */
- public interface SubmittedTask<T> {
- AsyncTask<T, ?, ?> getTask();
- T[] getParams();
+ public interface SubmittedTask {
+ Runnable getRunnable();
Object getIdentifier();
+ AsyncTask<?, ?, ?> getAsyncTask();
}
- private static final class SubmittedTaskImpl<T> implements SubmittedTask<T> {
+ private static final class SubmittedTaskImpl implements SubmittedTask {
private final Object mIdentifier;
- private final AsyncTask<T, ?, ?> mTask;
- private final T[] mParams;
+ private final Runnable mRunnable;
+ private final AsyncTask<?, ?, ?> mAsyncTask;
- public SubmittedTaskImpl(Object identifier, AsyncTask<T, ?, ?> task, T[] params) {
+ public SubmittedTaskImpl(Object identifier, Runnable runnable,
+ AsyncTask<?, ?, ?> asyncTask) {
mIdentifier = identifier;
- mTask = task;
- mParams = params;
+ mRunnable = runnable;
+ mAsyncTask = asyncTask;
}
@Override
@@ -91,13 +93,13 @@
}
@Override
- public AsyncTask<T, ?, ?> getTask() {
- return mTask;
+ public Runnable getRunnable() {
+ return mRunnable;
}
@Override
- public T[] getParams() {
- return mParams;
+ public AsyncTask<?, ?, ?> getAsyncTask() {
+ return mAsyncTask;
}
@Override
@@ -106,13 +108,40 @@
}
}
+ private class DelayedExecutor implements Executor {
+ private final Object mNextLock = new Object();
+ @GuardedBy("mNextLock") private Object mNextIdentifier;
+ @GuardedBy("mNextLock") private AsyncTask<?, ?, ?> mNextTask;
+
+ @Override
+ public void execute(Runnable command) {
+ synchronized (mNextLock) {
+ mSubmittedTasks.add(new SubmittedTaskImpl(mNextIdentifier,
+ command, checkNotNull(mNextTask)));
+ mNextIdentifier = null;
+ mNextTask = null;
+ }
+ }
+
+ public <T> AsyncTask<T, ?, ?> submit(Object identifier,
+ AsyncTask<T, ?, ?> task, T... params) {
+ synchronized (mNextLock) {
+ checkState(mNextIdentifier == null);
+ checkState(mNextTask == null);
+ mNextIdentifier = identifier;
+ mNextTask = checkNotNull(task, "Already had a valid task.\n"
+ + "Are you calling AsyncTaskExecutor.submit(...) from within the "
+ + "onPreExecute() method of another task being submitted?\n"
+ + "Sorry! Not that's not supported.");
+ }
+ return task.executeOnExecutor(this, params);
+ }
+ }
+
@Override
public <T> AsyncTask<T, ?, ?> submit(Object identifier, AsyncTask<T, ?, ?> task, T... params) {
AsyncTaskExecutors.checkCalledFromUiThread();
- synchronized (mLock) {
- mSubmittedTasks.add(new SubmittedTaskImpl<T>(identifier, task, params));
- return task;
- }
+ return mBlockingExecutor.submit(identifier, task, params);
}
/**
@@ -125,8 +154,8 @@
* <p>
* This method blocks until the AsyncTask has completely finished executing.
*/
- public void runTask(Enum<?> identifier) throws InterruptedException {
- List<SubmittedTask<?>> tasks = getSubmittedTasksByIdentifier(identifier, true);
+ public void runTask(Object identifier) throws InterruptedException {
+ List<SubmittedTask> tasks = getSubmittedTasksByIdentifier(identifier, true);
Assert.assertEquals("Expected one task " + identifier + ", got " + tasks, 1, tasks.size());
runTask(tasks.get(0));
}
@@ -141,30 +170,21 @@
* <p>
* This method blocks until the AsyncTask objects have completely finished executing.
*/
- public void runAllTasks(Enum<?> identifier) throws InterruptedException {
- List<SubmittedTask<?>> tasks = getSubmittedTasksByIdentifier(identifier, true);
+ public void runAllTasks(Object identifier) throws InterruptedException {
+ List<SubmittedTask> tasks = getSubmittedTasksByIdentifier(identifier, true);
Assert.assertTrue("There were no tasks with identifier " + identifier, tasks.size() > 0);
- for (SubmittedTask<?> task : tasks) {
+ for (SubmittedTask task : tasks) {
runTask(task);
}
}
/**
- * Executes a single {@link AsyncTask} using the supplied executors.
+ * Executes a single {@link SubmittedTask}.
* <p>
* Blocks until the task has completed running.
*/
- private <T> void runTask(SubmittedTask<T> submittedTask) throws InterruptedException {
- final AsyncTask<T, ?, ?> task = submittedTask.getTask();
- task.executeOnExecutor(mExecutor, submittedTask.getParams());
- // Block until the task has finished running in the background.
- try {
- task.get(mTimeoutMs, TimeUnit.MILLISECONDS);
- } catch (ExecutionException e) {
- throw new RuntimeException(e.getCause());
- } catch (TimeoutException e) {
- throw new RuntimeException("waited too long");
- }
+ private <T> void runTask(final SubmittedTask submittedTask) throws InterruptedException {
+ submittedTask.getRunnable().run();
// Block until the onPostExecute or onCancelled has finished.
// Unfortunately we can't be sure when the AsyncTask will have posted its result handling
// code to the main ui thread, the best we can do is wait for the Status to be FINISHED.
@@ -172,7 +192,7 @@
class AsyncTaskHasFinishedRunnable implements Runnable {
@Override
public void run() {
- if (task.getStatus() == AsyncTask.Status.FINISHED) {
+ if (submittedTask.getAsyncTask().getStatus() == AsyncTask.Status.FINISHED) {
latch.countDown();
} else {
mInstrumentation.waitForIdle(this);
@@ -183,14 +203,14 @@
Assert.assertTrue(latch.await(mTimeoutMs, TimeUnit.MILLISECONDS));
}
- private List<SubmittedTask<?>> getSubmittedTasksByIdentifier(
- Enum<?> identifier, boolean remove) {
+ private List<SubmittedTask> getSubmittedTasksByIdentifier(
+ Object identifier, boolean remove) {
Preconditions.checkNotNull(identifier, "can't lookup tasks by 'null' identifier");
- List<SubmittedTask<?>> results = Lists.newArrayList();
+ List<SubmittedTask> results = Lists.newArrayList();
synchronized (mLock) {
- Iterator<SubmittedTask<?>> iter = mSubmittedTasks.iterator();
+ Iterator<SubmittedTask> iter = mSubmittedTasks.iterator();
while (iter.hasNext()) {
- SubmittedTask<?> task = iter.next();
+ SubmittedTask task = iter.next();
if (identifier.equals(task.getIdentifier())) {
results.add(task);
iter.remove();
diff --git a/tests/src/com/android/contacts/util/IntegrationTestUtils.java b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
index afea349..66dd4ef 100644
--- a/tests/src/com/android/contacts/util/IntegrationTestUtils.java
+++ b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
@@ -90,7 +90,7 @@
* Waits for an idle sync on the main thread (see {@link Instrumentation#waitForIdle(Runnable)})
* before executing this callable.
*/
- private <T> T runOnUiThreadAndGetTheResult(Callable<T> callable) throws Throwable {
+ public <T> T runOnUiThreadAndGetTheResult(Callable<T> callable) throws Throwable {
FutureTask<T> future = new FutureTask<T>(callable);
mInstrumentation.waitForIdle(future);
try {