Merge "Call log duration display for calls less than a minute." into mnc-dev
diff --git a/res/drawable-hdpi/ic_card_phone.png b/res/drawable-hdpi/ic_card_phone.png
deleted file mode 100644
index 5b29a32..0000000
--- a/res/drawable-hdpi/ic_card_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_delete_wht_24dp.png b/res/drawable-hdpi/ic_delete_24dp.png
similarity index 100%
rename from res/drawable-hdpi/ic_delete_wht_24dp.png
rename to res/drawable-hdpi/ic_delete_24dp.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_card_phone.png b/res/drawable-mdpi/ic_card_phone.png
deleted file mode 100644
index fb9ab44..0000000
--- a/res/drawable-mdpi/ic_card_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_delete_wht_24dp.png b/res/drawable-mdpi/ic_delete_24dp.png
similarity index 100%
rename from res/drawable-mdpi/ic_delete_wht_24dp.png
rename to res/drawable-mdpi/ic_delete_24dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_card_phone.png b/res/drawable-xhdpi/ic_card_phone.png
deleted file mode 100644
index 77df721..0000000
--- a/res/drawable-xhdpi/ic_card_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_delete_wht_24dp.png b/res/drawable-xhdpi/ic_delete_24dp.png
similarity index 100%
rename from res/drawable-xhdpi/ic_delete_wht_24dp.png
rename to res/drawable-xhdpi/ic_delete_24dp.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_card_phone.png b/res/drawable-xxhdpi/ic_card_phone.png
deleted file mode 100644
index d7e52ed..0000000
--- a/res/drawable-xxhdpi/ic_card_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_delete_wht_24dp.png b/res/drawable-xxhdpi/ic_delete_24dp.png
similarity index 100%
rename from res/drawable-xxhdpi/ic_delete_wht_24dp.png
rename to res/drawable-xxhdpi/ic_delete_24dp.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_card_phone.png b/res/drawable-xxxhdpi/ic_card_phone.png
deleted file mode 100644
index a938659..0000000
--- a/res/drawable-xxxhdpi/ic_card_phone.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_delete_wht_24dp.png b/res/drawable-xxxhdpi/ic_delete_24dp.png
similarity index 100%
rename from res/drawable-xxxhdpi/ic_delete_wht_24dp.png
rename to res/drawable-xxxhdpi/ic_delete_24dp.png
Binary files differ
diff --git a/res/drawable/ic_calllog_delete.xml b/res/drawable/ic_calllog_delete.xml
deleted file mode 100644
index 2f9f0ae..0000000
--- a/res/drawable/ic_calllog_delete.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_delete_wht_24dp"
- android:gravity="center"
- android:tint="@color/actionbar_icon_color" />
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index c077851..abc0fbb 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -13,91 +13,98 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/call_detail"
android:layout_width="match_parent"
- android:layout_height="match_parent" >
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:background="@color/background_dialer_call_log" >
+ <!-- Caller information "card" -->
<LinearLayout
- android:id="@+id/call_detail"
+ android:id="@+id/caller_information"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:background="@color/background_dialer_call_log" >
- <!-- Caller information "card" -->
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/call_detail_horizontal_margin"
+ android:paddingTop="@dimen/call_detail_top_margin"
+ android:paddingBottom="@dimen/call_detail_bottom_margin"
+ android:baselineAligned="false"
+ android:orientation="horizontal"
+ android:translationZ="@dimen/call_detail_translation_z"
+ android:focusable="true"
+ android:background="@color/background_dialer_white" >
+
+ <QuickContactBadge
+ android:id="@+id/quick_contact_photo"
+ android:layout_width="@dimen/contact_photo_size"
+ android:layout_height="@dimen/contact_photo_size"
+ android:layout_alignParentStart="true"
+ android:layout_gravity="top"
+ android:layout_marginTop="3dp"
+ android:focusable="true" />
+
<LinearLayout
- android:id="@+id/caller_information"
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:paddingStart="@dimen/call_detail_horizontal_margin"
- android:paddingTop="@dimen/call_detail_top_margin"
- android:paddingBottom="@dimen/call_detail_bottom_margin"
- android:baselineAligned="false"
- android:orientation="horizontal"
- android:translationZ="@dimen/call_detail_translation_z"
- android:focusable="true"
- android:background="@color/background_dialer_white" >
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:gravity="center_vertical"
+ android:layout_marginStart="@dimen/call_detail_horizontal_margin">
- <QuickContactBadge
- android:id="@+id/quick_contact_photo"
- android:layout_width="@dimen/contact_photo_size"
- android:layout_height="@dimen/contact_photo_size"
- android:layout_alignParentStart="true"
- android:layout_gravity="top"
- android:layout_marginTop="3dp"
- android:focusable="true"
- />
-
- <LinearLayout
+ <TextView
+ android:id="@+id/caller_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center_vertical"
- android:layout_marginStart="@dimen/call_detail_horizontal_margin"
- >
- <TextView
- android:id="@+id/caller_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?attr/call_log_primary_text_color"
- android:textSize="@dimen/call_log_primary_text_size"
- android:includeFontPadding="false"
- android:layout_marginBottom="5dp"
- android:singleLine="true"
- />
- <TextView
- android:id="@+id/caller_number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?attr/call_log_secondary_text_color"
- android:textSize="@dimen/call_log_secondary_text_size"
- android:layout_marginBottom="1dp"
- android:singleLine="true"
- />
- <TextView
- android:id="@+id/phone_account_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?attr/call_log_secondary_text_color"
- android:textSize="@dimen/call_log_secondary_text_size"
- android:singleLine="true"
- android:visibility="gone"
- />
- </LinearLayout>
+ android:textColor="?attr/call_log_primary_text_color"
+ android:textSize="@dimen/call_log_primary_text_size"
+ android:includeFontPadding="false"
+ android:layout_marginBottom="5dp"
+ android:singleLine="true" />
+
+ <TextView
+ android:id="@+id/caller_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?attr/call_log_secondary_text_color"
+ android:textSize="@dimen/call_log_secondary_text_size"
+ android:layout_marginBottom="1dp"
+ android:singleLine="true" />
+
+ <TextView
+ android:id="@+id/phone_account_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?attr/call_log_secondary_text_color"
+ android:textSize="@dimen/call_log_secondary_text_size"
+ android:singleLine="true"
+ android:visibility="gone" />
+
</LinearLayout>
- <!--
- The list view is under everything.
- It contains a first header element which is hidden under the controls UI.
- When scrolling, the controls move up until the name bar hits the top.
- -->
- <ListView
- android:id="@+id/history"
- android:layout_width="match_parent"
- android:layout_height="fill_parent"
- />
-
+ <ImageView
+ android:id="@+id/call_back_button"
+ android:layout_width="@dimen/call_button_dimen"
+ android:layout_height="@dimen/call_button_dimen"
+ android:layout_marginEnd="16dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:src="@drawable/ic_call_24dp"
+ android:scaleType="center"
+ android:tint="@color/recent_call_log_item_phone_icon_tint"
+ android:contentDescription="@string/description_call_log_call_action"
+ android:visibility="gone" />
</LinearLayout>
-</RelativeLayout>
+
+ <!--
+ The list view is under everything.
+ It contains a first header element which is hidden under the controls UI.
+ When scrolling, the controls move up until the name bar hits the top.
+ -->
+ <ListView
+ android:id="@+id/history"
+ android:layout_width="match_parent"
+ android:layout_height="fill_parent" />
+
+</LinearLayout>
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index af8cb8b..7fce595 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -138,14 +138,14 @@
<ImageView
android:id="@+id/call_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="@dimen/call_button_dimen"
+ android:layout_height="@dimen/call_button_dimen"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/call_log_icon_margin"
android:background="?android:attr/selectableItemBackgroundBorderless"
- android:src="@drawable/ic_card_phone"
+ android:src="@drawable/ic_call_24dp"
+ android:scaleType="center"
android:tint="@color/recent_call_log_item_phone_icon_tint"
- android:alpha="0.3"
android:contentDescription="@string/description_call_log_call_action"
android:visibility="gone" />
diff --git a/res/layout/call_log_list_item_actions.xml b/res/layout/call_log_list_item_actions.xml
index f1d0e9e..569048b 100644
--- a/res/layout/call_log_list_item_actions.xml
+++ b/res/layout/call_log_list_item_actions.xml
@@ -66,7 +66,7 @@
<TextView
style="@style/CallLogActionTextStyle"
- android:text="@string/search_shortcut_add_to_existing_contact" />
+ android:text="@string/search_shortcut_add_to_contact" />
</LinearLayout>
diff --git a/res/layout/voicemail_playback_layout.xml b/res/layout/voicemail_playback_layout.xml
index 96feba6..97bb5f8 100644
--- a/res/layout/voicemail_playback_layout.xml
+++ b/res/layout/voicemail_playback_layout.xml
@@ -27,11 +27,6 @@
android:layout_height="80dp"
android:layout_marginTop="@dimen/call_detail_button_spacing">
- <!-- SeekBar left-right margin decreased from redlines 72dp by 8dp to account for
- half thumb width (thumb is 16dp).
- Vertically, SeekBar and rate buttons should be below centre, position achieved by
- making them centred but giving a difference between top and bottom padding,
- difference is currently 10dp. -->
<SeekBar
android:id="@+id/playback_seek"
android:layout_width="match_parent"
@@ -61,15 +56,12 @@
</RelativeLayout>
- <!-- Playback, speakerphone buttons. -->
- <LinearLayout
- android:id="@+id/buttons_linear_layout"
+ <LinearLayout android:id="@+id/buttons_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
- <ImageButton
- android:id="@+id/playback_start_stop"
+ <ImageButton android:id="@+id/playback_start_stop"
android:layout_width="match_parent"
android:layout_height="58dp"
android:layout_marginEnd="@dimen/call_detail_button_spacing"
@@ -78,8 +70,7 @@
android:src="@drawable/ic_hold_pause"
android:contentDescription="@string/voicemail_play_start_pause" />
- <ImageButton
- android:id="@+id/playback_speakerphone"
+ <ImageButton android:id="@+id/playback_speakerphone"
android:layout_width="match_parent"
android:layout_height="58dp"
android:layout_weight="1"
@@ -87,6 +78,15 @@
android:src="@drawable/ic_speakerphone_on"
android:contentDescription="@string/description_playback_speakerphone" />
+ <ImageButton android:id="@+id/delete_voicemail"
+ android:layout_width="match_parent"
+ android:layout_height="58dp"
+ android:layout_weight="1"
+ android:background="?android:attr/selectableItemBackground"
+ android:src="@drawable/ic_delete_24dp"
+ android:tint="@color/voicemail_playback_icon_tint"
+ android:contentDescription="@string/recentCalls_trashVoicemail" />
+
</LinearLayout>
</LinearLayout>
diff --git a/res/menu/call_details_options.xml b/res/menu/call_details_options.xml
index a48687e..b98ec9e 100644
--- a/res/menu/call_details_options.xml
+++ b/res/menu/call_details_options.xml
@@ -14,23 +14,21 @@
limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/menu_trash"
- android:icon="@drawable/ic_calllog_delete"
+
+ <item android:id="@+id/menu_trash"
+ android:icon="@drawable/ic_delete_24dp"
android:showAsAction="ifRoom"
android:title="@string/recentCalls_trashVoicemail"
- android:onClick="onMenuTrashVoicemail"
- />
- <item
- android:id="@+id/menu_remove_from_call_log"
- android:icon="@drawable/ic_calllog_delete"
+ android:onClick="onMenuTrashVoicemail" />
+
+ <item android:id="@+id/menu_remove_from_call_log"
+ android:icon="@drawable/ic_delete_24dp"
android:showAsAction="ifRoom"
android:title="@string/recentCalls_removeFromRecentList"
- android:onClick="onMenuRemoveFromCallLog"
- />
- <item
- android:id="@+id/menu_edit_number_before_call"
+ android:onClick="onMenuRemoveFromCallLog" />
+
+ <item android:id="@+id/menu_edit_number_before_call"
android:title="@string/recentCalls_editNumberBeforeCall"
- android:onClick="onMenuEditNumberBeforeCall"
- />
+ android:onClick="onMenuEditNumberBeforeCall" />
+
</menu>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 86ac9be..352bce5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -36,8 +36,10 @@
<!-- Color of the text describing an unconsumed voicemail. -->
<color name="call_log_voicemail_highlight_color">#33b5e5</color>
- <!-- Tint of the recent card phone icon -->
- <color name="recent_call_log_item_phone_icon_tint">#000000</color>
+ <!-- Tint of the recent card phone icon; 30% black -->
+ <color name="recent_call_log_item_phone_icon_tint">#4d000000</color>
+
+ <color name="voicemail_playback_icon_tint">#8e8e8e</color>
<!--
Colour of voicemail progress bar to the right of position indicator.
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b36b9d6..9d987e8 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -132,4 +132,6 @@
<dimen name="preference_padding_bottom">16dp</dimen>
<dimen name="preference_side_margin">16dp</dimen>
<dimen name="preference_summary_line_spacing_extra">4dp</dimen>
+
+ <dimen name="call_button_dimen">36dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c661e58..b852be8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -51,7 +51,7 @@
<string name="recentCalls_editNumberBeforeCall">Edit number before call</string>
<!-- Menu item used to add a number from the call log to contacts -->
- <string name="recentCalls_addToContact">Add to contacts</string>
+ <string name="recentCalls_addToContact">Add to a contact</string>
<!-- Menu item used to remove a single call from the call log -->
<string name="recentCalls_removeFromRecentList">Delete from call history</string>
@@ -503,7 +503,7 @@
<!-- Shortcut item used to add a number to an existing contact directly from search.
[CHAR LIMIT=25] -->
- <string name="search_shortcut_add_to_contact">Add to contact</string>
+ <string name="search_shortcut_add_to_contact">Add to a contact</string>
<!-- Shortcut item used to send a text message directly from search. [CHAR LIMIT=25] -->
<string name="search_shortcut_send_sms_message">Send SMS</string>
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 6da7c79..15ba5df 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -77,8 +77,6 @@
public static final String EXTRA_CALL_LOG_IDS = "EXTRA_CALL_LOG_IDS";
/** If we are started with a voicemail, we'll find the uri to play with this extra. */
public static final String EXTRA_VOICEMAIL_URI = "EXTRA_VOICEMAIL_URI";
- /** If we should immediately start playback of the voicemail, this extra will be set to true. */
- public static final String EXTRA_VOICEMAIL_START_PLAYBACK = "EXTRA_VOICEMAIL_START_PLAYBACK";
/** If the activity was triggered from a notification. */
public static final String EXTRA_FROM_NOTIFICATION = "EXTRA_FROM_NOTIFICATION";
@@ -97,11 +95,9 @@
@Override
public void onGetCallDetails(PhoneCallDetails[] details) {
- Context context = CallDetailActivity.this;
-
if (details == null) {
// Somewhere went wrong: we're going to bail out and show error to users.
- Toast.makeText(context, R.string.toast_call_detail_error,
+ Toast.makeText(mContext, R.string.toast_call_detail_error,
Toast.LENGTH_SHORT).show();
finish();
return;
@@ -119,9 +115,9 @@
// Cache the details about the phone number.
final boolean canPlaceCallsTo =
- PhoneNumberUtilsWrapper.canPlaceCallsTo(mNumber, numberPresentation);
- final PhoneNumberUtilsWrapper phoneUtils = new PhoneNumberUtilsWrapper(context);
- final boolean isVoicemailNumber =
+ PhoneNumberUtilsWrapper.canPlaceCallsTo(mNumber, numberPresentation);
+ final PhoneNumberUtilsWrapper phoneUtils = new PhoneNumberUtilsWrapper(mContext);
+ mIsVoicemailNumber =
phoneUtils.isVoicemailNumber(accountHandle, mNumber);
final boolean isSipNumber = PhoneNumberUtilsWrapper.isSipNumber(mNumber);
@@ -144,7 +140,9 @@
}
}
- String accountLabel = PhoneAccountUtils.getAccountLabel(context, accountHandle);
+ mCallButton.setVisibility(canPlaceCallsTo ? View.VISIBLE : View.GONE);
+
+ String accountLabel = PhoneAccountUtils.getAccountLabel(mContext, accountHandle);
if (!TextUtils.isEmpty(accountLabel)) {
mAccountLabel.setText(accountLabel);
mAccountLabel.setVisibility(View.VISIBLE);
@@ -153,14 +151,14 @@
}
mHasEditNumberBeforeCallOption =
- canPlaceCallsTo && !isSipNumber && !isVoicemailNumber;
+ canPlaceCallsTo && !isSipNumber && !mIsVoicemailNumber;
mHasTrashOption = hasVoicemail();
mHasRemoveFromCallLogOption = !hasVoicemail();
invalidateOptionsMenu();
ListView historyList = (ListView) findViewById(R.id.history);
historyList.setAdapter(
- new CallDetailHistoryAdapter(context, mInflater, mCallTypeHelper, details));
+ new CallDetailHistoryAdapter(mContext, mInflater, mCallTypeHelper, details));
String lookupKey = contactUri == null ? null
: ContactInfoHelper.getLookupKeyFromUri(contactUri);
@@ -168,7 +166,7 @@
final boolean isBusiness = mContactInfoHelper.isBusiness(firstDetails.sourceType);
final int contactType =
- isVoicemailNumber ? ContactPhotoManager.TYPE_VOICEMAIL :
+ mIsVoicemailNumber ? ContactPhotoManager.TYPE_VOICEMAIL :
isBusiness ? ContactPhotoManager.TYPE_BUSINESS :
ContactPhotoManager.TYPE_DEFAULT;
@@ -201,14 +199,17 @@
}
};
+ private Context mContext;
private CallTypeHelper mCallTypeHelper;
private QuickContactBadge mQuickContactBadge;
private TextView mCallerName;
private TextView mCallerNumber;
private TextView mAccountLabel;
+ private View mCallButton;
private ContactInfoHelper mContactInfoHelper;
- private String mNumber = null;
+ private String mNumber;
+ private boolean mIsVoicemailNumber;
private String mDefaultCountryIso;
/* package */ LayoutInflater mInflater;
@@ -230,6 +231,8 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mContext = this;
+
setContentView(R.layout.call_detail);
mInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
@@ -248,6 +251,14 @@
mDefaultCountryIso = GeoUtil.getCurrentCountryIso(this);
mContactPhotoManager = ContactPhotoManager.getInstance(this);
+ mCallButton = (View) findViewById(R.id.call_back_button);
+ mCallButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ mContext.startActivity(IntentUtil.getCallIntent(mNumber));
+ }
+ });
+
mContactInfoHelper = new ContactInfoHelper(this, GeoUtil.getCurrentCountryIso(this));
getActionBar().setDisplayHomeAsUpEnabled(true);
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 845f911..d57d87a 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -191,6 +191,7 @@
setHasOptionsMenu(true);
mVoicemailPlaybackPresenter = new VoicemailPlaybackPresenter(activity, state);
+ activity.setVolumeControlStream(VoicemailPlaybackPresenter.PLAYBACK_STREAM);
}
/** Called by the CallLogQueryHandler when the list of calls has been fetched or updated. */
diff --git a/src/com/android/dialer/calllog/GroupingListAdapter.java b/src/com/android/dialer/calllog/GroupingListAdapter.java
index 501e88d..8d3ab45 100644
--- a/src/com/android/dialer/calllog/GroupingListAdapter.java
+++ b/src/com/android/dialer/calllog/GroupingListAdapter.java
@@ -253,7 +253,6 @@
* corresponding cursor position.
*/
public void obtainPositionMetadata(PositionMetadata metadata, int position) {
-
// If the description object already contains requested information, just return
if (metadata.listPosition == position) {
return;
@@ -433,17 +432,4 @@
return -1;
}
}
-
- /**
- * Used for setting the cursor without triggering a UI thread update.
- */
- @NeededForTesting
- public void setCursorForTesting(Cursor cursor) {
- if (cursor != null) {
- mCursor = cursor;
- cursor.registerContentObserver(mChangeObserver);
- cursor.registerDataSetObserver(mDataSetObserver);
- mRowIdColumnIndex = cursor.getColumnIndexOrThrow("_id");
- }
- }
}
diff --git a/src/com/android/dialer/calllog/IntentProvider.java b/src/com/android/dialer/calllog/IntentProvider.java
index d7a35e8..a11d00b 100644
--- a/src/com/android/dialer/calllog/IntentProvider.java
+++ b/src/com/android/dialer/calllog/IntentProvider.java
@@ -83,24 +83,6 @@
};
}
- public static IntentProvider getPlayVoicemailIntentProvider(final long rowId,
- final String voicemailUri) {
- return new IntentProvider() {
- @Override
- public Intent getIntent(Context context) {
- Intent intent = new Intent(context, CallDetailActivity.class);
- intent.setData(ContentUris.withAppendedId(
- Calls.CONTENT_URI_WITH_VOICEMAIL, rowId));
- if (voicemailUri != null) {
- intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI,
- Uri.parse(voicemailUri));
- }
- intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK, true);
- return intent;
- }
- };
- }
-
public static IntentProvider getSendSmsIntentProvider(final String number) {
return new IntentProvider() {
@Override
@@ -129,7 +111,6 @@
intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI,
Uri.parse(voicemailUri));
}
- intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_START_PLAYBACK, false);
if (extraIds != null && extraIds.length > 0) {
intent.putExtra(CallDetailActivity.EXTRA_CALL_LOG_IDS, extraIds);
diff --git a/src/com/android/dialer/list/AllContactsFragment.java b/src/com/android/dialer/list/AllContactsFragment.java
index eaa5cc8..71c6980 100644
--- a/src/com/android/dialer/list/AllContactsFragment.java
+++ b/src/com/android/dialer/list/AllContactsFragment.java
@@ -16,6 +16,7 @@
package com.android.dialer.list;
+import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -39,6 +40,8 @@
*/
public class AllContactsFragment extends ContactEntryListFragment<ContactEntryListAdapter> {
+ private View mEmptyListView;
+
public AllContactsFragment() {
setQuickContactEnabled(false);
setAdjustSelectionBoundsEnabled(true);
@@ -52,10 +55,11 @@
public void onViewCreated(View view, android.os.Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- View emptyListView = view.findViewById(R.id.empty_list_view);
- DialerUtils.configureEmptyListView(emptyListView, R.drawable.empty_contacts,
+ mEmptyListView = view.findViewById(R.id.empty_list_view);
+ DialerUtils.configureEmptyListView(mEmptyListView, R.drawable.empty_contacts,
R.string.all_contacts_empty, getResources());
- getListView().setEmptyView(emptyListView);
+ getListView().setEmptyView(mEmptyListView);
+ mEmptyListView.setVisibility(View.GONE);
ViewUtil.addBottomPaddingToListViewForFab(getListView(), getResources());
}
@@ -68,6 +72,15 @@
}
@Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ super.onLoadFinished(loader, data);
+
+ if (data.getCount() == 0) {
+ mEmptyListView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
protected ContactEntryListAdapter createListAdapter() {
if (!PermissionsUtil.hasContactsPermissions(getActivity())) {
return new EmptyContactsListAdapter(getActivity());
diff --git a/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java b/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
index 8a43023..17c573f 100644
--- a/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
+++ b/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
@@ -3,6 +3,8 @@
import android.content.Context;
import android.content.res.Resources;
import android.telephony.PhoneNumberUtils;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
import android.view.View;
import android.view.ViewGroup;
@@ -36,6 +38,8 @@
private final boolean[] mShortcutEnabled = new boolean[SHORTCUT_COUNT];
+ private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
+
public DialerPhoneNumberListAdapter(Context context) {
super(context);
@@ -141,7 +145,9 @@
final String number = getFormattedQueryString();
switch (shortcutType) {
case SHORTCUT_DIRECT_CALL:
- text = resources.getString(R.string.search_shortcut_call_number, number);
+ text = resources.getString(
+ R.string.search_shortcut_call_number,
+ mBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR));
drawableId = R.drawable.ic_search_phone;
break;
case SHORTCUT_CREATE_NEW_CONTACT:
diff --git a/src/com/android/dialer/settings/SoundSettingsFragment.java b/src/com/android/dialer/settings/SoundSettingsFragment.java
index 43297b5..c7bb2d3 100644
--- a/src/com/android/dialer/settings/SoundSettingsFragment.java
+++ b/src/com/android/dialer/settings/SoundSettingsFragment.java
@@ -28,6 +28,7 @@
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import com.android.dialer.R;
@@ -208,8 +209,9 @@
}
private boolean shouldHideCarrierSettings() {
- int hideCarrierNetworkSetting = Settings.Global.getInt(getActivity().getContentResolver(),
- Settings.Global.HIDE_CARRIER_NETWORK_SETTINGS, SHOW_CARRIER_SETTINGS);
- return hideCarrierNetworkSetting == HIDE_CARRIER_SETTINGS;
+ CarrierConfigManager configManager = (CarrierConfigManager) getActivity().getSystemService(
+ Context.CARRIER_CONFIG_SERVICE);
+ return configManager.getConfig().getBoolean(
+ CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL);
}
}
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
index 703004d..0313f40 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackLayout.java
@@ -37,6 +37,7 @@
import com.android.common.io.MoreCloseables;
import com.android.dialer.R;
+import com.android.dialer.calllog.CallLogAsyncTaskUtil;
import com.google.common.base.Preconditions;
@@ -124,7 +125,7 @@
/**
* Handle state changes when the user manipulates the seek bar.
*/
- private final OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener() {
+ private final OnSeekBarChangeListener mSeekBarChangeListener = new OnSeekBarChangeListener() {
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (mPresenter != null) {
@@ -148,7 +149,7 @@
/**
* Click listener to toggle speakerphone.
*/
- private final View.OnClickListener speakerphoneListener = new View.OnClickListener() {
+ private final View.OnClickListener mSpeakerphoneListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPresenter != null) {
@@ -160,7 +161,7 @@
/**
* Click listener to play or pause voicemail playback.
*/
- private final View.OnClickListener startStopButtonListener = new View.OnClickListener() {
+ private final View.OnClickListener mStartStopButtonListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mPresenter == null) {
@@ -175,6 +176,16 @@
}
};
+ private final View.OnClickListener mDeleteButtonListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view ) {
+ if (mPresenter == null) {
+ return;
+ }
+ CallLogAsyncTaskUtil.deleteVoicemail(mContext, mPresenter.getVoicemailUri(), null);
+ }
+ };
+
private Context mContext;
private VoicemailPlaybackPresenter mPresenter;
@@ -183,6 +194,7 @@
private SeekBar mPlaybackSeek;
private ImageButton mStartStopButton;
private ImageButton mPlaybackSpeakerphone;
+ private ImageButton mDeleteButton;
private TextView mPlaybackPosition;
private PositionUpdater mPositionUpdater;
@@ -212,11 +224,13 @@
mPlaybackSeek = (SeekBar) findViewById(R.id.playback_seek);
mStartStopButton = (ImageButton) findViewById(R.id.playback_start_stop);
mPlaybackSpeakerphone = (ImageButton) findViewById(R.id.playback_speakerphone);
+ mDeleteButton = (ImageButton) findViewById(R.id.delete_voicemail);
mPlaybackPosition = (TextView) findViewById(R.id.playback_position_text);
- mPlaybackSeek.setOnSeekBarChangeListener(seekBarChangeListener);
- mStartStopButton.setOnClickListener(startStopButtonListener);
- mPlaybackSpeakerphone.setOnClickListener(speakerphoneListener);
+ mPlaybackSeek.setOnSeekBarChangeListener(mSeekBarChangeListener);
+ mStartStopButton.setOnClickListener(mStartStopButtonListener);
+ mPlaybackSpeakerphone.setOnClickListener(mSpeakerphoneListener);
+ mDeleteButton.setOnClickListener(mDeleteButtonListener);
}
@Override
diff --git a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
index 99d2734..da2a29c 100644
--- a/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/dialer/voicemail/VoicemailPlaybackPresenter.java
@@ -98,7 +98,7 @@
VoicemailContract.Voicemails.HAS_CONTENT,
};
- private static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL;
+ public static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL;
private static final int NUMBER_OF_THREADS_IN_POOL = 2;
// Time to wait for content to be fetched before timing out.
private static final long FETCH_CONTENT_TIMEOUT_MS = 20000;
@@ -141,11 +141,12 @@
* This variable is thread-contained, accessed only on the ui thread.
*/
private FetchResultHandler mFetchResultHandler;
+ private Handler mHandler = new Handler();
private PowerManager.WakeLock mProximityWakeLock;
private AudioManager mAudioManager;
- public VoicemailPlaybackPresenter(Activity activity, Bundle savedInstanceState) {
- mContext = activity;
+ public VoicemailPlaybackPresenter(Context context, Bundle savedInstanceState) {
+ mContext = context;
mAsyncTaskExecutor = AsyncTaskExecutors.createAsyncTaskExecutor();
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
@@ -173,8 +174,6 @@
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setOnCompletionListener(this);
-
- activity.setVolumeControlStream(PLAYBACK_STREAM);
}
/**
@@ -204,7 +203,7 @@
public void onPause(boolean isFinishing) {
// Do not pause for orientation changes.
- if (mMediaPlayer.isPlaying() && isFinishing) {
+ if (mIsPrepared && mMediaPlayer.isPlaying() && isFinishing) {
pausePlayback();
}
@@ -298,13 +297,12 @@
* was not available.
*/
private void requestContent() {
- Preconditions.checkState(mFetchResultHandler == null, "mFetchResultHandler should be null");
+ if (mFetchResultHandler != null) {
+ mFetchResultHandler.destroy();
+ }
- Handler handler = new Handler();
- mFetchResultHandler = new FetchResultHandler(handler);
- mContext.getContentResolver().registerContentObserver(
- mVoicemailUri, false, mFetchResultHandler);
- handler.postDelayed(mFetchResultHandler.getTimeoutRunnable(), FETCH_CONTENT_TIMEOUT_MS);
+ mFetchResultHandler = new FetchResultHandler(new Handler());
+ mFetchResultHandler.registerContentObserver(mVoicemailUri);
// Send voicemail fetch request.
Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, mVoicemailUri);
@@ -313,30 +311,37 @@
@ThreadSafe
private class FetchResultHandler extends ContentObserver implements Runnable {
- private AtomicBoolean mResultStillPending = new AtomicBoolean(true);
- private final Handler mHandler;
+ private AtomicBoolean mIsWaitingForResult = new AtomicBoolean(true);
+ private final Handler mFetchResultHandler;
public FetchResultHandler(Handler handler) {
super(handler);
- mHandler = handler;
+ mFetchResultHandler = handler;
}
- public Runnable getTimeoutRunnable() {
- return this;
+ public void registerContentObserver(Uri voicemailUri) {
+ if (mIsWaitingForResult.get()) {
+ mContext.getContentResolver().registerContentObserver(
+ voicemailUri, false, this);
+ mFetchResultHandler.postDelayed(this, FETCH_CONTENT_TIMEOUT_MS);
+ }
}
+ /**
+ * Stop waiting for content and notify UI if {@link FETCH_CONTENT_TIMEOUT_MS} has elapsed.
+ */
@Override
public void run() {
- if (mResultStillPending.getAndSet(false)) {
- mContext.getContentResolver().unregisterContentObserver(FetchResultHandler.this);
+ if (mIsWaitingForResult.getAndSet(false)) {
+ mContext.getContentResolver().unregisterContentObserver(this);
mView.setFetchContentTimeout();
}
}
public void destroy() {
- if (mResultStillPending.getAndSet(false)) {
- mContext.getContentResolver().unregisterContentObserver(FetchResultHandler.this);
- mHandler.removeCallbacks(this);
+ if (mIsWaitingForResult.getAndSet(false)) {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ mFetchResultHandler.removeCallbacks(this);
}
}
@@ -352,7 +357,7 @@
@Override
public void onPostExecute(Boolean hasContent) {
if (hasContent) {
- if (mResultStillPending.getAndSet(false)) {
+ if (mIsWaitingForResult.getAndSet(false)) {
mContext.getContentResolver().unregisterContentObserver(
FetchResultHandler.this);
prepareToPlayContent();
@@ -556,6 +561,10 @@
return mAudioManager.isSpeakerphoneOn();
}
+ public Uri getVoicemailUri() {
+ return mVoicemailUri;
+ }
+
private static synchronized ScheduledExecutorService getScheduledExecutorServiceInstance() {
if (mScheduledExecutorService == null) {
mScheduledExecutorService = Executors.newScheduledThreadPool(NUMBER_OF_THREADS_IN_POOL);
@@ -563,4 +572,8 @@
return mScheduledExecutorService;
}
+ @VisibleForTesting
+ public boolean isPlaying() {
+ return mIsPlaying;
+ }
}
diff --git a/tests/src/com/android/dialer/CallDetailActivityTest.java b/tests/src/com/android/dialer/CallDetailActivityTest.java
index 97b1b09..3b6b611 100644
--- a/tests/src/com/android/dialer/CallDetailActivityTest.java
+++ b/tests/src/com/android/dialer/CallDetailActivityTest.java
@@ -17,13 +17,11 @@
package com.android.dialer;
import static com.android.dialer.calllog.CallLogAsyncTaskUtil.Tasks.GET_CALL_DETAILS;
-import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
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;
@@ -36,31 +34,19 @@
import com.android.dialer.calllog.CallLogAsyncTaskUtil;
import com.android.dialer.util.AsyncTaskExecutors;
import com.android.dialer.util.FakeAsyncTaskExecutor;
-import com.android.contacts.common.test.IntegrationTestUtils;
-import com.android.dialer.util.LocaleTestUtils;
import com.android.internal.view.menu.ContextMenuBuilder;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Locale;
-
/**
* Unit tests for the {@link CallDetailActivity}. NOTE: The screen needs to be on for the
* UI-related tests to pass.
*/
@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;
- private LocaleTestUtils mLocaleTestUtils;
private FakeAsyncTaskExecutor mFakeAsyncTaskExecutor;
private CallDetailActivity mActivityUnderTest;
@@ -71,91 +57,25 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+
mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation());
AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory());
+
// I don't like the default of focus-mode for tests, the green focus border makes the
// screenshots look weak.
setActivityInitialTouchMode(true);
- mTestUtils = new IntegrationTestUtils(getInstrumentation());
- // Some of the tests rely on the text that appears on screen - safest to force a
- // specific locale.
- mLocaleTestUtils = new LocaleTestUtils(getInstrumentation().getTargetContext());
- mLocaleTestUtils.setLocale(Locale.US);
}
@Override
protected void tearDown() throws Exception {
- mLocaleTestUtils.restoreLocale();
- mLocaleTestUtils = null;
cleanUpUri();
- mTestUtils = null;
+
AsyncTaskExecutors.setFactoryForTest(null);
CallLogAsyncTaskUtil.resetForTest();
+
super.tearDown();
}
- public void testInitialActivityStartsWithFetchingVoicemail() throws Throwable {
- setActivityIntentForRealFileVoicemailEntry();
- startActivityUnderTest();
- // When the activity first starts, we will show "Loading voicemail" on the screen.
- // The duration should not be visible.
- assertHasOneTextViewContaining("Loading voicemail");
- assertZeroTextViewsContaining("00:00");
- }
-
- public void testWhenCheckForContentCompletes() throws Throwable {
- setActivityIntentForRealFileVoicemailEntry();
- startActivityUnderTest();
- // There is a background check that is testing to see if we have the content available.
- // Once that task completes, we shouldn't be showing the fetching message.
- mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
-
- // The voicemail async call may or may not return before we check the asserts.
- assertHasOneTextViewContaining("Buffering", "00:00");
- assertZeroTextViewsContaining("Loading voicemail");
- }
-
- public void testInvalidVoicemailShowsErrorMessage() throws Throwable {
- setActivityIntentForTestVoicemailEntry();
- startActivityUnderTest();
- mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
- // The media player will have thrown an IOException since the file doesn't exist.
- // This should have put a failed to play message on screen, buffering is gone.
- assertHasOneTextViewContaining("Couldn't play voicemail");
- assertZeroTextViewsContaining("Buffering");
- }
-
- public void testOnResumeDoesNotCreateManyFragments() throws Throwable {
- // There was a bug where every time the activity was resumed, a new fragment was created.
- // Before the fix, this was failing reproducibly with at least 3 "Buffering" views.
- setActivityIntentForRealFileVoicemailEntry();
- startActivityUnderTest();
- mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
- getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- getInstrumentation().callActivityOnPause(mActivityUnderTest);
- getInstrumentation().callActivityOnResume(mActivityUnderTest);
- getInstrumentation().callActivityOnPause(mActivityUnderTest);
- getInstrumentation().callActivityOnResume(mActivityUnderTest);
- }
- });
- assertHasOneTextViewContaining("Buffering", "00:00");
- }
-
- /**
- * Test for bug where increase rate button with invalid voicemail causes a crash.
- * <p>
- * The repro steps for this crash were to open a voicemail that does not have an attachment,
- * then click the play button (which just reported an error), then after that try to adjust the
- * rate. See http://b/5047879.
- */
- public void testClickIncreaseRateButtonWithInvalidVoicemailDoesNotCrash() throws Throwable {
- setActivityIntentForTestVoicemailEntry();
- startActivityUnderTest();
- mTestUtils.clickButton(mActivityUnderTest, R.id.playback_start_stop);
- }
-
/** Test for bug where missing Extras on intent used to start Activity causes NPE. */
public void testCallLogUriWithMissingExtrasShouldNotCauseNPE() throws Throwable {
setActivityIntentForTestCallEntry();
@@ -170,35 +90,32 @@
public void testVoicemailDoesNotHaveRemoveFromCallLog() throws Throwable {
setActivityIntentForTestVoicemailEntry();
startActivityUnderTest();
+ mFakeAsyncTaskExecutor.runTask(GET_CALL_DETAILS);
+
Menu menu = new ContextMenuBuilder(mActivityUnderTest);
mActivityUnderTest.onCreateOptionsMenu(menu);
mActivityUnderTest.onPrepareOptionsMenu(menu);
assertFalse(menu.findItem(R.id.menu_remove_from_call_log).isVisible());
+ assertTrue(menu.findItem(R.id.menu_trash).isVisible());
}
- /** Test to check that I haven't broken the remove-from-call-log entry from regular calls. */
+ /**
+ * Test to check that I haven't broken the remove-from-call-log entry from regular calls.
+ */
public void testRegularCallDoesHaveRemoveFromCallLog() throws Throwable {
setActivityIntentForTestCallEntry();
startActivityUnderTest();
+ mFakeAsyncTaskExecutor.runTask(GET_CALL_DETAILS);
+
Menu menu = new ContextMenuBuilder(mActivityUnderTest);
mActivityUnderTest.onCreateOptionsMenu(menu);
mActivityUnderTest.onPrepareOptionsMenu(menu);
assertTrue(menu.findItem(R.id.menu_remove_from_call_log).isVisible());
- }
-
- @Suppress
- public void testClickingCallStopsPlayback() throws Throwable {
- setActivityIntentForRealFileVoicemailEntry();
- startActivityUnderTest();
- mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
- mTestUtils.clickButton(mActivityUnderTest, R.id.playback_speakerphone);
- mTestUtils.clickButton(mActivityUnderTest, R.id.playback_start_stop);
- 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.
+ assertFalse(menu.findItem(R.id.menu_trash).isVisible());
}
private void setActivityIntentForTestCallEntry() {
+ assertNull(mVoicemailUri);
assertNull(mCallLogUri);
ContentResolver contentResolver = getContentResolver();
ContentValues values = new ContentValues();
@@ -225,36 +142,6 @@
setActivityIntent(intent);
}
- private void setActivityIntentForRealFileVoicemailEntry() throws IOException {
- assertNull(mVoicemailUri);
- 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();
- try (InputStream inputStream = assets.open(TEST_ASSET_NAME);
- OutputStream outputStream = getContentResolver().openOutputStream(mVoicemailUri)) {
- copyBetweenStreams(inputStream, outputStream);
- }
- 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;
- while ((bytesRead = in.read(buffer)) > 0) {
- out.write(buffer, 0, bytesRead);
- }
- }
-
private void cleanUpUri() {
if (mVoicemailUri != null) {
getContentResolver().delete(VoicemailContract.Voicemails.CONTENT_URI,
@@ -272,41 +159,9 @@
return getInstrumentation().getTargetContext().getContentResolver();
}
- private TextView assertHasOneTextViewContaining(String text) throws Throwable {
- assertNotNull(mActivityUnderTest);
- List<TextView> views = mTestUtils.getTextViewsWithString(mActivityUnderTest, text);
- assertEquals("There should have been one TextView with text '" + text + "' but found "
- + views, 1, views.size());
- return views.get(0);
- }
-
- private void assertHasOneTextViewContaining(String text1, String text2) throws Throwable {
- assertNotNull(mActivityUnderTest);
- List<TextView> view1s = mTestUtils.getTextViewsWithString(mActivityUnderTest, text1);
- List<TextView> view2s = mTestUtils.getTextViewsWithString(mActivityUnderTest, text2);
- assertEquals("There should have been one TextView with text '" + text1 + "' or text '"
- + text2 + "' but found " + view1s + view2s, 1, view1s.size() + view2s.size());
- }
-
- private void assertZeroTextViewsContaining(String text) throws Throwable {
- assertNotNull(mActivityUnderTest);
- List<TextView> views = mTestUtils.getTextViewsWithString(mActivityUnderTest, text);
- assertEquals("There should have been no TextViews with text '" + text + "' but found "
- + views, 0, views.size());
- }
-
private void startActivityUnderTest() throws Throwable {
assertNull(mActivityUnderTest);
mActivityUnderTest = getActivity();
assertNotNull("activity should not be null", mActivityUnderTest);
- // We have to run all tasks, not just one.
- // This is because it seems that we can have onResume, onPause, onResume during the course
- // of a single unit test.
- mFakeAsyncTaskExecutor.runAllTasks(GET_CALL_DETAILS);
- CallLogAsyncTaskUtil.resetForTest();
- }
-
- private AssetManager getAssets() {
- return getInstrumentation().getContext().getAssets();
}
}
diff --git a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
index 71554d6..3f66d58 100644
--- a/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogFragmentTest.java
@@ -129,7 +129,14 @@
mAdapter.pauseCache();
mParentView = new FrameLayout(mActivity);
mCursor = new MatrixCursor(CallLogQuery._PROJECTION);
- mAdapter.setCursorForTesting(mCursor);
+
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mAdapter.changeCursor(mCursor);
+ }
+ });
+ getInstrumentation().waitForIdleSync();
}
/**
@@ -316,7 +323,6 @@
public void testBindView_CallButton() {
mCursor.moveToFirst();
insert(TEST_NUMBER, Calls.PRESENTATION_ALLOWED, NOW, 0, Calls.INCOMING_TYPE);
- mAdapter.changeCursor(mCursor);
CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder)
mAdapter.onCreateViewHolder(mParentView, /* viewType */ 0);
bindViewForTest(viewHolder);
diff --git a/tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java b/tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java
new file mode 100644
index 0000000..dd86b0d
--- /dev/null
+++ b/tests/src/com/android/dialer/voicemail/VoicemailPlaybackTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2015 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.dialer.voicemail;
+
+import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.net.Uri;
+import android.provider.VoicemailContract;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.contacts.common.test.IntegrationTestUtils;
+import com.android.dialer.R;
+import com.android.dialer.util.AsyncTaskExecutors;
+import com.android.dialer.util.FakeAsyncTaskExecutor;
+import com.android.dialer.util.LocaleTestUtils;
+import com.android.dialer.voicemail.VoicemailPlaybackLayout;
+import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Unit tests for the {@link VoicemailPlaybackPresenter} and {@link VoicemailPlaybackLayout}.
+ */
+@LargeTest
+public class VoicemailPlaybackTest extends InstrumentationTestCase {
+ 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 Context mContext;
+ private VoicemailPlaybackPresenter mPresenter;
+ private VoicemailPlaybackLayout mLayout;
+
+ private Uri mVoicemailUri;
+ private IntegrationTestUtils mTestUtils;
+ private LocaleTestUtils mLocaleTestUtils;
+ private FakeAsyncTaskExecutor mFakeAsyncTaskExecutor;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation());
+ AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory());
+ mTestUtils = new IntegrationTestUtils(getInstrumentation());
+
+ // Some of the tests rely on the text - safest to force a specific locale.
+ mLocaleTestUtils = new LocaleTestUtils(getInstrumentation().getTargetContext());
+ mLocaleTestUtils.setLocale(Locale.US);
+
+ mContext = getInstrumentation().getTargetContext();
+ mLayout = new VoicemailPlaybackLayout(mContext);
+ mLayout.onFinishInflate();
+ mPresenter = new VoicemailPlaybackPresenter(mContext, null);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ cleanUpVoicemailUri();
+
+ mLocaleTestUtils.restoreLocale();
+ mLocaleTestUtils = null;
+
+ mLayout = null;
+ mPresenter = null;
+ mTestUtils = null;
+ AsyncTaskExecutors.setFactoryForTest(null);
+
+ super.tearDown();
+ }
+
+ public void testFetchingVoicemail() throws Throwable {
+ setUriForRealFileVoicemailEntry();
+ setPlaybackViewForPresenter();
+ assertHasOneTextViewContaining("Loading voicemail");
+ }
+
+ public void testWhenCheckForContentCompletes() throws Throwable {
+ setUriForRealFileVoicemailEntry();
+ setPlaybackViewForPresenter();
+
+ // There is a background check that is testing to see if we have the content available.
+ // Once that task completes, we shouldn't be showing the fetching message.
+ mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
+
+ assertHasOneTextViewContaining("Buffering");
+ assertHasZeroTextViewsContaining("Loading voicemail");
+ }
+
+ public void testInvalidVoicemailShowsErrorMessage() throws Throwable {
+ setUriForInvalidVoicemailEntry();
+ setPlaybackViewForPresenter();
+
+ mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
+
+ // The media player will have thrown an IOException since the file doesn't exist.
+ // This should have put a failed to play message on screen, buffering is gone.
+ assertHasOneTextViewContaining("Couldn't play voicemail");
+ assertHasZeroTextViewsContaining("Buffering");
+ }
+
+ public void testClickingSpeakerphoneButton() throws Throwable {
+ setUriForRealFileVoicemailEntry();
+ setPlaybackViewForPresenter();
+
+ // Wait for check for content to complete.
+ mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
+ getInstrumentation().waitForIdleSync();
+
+ // Force the speakerphone to false to start.
+ mPresenter.setSpeakerphoneOn(false);
+ assertFalse(mPresenter.isSpeakerphoneOn());
+
+ View speakerphoneButton = mLayout.findViewById(R.id.playback_speakerphone);
+ speakerphoneButton.performClick();
+ assertTrue(mPresenter.isSpeakerphoneOn());
+ }
+
+ private void cleanUpVoicemailUri() {
+ if (mVoicemailUri != null) {
+ getContentResolver().delete(VoicemailContract.Voicemails.CONTENT_URI,
+ "_ID = ?", new String[] { String.valueOf(ContentUris.parseId(mVoicemailUri)) });
+ mVoicemailUri = null;
+ }
+ }
+
+ private void setUriForRealFileVoicemailEntry() throws IOException {
+ assertNull(mVoicemailUri);
+ 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();
+ try (InputStream inputStream = assets.open(TEST_ASSET_NAME);
+ OutputStream outputStream = getContentResolver().openOutputStream(mVoicemailUri)) {
+ copyBetweenStreams(inputStream, outputStream);
+ }
+ }
+
+ private void setUriForInvalidVoicemailEntry() {
+ assertNull(mVoicemailUri);
+ ContentResolver contentResolver = getContentResolver();
+ ContentValues values = new ContentValues();
+ 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);
+ }
+
+ private void setPlaybackViewForPresenter() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mPresenter.setPlaybackView(mLayout, mVoicemailUri, false);
+ }
+ });
+ }
+
+ public void copyBetweenStreams(InputStream in, OutputStream out) throws IOException {
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = in.read(buffer)) > 0) {
+ out.write(buffer, 0, bytesRead);
+ }
+ }
+
+ private void assertHasOneTextViewContaining(String text) throws Throwable {
+ assertNotNull(mLayout);
+ List<TextView> views = mTestUtils.getTextViewsWithString(mLayout, text);
+ assertEquals("There should have been one TextView with text '" + text + "' but found "
+ + views, 1, views.size());
+ }
+
+ private void assertHasZeroTextViewsContaining(String text) throws Throwable {
+ assertNotNull(mLayout);
+ List<TextView> views = mTestUtils.getTextViewsWithString(mLayout, text);
+ assertEquals("There should have been no TextViews with text '" + text + "' but found "
+ + views, 0, views.size());
+ }
+
+ private ContentResolver getContentResolver() {
+ return getInstrumentation().getTargetContext().getContentResolver();
+ }
+
+ private AssetManager getAssets() {
+ return getInstrumentation().getContext().getAssets();
+ }
+}