summaryrefslogtreecommitdiff
path: root/src/com/android/dialer/calllog
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/dialer/calllog')
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java52
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java2
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemHelper.java203
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemViews.java12
4 files changed, 220 insertions, 49 deletions
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index a668196c5..32699e654 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -183,9 +183,11 @@ public class CallLogAdapter extends GroupingListAdapter
/** Can be set to true by tests to disable processing of requests. */
private volatile boolean mRequestProcessingDisabled = false;
- /** True if CallLogAdapter is created from the PhoneFavoriteFragment, where the primary
- * action should be set to call a number instead of opening the detail page. */
- private boolean mUseCallAsPrimaryAction = false;
+ /**
+ * Whether to show the secondary action button used to play voicemail or show call details.
+ * True if created from a CallLogFragment.
+ * False if created from the PhoneFavoriteFragment. */
+ private boolean mShowSecondaryActionButton = true;
private boolean mIsCallLog = true;
private int mNumMissedCalls = 0;
@@ -246,14 +248,14 @@ public class CallLogAdapter extends GroupingListAdapter
};
public CallLogAdapter(Context context, CallFetcher callFetcher,
- ContactInfoHelper contactInfoHelper, boolean useCallAsPrimaryAction,
+ ContactInfoHelper contactInfoHelper, boolean showSecondaryActionButton,
boolean isCallLog) {
super(context);
mContext = context;
mCallFetcher = callFetcher;
mContactInfoHelper = contactInfoHelper;
- mUseCallAsPrimaryAction = useCallAsPrimaryAction;
+ mShowSecondaryActionButton = showSecondaryActionButton;
mIsCallLog = isCallLog;
mContactInfoCache = ExpirableCache.create(CONTACT_INFO_CACHE_SIZE);
@@ -508,7 +510,7 @@ public class CallLogAdapter extends GroupingListAdapter
// Get the views to bind to.
CallLogListItemViews views = CallLogListItemViews.fromView(view);
views.primaryActionView.setOnClickListener(mActionListener);
- views.secondaryActionView.setOnClickListener(mActionListener);
+ views.secondaryActionButtonView.setOnClickListener(mActionListener);
view.setTag(views);
}
@@ -535,31 +537,30 @@ public class CallLogAdapter extends GroupingListAdapter
final ContactInfo cachedContactInfo = getContactInfoFromCallLog(c);
- if (!mUseCallAsPrimaryAction) {
- // Sets the primary action to open call detail page.
- views.primaryActionView.setTag(
- IntentProvider.getCallDetailIntentProvider(
- getCursor(), c.getPosition(), c.getLong(CallLogQuery.ID), count));
- } else if (PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation)) {
+ // Primary action is always to call, if possible.
+ if (PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation)) {
// Sets the primary action to call the number.
views.primaryActionView.setTag(IntentProvider.getReturnCallIntentProvider(number));
} else {
views.primaryActionView.setTag(null);
}
- // Store away the voicemail information so we can play it directly.
- if (callType == Calls.VOICEMAIL_TYPE) {
- String voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
- final long rowId = c.getLong(CallLogQuery.ID);
- views.secondaryActionView.setTag(
- IntentProvider.getPlayVoicemailIntentProvider(rowId, voicemailUri));
- } else if (!TextUtils.isEmpty(number)) {
- // Store away the number so we can call it directly if you click on the call icon.
- views.secondaryActionView.setTag(
- IntentProvider.getReturnCallIntentProvider(number));
+ if ( mShowSecondaryActionButton ) {
+ // Store away the voicemail information so we can play it directly.
+ if (callType == Calls.VOICEMAIL_TYPE) {
+ String voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
+ final long rowId = c.getLong(CallLogQuery.ID);
+ views.secondaryActionButtonView.setTag(
+ IntentProvider.getPlayVoicemailIntentProvider(rowId, voicemailUri));
+ } else {
+ // Store the call details information.
+ views.secondaryActionButtonView.setTag(
+ IntentProvider.getCallDetailIntentProvider(
+ getCursor(), c.getPosition(), c.getLong(CallLogQuery.ID), count));
+ }
} else {
// No action enabled.
- views.secondaryActionView.setTag(null);
+ views.secondaryActionButtonView.setTag(null);
}
// Lookup contacts with this number
@@ -624,7 +625,7 @@ public class CallLogAdapter extends GroupingListAdapter
// New items also use the highlighted version of the text.
final boolean isHighlighted = isNew;
mCallLogViewsHelper.setPhoneCallDetails(views, details, isHighlighted,
- mUseCallAsPrimaryAction);
+ mShowSecondaryActionButton);
if (photoId == 0 && photoUri != null) {
setPhoto(views, photoUri, lookupUri);
@@ -632,9 +633,6 @@ public class CallLogAdapter extends GroupingListAdapter
setPhoto(views, photoId, lookupUri);
}
- views.quickContactView.setContentDescription(views.phoneCallDetailsViews.nameView.
- getText());
-
// Listen for the first draw
if (mViewTreeObserver == null) {
mViewTreeObserver = view.getViewTreeObserver();
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 826abe11d..9526f392b 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -235,7 +235,7 @@ public class CallLogFragment extends ListFragment
updateEmptyMessage(mCallTypeFilter);
String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
mAdapter = ObjectFactory.newCallLogAdapter(getActivity(), this, new ContactInfoHelper(
- getActivity(), currentCountryIso), false, true);
+ getActivity(), currentCountryIso), true, true);
setListAdapter(mAdapter);
getListView().setItemsCanFocus(true);
}
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index a38ef012b..a85cd019e 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -17,6 +17,7 @@
package com.android.dialer.calllog;
import android.content.res.Resources;
+import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.text.TextUtils;
import android.view.View;
@@ -55,37 +56,201 @@ import com.android.dialer.R;
* @param views the views to populate
* @param details the details of a phone call needed to fill in the data
* @param isHighlighted whether to use the highlight text for the call
+ * @param showSecondaryActionButton whether to show the secondary action button or not
*/
public void setPhoneCallDetails(CallLogListItemViews views, PhoneCallDetails details,
- boolean isHighlighted, boolean useCallAsPrimaryAction) {
+ boolean isHighlighted, boolean showSecondaryActionButton) {
mPhoneCallDetailsHelper.setPhoneCallDetails(views.phoneCallDetailsViews, details,
isHighlighted);
- boolean canCall = PhoneNumberUtilsWrapper.canPlaceCallsTo(details.number,
- details.numberPresentation);
boolean canPlay = details.callTypes[0] == Calls.VOICEMAIL_TYPE;
- if (canPlay) {
- // Playback action takes preference.
- configurePlaySecondaryAction(views, isHighlighted);
- } else if (canCall && !useCallAsPrimaryAction) {
- // Call is the secondary action.
- configureCallSecondaryAction(views, details);
+ // Set the accessibility text for the contact badge
+ views.quickContactView.setContentDescription(getContactBadgeDescription(details));
+
+ // Set the primary action accessibility description
+ views.primaryActionView.setContentDescription(getCallDescription(details));
+
+ // If secondary action is visible, either show voicemail playback icon, or
+ // show the "clock" icon corresponding to the call details screen.
+ if (showSecondaryActionButton) {
+ if (canPlay) {
+ // Playback action takes preference.
+ configurePlaySecondaryAction(views, isHighlighted);
+ } else {
+ // Call details is the secondary action.
+ configureCallDetailsSecondaryAction(views, details);
+ }
} else {
- // No action available.
+ // No secondary action is to be shown (ie this is likely a PhoneFavoriteFragment)
views.secondaryActionView.setVisibility(View.GONE);
}
}
- /** Sets the secondary action to correspond to the call button. */
- private void configureCallSecondaryAction(CallLogListItemViews views,
+ /**
+ * Sets the secondary action to invoke call details.
+ *
+ * @param views the views to populate
+ * @param details the details of a phone call needed to fill in the call details data
+ */
+ private void configureCallDetailsSecondaryAction(CallLogListItemViews views,
PhoneCallDetails details) {
views.secondaryActionView.setVisibility(View.VISIBLE);
- views.secondaryActionView.setImageResource(R.drawable.ic_phone_dk);
- views.secondaryActionView.setContentDescription(getCallActionDescription(details));
+ // Use the small dark grey clock icon.
+ views.secondaryActionButtonView.setImageResource(R.drawable.ic_menu_history_dk);
+ views.secondaryActionButtonView.setContentDescription(
+ mResources.getString(R.string.description_call_details));
+ }
+
+ /**
+ * Returns the accessibility description for the contact badge for a call log entry.
+ *
+ * @param details Details of call.
+ * @return Accessibility description.
+ */
+ private CharSequence getContactBadgeDescription(PhoneCallDetails details) {
+ return mResources.getString(R.string.description_contact_details, getNameOrNumber(details));
}
- /** Returns the description used by the call action for this phone call. */
- private CharSequence getCallActionDescription(PhoneCallDetails details) {
+ /**
+ * Returns the accessibility description of the "return call/call" action for a call log
+ * entry.
+ * Accessibility text is a combination of:
+ * {Voicemail Prefix}. {Number of Calls}. {Caller information}.
+ * If most recent call is a voicemail, {Voicemail Prefix} is "New Voicemail.", otherwise "".
+ *
+ * If more than one call for the caller, {Number of Calls} is:
+ * "{number of calls} calls.", otherwise "".
+ *
+ * The {Caller Information} references the most recent call associated with the caller.
+ * For incoming calls:
+ * If missed call: Return missed call from {Name/Number} {Call Type} {Call Time}.
+ * If answered call: Return answered call from {Name/Number} {Call Type} {Call Time}.
+ *
+ * For unknown callers, drop the "Return" part, since the call can't be returned:
+ * If answered unknown: Answered call from {Name/Number} {Call Time}.
+ * If missed unknown: Missed call from {Name/Number} {Call Time}.
+ *
+ * For outgoing calls:
+ * If outgoing: Call {Name/Number] {Call Type}. {Last} called {Call Time}.
+ * Where {Last} is dropped if the number of calls for the caller is 1.
+ *
+ * Where:
+ * {Name/Number} is the name or number of the caller (as shown in call log).
+ * {Call type} is the contact phone number type (eg mobile) or location.
+ * {Call Time} is the time since the last call for the contact occurred.
+ *
+ * Examples:
+ * 3 calls. New Voicemail. Return missed call from Joe Smith mobile 2 hours ago.
+ * 2 calls. Call John Doe mobile. Last called 1 hour ago.
+ * @param details Details of call.
+ * @return Return call action description.
+ */
+ public CharSequence getCallDescription(PhoneCallDetails details) {
+ int lastCallType = getLastCallType(details.callTypes);
+ boolean isVoiceMail = lastCallType == Calls.VOICEMAIL_TYPE;
+
+ // Get the name or number of the caller.
+ final CharSequence nameOrNumber = getNameOrNumber(details);
+
+ // Get the call type or location of the caller; null if not applicable
+ final CharSequence typeOrLocation = mPhoneCallDetailsHelper.getCallTypeOrLocation(details);
+
+ // Get the time/date of the call
+ final CharSequence timeOfCall = mPhoneCallDetailsHelper.getCallDate(details);
+
+ StringBuilder callDescription = new StringBuilder();
+
+ // Prepend the voicemail indication.
+ if (isVoiceMail) {
+ callDescription.append(mResources.getString(R.string.description_new_voicemail));
+ }
+
+ // Add number of calls if more than one.
+ if (details.callTypes.length > 1) {
+ callDescription.append(mResources.getString(R.string.description_num_calls,
+ details.callTypes.length));
+ }
+
+ int stringID = getCallDescriptionStringID(details);
+
+ // Use chosen string resource to build up the message.
+ callDescription.append(mResources.getString(stringID,
+ nameOrNumber,
+ // If no type or location can be determined, sub in empty string.
+ typeOrLocation == null ? "" : typeOrLocation,
+ timeOfCall));
+
+ return callDescription;
+ }
+
+ /**
+ * Determine the appropriate string ID to describe a call for accessibility purposes.
+ *
+ * @param details Call details.
+ * @return String resource ID to use.
+ */
+ public int getCallDescriptionStringID(PhoneCallDetails details) {
+ int lastCallType = getLastCallType(details.callTypes);
+ boolean isNumberCallable = PhoneNumberUtilsWrapper.canPlaceCallsTo(details.number,
+ details.numberPresentation);
+
+ // Default string to use is "call XYZ..." just in case we manage to fall through.
+ int stringID = R.string.description_call_last_multiple;
+
+ if (!isNumberCallable) {
+ // Number isn't callable; this is an incoming call from an unknown caller.
+ // An uncallable outgoing call wouldn't be in the call log.
+
+ // Voicemail and missed calls are both considered missed.
+ if (lastCallType == Calls.VOICEMAIL_TYPE ||
+ lastCallType == Calls.MISSED_TYPE) {
+ stringID = R.string.description_unknown_missed_call;
+ } else if (lastCallType == Calls.INCOMING_TYPE) {
+ stringID = R.string.description_unknown_answered_call;
+ }
+ } else {
+ // Known caller, so callable.
+
+ // Missed call (ie voicemail or missed)
+ if (lastCallType == Calls.VOICEMAIL_TYPE ||
+ lastCallType == Calls.MISSED_TYPE) {
+ stringID = R.string.description_return_missed_call;
+ } else if (lastCallType == Calls.INCOMING_TYPE) {
+ // Incoming answered.
+ stringID = R.string.description_return_answered_call;
+ } else {
+ // Outgoing call.
+
+ // If we have a history of multiple calls
+ if (details.callTypes.length > 1) {
+ stringID = R.string.description_call_last_multiple;
+ } else {
+ stringID = R.string.description_call_last;
+ }
+ }
+ }
+ return stringID;
+ }
+
+ /**
+ * Determine the call type for the most recent call.
+ * @param callTypes Call types to check.
+ * @return Call type.
+ */
+ private int getLastCallType(int[] callTypes) {
+ if (callTypes.length > 0) {
+ return callTypes[0];
+ } else {
+ return Calls.MISSED_TYPE;
+ }
+ }
+
+ /**
+ * Return the name or number of the caller specified by the details.
+ * @param details Call details
+ * @return the name (if known) of the caller, otherwise the formatted number.
+ */
+ private CharSequence getNameOrNumber(PhoneCallDetails details) {
final CharSequence recipient;
if (!TextUtils.isEmpty(details.name)) {
recipient = details.name;
@@ -93,15 +258,15 @@ import com.android.dialer.R;
recipient = mPhoneNumberHelper.getDisplayNumber(
details.number, details.numberPresentation, details.formattedNumber);
}
- return mResources.getString(R.string.description_call, recipient);
+ return recipient;
}
/** Sets the secondary action to correspond to the play button. */
private void configurePlaySecondaryAction(CallLogListItemViews views, boolean isHighlighted) {
views.secondaryActionView.setVisibility(View.VISIBLE);
- views.secondaryActionView.setImageResource(
+ views.secondaryActionButtonView.setImageResource(
isHighlighted ? R.drawable.ic_play_active_holo_dark : R.drawable.ic_play_holo_light);
- views.secondaryActionView.setContentDescription(
+ views.secondaryActionButtonView.setContentDescription(
mResources.getString(R.string.description_call_log_play_button));
}
}
diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViews.java
index ed6218f86..a3789569e 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViews.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViews.java
@@ -34,19 +34,25 @@ public final class CallLogListItemViews {
public final QuickContactBadge quickContactView;
/** The primary action view of the entry. */
public final View primaryActionView;
+ /** The secondary action view, which includes both the vertical divider line and
+ * the action button itself. Used so that the button and divider line can be
+ * made visible/hidden as a whole. */
+ public final View secondaryActionView;
/** The secondary action button on the entry. */
- public final ImageView secondaryActionView;
+ public final ImageView secondaryActionButtonView;
/** The details of the phone call. */
public final PhoneCallDetailsViews phoneCallDetailsViews;
/** The text of the header of a section. */
public final TextView listHeaderTextView;
private CallLogListItemViews(QuickContactBadge quickContactView, View primaryActionView,
- ImageView secondaryActionView, PhoneCallDetailsViews phoneCallDetailsViews,
+ View secondaryActionView, ImageView secondaryActionButtonView,
+ PhoneCallDetailsViews phoneCallDetailsViews,
TextView listHeaderTextView) {
this.quickContactView = quickContactView;
this.primaryActionView = primaryActionView;
this.secondaryActionView = secondaryActionView;
+ this.secondaryActionButtonView = secondaryActionButtonView;
this.phoneCallDetailsViews = phoneCallDetailsViews;
this.listHeaderTextView = listHeaderTextView;
}
@@ -55,6 +61,7 @@ public final class CallLogListItemViews {
return new CallLogListItemViews(
(QuickContactBadge) view.findViewById(R.id.quick_contact_photo),
view.findViewById(R.id.primary_action_view),
+ view.findViewById(R.id.secondary_action_view),
(ImageView) view.findViewById(R.id.secondary_action_icon),
PhoneCallDetailsViews.fromView(view),
(TextView) view.findViewById(R.id.call_log_header));
@@ -65,6 +72,7 @@ public final class CallLogListItemViews {
return new CallLogListItemViews(
new QuickContactBadge(context),
new View(context),
+ new View(context),
new ImageView(context),
PhoneCallDetailsViews.createForTest(context),
new TextView(context));