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/CallLogAsyncTaskUtil.java144
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemHelper.java6
-rw-r--r--src/com/android/dialer/calllog/CallLogQueryHandler.java3
-rw-r--r--src/com/android/dialer/calllog/CallTypeHelper.java35
-rw-r--r--src/com/android/dialer/calllog/CallTypeIconsView.java10
-rw-r--r--src/com/android/dialer/calllog/PhoneCallDetailsHelper.java72
6 files changed, 209 insertions, 61 deletions
diff --git a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
index aa994d25a..89932ffce 100644
--- a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
+++ b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
@@ -31,6 +31,7 @@ import android.util.Log;
import com.android.contacts.common.GeoUtil;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.PhoneCallDetails;
+import com.android.dialer.util.AppCompatConstants;
import com.android.dialer.util.AsyncTaskExecutor;
import com.android.dialer.util.AsyncTaskExecutors;
import com.android.dialer.util.PhoneNumberUtil;
@@ -45,6 +46,7 @@ public class CallLogAsyncTaskUtil {
public enum Tasks {
DELETE_VOICEMAIL,
DELETE_CALL,
+ MARK_BLOCKED,
MARK_VOICEMAIL_READ,
GET_CALL_DETAILS,
}
@@ -79,12 +81,31 @@ public class CallLogAsyncTaskUtil {
static final int TRANSCRIPTION_COLUMN_INDEX = 11;
}
+ private static class CallLogMarkBlockedQuery {
+ static final String[] PROJECTION = new String[] {
+ CallLog.Calls._ID,
+ CallLog.Calls.DATE
+ };
+
+ static final int ID_COLUMN_INDEX = 0;
+ static final int DATE_COLUMN_INDEX = 1;
+ }
+
public interface CallLogAsyncTaskListener {
public void onDeleteCall();
public void onDeleteVoicemail();
public void onGetCallDetails(PhoneCallDetails[] details);
}
+ public interface OnCallLogQueryFinishedListener {
+ public void onQueryFinished(boolean hasEntry);
+ }
+
+ // Try to identify if a call log entry corresponds to a number which was blocked. We match by
+ // by comparing its creation time to the time it was added in the InCallUi and seeing if they
+ // fall within a certain threshold.
+ private static final int MATCH_BLOCKED_CALL_THRESHOLD_MS = 1500;
+
private static AsyncTaskExecutor sAsyncTaskExecutor;
private static void initTaskExecutor() {
@@ -156,8 +177,8 @@ public class CallLogAsyncTaskUtil {
boolean isVoicemail = PhoneNumberUtil.isVoicemailNumber(context, accountHandle, number);
boolean shouldLookupNumber =
PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation) && !isVoicemail;
-
ContactInfo info = ContactInfo.EMPTY;
+
if (shouldLookupNumber) {
ContactInfo lookupInfo = contactInfoHelper.lookupNumber(number, countryIso);
info = lookupInfo != null ? lookupInfo : ContactInfo.EMPTY;
@@ -205,7 +226,7 @@ public class CallLogAsyncTaskUtil {
*
* @param context The context.
* @param callIds String of the callIds to delete from the call log, delimited by commas (",").
- * @param callLogAsyncTaskListenerg The listener to invoke after the entries have been deleted.
+ * @param callLogAsyncTaskListener The listener to invoke after the entries have been deleted.
*/
public static void deleteCalls(
final Context context,
@@ -215,26 +236,88 @@ public class CallLogAsyncTaskUtil {
initTaskExecutor();
}
- sAsyncTaskExecutor.submit(Tasks.DELETE_CALL,
- new AsyncTask<Void, Void, Void>() {
- @Override
- public Void doInBackground(Void... params) {
- context.getContentResolver().delete(
- TelecomUtil.getCallLogUri(context),
- CallLog.Calls._ID + " IN (" + callIds + ")", null);
- return null;
- }
+ sAsyncTaskExecutor.submit(Tasks.DELETE_CALL, new AsyncTask<Void, Void, Void>() {
+ @Override
+ public Void doInBackground(Void... params) {
+ context.getContentResolver().delete(
+ TelecomUtil.getCallLogUri(context),
+ CallLog.Calls._ID + " IN (" + callIds + ")", null);
+ return null;
+ }
- @Override
- public void onPostExecute(Void result) {
- if (callLogAsyncTaskListener != null) {
- callLogAsyncTaskListener.onDeleteCall();
- }
+ @Override
+ public void onPostExecute(Void result) {
+ if (callLogAsyncTaskListener != null) {
+ callLogAsyncTaskListener.onDeleteCall();
+ }
+ }
+ });
+ }
+
+ /**
+ * Marks last call made by the number the call type of the specified call as BLOCKED in the call log.
+ *
+ * @param context The context.
+ * @param number Number of which to mark the most recent call as BLOCKED.
+ * @param timeAddedMs The time the number was added to InCall, in milliseconds.
+ * @param listener The listener to invoke after looking up for a call log entry matching the
+ * number and time added.
+ */
+ public static void markCallAsBlocked(
+ final Context context,
+ final String number,
+ final long timeAddedMs,
+ final OnCallLogQueryFinishedListener listener) {
+ if (sAsyncTaskExecutor == null) {
+ initTaskExecutor();
+ }
+
+ sAsyncTaskExecutor.submit(Tasks.MARK_BLOCKED, new AsyncTask<Void, Void, Long>() {
+ @Override
+ public Long doInBackground(Void... params) {
+ // First, lookup the call log entry of the most recent call with this number.
+ Cursor cursor = context.getContentResolver().query(
+ TelecomUtil.getCallLogUri(context),
+ CallLogMarkBlockedQuery.PROJECTION,
+ CallLog.Calls.NUMBER + "= ?",
+ new String[] { number },
+ CallLog.Calls.DATE + " DESC LIMIT 1");
+
+ // If found, return the call log entry id.
+ if (cursor.moveToFirst()) {
+ long creationTime = cursor.getLong(CallLogMarkBlockedQuery.DATE_COLUMN_INDEX);
+ if (timeAddedMs > creationTime
+ && timeAddedMs - creationTime < MATCH_BLOCKED_CALL_THRESHOLD_MS) {
+ return cursor.getLong(CallLogMarkBlockedQuery.ID_COLUMN_INDEX);
}
- });
+ }
+ return (long) -1;
+ }
+
+ @Override
+ public void onPostExecute(Long callLogEntryId) {
+ if (listener != null) {
+ listener.onQueryFinished(callLogEntryId >= 0);
+ }
+
+ if (callLogEntryId < 0) {
+ return;
+ }
+ // Then, update that call log entry to have type BLOCKED.
+ final ContentValues values = new ContentValues();
+ values.put(CallLog.Calls.TYPE, AppCompatConstants.CALLS_BLOCKED_TYPE);
+
+ context.getContentResolver().update(
+ TelecomUtil.getCallLogUri(context),
+ values,
+ CallLog.Calls._ID + "= ?",
+ new String[] { Long.toString(callLogEntryId) });
+ }
+ });
}
+
public static void markVoicemailAsRead(final Context context, final Uri voicemailUri) {
if (sAsyncTaskExecutor == null) {
initTaskExecutor();
@@ -266,21 +349,20 @@ public class CallLogAsyncTaskUtil {
initTaskExecutor();
}
- sAsyncTaskExecutor.submit(Tasks.DELETE_VOICEMAIL,
- new AsyncTask<Void, Void, Void>() {
- @Override
- public Void doInBackground(Void... params) {
- context.getContentResolver().delete(voicemailUri, null, null);
- return null;
- }
+ sAsyncTaskExecutor.submit(Tasks.DELETE_VOICEMAIL, new AsyncTask<Void, Void, Void>() {
+ @Override
+ public Void doInBackground(Void... params) {
+ context.getContentResolver().delete(voicemailUri, null, null);
+ return null;
+ }
- @Override
- public void onPostExecute(Void result) {
- if (callLogAsyncTaskListener != null) {
- callLogAsyncTaskListener.onDeleteVoicemail();
- }
- }
- });
+ @Override
+ public void onPostExecute(Void result) {
+ if (callLogAsyncTaskListener != null) {
+ callLogAsyncTaskListener.onDeleteVoicemail();
+ }
+ }
+ });
}
@VisibleForTesting
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index d18e274ba..8e45dd36f 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -24,6 +24,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.dialer.PhoneCallDetails;
+import com.android.dialer.util.AppCompatConstants;
import com.android.dialer.R;
/**
@@ -220,11 +221,12 @@ import com.android.dialer.R;
int lastCallType = getLastCallType(callTypes);
int stringID;
- if (lastCallType == Calls.VOICEMAIL_TYPE || lastCallType == Calls.MISSED_TYPE) {
+ if (lastCallType == AppCompatConstants.CALLS_VOICEMAIL_TYPE
+ || lastCallType == AppCompatConstants.CALLS_MISSED_TYPE) {
//Message: Missed call from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
//<PhoneAccount>.
stringID = R.string.description_incoming_missed_call;
- } else if (lastCallType == Calls.INCOMING_TYPE) {
+ } else if (lastCallType == AppCompatConstants.CALLS_INCOMING_TYPE) {
//Message: Answered call from <NameOrNumber>, <TypeOrLocation>, <TimeOfCall>,
//<PhoneAccount>.
stringID = R.string.description_incoming_answered_call;
diff --git a/src/com/android/dialer/calllog/CallLogQueryHandler.java b/src/com/android/dialer/calllog/CallLogQueryHandler.java
index 771df99e2..81e49d2d4 100644
--- a/src/com/android/dialer/calllog/CallLogQueryHandler.java
+++ b/src/com/android/dialer/calllog/CallLogQueryHandler.java
@@ -36,6 +36,7 @@ import android.util.Log;
import com.android.contacts.common.database.NoNullCursorAsyncQueryHandler;
import com.android.contacts.common.util.PermissionsUtil;
+import com.android.dialer.util.AppCompatConstants;
import com.android.dialer.util.TelecomUtil;
import com.android.dialer.voicemail.VoicemailStatusHelperImpl;
@@ -180,7 +181,7 @@ public class CallLogQueryHandler extends NoNullCursorAsyncQueryHandler {
selectionArgs.add(Integer.toString(callType));
} else {
where.append(" AND NOT ");
- where.append("(" + Calls.TYPE + " = " + Calls.VOICEMAIL_TYPE + ")");
+ where.append("(" + Calls.TYPE + " = " + AppCompatConstants.CALLS_VOICEMAIL_TYPE + ")");
}
if (newerThan > 0) {
diff --git a/src/com/android/dialer/calllog/CallTypeHelper.java b/src/com/android/dialer/calllog/CallTypeHelper.java
index 36c0975bd..acc114c5c 100644
--- a/src/com/android/dialer/calllog/CallTypeHelper.java
+++ b/src/com/android/dialer/calllog/CallTypeHelper.java
@@ -17,9 +17,9 @@
package com.android.dialer.calllog;
import android.content.res.Resources;
-import android.provider.CallLog.Calls;
import com.android.dialer.R;
+import com.android.dialer.util.AppCompatConstants;
/**
* Helper class to perform operations related to call types.
@@ -39,6 +39,10 @@ public class CallTypeHelper {
private final CharSequence mMissedVideoName;
/** Name used to identify voicemail calls. */
private final CharSequence mVoicemailName;
+ /** Name used to identify rejected calls. */
+ private final CharSequence mRejectedName;
+ /** Name used to identify blocked calls. */
+ private final CharSequence mBlockedName;
/** Color used to identify new missed calls. */
private final int mNewMissedColor;
/** Color used to identify new voicemail calls. */
@@ -53,6 +57,8 @@ public class CallTypeHelper {
mOutgoingVideoName = resources.getString(R.string.type_outgoing_video);
mMissedVideoName = resources.getString(R.string.type_missed_video);
mVoicemailName = resources.getString(R.string.type_voicemail);
+ mRejectedName = resources.getString(R.string.type_rejected);
+ mBlockedName = resources.getString(R.string.type_blocked);
mNewMissedColor = resources.getColor(R.color.call_log_missed_call_highlight_color);
mNewVoicemailColor = resources.getColor(R.color.call_log_voicemail_highlight_color);
}
@@ -60,30 +66,36 @@ public class CallTypeHelper {
/** Returns the text used to represent the given call type. */
public CharSequence getCallTypeText(int callType, boolean isVideoCall) {
switch (callType) {
- case Calls.INCOMING_TYPE:
+ case AppCompatConstants.CALLS_INCOMING_TYPE:
if (isVideoCall) {
return mIncomingVideoName;
} else {
return mIncomingName;
}
- case Calls.OUTGOING_TYPE:
+ case AppCompatConstants.CALLS_OUTGOING_TYPE:
if (isVideoCall) {
return mOutgoingVideoName;
} else {
return mOutgoingName;
}
- case Calls.MISSED_TYPE:
+ case AppCompatConstants.CALLS_MISSED_TYPE:
if (isVideoCall) {
return mMissedVideoName;
} else {
return mMissedName;
}
- case Calls.VOICEMAIL_TYPE:
+ case AppCompatConstants.CALLS_VOICEMAIL_TYPE:
return mVoicemailName;
+ case AppCompatConstants.CALLS_REJECTED_TYPE:
+ return mRejectedName;
+
+ case AppCompatConstants.CALLS_BLOCKED_TYPE:
+ return mBlockedName;
+
default:
return mMissedName;
}
@@ -92,18 +104,18 @@ public class CallTypeHelper {
/** Returns the color used to highlight the given call type, null if not highlight is needed. */
public Integer getHighlightedColor(int callType) {
switch (callType) {
- case Calls.INCOMING_TYPE:
+ case AppCompatConstants.CALLS_INCOMING_TYPE:
// New incoming calls are not highlighted.
return null;
- case Calls.OUTGOING_TYPE:
+ case AppCompatConstants.CALLS_OUTGOING_TYPE:
// New outgoing calls are not highlighted.
return null;
- case Calls.MISSED_TYPE:
+ case AppCompatConstants.CALLS_MISSED_TYPE:
return mNewMissedColor;
- case Calls.VOICEMAIL_TYPE:
+ case AppCompatConstants.CALLS_VOICEMAIL_TYPE:
return mNewVoicemailColor;
default:
@@ -115,7 +127,8 @@ public class CallTypeHelper {
}
public static boolean isMissedCallType(int callType) {
- return (callType != Calls.INCOMING_TYPE && callType != Calls.OUTGOING_TYPE &&
- callType != Calls.VOICEMAIL_TYPE);
+ return (callType != AppCompatConstants.CALLS_INCOMING_TYPE
+ && callType != AppCompatConstants.CALLS_OUTGOING_TYPE
+ && callType != AppCompatConstants.CALLS_VOICEMAIL_TYPE);
}
}
diff --git a/src/com/android/dialer/calllog/CallTypeIconsView.java b/src/com/android/dialer/calllog/CallTypeIconsView.java
index 31d4f4b0e..d680cfe42 100644
--- a/src/com/android/dialer/calllog/CallTypeIconsView.java
+++ b/src/com/android/dialer/calllog/CallTypeIconsView.java
@@ -23,13 +23,13 @@ import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.provider.CallLog.Calls;
import android.util.AttributeSet;
import android.view.View;
import com.android.contacts.common.testing.NeededForTesting;
import com.android.contacts.common.util.BitmapUtil;
import com.android.dialer.R;
+import com.android.dialer.util.AppCompatConstants;
import com.google.common.collect.Lists;
import java.util.List;
@@ -106,13 +106,13 @@ public class CallTypeIconsView extends View {
private Drawable getCallTypeDrawable(int callType) {
switch (callType) {
- case Calls.INCOMING_TYPE:
+ case AppCompatConstants.CALLS_INCOMING_TYPE:
return mResources.incoming;
- case Calls.OUTGOING_TYPE:
+ case AppCompatConstants.CALLS_OUTGOING_TYPE:
return mResources.outgoing;
- case Calls.MISSED_TYPE:
+ case AppCompatConstants.CALLS_MISSED_TYPE:
return mResources.missed;
- case Calls.VOICEMAIL_TYPE:
+ case AppCompatConstants.CALLS_VOICEMAIL_TYPE:
return mResources.voicemail;
default:
// It is possible for users to end up with calls with unknown call types in their
diff --git a/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java
index 54324cdde..37920565a 100644
--- a/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java
+++ b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java
@@ -16,11 +16,11 @@
package com.android.dialer.calllog;
+import com.google.common.collect.Lists;
+
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telecom.PhoneAccount;
@@ -34,16 +34,15 @@ import com.android.contacts.common.util.PhoneNumberHelper;
import com.android.dialer.PhoneCallDetails;
import com.android.dialer.R;
import com.android.dialer.util.DialerUtils;
-import com.android.dialer.util.PhoneNumberUtil;
-
-import com.google.common.collect.Lists;
import java.util.ArrayList;
+import java.util.Calendar;
/**
* Helper class to fill in the views in {@link PhoneCallDetailsViews}.
*/
public class PhoneCallDetailsHelper {
+
/** The maximum number of icons will be shown to represent the call types in a group. */
private static final int MAX_CALL_TYPE_ICONS = 3;
@@ -53,6 +52,9 @@ public class PhoneCallDetailsHelper {
private Long mCurrentTimeMillisForTest;
private final TelecomCallLogCache mTelecomCallLogCache;
+ /** Calendar used to construct dates */
+ private final Calendar mCalendar;
+
/**
* List of items to be concatenated together for accessibility descriptions
*/
@@ -72,6 +74,7 @@ public class PhoneCallDetailsHelper {
mContext = context;
mResources = resources;
mTelecomCallLogCache = telecomCallLogCache;
+ mCalendar = Calendar.getInstance();
}
/** Fills the call details views with content. */
@@ -178,6 +181,7 @@ public class PhoneCallDetailsHelper {
* For a call, if there is an associated contact for the caller, return the known call type
* (e.g. mobile, home, work). If there is no associated contact, attempt to use the caller's
* location if known.
+ *
* @param details Call details to use.
* @return Type of call (mobile/home) if known, or the location of the caller (if known).
*/
@@ -205,16 +209,62 @@ public class PhoneCallDetailsHelper {
}
/**
- * Get the call date/time of the call, relative to the current time.
- * e.g. 3 minutes ago
+ * Get the call date/time of the call. For the call log this is relative to the current time.
+ * e.g. 3 minutes ago. For voicemail, see {@link #getGranularDateTime(PhoneCallDetails)}
+ *
* @param details Call details to use.
* @return String representing when the call occurred.
*/
public CharSequence getCallDate(PhoneCallDetails details) {
- return DateUtils.getRelativeTimeSpanString(details.date,
- getCurrentTimeMillis(),
- DateUtils.MINUTE_IN_MILLIS,
- DateUtils.FORMAT_ABBREV_RELATIVE);
+ if (details.callTypes[0] == Calls.VOICEMAIL_TYPE) {
+ return getGranularDateTime(details);
+ }
+
+ return DateUtils.getRelativeTimeSpanString(details.date, getCurrentTimeMillis(),
+ DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE);
+ }
+
+ /**
+ * Get the granular version of the call date/time of the call. The result is always in the form
+ * 'DATE at TIME'. The date value changes based on when the call was created.
+ *
+ * If created today, DATE is 'Today'
+ * If created this year, DATE is 'MMM dd'
+ * Otherwise, DATE is 'MMM dd, yyyy'
+ *
+ * TIME is the localized time format, e.g. 'hh:mm a' or 'HH:mm'
+ *
+ * @param details Call details to use
+ * @return String representing when the call occurred
+ */
+ public CharSequence getGranularDateTime(PhoneCallDetails details) {
+ return mResources.getString(R.string.voicemailCallLogDateTimeFormat,
+ getGranularDate(details.date),
+ DateUtils.formatDateTime(mContext, details.date, DateUtils.FORMAT_SHOW_TIME));
+ }
+
+ /**
+ * Get the granular version of the call date. See {@link #getGranularDateTime(PhoneCallDetails)}
+ */
+ private String getGranularDate(long date) {
+ if (DateUtils.isToday(date)) {
+ return mResources.getString(R.string.voicemailCallLogToday);
+ }
+ return DateUtils.formatDateTime(mContext, date, DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_ABBREV_MONTH
+ | (shouldShowYear(date) ? DateUtils.FORMAT_SHOW_YEAR : DateUtils.FORMAT_NO_YEAR));
+ }
+
+ /**
+ * Determines whether the year should be shown for the given date
+ *
+ * @return {@code true} if date is within the current year, {@code false} otherwise
+ */
+ private boolean shouldShowYear(long date) {
+ mCalendar.setTimeInMillis(getCurrentTimeMillis());
+ int currentYear = mCalendar.get(Calendar.YEAR);
+ mCalendar.setTimeInMillis(date);
+ return currentYear != mCalendar.get(Calendar.YEAR);
}
/** Sets the text of the header view for the details page of a phone call. */