13d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer/*
23d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Copyright (C) 2016 The Android Open Source Project
33d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *
43d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Licensed under the Apache License, Version 2.0 (the "License");
53d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * you may not use this file except in compliance with the License.
63d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * You may obtain a copy of the License at
73d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *
83d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *      http://www.apache.org/licenses/LICENSE-2.0
93d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer *
103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * Unless required by applicable law or agreed to in writing, software
113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * distributed under the License is distributed on an "AS IS" BASIS,
123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * See the License for the specific language governing permissions and
143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer * limitations under the License.
153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer */
163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerpackage com.android.car.dialer;
173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.ContentResolver;
193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.Context;
203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.content.res.Resources;
213d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.database.Cursor;
223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.graphics.Bitmap;
233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.os.AsyncTask;
243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.provider.CallLog;
256f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathanimport android.support.annotation.NonNull;
263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.telephony.PhoneNumberUtils;
273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.text.TextUtils;
283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport android.text.format.DateUtils;
296f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
309c60bc83bd37ae212e66f2e27b821cebbe7beeb2Rakesh Iyerimport com.android.car.apps.common.CircleBitmapDrawable;
316f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathanimport com.android.car.apps.common.LetterTileDrawable;
326f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathanimport com.android.car.dialer.telecom.PhoneLoader;
336f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathanimport com.android.car.dialer.telecom.TelecomUtils;
343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport java.util.ArrayList;
363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyerimport java.util.List;
373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
386f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathanclass CallLogListingTask extends AsyncTask<Void, Void, Void> {
396f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    static class CallLogItem {
406f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        final String mTitle;
416f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        final String mText;
426f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        final String mNumber;
436f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        final Bitmap mIcon;
446f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
456f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        public CallLogItem(String title, String text, String number, Bitmap icon) {
466f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mTitle = title;
476f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mText = text;
486f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mNumber = number;
496f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            mIcon = icon;
506f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        }
516f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    }
526f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
536f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    interface LoadCompleteListener {
546f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        void onLoadComplete(List<CallLogItem> items);
556f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    }
566f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    // Like a constant but needs a context so not static.
593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private final String VOICEMAIL_NUMBER;
603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private Context mContext;
623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private Cursor mCursor;
636f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    private List<CallLogItem> mItems;
646f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    private LoadCompleteListener mListener;
656f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
666f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    CallLogListingTask(Context context, Cursor cursor,
676f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan            @NonNull LoadCompleteListener listener) {
686f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mContext = context;
696f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mCursor = cursor;
706f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mItems = new ArrayList<>(mCursor.getCount());
716f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mListener = listener;
723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        VOICEMAIL_NUMBER = TelecomUtils.getVoicemailNumber(mContext);
733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private String maybeAppendCount(StringBuilder sb, int count) {
763d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (count > 1) {
773d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            sb.append(" (").append(count).append(")");
783d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
793d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return sb.toString();
803d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
813d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
823d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private String getContactName(String cachedName, String number,
833d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            int count, boolean isVoicemail) {
843d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (cachedName != null) {
853d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return maybeAppendCount(new StringBuilder(cachedName), count);
863d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
873d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        StringBuilder sb = new StringBuilder();
893d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (isVoicemail) {
903d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            sb.append(mContext.getString(R.string.voicemail));
913d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } else {
923d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            String displayName = TelecomUtils.getDisplayName(mContext, number);
933d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (TextUtils.isEmpty(displayName)) {
943d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                displayName = mContext.getString(R.string.unknown);
953d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
963d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            sb.append(displayName);
973d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
983d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
993d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return maybeAppendCount(sb, count);
1003d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
1013d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1023d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private Bitmap getContactImage(Context context, ContentResolver contentResolver,
1033d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            String name, String number) {
1043d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        Resources r = context.getResources();
1053d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        int size = r.getDimensionPixelSize(R.dimen.dialer_menu_icon_container_width);
1063d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1073d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        Bitmap bitmap = TelecomUtils.getContactPhotoFromNumber(contentResolver, number);
1083d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (bitmap != null) {
1093d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return new CircleBitmapDrawable(r, bitmap).toBitmap(size);
1103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
1113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        LetterTileDrawable letterTileDrawable = new LetterTileDrawable(r);
1133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        letterTileDrawable.setContactDetails(name, number);
1143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        letterTileDrawable.setIsCircular(true);
1153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return letterTileDrawable.toBitmap(size);
1163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
1173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private static CharSequence getRelativeTime(long millis) {
1193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        boolean validTimestamp = millis > 0;
1203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1213d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return validTimestamp ? DateUtils.getRelativeTimeSpanString(
1223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                millis, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS,
1233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                DateUtils.FORMAT_ABBREV_RELATIVE) : null;
1243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
1253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    @Override
1273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    protected Void doInBackground(Void... voids) {
1283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        ContentResolver resolver = mContext.getContentResolver();
1293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1303d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        try {
1313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (mCursor != null) {
1323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                int cachedNameColumn = PhoneLoader.getNameColumnIndex(mCursor);
1333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                int numberColumn = PhoneLoader.getNumberColumnIndex(mCursor);
1343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                int dateColumn = mCursor.getColumnIndex(CallLog.Calls.DATE);
1353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                while (mCursor.moveToNext()) {
1373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    int count = 1;
1383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    String number = mCursor.getString(numberColumn);
1393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1403d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // We want to group calls to the same number into one so seek forward as many
1413d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // entries as possible as long as the number is the same.
1423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    int position = mCursor.getPosition();
1433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    while (mCursor.moveToNext()) {
1443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        String nextNumber = mCursor.getString(numberColumn);
1453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        if (equalNumbers(number, nextNumber)) {
1463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                            count++;
1473d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        } else {
1483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                            break;
1493d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        }
1503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    }
1513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    mCursor.moveToPosition(position);
1523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1533d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    boolean isVoicemail = number.equals(VOICEMAIL_NUMBER);
1543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    String name = getContactName(mCursor.getString(cachedNameColumn),
1553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                            number, count, isVoicemail);
1563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // Not sure why this is the only column checked here but I'm assuming this was
1583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // to work around some bug on some device.
1593d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    long millis = dateColumn == -1 ? 0 : mCursor.getLong(dateColumn);
1603d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1613d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    StringBuffer secondaryText = new StringBuffer();
1623d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    CharSequence relativeDate = getRelativeTime(millis);
1633d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1643d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // Append the type (work, mobile etc.) if it isnt voicemail.
1653d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    if (!isVoicemail) {
1663d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        CharSequence type = TelecomUtils.getTypeFromNumber(mContext, number);
1673d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        secondaryText.append(type);
1683d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(relativeDate)) {
1693d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                            secondaryText.append(", ");
1703d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        }
1713d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    }
1723d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1733d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // Add in the timestamp.
1743d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    if (relativeDate != null) {
1753d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        secondaryText.append(relativeDate);
1763d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    }
1773d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1783d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    Bitmap contactImage = getContactImage(mContext, resolver, name, number);
1796f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
1806f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                    CallLogItem item =
1816f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                            new CallLogItem(name, secondaryText.toString(), number, contactImage);
1826f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan                    mItems.add(item);
1833d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1843d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // Since we deduplicated count rows, we can move all the way to that row so the
1853d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    // next iteration takes us to the row following the last duplicate row.
1863d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    if (count > 1) {
1873d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                        mCursor.moveToPosition(position + count - 1);
1883d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                    }
1893d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                }
1903d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
1913d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } finally {
1923d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            if (mCursor != null) {
1933d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer                mCursor.close();
1943d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            }
1953d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
1963d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return null;
1973d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
1983d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
1996f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    @Override
2006f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    protected void onPostExecute(Void aVoid) {
2016f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan        mListener.onLoadComplete(mItems);
2026f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan    }
2036f8e1dbe4629b499128dade1e6d83e37147403c4Srinivas Visvanathan
2043d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    /**
2053d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * Determines if the specified number is actually a URI
2063d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * (i.e. a SIP address) rather than a regular PSTN phone number,
2073d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * based on whether or not the number contains an "@" character.
2083d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     *
2093d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * @return true if number contains @
2103d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     *
2113d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * from android.telephony.PhoneNumberUtils
2123d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     */
2133d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    public static boolean isUriNumber(String number) {
2143d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        // Note we allow either "@" or "%40" to indicate a URI, in case
2153d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        // the passed-in string is URI-escaped.  (Neither "@" nor "%40"
2163d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        // will ever be found in a legal PSTN number.)
2173d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return number != null && (number.contains("@") || number.contains("%40"));
2183d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
2193d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2203d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private static boolean equalNumbers(String number1, String number2) {
2213d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (isUriNumber(number1) || isUriNumber(number2)) {
2223d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return compareSipAddresses(number1, number2);
2233d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } else {
2243d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return PhoneNumberUtils.compare(number1, number2);
2253d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
2263d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
2273d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2283d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private static boolean compareSipAddresses(String number1, String number2) {
2293d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (number1 == null || number2 == null) {
2303d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            return number1 == null && number2 == null;
2313d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
2323d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2333d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        String[] address1 = splitSipAddress(number1);
2343d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        String[] address2 = splitSipAddress(number2);
2353d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2363d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return address1[0].equals(address2[0]) && address1[1].equals(address2[1]);
2373d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
2383d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer
2393d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    /**
2403d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * Splits a sip address on either side of the @ sign and returns both halves.
2413d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * If there is no @ sign, user info will be number and rest will be empty string
2423d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * @param number the sip number to split
2433d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     * @return a string array of size 2. Element 0 is the user info (left side of @ sign) and
2443d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     *         element 1 is the rest (right side of @ sign).
2453d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer     */
2463d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    private static String[] splitSipAddress(String number) {
2473d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        String[] values = new String[2];
2483d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        int index = number.indexOf('@');
2493d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        if (index == -1) {
2503d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            values[0] = number;
2513d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            values[1] = "";
2523d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        } else {
2533d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            values[0] = number.substring(0, index);
2543d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer            values[1] = number.substring(index);
2553d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        }
2563d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer        return values;
2573d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer    }
2583d724a4b70dd9a08d9adddc3b403edfd572bcaa6Rakesh Iyer}
259