1732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov/*
2732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project
3732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov *
4732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
5732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * you may not use this file except in compliance with the License.
6732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * You may obtain a copy of the License at
7732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov *
8732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
9732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov *
10732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
11732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
12732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * See the License for the specific language governing permissions and
14732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov * limitations under the License.
15732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov */
16732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikovpackage com.android.contacts.list;
17732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov
1893a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikovimport com.android.common.widget.CompositeCursorAdapter.Partition;
1968e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikovimport com.android.contacts.R;
206cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuanimport com.android.contacts.util.ContactLoaderUtils;
21753f8f6fde5a4f74181310593acebee94a014fe2Dmitri Plotnikovimport com.android.contacts.widget.AutoScrollListView;
2268e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov
23d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikovimport android.app.Activity;
24892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikovimport android.content.ContentResolver;
257d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikovimport android.content.ContentUris;
26cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikovimport android.content.Loader;
276e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikovimport android.content.SharedPreferences;
28d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikovimport android.content.SharedPreferences.Editor;
29cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikovimport android.database.Cursor;
30732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikovimport android.net.Uri;
316cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuanimport android.os.AsyncTask;
32cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikovimport android.os.Bundle;
33d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikovimport android.os.Handler;
34d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikovimport android.os.Message;
35d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikovimport android.preference.PreferenceManager;
367ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikovimport android.provider.ContactsContract;
37cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
387ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikovimport android.provider.ContactsContract.Directory;
397ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikovimport android.text.TextUtils;
40264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikovimport android.util.Log;
41732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov
42892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikovimport java.util.List;
43892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov
44732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov/**
45416b569901ce4c577c1f76c3f29496d1adab29e1Dmitri Plotnikov * Fragment containing a contact list used for browsing (as compared to
46416b569901ce4c577c1f76c3f29496d1adab29e1Dmitri Plotnikov * picking a contact with one of the PICK intents).
47732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov */
48238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikovpublic abstract class ContactBrowseListFragment extends
49238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov        ContactEntryListFragment<ContactListAdapter> {
50732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov
51264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    private static final String TAG = "ContactList";
52264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov
53cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    private static final String KEY_SELECTED_URI = "selectedUri";
546e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    private static final String KEY_SELECTION_VERIFIED = "selectionVerified";
55264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    private static final String KEY_FILTER = "filter";
56682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov    private static final String KEY_LAST_SELECTED_POSITION = "lastSelected";
57d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
58d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private static final String PERSISTENT_SELECTION_PREFIX = "defaultContactBrowserSelection";
59d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
60d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    /**
61d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * The id for a delayed message that triggers automatic selection of the first
62d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * found contact in search mode.
63d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     */
64d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private static final int MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT = 1;
65d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
66d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    /**
67d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * The delay that is used for automatically selecting the first found contact.
68d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     */
69d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private static final int DELAY_AUTOSELECT_FIRST_FOUND_CONTACT_MILLIS = 500;
70d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
71d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    /**
72d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * The minimum number of characters in the search query that is required
73d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * before we automatically select the first found contact.
74d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     */
75d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private static final int AUTOSELECT_FIRST_FOUND_CONTACT_MIN_QUERY_LENGTH = 2;
76d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
77d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private SharedPreferences mPrefs;
78d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private Handler mHandler;
793c69e21d278b1f99b9af817f8459044215238938Dmitri Plotnikov
80d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private boolean mStartedLoading;
81d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private boolean mSelectionRequired;
82d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private boolean mSelectionToScreenRequested;
83d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private boolean mSmoothScrollRequested;
84d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private boolean mSelectionPersistenceRequested;
85cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    private Uri mSelectedContactUri;
867ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov    private long mSelectedContactDirectoryId;
877ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov    private String mSelectedContactLookupKey;
887d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov    private long mSelectedContactId;
896e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    private boolean mSelectionVerified;
90682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov    private int mLastSelectedPosition = -1;
91892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov    private boolean mRefreshingContactUri;
92d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private ContactListFilter mFilter;
93d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX;
94cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
956e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    protected OnContactBrowserActionListener mListener;
966cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan    private ContactLookupTask mContactLookupTask;
97732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov
986cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan    private final class ContactLookupTask extends AsyncTask<Void, Void, Uri> {
995ffd9298a6cd842c5bfb2612a2eda798fa92b7adDmitri Plotnikov
1006cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        private final Uri mUri;
1016cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        private boolean mIsCancelled;
102892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov
1036cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        public ContactLookupTask(Uri uri) {
1046cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            mUri = uri;
1055ffd9298a6cd842c5bfb2612a2eda798fa92b7adDmitri Plotnikov        }
1065ffd9298a6cd842c5bfb2612a2eda798fa92b7adDmitri Plotnikov
1075ffd9298a6cd842c5bfb2612a2eda798fa92b7adDmitri Plotnikov        @Override
1086cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        protected Uri doInBackground(Void... args) {
1096cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            Cursor cursor = null;
1106cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            try {
1116cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                final ContentResolver resolver = getContext().getContentResolver();
1126cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(resolver, mUri);
1136cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                cursor = resolver.query(uriCurrentFormat,
1146cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                        new String[] { Contacts._ID, Contacts.LOOKUP_KEY }, null, null, null);
1156cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan
1166cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                if (cursor != null && cursor.moveToFirst()) {
1176cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                    final long contactId = cursor.getLong(0);
1186cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                    final String lookupKey = cursor.getString(1);
1196cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                    if (contactId != 0 && !TextUtils.isEmpty(lookupKey)) {
1206cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                        return Contacts.getLookupUri(contactId, lookupKey);
1216cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                    }
1228773bcb491d18e88b4e3d1f9cf7c57f6bc8e69edDmitri Plotnikov                }
123892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov
1246cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                Log.e(TAG, "Error: No contact ID or lookup key for contact " + mUri);
1256cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                return null;
1266cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            } finally {
1276cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                if (cursor != null) {
1286cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                    cursor.close();
1296cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                }
130892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov            }
1316cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        }
132892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov
1336cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        public void cancel() {
1346cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            super.cancel(true);
1356cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            // Use a flag to keep track of whether the {@link AsyncTask} was cancelled or not in
1366cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            // order to ensure onPostExecute() is not executed after the cancel request. The flag is
1376cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            // necessary because {@link AsyncTask} still calls onPostExecute() if the cancel request
1386cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            // came after the worker thread was finished.
1396cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            mIsCancelled = true;
1406cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        }
141a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov
1426cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        @Override
1436cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        protected void onPostExecute(Uri uri) {
1446cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            // Make sure the {@link Fragment} is at least still attached to the {@link Activity}
145db90ba16b3d99819e2be961ee6ecf0d532237408Katherine Kuan            // before continuing. Null URIs should still be allowed so that the list can be
146db90ba16b3d99819e2be961ee6ecf0d532237408Katherine Kuan            // refreshed and a default contact can be selected (i.e. the case of deleted
147db90ba16b3d99819e2be961ee6ecf0d532237408Katherine Kuan            // contacts).
148db90ba16b3d99819e2be961ee6ecf0d532237408Katherine Kuan            if (mIsCancelled || !isAdded()) {
1496cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan                return;
1506cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            }
151db90ba16b3d99819e2be961ee6ecf0d532237408Katherine Kuan            onContactUriQueryFinished(uri);
1525ffd9298a6cd842c5bfb2612a2eda798fa92b7adDmitri Plotnikov        }
153892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov    }
154892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov
1555251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov    private boolean mDelaySelection;
1565251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov
157d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private Handler getHandler() {
158d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mHandler == null) {
159d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mHandler = new Handler() {
160d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                @Override
161d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                public void handleMessage(Message msg) {
162d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                    switch (msg.what) {
163d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                        case MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT:
164d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                            selectDefaultContact();
165d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                            break;
166d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                    }
167d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                }
168d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            };
169d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
170d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        return mHandler;
171d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
172d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
173d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    @Override
174d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    public void onAttach(Activity activity) {
175d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        super.onAttach(activity);
176d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
177264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        restoreFilter();
178264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        restoreSelectedUri(false);
179d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
180d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
181fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov    @Override
1821db00f68b34f6cf7e9d19fedb559cf12f8c05e9cMakoto Onuki    protected void setSearchMode(boolean flag) {
183fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        if (isSearchMode() != flag) {
184fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov            if (!flag) {
185fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov                restoreSelectedUri(true);
186fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov            }
187fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov            super.setSearchMode(flag);
188fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        }
189d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
190d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
191d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    public void setFilter(ContactListFilter filter) {
192a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov        setFilter(filter, true);
193a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov    }
194a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov
195a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov    public void setFilter(ContactListFilter filter, boolean restoreSelectedUri) {
196d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mFilter == null && filter == null) {
197d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return;
198d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
199d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
200d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mFilter != null && mFilter.equals(filter)) {
201d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return;
202d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
203d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
2048daa1797310aca2333efcff0a0e0b0ed03187fffDmitri Plotnikov        Log.v(TAG, "New filter: " + filter);
205264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov
206d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        mFilter = filter;
207682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        mLastSelectedPosition = -1;
208264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        saveFilter();
209a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov        if (restoreSelectedUri) {
210a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov            mSelectedContactUri = null;
211a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov            restoreSelectedUri(true);
212a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov        }
213d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        reloadData();
214d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
215d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
216d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    public ContactListFilter getFilter() {
217d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        return mFilter;
218d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
219d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
22068e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov    @Override
221cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    public void restoreSavedState(Bundle savedState) {
222cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        super.restoreSavedState(savedState);
223cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
224cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        if (savedState == null) {
225cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov            return;
226cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        }
227cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
228264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        mFilter = savedState.getParcelable(KEY_FILTER);
229cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        mSelectedContactUri = savedState.getParcelable(KEY_SELECTED_URI);
2306e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov        mSelectionVerified = savedState.getBoolean(KEY_SELECTION_VERIFIED);
231682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        mLastSelectedPosition = savedState.getInt(KEY_LAST_SELECTED_POSITION);
232580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov        parseSelectedContactUri();
233cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    }
234cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
235cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    @Override
236cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    public void onSaveInstanceState(Bundle outState) {
237cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        super.onSaveInstanceState(outState);
238264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        outState.putParcelable(KEY_FILTER, mFilter);
239cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        outState.putParcelable(KEY_SELECTED_URI, mSelectedContactUri);
2406e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov        outState.putBoolean(KEY_SELECTION_VERIFIED, mSelectionVerified);
241682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        outState.putInt(KEY_LAST_SELECTED_POSITION, mLastSelectedPosition);
242cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    }
243cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
244892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov    protected void refreshSelectedContactUri() {
2456cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan        if (mContactLookupTask != null) {
2466cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            mContactLookupTask.cancel();
247892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        }
248cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
249d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (!isSelectionVisible()) {
250d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return;
251d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
252d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
253892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        mRefreshingContactUri = true;
254d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
255d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mSelectedContactUri == null) {
256892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov            onContactUriQueryFinished(null);
257d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return;
258d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
259d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
260d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mSelectedContactDirectoryId != Directory.DEFAULT
261d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                && mSelectedContactDirectoryId != Directory.LOCAL_INVISIBLE) {
262892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov            onContactUriQueryFinished(mSelectedContactUri);
2637ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov        } else {
2646cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            mContactLookupTask = new ContactLookupTask(mSelectedContactUri);
2656cd5b0ab721bcc97d465c768a13e292e59259274Katherine Kuan            mContactLookupTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
266892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        }
267d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
268d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
269892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov    protected void onContactUriQueryFinished(Uri uri) {
270892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        mRefreshingContactUri = false;
271892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        mSelectedContactUri = uri;
272892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        parseSelectedContactUri();
273892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        checkSelection();
2747ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov    }
2757ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov
276cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    @Override
27768e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov    protected void prepareEmptyView() {
27868e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov        if (isSearchMode()) {
27968e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov            return;
28068e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov        } else if (isSyncActive()) {
28168e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov            if (hasIccCard()) {
28268e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov                setEmptyText(R.string.noContactsHelpTextWithSync);
28368e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov            } else {
28468e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov                setEmptyText(R.string.noContactsNoSimHelpTextWithSync);
28568e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov            }
28668e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov        } else {
28768e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov            if (hasIccCard()) {
28868e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov                setEmptyText(R.string.noContactsHelpText);
28968e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov            } else {
29068e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov                setEmptyText(R.string.noContactsNoSimHelpText);
29168e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov            }
29268e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov        }
29368e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov    }
29468e32a3e3248a36f90e43e4f970ebe0196e74e43Dmitri Plotnikov
295cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    public Uri getSelectedContactUri() {
296cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        return mSelectedContactUri;
297cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    }
298cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
299d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    /**
300d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * Sets the new selection for the list.
301d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     */
302cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    public void setSelectedContactUri(Uri uri) {
303264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        setSelectedContactUri(uri, true, true, true, false);
304d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
305d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
3065251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov    @Override
3075251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov    public void setQueryString(String queryString, boolean delaySelection) {
3085251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov        mDelaySelection = delaySelection;
3095251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov        super.setQueryString(queryString, delaySelection);
3105251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov    }
3115251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov
312264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    /**
313e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     * Sets whether or not a contact selection must be made.
314e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     * @param required if true, we need to check if the selection is present in
315e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     *            the list and if not notify the listener so that it can load a
316e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     *            different list.
317e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     * TODO: Figure out how to reconcile this with {@link #setSelectedContactUri},
318e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     * without causing unnecessary loading of the list if the selected contact URI is
319e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     * the same as before.
320e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan     */
321e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan    public void setSelectionRequired(boolean required) {
322e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan        mSelectionRequired = required;
323e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan    }
324e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan
325e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan    /**
326264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     * Sets the new contact selection.
327264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     *
328264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     * @param uri the new selection
329264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     * @param required if true, we need to check if the selection is present in
330264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     *            the list and if not notify the listener so that it can load a
331264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     *            different list
332264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     * @param smoothScroll if true, the UI will roll smoothly to the new
333264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     *            selection
334264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     * @param persistent if true, the selection will be stored in shared
335264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     *            preferences.
336264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     * @param willReloadData if true, the selection will be remembered but not
337264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     *            actually shown, because we are expecting that the data will be
338264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     *            reloaded momentarily
339264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov     */
340264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    private void setSelectedContactUri(Uri uri, boolean required, boolean smoothScroll,
341264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            boolean persistent, boolean willReloadData) {
342d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        mSmoothScrollRequested = smoothScroll;
343d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        mSelectionToScreenRequested = true;
344d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
345174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov        if ((mSelectedContactUri == null && uri != null)
346cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov                || (mSelectedContactUri != null && !mSelectedContactUri.equals(uri))) {
347d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mSelectionVerified = false;
348d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mSelectionRequired = required;
349d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mSelectionPersistenceRequested = persistent;
3507ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov            mSelectedContactUri = uri;
351580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov            parseSelectedContactUri();
3527ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov
353264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            if (!willReloadData) {
354264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov                // Configure the adapter to show the selection based on the
355264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov                // lookup key extracted from the URI
356264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov                ContactListAdapter adapter = getAdapter();
357264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov                if (adapter != null) {
3587d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                    adapter.setSelectedContact(mSelectedContactDirectoryId,
3597d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                            mSelectedContactLookupKey, mSelectedContactId);
3602f28edacb95db9ee56631815f592e46ec928a33fDmitri Plotnikov                    getListView().invalidateViews();
361264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov                }
362264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            }
363264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov
364892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov            // Also, launch a loader to pick up a new lookup URI in case it has changed
365892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov            refreshSelectedContactUri();
3667ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov        }
3677ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov    }
3687ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov
369580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov    private void parseSelectedContactUri() {
370580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov        if (mSelectedContactUri != null) {
371580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov            String directoryParam =
372892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov                    mSelectedContactUri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
37390715b38713ea97504f2b4a8452c8dd46d1c20ecDmitri Plotnikov            mSelectedContactDirectoryId = TextUtils.isEmpty(directoryParam) ? Directory.DEFAULT
374580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov                    : Long.parseLong(directoryParam);
37590715b38713ea97504f2b4a8452c8dd46d1c20ecDmitri Plotnikov            if (mSelectedContactUri.toString().startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
376892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov                List<String> pathSegments = mSelectedContactUri.getPathSegments();
377892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov                mSelectedContactLookupKey = Uri.encode(pathSegments.get(2));
378b906cbe036505547895a568b20187c8361b89fffDmitri Plotnikov                if (pathSegments.size() == 4) {
3790c708094307e6c6b782095c854a1b545b6972b86Dmitri Plotnikov                    mSelectedContactId = ContentUris.parseId(mSelectedContactUri);
3800c708094307e6c6b782095c854a1b545b6972b86Dmitri Plotnikov                }
381fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov            } else if (mSelectedContactUri.toString().startsWith(Contacts.CONTENT_URI.toString()) &&
382fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov                    mSelectedContactUri.getPathSegments().size() >= 2) {
3837d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                mSelectedContactLookupKey = null;
3847d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                mSelectedContactId = ContentUris.parseId(mSelectedContactUri);
38590715b38713ea97504f2b4a8452c8dd46d1c20ecDmitri Plotnikov            } else {
3867d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                Log.e(TAG, "Unsupported contact URI: " + mSelectedContactUri);
38790715b38713ea97504f2b4a8452c8dd46d1c20ecDmitri Plotnikov                mSelectedContactLookupKey = null;
3887d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                mSelectedContactId = 0;
38990715b38713ea97504f2b4a8452c8dd46d1c20ecDmitri Plotnikov            }
39090715b38713ea97504f2b4a8452c8dd46d1c20ecDmitri Plotnikov
391580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov        } else {
392580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov            mSelectedContactDirectoryId = Directory.DEFAULT;
393580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov            mSelectedContactLookupKey = null;
3947d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov            mSelectedContactId = 0;
395580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov        }
396580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov    }
397580286bf8b280cfb607942cd207b3eb68fb8af66Dmitri Plotnikov
3987ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov    @Override
3997ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov    protected void configureAdapter() {
4007ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov        super.configureAdapter();
4017ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov
4027ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov        ContactListAdapter adapter = getAdapter();
4037ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov        if (adapter == null) {
4047ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov            return;
405cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov        }
4067ccdc1f5337f2cb7b311358c8bb3c68aef6213d1Dmitri Plotnikov
4078fdf890892dd5aeec35f693c158777f9fdd7d0e4Isaac Katzenelson        boolean searchMode = isSearchMode();
4088fdf890892dd5aeec35f693c158777f9fdd7d0e4Isaac Katzenelson        if (!searchMode && mFilter != null) {
409d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            adapter.setFilter(mFilter);
4103c8c3e811917998620b4526330b83d32d3c17078Dmitri Plotnikov            if (mSelectionRequired
4113c8c3e811917998620b4526330b83d32d3c17078Dmitri Plotnikov                    || mFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
4127d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                adapter.setSelectedContact(
4137d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                        mSelectedContactDirectoryId, mSelectedContactLookupKey, mSelectedContactId);
41493a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov            }
415d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
4160a4d2258411478c7c78790cd55ba25c99f588c26Dave Santoro
4178fdf890892dd5aeec35f693c158777f9fdd7d0e4Isaac Katzenelson        // Display the user's profile if not in search mode
4188fdf890892dd5aeec35f693c158777f9fdd7d0e4Isaac Katzenelson        adapter.setIncludeProfile(!searchMode);
4196e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    }
4206e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
4216e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    @Override
422174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
423174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov        super.onLoadFinished(loader, data);
424d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        mSelectionVerified = false;
425892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov
426892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        // Refresh the currently selected lookup in case it changed while we were sleeping
427892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        refreshSelectedContactUri();
4286e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    }
4296e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
4300cd01309feeaf08b1a9852d33fc123c6cbddca6cDmitri Plotnikov    @Override
4314ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn    public void onLoaderReset(Loader<Cursor> loader) {
4324ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn    }
4334ef95cc3329b4ad9fa450e4090efaad9935d493fDianne Hackborn
4346e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    private void checkSelection() {
435174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov        if (mSelectionVerified) {
4366e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov            return;
4376e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov        }
4386e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
43993a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        if (mRefreshingContactUri) {
44093a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov            return;
44193a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        }
44293a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov
44393a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        if (isLoadingDirectoryList()) {
4446e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov            return;
4456e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov        }
4466e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
447174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov        ContactListAdapter adapter = getAdapter();
448264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        if (adapter == null) {
449d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return;
450d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
451d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
45293a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        boolean directoryLoading = true;
45393a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        int count = adapter.getPartitionCount();
45493a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        for (int i = 0; i < count; i++) {
45593a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov            Partition partition = adapter.getPartition(i);
45693a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov            if (partition instanceof DirectoryPartition) {
45793a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov                DirectoryPartition directory = (DirectoryPartition) partition;
45893a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov                if (directory.getDirectoryId() == mSelectedContactDirectoryId) {
45993a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov                    directoryLoading = directory.isLoading();
46093a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov                    break;
46193a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov                }
46293a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov            }
46393a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        }
46493a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov
46593a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        if (directoryLoading) {
46693a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov            return;
46793a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov        }
46893a05db5aa59dc031ccd5ce76f816f7b2ab1d3a4Dmitri Plotnikov
4697d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov        adapter.setSelectedContact(
4707d402246e9ac26e05eeb25528bc74083412d1a5aDmitri Plotnikov                mSelectedContactDirectoryId, mSelectedContactLookupKey, mSelectedContactId);
471264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov
472e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan        final int selectedPosition = adapter.getSelectedContactPosition();
473682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        if (selectedPosition != -1) {
474682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov            mLastSelectedPosition = selectedPosition;
475682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        } else {
476d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            if (isSearchMode()) {
4775251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                if (mDelaySelection) {
4785251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                    selectFirstFoundContactAfterDelay();
4795251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                    if (mListener != null) {
4805251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                        mListener.onSelectionChange();
4815251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                    }
4825251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                    return;
483264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov                }
4845251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov            } else if (mSelectionRequired) {
4858fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                // A specific contact was requested, but it's not in the loaded list.
4868fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov
4878fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                // Try reconfiguring and reloading the list that will hopefully contain
4888fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                // the requested contact. Only take one attempt to avoid an infinite loop
4898fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                // in case the contact cannot be found at all.
4908fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                mSelectionRequired = false;
4918fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov
4928fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                // If we were looking at a different specific contact, just reload
4938fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                if (mFilter != null
4948fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                        && mFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
4958fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                    reloadData();
4968fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                } else {
4978fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                    // Otherwise, call the listener, which will adjust the filter.
4988fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                    notifyInvalidSelection();
4998fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                }
5008fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                return;
5015251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov            } else if (mFilter != null
5028fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                    && mFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
5035251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                // If we were trying to load a specific contact, but that contact no longer
5045251884bbcdb92dad577d027126547527285fcceDmitri Plotnikov                // exists, call the listener, which will adjust the filter.
5058fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                notifyInvalidSelection();
5068fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov                return;
5078fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov            }
5088fe7821d91764dc33270f70e1f08ec05647ef041Dmitri Plotnikov
509264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            saveSelectedUri(null);
510264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            selectDefaultContact();
511d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
512d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
513d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        mSelectionRequired = false;
514d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        mSelectionVerified = true;
515d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
516d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mSelectionPersistenceRequested) {
517d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            saveSelectedUri(mSelectedContactUri);
518d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mSelectionPersistenceRequested = false;
519d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
520d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
521d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mSelectionToScreenRequested) {
522e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan            requestSelectionToScreen(selectedPosition);
523d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
524d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
5252f28edacb95db9ee56631815f592e46ec928a33fDmitri Plotnikov        getListView().invalidateViews();
526264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov
527d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mListener != null) {
528d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mListener.onSelectionChange();
529d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
530d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
531d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
532d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    /**
533d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * Automatically selects the first found contact in search mode.  The selection
534d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * is updated after a delay to allow the user to type without to much UI churn
535d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     * and to save bandwidth on directory queries.
536d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov     */
537d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    public void selectFirstFoundContactAfterDelay() {
538d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        Handler handler = getHandler();
539d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        handler.removeMessages(MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT);
540d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
541d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        String queryString = getQueryString();
542d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (queryString != null
543d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                && queryString.length() >= AUTOSELECT_FIRST_FOUND_CONTACT_MIN_QUERY_LENGTH) {
544d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            handler.sendEmptyMessageDelayed(MESSAGE_AUTOSELECT_FIRST_FOUND_CONTACT,
545d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                    DELAY_AUTOSELECT_FIRST_FOUND_CONTACT_MILLIS);
546d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        } else {
547264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            setSelectedContactUri(null, false, false, false, false);
548d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
549d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
550d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
551d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    protected void selectDefaultContact() {
552682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        Uri contactUri = null;
55307bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov        ContactListAdapter adapter = getAdapter();
554682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        if (mLastSelectedPosition != -1) {
55507bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov            int count = adapter.getCount();
55607bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov            int pos = mLastSelectedPosition;
55707bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov            if (pos >= count && count > 0) {
55807bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov                pos = count - 1;
55907bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov            }
56007bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov            contactUri = adapter.getContactUri(pos);
561682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        }
562682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov
563682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        if (contactUri == null) {
56407bf52d66b6a17be1d1a1016fdf53321a1b83861Dmitri Plotnikov            contactUri = adapter.getFirstContactUri();
565682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        }
566682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov
567682e152f65a14971d7df191ff849f9db9d50d617Dmitri Plotnikov        setSelectedContactUri(contactUri, false, mSmoothScrollRequested, false, false);
568d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    }
569d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov
570e1cabcd0956f24a3d3cbe0777b430030f681a739Katherine Kuan    protected void requestSelectionToScreen(int selectedPosition) {
571d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (selectedPosition != -1) {
572753f8f6fde5a4f74181310593acebee94a014fe2Dmitri Plotnikov            AutoScrollListView listView = (AutoScrollListView)getListView();
573753f8f6fde5a4f74181310593acebee94a014fe2Dmitri Plotnikov            listView.requestPositionToScreen(
574d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov                    selectedPosition + listView.getHeaderViewsCount(), mSmoothScrollRequested);
575d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mSelectionToScreenRequested = false;
5766e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov        }
5776e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    }
5786e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
579174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov    @Override
580174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov    public boolean isLoading() {
581892fb517ff1ba2e3f8804b0a9365a2173bff1f3aDmitri Plotnikov        return mRefreshingContactUri || super.isLoading();
582174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov    }
583174fdc2dcb965f11cf4eb25e4ea961f0e1e56c85Dmitri Plotnikov
5846e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    @Override
585264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    protected void startLoading() {
586264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        mStartedLoading = true;
587264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        mSelectionVerified = false;
588264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        super.startLoading();
5896e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    }
5906e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
591a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov    public void reloadDataAndSetSelectedUri(Uri uri) {
592a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov        setSelectedContactUri(uri, true, true, true, true);
593a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov        reloadData();
594a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov    }
595a5a2744ab8102cf4ff5fbd3e1fa074a45257b3ddDmitri Plotnikov
5966e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    @Override
5976e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    public void reloadData() {
598d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mStartedLoading) {
599d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            mSelectionVerified = false;
60004bad51421ca4adab40900324dc2e108f5554e04Dmitri Plotnikov            mLastSelectedPosition = -1;
601d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            super.reloadData();
602d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
603cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov    }
604cfc648986f569bde83715584a91f89ed28dd8335Dmitri Plotnikov
605416b569901ce4c577c1f76c3f29496d1adab29e1Dmitri Plotnikov    public void setOnContactListActionListener(OnContactBrowserActionListener listener) {
606732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov        mListener = listener;
607732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov    }
608732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov
609238d9847d8f2ace658fb7337c8847a2088ddc9d1Dmitri Plotnikov    public void createNewContact() {
6107152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onCreateNewContactAction();
611732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov    }
612732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov
613e20d3432a370dd3996deec2df4e3cdf726c94992Daniel Lehmann    public void viewContact(Uri contactUri) {
614264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        setSelectedContactUri(contactUri, false, false, true, false);
615a5b3d4642e709153e202b187e8c9021506882323Daniel Lehmann        if (mListener != null) mListener.onViewContactAction(contactUri);
6161323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    }
6171323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov
6181323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    public void editContact(Uri contactUri) {
6197152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onEditContactAction(contactUri);
6201323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    }
6211323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov
6221323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    public void deleteContact(Uri contactUri) {
6237152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onDeleteContactAction(contactUri);
6241323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    }
6251323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov
6261323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    public void addToFavorites(Uri contactUri) {
6277152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onAddToFavoritesAction(contactUri);
6281323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    }
6291323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov
6301323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    public void removeFromFavorites(Uri contactUri) {
6317152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onRemoveFromFavoritesAction(contactUri);
6321323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    }
6331323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov
6341323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    public void callContact(Uri contactUri) {
6357152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onCallContactAction(contactUri);
6361323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    }
637732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov
6381323d69c40649914ae2195088573a20cc35da86eDmitri Plotnikov    public void smsContact(Uri contactUri) {
6397152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onSmsContactAction(contactUri);
640732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov    }
641e3fbfd99842607a0c208d0a930878bb54bb91dedDmitri Plotnikov
6426e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    private void notifyInvalidSelection() {
6437152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onInvalidSelection();
6446e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    }
6456e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
646e3fbfd99842607a0c208d0a930878bb54bb91dedDmitri Plotnikov    @Override
647e3fbfd99842607a0c208d0a930878bb54bb91dedDmitri Plotnikov    protected void finish() {
648e3fbfd99842607a0c208d0a930878bb54bb91dedDmitri Plotnikov        super.finish();
6497152124ac79a2faf6fd8e4135069feb92edeb1feDmitri Plotnikov        if (mListener != null) mListener.onFinishAction();
650e3fbfd99842607a0c208d0a930878bb54bb91dedDmitri Plotnikov    }
6518c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov
652d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private void saveSelectedUri(Uri contactUri) {
653fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        if (isSearchMode()) {
654fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov            return;
6558c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov        }
6568c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov
657fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        ContactListFilter.storeToPreferences(mPrefs, mFilter);
658fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov
659fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        Editor editor = mPrefs.edit();
660fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        if (contactUri == null) {
661fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov            editor.remove(getPersistentSelectionKey());
662fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        } else {
663fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov            editor.putString(getPersistentSelectionKey(), contactUri.toString());
6648c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov        }
665fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        editor.apply();
6668c6955ff3c05e1f3899110701c3cb5559a492f1eDmitri Plotnikov    }
6676e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
668264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    private void restoreSelectedUri(boolean willReloadData) {
669264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        // The meaning of mSelectionRequired is that we need to show some
670264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        // selection other than the previous selection saved in shared preferences
671264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        if (mSelectionRequired) {
672d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return;
673d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
6746e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov
675d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        String selectedUri = mPrefs.getString(getPersistentSelectionKey(), null);
676d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (selectedUri == null) {
677264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            setSelectedContactUri(null, false, false, false, willReloadData);
678d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        } else {
679264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov            setSelectedContactUri(Uri.parse(selectedUri), false, false, false, willReloadData);
680264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov        }
681264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    }
682264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov
683264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    private void saveFilter() {
684fa49a66979567894c85fe2489d1375216d67597eDmitri Plotnikov        ContactListFilter.storeToPreferences(mPrefs, mFilter);
685264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    }
686264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov
687264023c04b75043fa77267fd1b940d0afb13421dDmitri Plotnikov    private void restoreFilter() {
688d4ed72eb6610b1318545741140569a973c4ab452Daisuke Miyakawa        mFilter = ContactListFilter.restoreDefaultPreferences(mPrefs);
6896e850a046fcea8ba82a793b43944051246d08180Dmitri Plotnikov    }
69030cc853792b4a71871cef8bca03b67b805fdc34eDmitri Plotnikov
691d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov    private String getPersistentSelectionKey() {
692d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        if (mFilter == null) {
693d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return mPersistentSelectionPrefix;
694d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        } else {
695d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov            return mPersistentSelectionPrefix + "-" + mFilter.getId();
696d959104d37df65f0d6de9290c3fa2b59065be0fcDmitri Plotnikov        }
69730cc853792b4a71871cef8bca03b67b805fdc34eDmitri Plotnikov    }
6980cd01309feeaf08b1a9852d33fc123c6cbddca6cDmitri Plotnikov
6990cd01309feeaf08b1a9852d33fc123c6cbddca6cDmitri Plotnikov    public boolean isOptionsMenuChanged() {
7000cd01309feeaf08b1a9852d33fc123c6cbddca6cDmitri Plotnikov        // This fragment does not have an option menu of its own
7010cd01309feeaf08b1a9852d33fc123c6cbddca6cDmitri Plotnikov        return false;
7020cd01309feeaf08b1a9852d33fc123c6cbddca6cDmitri Plotnikov    }
703732f65236e7f804941e84757c077a84eb11eab16Dmitri Plotnikov}
704