Remove "Remove from call log" from menu for voicemails.
- When looking at a voicemail we shouldn't remove from call log, because
we can just hit the trash button.
Bug: 5054103
Change-Id: I97c5870f12a7d495d2c49bb94f0795a1b3e12f9e
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 14fec85..324ab20 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -169,7 +169,6 @@
});
}
-
@Override
public void onResume() {
super.onResume();
@@ -184,24 +183,31 @@
* playback. If it doesn't, then hide the voicemail ui.
*/
private void optionallyHandleVoicemail() {
- Uri voicemailUri = getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI);
- FragmentManager manager = getFragmentManager();
- VoicemailPlaybackFragment fragment = (VoicemailPlaybackFragment) manager.findFragmentById(
- R.id.voicemail_playback_fragment);
- if (voicemailUri != null) {
- // Has voicemail uri: leave the fragment visible. Optionally start the playback.
+ if (hasVoicemail()) {
+ // Has voicemail: leave the fragment visible. Optionally start the playback.
// Do a query to fetch the voicemail status messages.
boolean startPlayback = getIntent().getBooleanExtra(
EXTRA_VOICEMAIL_START_PLAYBACK, false);
- fragment.setVoicemailUri(voicemailUri, startPlayback);
+ Uri voicemailUri = getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI);
+ getVoicemailPlaybackFragment().setVoicemailUri(voicemailUri, startPlayback);
mAsyncQueryHandler.startVoicemailStatusQuery(voicemailUri);
} else {
// No voicemail uri: hide the voicemail fragment and the status view.
- manager.beginTransaction().hide(fragment).commit();
+ getFragmentManager().beginTransaction().hide(getVoicemailPlaybackFragment()).commit();
mStatusMessageView.setVisibility(View.GONE);
}
}
+ private boolean hasVoicemail() {
+ return getIntent().getParcelableExtra(EXTRA_VOICEMAIL_URI) != null;
+ }
+
+ private VoicemailPlaybackFragment getVoicemailPlaybackFragment() {
+ FragmentManager manager = getFragmentManager();
+ return (VoicemailPlaybackFragment) manager.findFragmentById(
+ R.id.voicemail_playback_fragment);
+ }
+
/**
* Returns the list of URIs to show.
* <p>
@@ -349,24 +355,27 @@
}
// This action deletes all elements in the group from the call log.
- actions.add(new ViewEntry(android.R.drawable.ic_menu_close_clear_cancel,
- getString(R.string.recentCalls_removeFromRecentList),
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- StringBuilder callIds = new StringBuilder();
- for (Uri callUri : callUris) {
- if (callIds.length() != 0) {
- callIds.append(",");
+ // We don't have this action for voicemails, because you can just use the trash button.
+ if (!hasVoicemail()) {
+ actions.add(new ViewEntry(android.R.drawable.ic_menu_close_clear_cancel,
+ getString(R.string.recentCalls_removeFromRecentList),
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ StringBuilder callIds = new StringBuilder();
+ for (Uri callUri : callUris) {
+ if (callIds.length() != 0) {
+ callIds.append(",");
+ }
+ callIds.append(ContentUris.parseId(callUri));
}
- callIds.append(ContentUris.parseId(callUri));
- }
- getContentResolver().delete(Calls.CONTENT_URI_WITH_VOICEMAIL,
- Calls._ID + " IN (" + callIds + ")", null);
- finish();
- }
- }));
+ getContentResolver().delete(Calls.CONTENT_URI_WITH_VOICEMAIL,
+ Calls._ID + " IN (" + callIds + ")", null);
+ finish();
+ }
+ }));
+ }
if (canPlaceCallsTo && !isSipNumber && !isVoicemailNumber) {
// "Edit the number before calling" is only available for PSTN numbers.
diff --git a/tests/src/com/android/contacts/CallDetailActivityTest.java b/tests/src/com/android/contacts/CallDetailActivityTest.java
index a36216e..665bc92 100644
--- a/tests/src/com/android/contacts/CallDetailActivityTest.java
+++ b/tests/src/com/android/contacts/CallDetailActivityTest.java
@@ -17,6 +17,7 @@
package com.android.contacts;
import com.android.contacts.util.IntegrationTestUtils;
+import com.android.contacts.util.LocaleTestUtils;
import com.google.common.base.Preconditions;
import android.app.Activity;
@@ -28,6 +29,8 @@
import android.provider.CallLog;
import android.test.ActivityInstrumentationTestCase2;
+import java.util.Locale;
+
/**
* Unit tests for the {@link CallDetailActivity}.
*/
@@ -35,6 +38,7 @@
private static final String FAKE_VOICEMAIL_URI_STRING = "content://fake_uri";
private Uri mUri;
private IntegrationTestUtils mTestUtils;
+ private LocaleTestUtils mLocaleTestUtils;
public CallDetailActivityTest() {
super(CallDetailActivity.class);
@@ -47,10 +51,16 @@
// 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;
super.tearDown();
@@ -61,7 +71,7 @@
* <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.
+ * rate. See http://b/5047879.
*/
public void testClickIncreaseRateButtonWithInvalidVoicemailDoesNotCrash() throws Throwable {
setActivityIntentForTestVoicemailEntry();
@@ -76,6 +86,28 @@
getActivity();
}
+ /**
+ * Test for bug where voicemails should not have remove-from-call-log entry.
+ * <p>
+ * See http://b/5054103.
+ */
+ public void testVoicemailDoesNotHaveRemoveFromCallLog() throws Throwable {
+ setActivityIntentForTestVoicemailEntry();
+ getActivity();
+ assertEquals(0, countTextViewsContaining("Remove from call log"));
+ }
+
+ /** Test to check that I haven't broken the remove-from-call-log entry from regular calls. */
+ public void testRegularCallDoesHaveRemoveFromCallLog() throws Throwable {
+ setActivityIntentForTestCallEntry();
+ getActivity();
+ assertEquals(1, countTextViewsContaining("Remove from call log"));
+ }
+
+ private int countTextViewsContaining(String text) throws Throwable {
+ return mTestUtils.getTextViewsWithString(getActivity(), text).size();
+ }
+
private void setActivityIntentForTestCallEntry() {
createTestCallEntry(false);
setActivityIntent(new Intent(Intent.ACTION_VIEW, mUri));
diff --git a/tests/src/com/android/contacts/util/IntegrationTestUtils.java b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
index 45dc981..a61ea57 100644
--- a/tests/src/com/android/contacts/util/IntegrationTestUtils.java
+++ b/tests/src/com/android/contacts/util/IntegrationTestUtils.java
@@ -27,9 +27,13 @@
import android.content.Context;
import android.os.PowerManager;
import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
import junit.framework.Assert;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -118,4 +122,55 @@
}
}
}
+
+ /**
+ * Gets all {@link TextView} objects whose {@link TextView#getText()} contains the given text as
+ * a substring.
+ */
+ public List<TextView> getTextViewsWithString(final Activity activity, final String text)
+ throws Throwable {
+ return runOnUiThreadAndGetTheResult(new Callable<List<TextView>>() {
+ @Override
+ public List<TextView> call() throws Exception {
+ List<TextView> matchingViews = new ArrayList<TextView>();
+ for (TextView textView : getAllViews(TextView.class, getRootView(activity))) {
+ if (textView.getText().toString().contains(text)) {
+ matchingViews.add(textView);
+ }
+ }
+ return matchingViews;
+ }
+ });
+ }
+
+ /** Find the root view for a given activity. */
+ public static View getRootView(Activity activity) {
+ return activity.findViewById(android.R.id.content).getRootView();
+ }
+
+ /**
+ * Gets a list of all views of a given type, rooted at the given parent.
+ * <p>
+ * This method will recurse down through all {@link ViewGroup} instances looking for
+ * {@link View} instances of the supplied class type. Specifically it will use the
+ * {@link Class#isAssignableFrom(Class)} method as the test for which views to add to the list,
+ * so if you provide {@code View.class} as your type, you will get every view. The parent itself
+ * will be included also, should it be of the right type.
+ * <p>
+ * This call manipulates the ui, and as such should only be called from the application's main
+ * thread.
+ */
+ private static <T extends View> List<T> getAllViews(final Class<T> clazz, final View parent) {
+ List<T> results = new ArrayList<T>();
+ if (parent.getClass().equals(clazz)) {
+ results.add(clazz.cast(parent));
+ }
+ if (parent instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) parent;
+ for (int i = 0; i < viewGroup.getChildCount(); ++i) {
+ results.addAll(getAllViews(clazz, viewGroup.getChildAt(i)));
+ }
+ }
+ return results;
+ }
}