Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit edb22da2 authored by Andrew Lee's avatar Andrew Lee
Browse files

Change PhoneCallDetail fields to be non-final.

It's been a pain to add/change fields on PhoneCallDetails because
a multitude of parameters required for the constructors to create
an instance. I ran into this while considering how to add an
objectId to its parameters, and have previously too...

Make fields non-final so that they are more easily set. This has
the side-effect of making the casing of some initialization code
more straightforward.

+ Change it's constructor to a subset of required fields.
+ Simplify/reorganize CallLogAdapter and CallLogAsyncTaskUtil code.
+ Simplify tests.

Bug: 21733599
Change-Id: I236dfb0b8e6513f4b44dbdae17ce2eb9c9ae4778
parent 02db7555
Loading
Loading
Loading
Loading
+49 −93
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.dialer;

import com.google.common.annotations.VisibleForTesting;
import com.android.dialer.calllog.PhoneNumberDisplayUtil;

import android.content.Context;
@@ -29,124 +28,81 @@ import android.text.TextUtils;

/**
 * The details of a phone call to be shown in the UI.
 *
 * TODO: Create a builder, to make it easier to construct an instance.
 */
public class PhoneCallDetails {
    /** The number of the other party involved in the call. */
    public final CharSequence number;
    /** The number presenting rules set by the network, e.g., {@link Calls#PRESENTATION_ALLOWED} */
    public final int numberPresentation;
    /** The formatted version of {@link #number}. */
    public final CharSequence formattedNumber;
    /** The country corresponding with the phone number. */
    public final String countryIso;
    /** The geocoded location for the phone number. */
    public final String geocode;
    // The number of the other party involved in the call.
    public CharSequence number;
    // The number presenting rules set by the network, e.g., {@link Calls#PRESENTATION_ALLOWED}
    public int numberPresentation;
    // The formatted version of {@link #number}.
    public CharSequence formattedNumber;
    // The country corresponding with the phone number.
    public String countryIso;
    // The geocoded location for the phone number.
    public String geocode;

    /**
     * The type of calls, as defined in the call log table, e.g., {@link Calls#INCOMING_TYPE}.
     * <p>
     * There might be multiple types if this represents a set of entries grouped together.
     */
    public final int[] callTypes;
    /** The date of the call, in milliseconds since the epoch. */
    public final long date;
    /** The duration of the call in milliseconds, or 0 for missed calls. */
    public final long duration;
    /** The name of the contact, or the empty string. */
    public final CharSequence name;
    /** The type of phone, e.g., {@link Phone#TYPE_HOME}, 0 if not available. */
    public final int numberType;
    /** The custom label associated with the phone number in the contact, or the empty string. */
    public final CharSequence numberLabel;
    /** The URI of the contact associated with this phone call. */
    public final Uri contactUri;
    public int[] callTypes;

    // The date of the call, in milliseconds since the epoch.
    public long date;
    // The duration of the call in milliseconds, or 0 for missed calls.
    public long duration;
    // The name of the contact, or the empty string.
    public CharSequence name;
    // The type of phone, e.g., {@link Phone#TYPE_HOME}, 0 if not available.
    public int numberType;
    // The custom label associated with the phone number in the contact, or the empty string.
    public CharSequence numberLabel;
    // The URI of the contact associated with this phone call.
    public Uri contactUri;
    /**
     * The photo URI of the picture of the contact that is associated with this phone call or
     * null if there is none.
     * <p>
     * This is meant to store the high-res photo only.
     */
    public final Uri photoUri;
    /**
     * The source type of the contact associated with this call.
     */
    public final int sourceType;
    public Uri photoUri;

    /**
     * The unique identifier for the account associated with the call.
     */
    public final PhoneAccountHandle accountHandle;
    /**
     * Features applicable to this call.
     */
    public final int features;
    /**
     * Total data usage for this call.
     */
    public final Long dataUsage;
    /**
     * Voicemail transcription
     */
    public final String transcription;
    // The source type of the contact associated with this call.
    public int sourceType;

    // The unique identifier for the account associated with the call.
    public PhoneAccountHandle accountHandle;

    // Features applicable to this call.
    public int features;

    // Total data usage for this call.
    public Long dataUsage;

    public final String displayNumber;
    public final boolean isVoicemail;
    // Voicemail transcription
    public String transcription;

    public String displayNumber;
    public boolean isVoicemail;

    /**
     * Create the details for a call, with empty defaults specified for extra fields that are
     * not necessary for testing.
     * Constructor with required fields for the details of a call with a number associated with a
     * contact.
     */
    @VisibleForTesting
    public PhoneCallDetails(Context context, CharSequence number, int numberPresentation,
            CharSequence formattedNumber, String countryIso, String geocode,
            int[] callTypes, long date, long duration, boolean isVoicemail) {
        this(context, number, numberPresentation, formattedNumber, countryIso, geocode,
                callTypes, date, duration, "", 0, "", null, null, 0, null, 0, null, null,
                isVoicemail);
    }

    /** Create the details for a call with a number not associated with a contact. */
    public PhoneCallDetails(Context context, CharSequence number, int numberPresentation,
            CharSequence formattedNumber, String countryIso, String geocode,
            int[] callTypes, long date, long duration,
            PhoneAccountHandle accountHandle, int features, Long dataUsage, String transcription,
    public PhoneCallDetails(
            Context context,
            CharSequence number,
            int numberPresentation,
            CharSequence formattedNumber,
            boolean isVoicemail) {
        this(context, number, numberPresentation, formattedNumber, countryIso, geocode,
                callTypes, date, duration, "", 0, "", null, null, 0, accountHandle, features,
                dataUsage, transcription, isVoicemail);
    }

    /** Create the details for a call with a number associated with a contact. */
    public PhoneCallDetails(Context context, CharSequence number, int numberPresentation,
            CharSequence formattedNumber, String countryIso, String geocode,
            int[] callTypes, long date, long duration, CharSequence name,
            int numberType, CharSequence numberLabel, Uri contactUri, Uri photoUri,
            int sourceType, PhoneAccountHandle accountHandle, int features, Long dataUsage,
            String transcription, boolean isVoicemail) {
        this.number = number;
        this.numberPresentation = numberPresentation;
        this.formattedNumber = formattedNumber;
        this.countryIso = countryIso;
        this.geocode = geocode;
        this.callTypes = callTypes;
        this.date = date;
        this.duration = duration;
        this.name = name;
        this.numberType = numberType;
        this.numberLabel = numberLabel;
        this.contactUri = contactUri;
        this.photoUri = photoUri;
        this.sourceType = sourceType;
        this.accountHandle = accountHandle;
        this.features = features;
        this.dataUsage = dataUsage;
        this.transcription = transcription;
        this.isVoicemail = isVoicemail;

        this.displayNumber = PhoneNumberDisplayUtil.getDisplayNumber(
                context,
                this.accountHandle,
                this.number,
                this.numberPresentation,
                this.formattedNumber,
+54 −72
Original line number Diff line number Diff line
@@ -350,46 +350,13 @@ public class CallLogAdapter extends GroupingListAdapter
        }
        int count = getGroupSize(position);

        CallLogListItemViewHolder views = (CallLogListItemViewHolder) viewHolder;

        // Default case: an item in the call log.
        views.primaryActionView.setVisibility(View.VISIBLE);

        final String number = c.getString(CallLogQuery.NUMBER);
        final int numberPresentation = c.getInt(CallLogQuery.NUMBER_PRESENTATION);
        final long date = c.getLong(CallLogQuery.DATE);
        final long duration = c.getLong(CallLogQuery.DURATION);
        final int callType = c.getInt(CallLogQuery.CALL_TYPE);
        final PhoneAccountHandle accountHandle = PhoneAccountUtils.getAccount(
                c.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME),
                c.getString(CallLogQuery.ACCOUNT_ID));
        final String countryIso = c.getString(CallLogQuery.COUNTRY_ISO);

        final long rowId = c.getLong(CallLogQuery.ID);
        views.rowId = rowId;

        // Check if the day group has changed and display a header if necessary.
        int currentGroup = getDayGroupForCall(rowId);
        int previousGroup = getPreviousDayGroup(c);
        if (currentGroup != previousGroup) {
            views.dayGroupHeader.setVisibility(View.VISIBLE);
            views.dayGroupHeader.setText(getGroupDescription(currentGroup));
        } else {
            views.dayGroupHeader.setVisibility(View.GONE);
        }

        // Store some values used when the actions ViewStub is inflated on expansion of the actions
        // section.
        views.number = number;
        views.numberPresentation = numberPresentation;
        views.callType = callType;
        views.accountHandle = accountHandle;
        views.voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
        // Stash away the Ids of the calls so that we can support deleting a row in the call log.
        views.callIds = getCallIds(c, count);

        final ContactInfo cachedContactInfo = mContactInfoHelper.getContactInfo(c);

        final boolean isVoicemailNumber =
                mPhoneNumberUtilsWrapper.isVoicemailNumber(accountHandle, number);

@@ -402,66 +369,81 @@ public class CallLogAdapter extends GroupingListAdapter
            // Lookup contacts with this number
            info = mContactInfoCache.getValue(number, countryIso, cachedContactInfo);
        }

        final Uri lookupUri = info.lookupUri;
        final String name = info.name;
        final int ntype = info.type;
        final String label = info.label;
        final long photoId = info.photoId;
        final Uri photoUri = info.photoUri;
        CharSequence formattedNumber = info.formattedNumber == null
                ? null : PhoneNumberUtils.createTtsSpannable(info.formattedNumber);
        final int[] callTypes = getCallTypes(c, count);
        final String geocode = c.getString(CallLogQuery.GEOCODED_LOCATION);
        final int sourceType = info.sourceType;
        final int features = getCallFeatures(c, count);
        final String transcription = c.getString(CallLogQuery.TRANSCRIPTION);
        Long dataUsage = null;

        final PhoneCallDetails details = new PhoneCallDetails(
                mContext, number, numberPresentation, formattedNumber, isVoicemailNumber);
        details.accountHandle = accountHandle;
        details.callTypes = getCallTypes(c, count);
        details.countryIso = countryIso;
        details.date = c.getLong(CallLogQuery.DATE);
        details.duration = c.getLong(CallLogQuery.DURATION);
        details.features = getCallFeatures(c, count);
        details.geocode = c.getString(CallLogQuery.GEOCODED_LOCATION);
        details.transcription = c.getString(CallLogQuery.TRANSCRIPTION);

        if (!c.isNull(CallLogQuery.DATA_USAGE)) {
            dataUsage = c.getLong(CallLogQuery.DATA_USAGE);
            details.dataUsage = c.getLong(CallLogQuery.DATA_USAGE);
        }

        final PhoneCallDetails details;
        if (!TextUtils.isEmpty(info.name)) {
            details.contactUri = info.lookupUri;
            details.name = info.name;
            details.numberType = info.type;
            details.numberLabel = info.label;
            details.photoUri = info.photoUri;
            details.sourceType = info.sourceType;
        }

        CallLogListItemViewHolder views = (CallLogListItemViewHolder) viewHolder;
        views.info = info;
        views.rowId = c.getLong(CallLogQuery.ID);
        // Store values used when the actions ViewStub is inflated on expansion.
        views.number = number;
        views.numberPresentation = numberPresentation;
        views.callType = c.getInt(CallLogQuery.CALL_TYPE);
        views.accountHandle = accountHandle;
        views.voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
        // Stash away the Ids of the calls so that we can support deleting a row in the call log.
        views.callIds = getCallIds(c, count);

        // The entry can only be reported as invalid if it has a valid ID and the source of the
        // entry supports marking entries as invalid.
        views.canBeReportedAsInvalid = mContactInfoHelper.canReportAsInvalid(info.sourceType,
                info.objectId);
        views.canBeReportedAsInvalid = mContactInfoHelper.canReportAsInvalid(
                info.sourceType, info.objectId);

        // Update the expanded position if the rowIds match, in case ViewHolders were added/removed.
        if (mCurrentlyExpandedRowId == rowId) {
            mCurrentlyExpandedPosition = position;
        }
        // Restore expansion state of the row on rebind. Inflate the actions ViewStub if required,
        // and set its visibility state accordingly.
        views.showActions(mCurrentlyExpandedPosition == position, mOnReportButtonClickListener);
        // Default case: an item in the call log.
        views.primaryActionView.setVisibility(View.VISIBLE);

        if (TextUtils.isEmpty(name)) {
            details = new PhoneCallDetails(mContext, number, numberPresentation, formattedNumber,
                    countryIso, geocode, callTypes, date, duration, accountHandle, features,
                    dataUsage, transcription, isVoicemailNumber);
        // Check if the day group has changed and display a header if necessary.
        int currentGroup = getDayGroupForCall(views.rowId);
        int previousGroup = getPreviousDayGroup(c);
        if (currentGroup != previousGroup) {
            views.dayGroupHeader.setVisibility(View.VISIBLE);
            views.dayGroupHeader.setText(getGroupDescription(currentGroup));
        } else {
            details = new PhoneCallDetails(mContext, number, numberPresentation, formattedNumber,
                    countryIso, geocode, callTypes, date, duration, name, ntype, label, lookupUri,
                    photoUri, sourceType, accountHandle, features, dataUsage, transcription,
                    isVoicemailNumber);
            views.dayGroupHeader.setVisibility(View.GONE);
        }

        mCallLogViewsHelper.setPhoneCallDetails(mContext, views, details);
        // Update the expanded position if the rowIds match, in case ViewHolders were added/removed.
        // Then restore the state of the row on rebind.
        if (mCurrentlyExpandedRowId == views.rowId) {
            mCurrentlyExpandedPosition = position;
        }
        views.showActions(mCurrentlyExpandedPosition == position, mOnReportButtonClickListener);
        views.updateCallButton();

        String nameForDefaultImage = null;
        if (TextUtils.isEmpty(name)) {
        if (TextUtils.isEmpty(info.name)) {
            nameForDefaultImage = details.displayNumber;
        } else {
            nameForDefaultImage = name;
            nameForDefaultImage = info.name;
        }
        views.setPhoto(info.photoId, info.photoUri, info.lookupUri, nameForDefaultImage,
                isVoicemailNumber, mContactInfoHelper.isBusiness(info.sourceType));

        views.setPhoto(photoId, photoUri, lookupUri, nameForDefaultImage, isVoicemailNumber,
                mContactInfoHelper.isBusiness(info.sourceType));

        views.updateCallButton();
        mCallLogViewsHelper.setPhoneCallDetails(mContext, views, details);

        // Listen for the first draw
        if (mViewTreeObserver == null) {
+27 −50
Original line number Diff line number Diff line
@@ -139,35 +139,15 @@ public class CallLogAsyncTaskUtil {
            }

            // Read call log.
            final String countryIso = cursor.getString(CallDetailQuery.COUNTRY_ISO_COLUMN_INDEX);
            final String number = cursor.getString(CallDetailQuery.NUMBER_COLUMN_INDEX);
            final int numberPresentation =
                    cursor.getInt(CallDetailQuery.NUMBER_PRESENTATION_COLUMN_INDEX);
            final long date = cursor.getLong(CallDetailQuery.DATE_COLUMN_INDEX);
            final long duration = cursor.getLong(CallDetailQuery.DURATION_COLUMN_INDEX);
            final int callType = cursor.getInt(CallDetailQuery.CALL_TYPE_COLUMN_INDEX);
            final String geocode = cursor.getString(CallDetailQuery.GEOCODED_LOCATION_COLUMN_INDEX);
            final String transcription =
                    cursor.getString(CallDetailQuery.TRANSCRIPTION_COLUMN_INDEX);

            final PhoneAccountHandle accountHandle = PhoneAccountUtils.getAccount(
                    cursor.getString(CallDetailQuery.ACCOUNT_COMPONENT_NAME),
                    cursor.getString(CallDetailQuery.ACCOUNT_ID));

            String countryIso = cursor.getString(CallDetailQuery.COUNTRY_ISO_COLUMN_INDEX);
            if (TextUtils.isEmpty(countryIso)) {
                countryIso = GeoUtil.getCurrentCountryIso(context);
            }

            // Formatted phone number.
            final CharSequence formattedNumber;
            // Read contact specifics.
            final CharSequence nameText;
            final int numberType;
            final CharSequence numberLabel;
            final Uri photoUri;
            final Uri lookupUri;
            int sourceType;

            // If this is not a regular number, there is no point in looking it up in the contacts.
            ContactInfoHelper contactInfoHelper =
                    new ContactInfoHelper(context, GeoUtil.getCurrentCountryIso(context));
@@ -178,39 +158,36 @@ public class CallLogAsyncTaskUtil {
                    PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation)
                            && !isVoicemail;
            ContactInfo info = shouldLookupNumber
                            ? contactInfoHelper.lookupNumber(number, countryIso) : null;

            if (info == null) {
                formattedNumber = PhoneNumberDisplayUtil.getDisplayNumber(
                        context, accountHandle, number, numberPresentation, null, isVoicemail);
                nameText = "";
                numberType = 0;
                numberLabel = "";
                photoUri = null;
                lookupUri = null;
                sourceType = 0;
            } else {
                formattedNumber = info.formattedNumber;
                nameText = info.name;
                numberType = info.type;
                numberLabel = info.label;
                photoUri = info.photoUri;
                lookupUri = info.lookupUri;
                sourceType = info.sourceType;
            }

                            ? contactInfoHelper.lookupNumber(number, countryIso)
                            : ContactInfo.EMPTY;
            PhoneCallDetails details = new PhoneCallDetails(
                    context, number, numberPresentation, info.formattedNumber, isVoicemail);

            details.accountHandle = accountHandle;
            details.contactUri = info.lookupUri;
            details.name = info.name;
            details.numberType = info.type;
            details.numberLabel = info.label;
            details.photoUri = info.photoUri;
            details.sourceType = info.sourceType;

            details.callTypes = new int[] {
                    cursor.getInt(CallDetailQuery.CALL_TYPE_COLUMN_INDEX)
            };
            details.date = cursor.getLong(CallDetailQuery.DATE_COLUMN_INDEX);
            details.duration = cursor.getLong(CallDetailQuery.DURATION_COLUMN_INDEX);
            details.features = cursor.getInt(CallDetailQuery.FEATURES);
            details.geocode = cursor.getString(CallDetailQuery.GEOCODED_LOCATION_COLUMN_INDEX);
            details.transcription = cursor.getString(CallDetailQuery.TRANSCRIPTION_COLUMN_INDEX);

            final int features = cursor.getInt(CallDetailQuery.FEATURES);
            details.countryIso = !TextUtils.isEmpty(countryIso) ? countryIso
                    : GeoUtil.getCurrentCountryIso(context);

            Long dataUsage = null;
            if (!cursor.isNull(CallDetailQuery.DATA_USAGE)) {
                dataUsage = cursor.getLong(CallDetailQuery.DATA_USAGE);
                details.dataUsage = cursor.getLong(CallDetailQuery.DATA_USAGE);
            }

            return new PhoneCallDetails(context, number, numberPresentation, formattedNumber,
                    countryIso, geocode, new int[]{ callType }, date, duration, nameText,
                    numberType, numberLabel, lookupUri, photoUri, sourceType, accountHandle,
                    features, dataUsage, transcription, isVoicemail);
            return details;
        } finally {
            if (cursor != null) {
                cursor.close();
+3 −3
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ import com.android.dialer.R;
            callDescription.append(mResources.getString(R.string.description_video_call));
        }

        int stringID = getCallDescriptionStringID(details);
        int stringID = getCallDescriptionStringID(details.callTypes);
        String accountLabel = PhoneAccountUtils.getAccountLabel(context, details.accountHandle);

        // Use chosen string resource to build up the message.
@@ -213,8 +213,8 @@ import com.android.dialer.R;
     * @param details Call details.
     * @return String resource ID to use.
     */
    public int getCallDescriptionStringID(PhoneCallDetails details) {
        int lastCallType = getLastCallType(details.callTypes);
    public int getCallDescriptionStringID(int[] callTypes) {
        int lastCallType = getLastCallType(callTypes);
        int stringID;

        if (lastCallType == Calls.VOICEMAIL_TYPE || lastCallType == Calls.MISSED_TYPE) {
+0 −5
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.PhoneLookup;
import android.telecom.PhoneAccountHandle;
import android.text.TextUtils;
import android.util.Log;

@@ -122,12 +121,8 @@ public class DefaultVoicemailNotifier {
            // Check if we already know the name associated with this number.
            String name = names.get(newCall.number);
            if (name == null) {
                PhoneAccountHandle accountHandle = PhoneAccountUtils.getAccount(
                        newCall.accountComponentName,
                        newCall.accountId);
                name = PhoneNumberDisplayUtil.getDisplayName(
                        mContext,
                        accountHandle,
                        newCall.number,
                        newCall.numberPresentation,
                        /* isVoicemail */ false).toString();
Loading