diff options
Diffstat (limited to 'java')
4 files changed, 232 insertions, 50 deletions
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index e79c89c57..228321581 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -64,6 +64,7 @@ import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; import com.android.dialer.calldetails.CallDetailsEntries; import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction; import com.android.dialer.calllogutils.PhoneAccountUtils; import com.android.dialer.calllogutils.PhoneCallDetails; import com.android.dialer.common.Assert; @@ -479,8 +480,17 @@ public class CallLogAdapter extends GroupingListAdapter @NonNull private final Set<Uri> mHiddenItemUris = new ArraySet<>(); private CallLogListItemViewHolder.OnClickListener mBlockReportSpamListener; + + /** + * Map, keyed by call ID, used to track the callback action for a call. Calls associated with the + * same callback action will be put into the same primary call group in {@link + * com.android.dialer.app.calllog.CallLogGroupBuilder}. This information is used to set the + * callback icon and trigger the corresponding action. + */ + private final Map<Long, Integer> mCallbackActions = new ArrayMap<>(); + /** - * Map, keyed by call Id, used to track the day group for a call. As call log entries are put into + * Map, keyed by call ID, used to track the day group for a call. As call log entries are put into * the primary call groups in {@link com.android.dialer.app.calllog.CallLogGroupBuilder}, they are * also assigned a secondary "day group". This map tracks the day group assigned to all calls in * the call log. This information is used to trigger the display of a day group header above the @@ -491,7 +501,7 @@ public class CallLogAdapter extends GroupingListAdapter * previous day group without having to reverse the cursor to the start of the previous day call * log entry. */ - private Map<Long, Integer> mDayGroups = new ArrayMap<>(); + private final Map<Long, Integer> mDayGroups = new ArrayMap<>(); private boolean mLoading = true; private ContactsPreferences mContactsPreferences; @@ -688,7 +698,7 @@ public class CallLogAdapter extends GroupingListAdapter @Override protected void addGroups(Cursor cursor) { - mCallLogGroupBuilder.addGroups(cursor); + mCallLogGroupBuilder.addGroups(cursor, mActivity); } @Override @@ -865,10 +875,11 @@ public class CallLogAdapter extends GroupingListAdapter protected void onPostExecute(Boolean success) { views.isLoaded = true; if (success) { - int currentGroup = getDayGroupForCall(views.rowId); - if (currentGroup != details.previousGroup) { + views.callbackAction = getCallbackAction(views.rowId); + int currentDayGroup = getDayGroup(views.rowId); + if (currentDayGroup != details.previousGroup) { views.dayGroupHeaderVisibility = View.VISIBLE; - views.dayGroupHeaderText = getGroupDescription(currentGroup); + views.dayGroupHeaderText = getGroupDescription(currentDayGroup); } else { views.dayGroupHeaderVisibility = View.GONE; } @@ -1226,7 +1237,7 @@ public class CallLogAdapter extends GroupingListAdapter cursor.moveToPosition(startingPosition); return CallLogGroupBuilder.DAY_GROUP_NONE; } - int result = getDayGroupForCall(cursor.getLong(CallLogQuery.ID)); + int result = getDayGroup(cursor.getLong(CallLogQuery.ID)); cursor.moveToPosition(startingPosition); return result; } @@ -1236,14 +1247,30 @@ public class CallLogAdapter extends GroupingListAdapter } /** - * Given a call Id, look up the day group that the call belongs to. The day group data is - * populated in {@link com.android.dialer.app.calllog.CallLogGroupBuilder}. + * Given a call ID, look up its callback action. Callback action data are populated in {@link + * com.android.dialer.app.calllog.CallLogGroupBuilder}. * - * @param callId The call to retrieve the day group for. + * @param callId The call ID to retrieve the callback action. + * @return The callback action for the call. + */ + @MainThread + private int getCallbackAction(long callId) { + Integer result = mCallbackActions.get(callId); + if (result != null) { + return result; + } + return CallbackAction.NONE; + } + + /** + * Given a call ID, look up the day group the call belongs to. Day group data are populated in + * {@link com.android.dialer.app.calllog.CallLogGroupBuilder}. + * + * @param callId The call ID to retrieve the day group. * @return The day group for the call. */ @MainThread - private int getDayGroupForCall(long callId) { + private int getDayGroup(long callId) { Integer result = mDayGroups.get(callId); if (result != null) { return result; @@ -1306,17 +1333,27 @@ public class CallLogAdapter extends GroupingListAdapter } /** + * Stores the callback action associated with a call in the call log. + * + * @param rowId The row ID of the current call. + * @param callbackAction The current call's callback action. + */ + @Override + @MainThread + public void setCallbackAction(long rowId, @CallbackAction int callbackAction) { + mCallbackActions.put(rowId, callbackAction); + } + + /** * Stores the day group associated with a call in the call log. * - * @param rowId The row Id of the current call. + * @param rowId The row ID of the current call. * @param dayGroup The day group the call belongs in. */ @Override @MainThread public void setDayGroup(long rowId, int dayGroup) { - if (!mDayGroups.containsKey(rowId)) { - mDayGroups.put(rowId, dayGroup); - } + mDayGroups.put(rowId, dayGroup); } /** Clears the day group associations on re-bind of the call log. */ diff --git a/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java b/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java index 45ff3783d..57a8be730 100644 --- a/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java +++ b/java/com/android/dialer/app/calllog/CallLogGroupBuilder.java @@ -16,6 +16,7 @@ package com.android.dialer.app.calllog; +import android.content.Context; import android.database.Cursor; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; @@ -25,6 +26,8 @@ import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.text.format.Time; import com.android.contacts.common.util.DateUtils; +import com.android.dialer.calllogutils.CallbackActionHelper; +import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction; import com.android.dialer.compat.AppCompatConstants; import com.android.dialer.phonenumbercache.CallLogQuery; import com.android.dialer.phonenumberutil.PhoneNumberHelper; @@ -71,7 +74,7 @@ public class CallLogGroupBuilder { * * @see GroupingListAdapter#addGroups(Cursor) */ - public void addGroups(Cursor cursor) { + public void addGroups(Cursor cursor, Context context) { final int count = cursor.getCount(); if (count == 0) { return; @@ -90,23 +93,32 @@ public class CallLogGroupBuilder { int groupDayGroup = getDayGroup(firstDate, currentTime); mGroupCreator.setDayGroup(firstRowId, groupDayGroup); - // Instantiate the group values to those of the first call in the cursor. + // Determine the callback action for the first call in the cursor. String groupNumber = cursor.getString(CallLogQuery.NUMBER); + String groupAccountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME); + int groupFeatures = cursor.getInt(CallLogQuery.FEATURES); + int groupCallbackAction = + CallbackActionHelper.getCallbackAction( + groupNumber, groupFeatures, groupAccountComponentName, context); + mGroupCreator.setCallbackAction(firstRowId, groupCallbackAction); + + // Instantiate other group values to those of the first call in the cursor. + String groupAccountId = cursor.getString(CallLogQuery.ACCOUNT_ID); String groupPostDialDigits = (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.POST_DIAL_DIGITS) : ""; String groupViaNumbers = (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.VIA_NUMBER) : ""; int groupCallType = cursor.getInt(CallLogQuery.CALL_TYPE); - String groupAccountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME); - String groupAccountId = cursor.getString(CallLogQuery.ACCOUNT_ID); int groupSize = 1; String number; String numberPostDialDigits; String numberViaNumbers; int callType; + int features; String accountComponentName; String accountId; + int callbackAction; while (cursor.moveToNext()) { // Obtain the values for the current call to group. @@ -118,21 +130,28 @@ public class CallLogGroupBuilder { numberViaNumbers = (VERSION.SDK_INT >= VERSION_CODES.N) ? cursor.getString(CallLogQuery.VIA_NUMBER) : ""; callType = cursor.getInt(CallLogQuery.CALL_TYPE); + features = cursor.getInt(CallLogQuery.FEATURES); accountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME); accountId = cursor.getString(CallLogQuery.ACCOUNT_ID); + callbackAction = + CallbackActionHelper.getCallbackAction(number, features, accountComponentName, context); final boolean isSameNumber = equalNumbers(groupNumber, number); final boolean isSamePostDialDigits = groupPostDialDigits.equals(numberPostDialDigits); final boolean isSameViaNumbers = groupViaNumbers.equals(numberViaNumbers); final boolean isSameAccount = isSameAccount(groupAccountComponentName, accountComponentName, groupAccountId, accountId); + final boolean isSameCallbackAction = (groupCallbackAction == callbackAction); - // Group with the same number and account. Never group voicemails. Only group blocked - // calls with other blocked calls. + // Group calls with the following criteria: + // (1) Calls with the same number, account, and callback action should be in the same group; + // (2) Never group voice mails; and + // (3) Only group blocked calls with other blocked calls. if (isSameNumber && isSameAccount && isSamePostDialDigits && isSameViaNumbers + && isSameCallbackAction && areBothNotVoicemail(callType, groupCallType) && (areBothNotBlocked(callType, groupCallType) || areBothBlocked(callType, groupCallType))) { @@ -158,10 +177,12 @@ public class CallLogGroupBuilder { groupCallType = callType; groupAccountComponentName = accountComponentName; groupAccountId = accountId; + groupCallbackAction = callbackAction; } - // Save the day group associated with the current call. + // Save the callback action and the day group associated with the current call. final long currentCallId = cursor.getLong(CallLogQuery.ID); + mGroupCreator.setCallbackAction(currentCallId, groupCallbackAction); mGroupCreator.setDayGroup(currentCallId, groupDayGroup); } @@ -259,12 +280,22 @@ public class CallLogGroupBuilder { void addGroup(int cursorPosition, int size); /** + * Defines the interface for tracking each call's callback action. Calls in a call group are + * associated with the same callback action as the first call in the group. The value of a + * callback action should be one of the categories in {@link CallbackAction}. + * + * @param rowId The row ID of the current call. + * @param callbackAction The current call's callback action. + */ + void setCallbackAction(long rowId, @CallbackAction int callbackAction); + + /** * Defines the interface for tracking the day group each call belongs to. Calls in a call group * are assigned the same day group as the first call in the group. The day group assigns calls * to the buckets: Today, Yesterday, Last week, and Other * - * @param rowId The row Id of the current call. - * @param dayGroup The day group the call belongs in. + * @param rowId The row ID of the current call. + * @param dayGroup The day group the call belongs to. */ void setDayGroup(long rowId, int dayGroup); diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java index f0eee112b..225b6527e 100644 --- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java +++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java @@ -66,6 +66,7 @@ import com.android.dialer.callcomposer.CallComposerActivity; import com.android.dialer.calldetails.CallDetailsActivity; import com.android.dialer.calldetails.CallDetailsEntries; import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.compat.CompatUtils; @@ -228,6 +229,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private final View.OnLongClickListener longPressListener; private boolean mVoicemailPrimaryActionButtonClicked; + public int callbackAction; public int dayGroupHeaderVisibility; public CharSequence dayGroupHeaderText; public boolean isAttachedToWindow; @@ -511,36 +513,53 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder } else { primaryActionButtonView.setVisibility(View.GONE); } - } else { - // Treat as normal list item; show call button, if possible. - if (PhoneNumberHelper.canPlaceCallsTo(number, numberPresentation)) { - boolean isVoicemailNumber = mCallLogCache.isVoicemailNumber(accountHandle, number); + return; + } + + // Treat as normal list item; show call button, if possible. + if (!PhoneNumberHelper.canPlaceCallsTo(number, numberPresentation)) { + primaryActionButtonView.setTag(null); + primaryActionButtonView.setVisibility(View.GONE); + return; + } - if (!isVoicemailNumber && showLightbringerPrimaryButton()) { + switch (callbackAction) { + case CallbackAction.IMS_VIDEO: + primaryActionButtonView.setTag( + IntentProvider.getReturnVideoCallIntentProvider(number, accountHandle)); + primaryActionButtonView.setContentDescription( + TextUtils.expandTemplate( + mContext.getString(R.string.description_video_call_action), validNameOrNumber)); + primaryActionButtonView.setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24); + primaryActionButtonView.setVisibility(View.VISIBLE); + break; + case CallbackAction.LIGHTBRINGER: + if (showLightbringerPrimaryButton()) { CallIntentBuilder.increaseLightbringerCallButtonAppearInCollapsedCallLogItemCount(); primaryActionButtonView.setTag(IntentProvider.getLightbringerIntentProvider(number)); - primaryActionButtonView.setContentDescription( - TextUtils.expandTemplate( - mContext.getString(R.string.description_video_call_action), validNameOrNumber)); - primaryActionButtonView.setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24); - primaryActionButtonView.setVisibility(View.VISIBLE); - return; + } else { + primaryActionButtonView.setTag( + IntentProvider.getReturnVideoCallIntentProvider(number, accountHandle)); } - - if (isVoicemailNumber) { - // Call to generic voicemail number, in case there are multiple accounts. + primaryActionButtonView.setContentDescription( + TextUtils.expandTemplate( + mContext.getString(R.string.description_video_call_action), validNameOrNumber)); + primaryActionButtonView.setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24); + primaryActionButtonView.setVisibility(View.VISIBLE); + break; + case CallbackAction.VOICE: + if (mCallLogCache.isVoicemailNumber(accountHandle, number)) { + // Call to generic voicemail number, in case there are multiple accounts primaryActionButtonView.setTag(IntentProvider.getReturnVoicemailCallIntentProvider()); + } else if (this.info != null && this.info.lookupKey != null) { + primaryActionButtonView.setTag( + IntentProvider.getAssistedDialIntentProvider( + number + postDialDigits, + mContext, + mContext.getSystemService(TelephonyManager.class))); } else { - if (this.info != null && this.info.lookupKey != null) { - primaryActionButtonView.setTag( - IntentProvider.getAssistedDialIntentProvider( - number + postDialDigits, - mContext, - mContext.getSystemService(TelephonyManager.class))); - } else { - primaryActionButtonView.setTag( - IntentProvider.getReturnCallIntentProvider(number + postDialDigits)); - } + primaryActionButtonView.setTag( + IntentProvider.getReturnCallIntentProvider(number + postDialDigits)); } primaryActionButtonView.setContentDescription( @@ -548,10 +567,10 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mContext.getString(R.string.description_call_action), validNameOrNumber)); primaryActionButtonView.setImageResource(R.drawable.quantum_ic_call_vd_theme_24); primaryActionButtonView.setVisibility(View.VISIBLE); - } else { + break; + default: primaryActionButtonView.setTag(null); primaryActionButtonView.setVisibility(View.GONE); - } } } diff --git a/java/com/android/dialer/calllogutils/CallbackActionHelper.java b/java/com/android/dialer/calllogutils/CallbackActionHelper.java new file mode 100644 index 000000000..297d5e649 --- /dev/null +++ b/java/com/android/dialer/calllogutils/CallbackActionHelper.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2017 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.calllogutils; + +import android.content.Context; +import android.provider.CallLog.Calls; +import android.support.annotation.IntDef; +import android.text.TextUtils; +import com.android.dialer.lightbringer.Lightbringer; +import com.android.dialer.lightbringer.LightbringerComponent; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** Helper class to determine the callback action associated with a call in the call log. */ +public class CallbackActionHelper { + + /** Specifies the action a user can take to make a callback. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + CallbackAction.NONE, + CallbackAction.IMS_VIDEO, + CallbackAction.LIGHTBRINGER, + CallbackAction.VOICE + }) + public @interface CallbackAction { + int NONE = 0; + int IMS_VIDEO = 1; + int LIGHTBRINGER = 2; + int VOICE = 3; + } + + /** + * Returns the {@link CallbackAction} that can be associated with a call. + * + * @param number The phone number in column {@link android.provider.CallLog.Calls#NUMBER}. + * @param features Value of features in column {@link android.provider.CallLog.Calls#FEATURES}. + * @param phoneAccountComponentName Account name in column {@link + * android.provider.CallLog.Calls#PHONE_ACCOUNT_COMPONENT_NAME}. + * @param context The context in which the method is called. + * @return One of the values in {@link CallbackAction} + */ + public static @CallbackAction int getCallbackAction( + String number, int features, String phoneAccountComponentName, Context context) { + return getCallbackAction( + number, features, isLightbringerCall(phoneAccountComponentName, context)); + } + + /** + * Returns the {@link CallbackAction} that can be associated with a call. + * + * @param number The phone number in column {@link android.provider.CallLog.Calls#NUMBER}. + * @param features Value of features in column {@link android.provider.CallLog.Calls#FEATURES}. + * @param isLightbringerCall Whether the call is a Lightbringer call. + * @return One of the values in {@link CallbackAction} + */ + public static @CallbackAction int getCallbackAction( + String number, int features, boolean isLightbringerCall) { + if (TextUtils.isEmpty(number)) { + return CallbackAction.NONE; + } + if (isLightbringerCall) { + return CallbackAction.LIGHTBRINGER; + } + + boolean isVideoCall = (features & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO; + if (isVideoCall) { + return CallbackAction.IMS_VIDEO; + } + + return CallbackAction.VOICE; + } + + private static boolean isLightbringerCall(String phoneAccountComponentName, Context context) { + Lightbringer lightBringer = LightbringerComponent.get(context).getLightbringer(); + return lightBringer.getPhoneAccountComponentName() != null + && lightBringer + .getPhoneAccountComponentName() + .flattenToString() + .equals(phoneAccountComponentName); + } +} |