summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/datamodel/FrequentContactsCursorQueryData.java
blob: d1759ad5fb05b8c17614c2bcabaad8c5e5e299e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Copyright (C) 2015 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.messaging.datamodel;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;

import com.android.messaging.util.FallbackStrategies;
import com.android.messaging.util.FallbackStrategies.Strategy;
import com.android.messaging.util.LogUtil;
import com.android.messaging.util.OsUtil;

/**
 * Helper for querying frequent (and/or starred) contacts.
 */
public class FrequentContactsCursorQueryData extends CursorQueryData {
    private static final String TAG = LogUtil.BUGLE_TAG;

    private static class FrequentContactsCursorLoader extends BoundCursorLoader {
        private final Uri mOriginalUri;

        FrequentContactsCursorLoader(String bindingId, Context context, Uri uri,
                String[] projection, String selection, String[] selectionArgs, String sortOrder) {
            super(bindingId, context, uri, projection, selection, selectionArgs, sortOrder);
            mOriginalUri = uri;
        }

        @Override
        public Cursor loadInBackground() {
            return FallbackStrategies
                    .startWith(new PrimaryStrequentContactsQueryStrategy())
                    .thenTry(new FrequentOnlyContactsQueryStrategy())
                    .thenTry(new PhoneOnlyStrequentContactsQueryStrategy())
                    .execute(null);
        }

        private abstract class StrequentContactsQueryStrategy implements Strategy<Void, Cursor> {
            @Override
            public Cursor execute(Void params) throws Exception {
                final Uri uri = getUri();
                if (uri != null) {
                    setUri(uri);
                }
                return FrequentContactsCursorLoader.super.loadInBackground();
            }
            protected abstract Uri getUri();
        }

        private class PrimaryStrequentContactsQueryStrategy extends StrequentContactsQueryStrategy {
            @Override
            protected Uri getUri() {
                // Use the original URI requested.
                return mOriginalUri;
            }
        }

        private class FrequentOnlyContactsQueryStrategy extends StrequentContactsQueryStrategy {
            @Override
            protected Uri getUri() {
                // Some phones have a buggy implementation of the Contacts provider which crashes
                // when we query for strequent (starred+frequent) contacts (b/17991485).
                // If this happens, switch to just querying for frequent contacts.
                return Contacts.CONTENT_FREQUENT_URI;
            }
        }

        private class PhoneOnlyStrequentContactsQueryStrategy extends
                StrequentContactsQueryStrategy {
            @Override
            protected Uri getUri() {
                // Some 3rd party ROMs have content provider
                // implementation where invalid SQL queries are returned for regular strequent
                // queries. Using strequent_phone_only query as a fallback to display only phone
                // contacts. This is the last-ditch effort; if this fails, we will display an
                // empty frequent list (b/18354836).
                final String strequentQueryParam = OsUtil.isAtLeastL() ?
                        ContactsContract.STREQUENT_PHONE_ONLY : "strequent_phone_only";
                // TODO: Handle enterprise contacts post M once contacts provider supports it
                return Contacts.CONTENT_STREQUENT_URI.buildUpon()
                        .appendQueryParameter(strequentQueryParam, "true").build();
            }
        }
    }

    public FrequentContactsCursorQueryData(Context context, String[] projection,
            String selection, String[] selectionArgs, String sortOrder) {
        // TODO: Handle enterprise contacts post M once contacts provider supports it
        super(context, Contacts.CONTENT_STREQUENT_URI, projection, selection, selectionArgs,
                sortOrder);
    }

    @Override
    public BoundCursorLoader createBoundCursorLoader(String bindingId) {
        return new FrequentContactsCursorLoader(bindingId, mContext, mUri, mProjection, mSelection,
                mSelectionArgs, mSortOrder);
    }
}