1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.contacts.list;
17
18import android.content.Context;
19import android.content.CursorLoader;
20import android.database.Cursor;
21import android.database.MergeCursor;
22import android.database.sqlite.SQLiteException;
23import android.os.Bundle;
24import android.provider.ContactsContract.Contacts;
25
26import com.google.common.collect.Lists;
27
28import java.util.List;
29
30/**
31 * A loader for use in the default contact list, which will also query for favorite contacts
32 * if configured to do so.
33 */
34public class FavoritesAndContactsLoader extends CursorLoader {
35
36    private boolean mLoadFavorites;
37
38    private String[] mProjection;
39
40
41    public FavoritesAndContactsLoader(Context context) {
42        super(context);
43    }
44
45    /** Whether to load favorites and merge results in before any other results. */
46    public void setLoadFavorites(boolean flag) {
47        mLoadFavorites = flag;
48    }
49
50    public void setProjection(String[] projection) {
51        super.setProjection(projection);
52        mProjection = projection;
53    }
54
55    @Override
56    public Cursor loadInBackground() {
57        List<Cursor> cursors = Lists.newArrayList();
58        if (mLoadFavorites) {
59            cursors.add(loadFavoritesContacts());
60        }
61        final Cursor contactsCursor = loadContacts();
62        cursors.add(contactsCursor);
63        return new MergeCursor(cursors.toArray(new Cursor[cursors.size()])) {
64            @Override
65            public Bundle getExtras() {
66                // Need to get the extras from the contacts cursor.
67                return contactsCursor == null ? new Bundle() : contactsCursor.getExtras();
68            }
69        };
70    }
71
72    private Cursor loadContacts() {
73        // ContactsCursor.loadInBackground() can return null; MergeCursor
74        // correctly handles null cursors.
75        try {
76            return super.loadInBackground();
77
78        } catch (NullPointerException | SQLiteException | SecurityException e) {
79            // Ignore NPEs, SQLiteExceptions and SecurityExceptions thrown by providers
80        }
81        return null;
82    }
83
84    private Cursor loadFavoritesContacts() {
85        final StringBuilder selection = new StringBuilder();
86        selection.append(Contacts.STARRED + "=?");
87        final ContactListFilter filter =
88                ContactListFilterController.getInstance(getContext()).getFilter();
89        if (filter != null && filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
90            selection.append(" AND ").append(Contacts.IN_VISIBLE_GROUP + "=1");
91        }
92        return getContext().getContentResolver().query(
93                Contacts.CONTENT_URI, mProjection, selection.toString(), new String[]{"1"},
94                getSortOrder());
95    }
96}
97