ConversationList.java revision 1bb6975b0a9a5a4b38aef689305b1e7eb5b61b08
172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/*
272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 Esmertec AG.
372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * you may not use this file except in compliance with the License.
772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * You may obtain a copy of the License at
872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
1072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project *
1172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * See the License for the specific language governing permissions and
1572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * limitations under the License.
1672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
1772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
1872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpackage com.android.mms.ui;
1972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.R;
2172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.transaction.MessagingNotification;
227d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylorimport com.android.mms.ui.RecipientList.Recipient;
2372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.android.mms.util.ContactInfoCache;
2472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.google.android.mms.pdu.PduHeaders;
2572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport com.google.android.mms.util.SqliteWrapper;
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
2772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.AlertDialog;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.ListActivity;
2972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.AsyncQueryHandler;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver;
3172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentUris;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Context;
3372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.DialogInterface;
3472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent;
3572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.DialogInterface.OnClickListener;
3672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.res.Configuration;
3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.ContentObserver;
3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.sqlite.SQLiteException;
4072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.net.Uri;
4172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Bundle;
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Handler;
4372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.Contacts;
4472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.Contacts.People;
457d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylorimport android.provider.Contacts.Intents.Insert;
4672b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Projectimport android.provider.Telephony.Mms;
4772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.Telephony.Threads;
4872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.provider.Telephony.Sms.Conversations;
4972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.text.TextUtils;
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Config;
5172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.ContextMenu;
5372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.KeyEvent;
5472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.LayoutInflater;
5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.Menu;
5672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.MenuItem;
5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.View;
5872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.Window;
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.ContextMenu.ContextMenuInfo;
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.View.OnCreateContextMenuListener;
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.View.OnKeyListener;
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.AdapterView;
6372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.ListView;
6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport java.util.concurrent.ConcurrentHashMap;
6672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
6872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * This activity provides a list view of existing conversations.
6972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
7072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectpublic class ConversationList extends ListActivity {
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final String TAG = "ConversationList";
7272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean DEBUG = false;
7372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean LOCAL_LOGV = Config.LOGV && DEBUG;
7472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int THREAD_LIST_QUERY_TOKEN = 1701;
7672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int SEARCH_TOKEN            = 1702;
7772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int DELETE_CONVERSATION_TOKEN = 1801;
7972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // IDs of the main menu items.
8172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int MENU_COMPOSE_NEW            = 0;
8272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int MENU_SEARCH                 = 1;
8372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int MENU_DELETE_ALL             = 3;
8472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int MENU_PREFERENCES            = 4;
8572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int MENU_VIEW_BROADCAST_THREADS = 5;
8672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // IDs of the context menu items for the list of conversations.
8872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static final int MENU_DELETE                = 0;
8972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int MENU_VIEW                 = 1;
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final int MENU_VIEW_CONTACT         = 2;
917d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor    private static final int MENU_ADD_TO_CONTACTS      = 3;
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private Cursor mCursor;
9472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ThreadListQueryHandler mQueryHandler;
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ConversationListAdapter mListAdapter;
9672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private CharSequence mTitle;
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private Uri mBaseUri;
9872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private String mQuery;
9972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private String[] mProjection;
10072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private int mQueryToken;
10172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private String mFilter;
10272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private boolean mSearchFlag;
10372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private CachingNameStore mCachingNameStore;
10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
10572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
10672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * An interface that's passed down to ListAdapters to use
10772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * for looking up the names of contact numbers.
10872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
10972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public static interface CachingNameStore {
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Returns comma-separated list of contact's display names
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // given a semicolon-delimited string of canonical phone
11272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // numbers.
11372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public String getContactNames(String addresses);
11472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
11572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
11672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
11772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onCreate(Bundle savedInstanceState) {
11872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onCreate(savedInstanceState);
11972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
12172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        setContentView(R.layout.conversation_list_screen);
12272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mQueryHandler = new ThreadListQueryHandler(getContentResolver());
12472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
12572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ListView listView = getListView();
12672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        LayoutInflater inflater = LayoutInflater.from(this);
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ConversationHeaderView headerView = (ConversationHeaderView)
12872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                inflater.inflate(R.layout.conversation_header, listView, false);
12972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        headerView.bind(getString(R.string.new_message),
13072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                getString(R.string.create_new_message));
13172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        listView.addHeaderView(headerView, null, true);
13272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        listView.setOnCreateContextMenuListener(mConvListOnCreateContextMenuListener);
13472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        listView.setOnKeyListener(mThreadListKeyListener);
13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mCachingNameStore = new CachingNameStoreImpl(this);
13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (savedInstanceState != null) {
13972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mBaseUri = (Uri) savedInstanceState.getParcelable("base_uri");
14072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mSearchFlag = savedInstanceState.getBoolean("search_flag");
14172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mFilter = savedInstanceState.getString("filter");
14272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mQueryToken = savedInstanceState.getInt("query_token");
14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
14572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        handleCreationIntent(getIntent());
14672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
14772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
14872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    static public boolean isFailedToDeliver(Intent intent) {
14972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return (intent != null) && intent.getBooleanExtra("undelivered_flag", false);
15072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
15172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
15372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onNewIntent(Intent intent) {
15472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Handle intents that occur after the activity has already been created.
15572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        handleCreationIntent(intent);
15672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
15772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ComposeMessageActivity.cancelFailedToDeliverNotification(intent, getApplicationContext());
15872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
15972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void handleCreationIntent(Intent intent) {
16172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Handle intents that occur upon creation of the activity.
16272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        initNormalQueryArgs();
163591d17e9a51bb9f829d6860dc7aa0bad25062cd5The Android Open Source Project
164591d17e9a51bb9f829d6860dc7aa0bad25062cd5The Android Open Source Project        // Cancel any failed message notifications
165591d17e9a51bb9f829d6860dc7aa0bad25062cd5The Android Open Source Project        MessagingNotification.cancelNotification(getApplicationContext(),
166591d17e9a51bb9f829d6860dc7aa0bad25062cd5The Android Open Source Project                    MessagingNotification.MESSAGE_FAILED_NOTIFICATION_ID);
167591d17e9a51bb9f829d6860dc7aa0bad25062cd5The Android Open Source Project   }
16872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
16972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
17072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onResume() {
17172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onResume();
17272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
17372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mListAdapter != null) {
17472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mListAdapter.initDraftCache();  // we might have a draft now
17572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mListAdapter.registerObservers();
17672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
17772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
17872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        getContentResolver().delete(Threads.OBSOLETE_THREADS_URI, null, null);
17972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        startAsyncQuery();
18172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // force invalidate the contact info cache, so we will query for fresh info again.
18372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // This is so we can get fresh presence info again on the screen, since the presence
18472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // info changes pretty quickly, and we can't get change notifications when presence is
18572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // updated in the ContactsProvider.
18672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContactInfoCache.getInstance().invalidateCache();
18772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
18872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
18972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
19072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onSaveInstanceState(Bundle outState) {
19172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onSaveInstanceState(outState);
19272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
19372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        outState.putParcelable("base_uri", mBaseUri);
19472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        outState.putInt("query_token", mQueryToken);
19572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        outState.putBoolean("search_flag", mSearchFlag);
19672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mSearchFlag) {
19772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            outState.putString("filter", mFilter);
19872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
19972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
20072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
20272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onPause() {
20372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onPause();
20472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
20572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mListAdapter != null) {
20672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mListAdapter.unregisterObservers();
20772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
20872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
20972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
21072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
21172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onStop() {
21272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onStop();
21372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
21472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mCursor != null) {
21572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (mListAdapter != null) {
21672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mListAdapter.changeCursor(null);
21772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
21872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mCursor.close();
21972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mCursor = null;
22072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
22172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
22272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
22472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onDestroy() {
22572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onDestroy();
22672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
22772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mCursor != null) {
22872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mCursor.close();
22972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
23072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
23172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
23272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void initNormalQueryArgs() {
23372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Uri.Builder builder = Threads.CONTENT_URI.buildUpon();
23472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.appendQueryParameter("simple", "true");
23572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mBaseUri = builder.build();
23672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mQuery = null;
23772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mProjection = ConversationListAdapter.PROJECTION;
23872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mQueryToken = THREAD_LIST_QUERY_TOKEN;
23972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mTitle = getString(R.string.app_label);
24072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
24172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
24272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void startAsyncQuery() {
24372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
24472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            setTitle(getString(R.string.refreshing));
24572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            setProgressBarIndeterminateVisibility(true);
24672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
24772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mQueryHandler.cancelOperation(THREAD_LIST_QUERY_TOKEN);
24872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // FIXME: I have to pass the mQueryToken as cookie since the
24972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // AsyncQueryHandler.onQueryComplete() method doesn't provide
25072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // the same token as what I input here.
25172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mQueryHandler.startQuery(0, mQueryToken, mBaseUri, mProjection, mQuery, null,
25272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Conversations.DEFAULT_SORT_ORDER);
25372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (SQLiteException e) {
25472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            SqliteWrapper.checkSQLiteException(this, e);
25572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
25672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
25772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
25872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
25972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
26072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        menu.clear();
26172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
26272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        menu.add(0, MENU_COMPOSE_NEW, 0, R.string.menu_compose_new).setIcon(
26372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                com.android.internal.R.drawable.ic_menu_compose);
26472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Removed search as part of b/1205708
26572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        //menu.add(0, MENU_SEARCH, 0, R.string.menu_search).setIcon(
26672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        //        R.drawable.ic_menu_search).setAlphabeticShortcut(SearchManager.MENU_KEY);
26772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if ((mCursor != null) && (mCursor.getCount() > 0) && !mSearchFlag) {
26872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            menu.add(0, MENU_DELETE_ALL, 0, R.string.menu_delete_all).setIcon(
26972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    android.R.drawable.ic_menu_delete);
27072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
27172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
27272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        menu.add(0, MENU_PREFERENCES, 0, R.string.menu_preferences).setIcon(
27372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                android.R.drawable.ic_menu_preferences);
27472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
27572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return true;
27672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
27772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
27872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
27972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onOptionsItemSelected(MenuItem item) {
28072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        switch(item.getItemId()) {
28172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_COMPOSE_NEW:
28272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                createNewMessage();
28372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
28472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_SEARCH:
28572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                onSearchRequested();
28672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
28772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_DELETE_ALL:
28872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                confirmDeleteDialog(new DeleteThreadListener(-1L), true);
28972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
29072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_PREFERENCES: {
29172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Intent intent = new Intent(this, MessagingPreferenceActivity.class);
29272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                startActivityIfNeeded(intent, -1);
29372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
29472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
29572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            default:
29672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return true;
29772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
29872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return false;
29972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
30072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
30172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
30272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onListItemClick(ListView l, View v, int position, long id) {
30372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (LOCAL_LOGV) {
30472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Log.v(TAG, "onListItemClick: position=" + position + ", id=" + id);
30572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
30672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
30772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (position == 0) {
30872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            createNewMessage();
30972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else if (v instanceof ConversationHeaderView) {
31072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            ConversationHeaderView headerView = (ConversationHeaderView) v;
31172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            ConversationHeader ch = headerView.getConversationHeader();
31272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
31372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // TODO: The 'from' view of the ConversationHeader was
31472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // repurposed to be the cached display value, rather than
31572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // the old raw value, which openThread() wanted.  But it
31672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // turns out openThread() doesn't need it:
31772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // ComposeMessageActivity will load it.  That's not ideal,
31872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // though, as it's an SQLite query.  So fix this later to
31972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            // save some latency on starting ComposeMessageActivity.
32072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String somethingDelimitedAddresses = null;
32172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            openThread(ch.getThreadId(), somethingDelimitedAddresses);
32272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
32372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
32472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
32572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void createNewMessage() {
32672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Intent intent = new Intent(this, ComposeMessageActivity.class);
32772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        startActivity(intent);
32872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
32972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void openThread(long threadId, String address) {
33172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        Intent intent = new Intent(this, ComposeMessageActivity.class);
33272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        intent.putExtra("thread_id", threadId);
33372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (!TextUtils.isEmpty(address)) {
33472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            intent.putExtra("address", address);
33572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
33672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        startActivity(intent);
33772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
33872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
33972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void viewContact(String address) {
34072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // address must be a single recipient
34172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ContactInfoCache cache = ContactInfoCache.getInstance();
34272b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Project        ContactInfoCache.CacheEntry info;
34372b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Project        if (Mms.isEmailAddress(address)) {
34472b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Project            info = cache.getContactInfoForEmailAddress(getApplicationContext(), address,
34572b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Project                    true /* allow query */);
34672b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Project        } else {
34772b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Project            info = cache.getContactInfo(this, address);
34872b7fda4ff5e94ba1a13c41601ac1cd61c0d6663The Android Open Source Project        }
3495d2d0046ada7b53205e537d8675d32a8785e8d1dThe Android Open Source Project        if (info != null && info.person_id > 0) {
35072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, info.person_id);
35172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
35272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            startActivity(intent);
35372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
35472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
35572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
3567d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor    public static Intent createAddContactIntent(String address) {
3577d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        // address must be a single recipient
3581bb6975b0a9a5a4b38aef689305b1e7eb5b61b08Tom Taylor        Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
3591bb6975b0a9a5a4b38aef689305b1e7eb5b61b08Tom Taylor        intent.setType(Contacts.People.CONTENT_ITEM_TYPE);
3607d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        if (Recipient.isPhoneNumber(address)) {
3617d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor            intent.putExtra(Insert.PHONE, address);
3627d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        } else {
3637d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor            intent.putExtra(Insert.EMAIL, address);
3647d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        }
3657d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        return intent;
3667d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor    }
3677d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor
36872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final OnCreateContextMenuListener mConvListOnCreateContextMenuListener =
36972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        new OnCreateContextMenuListener() {
37072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void onCreateContextMenu(ContextMenu menu, View v,
37172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ContextMenuInfo menuInfo) {
37272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if ((mCursor != null) && (mCursor.getCount() > 0) && !mSearchFlag) {
37372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                String address = MessageUtils.getRecipientsByIds(
37472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        ConversationList.this,
37572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        mCursor.getString(ConversationListAdapter.COLUMN_RECIPIENTS_IDS),
37672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        true /* allow query */);
37772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // The Recipient IDs column is separated with semicolons for some reason.
37872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // We should fix this in the content provider rework.
37972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                CharSequence from = (ContactInfoCache.getInstance().getContactName(
38072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        ConversationList.this, address)).replace(';', ',');
38172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                menu.setHeaderTitle(from);
38272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
38372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                AdapterView.AdapterContextMenuInfo info =
38472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        (AdapterView.AdapterContextMenuInfo) menuInfo;
38572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (info.position > 0) {
38672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    menu.add(0, MENU_VIEW, 0, R.string.menu_view);
38772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
38872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    // Only show if there's a single recipient
3897d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                    String recipient = getAddress();
3907d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                    if (!recipient.contains(";")) {
3917d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                        // do we have this recipient in contacts?
3927d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                        ContactInfoCache.CacheEntry entry = ContactInfoCache.getInstance()
3937d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                            .getContactInfo(ConversationList.this, recipient);
3947d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor
3957d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                        if (entry != null && entry.person_id > 0) {
3967d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                            menu.add(0, MENU_VIEW_CONTACT, 0, R.string.menu_view_contact);
3977d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                        } else {
3987d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                            menu.add(0, MENU_ADD_TO_CONTACTS, 0, R.string.menu_add_to_contacts);
3997d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                        }
40072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
40172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    menu.add(0, MENU_DELETE, 0, R.string.menu_delete);
40272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
40372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
40472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    };
40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
40772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
40872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onContextItemSelected(MenuItem item) {
40972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        long threadId = mCursor.getLong(ConversationListAdapter.COLUMN_ID);
41072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        switch (item.getItemId()) {
41172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_DELETE: {
41272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                DeleteThreadListener l = new DeleteThreadListener(threadId);
41372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                confirmDeleteDialog(l, false);
41472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
41572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
41672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_VIEW: {
41772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                String address = getAddress();
41872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                openThread(threadId, address);
41972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
42072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
42172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_VIEW_CONTACT: {
42272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                String address = getAddress();
42372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                viewContact(address);
42472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
42572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
4267d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor            case MENU_ADD_TO_CONTACTS: {
4277d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                String address = getAddress();
4287d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                startActivity(createAddContactIntent(address));
4297d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                break;
4307d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor            }
43172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            default:
43272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
43372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
43472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
43572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return super.onContextItemSelected(item);
43672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
43772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
43872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private String getAddress() {
43972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        long threadId = mCursor.getLong(ConversationListAdapter.COLUMN_ID);
44072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        String address = null;
44172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (mListAdapter.isSimpleMode()) {
44272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            address = MessageUtils.getRecipientsByIds(
44372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    this,
44472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mCursor.getString(ConversationListAdapter.COLUMN_RECIPIENTS_IDS),
44572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    true /* allow query */);
44672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } else {
44772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String msgType = mCursor.getString(ConversationListAdapter.COLUMN_MESSAGE_TYPE);
44872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (msgType.equals("sms")) {
44972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                address = mCursor.getString(ConversationListAdapter.COLUMN_SMS_ADDRESS);
45072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
45172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                address = MessageUtils.getAddressByThreadId(this, threadId);
45272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project           }
45372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
45472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return address;
45572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
45672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
45772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onConfigurationChanged(Configuration newConfig) {
45872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // We override this method to avoid restarting the entire
45972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // activity when the keyboard is opened (declared in
46072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // AndroidManifest.xml).  Because the only translatable text
46172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // in this activity is "New Message", which has the full width
46272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // of phone to work with, localization shouldn't be a problem:
46372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // no abbreviated alternate words should be needed even in
46472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // 'wide' languages like German or Russian.
46572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
46672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onConfigurationChanged(newConfig);
46772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (DEBUG) Log.v(TAG, "onConfigurationChanged: " + newConfig);
46872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
46972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
47072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void confirmDeleteDialog(OnClickListener listener, boolean deleteAll) {
47172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        AlertDialog.Builder builder = new AlertDialog.Builder(this);
47272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setTitle(R.string.confirm_dialog_title);
47372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setIcon(android.R.drawable.ic_dialog_alert);
47472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setCancelable(true);
47572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setPositiveButton(R.string.yes, listener);
47672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setNegativeButton(R.string.no, null);
47772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.setMessage(deleteAll
47872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ? R.string.confirm_delete_all_conversations
47972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                : R.string.confirm_delete_conversation);
48072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
48172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        builder.show();
48272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
48372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
48472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final OnKeyListener mThreadListKeyListener = new OnKeyListener() {
48572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public boolean onKey(View v, int keyCode, KeyEvent event) {
48672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (event.getAction() == KeyEvent.ACTION_DOWN) {
48772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                switch (keyCode) {
48872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    case KeyEvent.KEYCODE_DEL: {
48972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        long id = getListView().getSelectedItemId();
49072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (id > 0) {
49172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            DeleteThreadListener l = new DeleteThreadListener(
49272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                    id);
49372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            confirmDeleteDialog(l, false);
49472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
49572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return true;
49672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
49772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    case KeyEvent.KEYCODE_BACK: {
49872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (mSearchFlag) {
49972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            mSearchFlag = false;
50072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            initNormalQueryArgs();
50172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            startAsyncQuery();
50272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
50372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            return true;
50472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
50572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        break;
50672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
50772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
50872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
50972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return false;
51072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
51172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    };
51272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
51372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private class DeleteThreadListener implements OnClickListener {
51472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private final Uri mDeleteUri;
51572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private final long mThreadId;
51672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
51772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public DeleteThreadListener(long threadId) {
51872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mThreadId = threadId;
51972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
52072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (threadId != -1) {
52172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mDeleteUri = ContentUris.withAppendedId(
52272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Threads.CONTENT_URI, threadId);
52372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
52472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mDeleteUri = Threads.CONTENT_URI;
52572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
52672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
52772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
52872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void onClick(DialogInterface dialog, int whichButton) {
52972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            MessageUtils.handleReadReport(ConversationList.this, mThreadId,
53072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    PduHeaders.READ_STATUS__DELETED_WITHOUT_BEING_READ, new Runnable() {
53172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                public void run() {
53272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    mQueryHandler.startDelete(DELETE_CONVERSATION_TOKEN,
53372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                            null, mDeleteUri, null, null);
53472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
53572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            });
53672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
53772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
53872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
53972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final class ThreadListQueryHandler extends AsyncQueryHandler {
54072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public ThreadListQueryHandler(ContentResolver contentResolver) {
54172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            super(contentResolver);
54272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
54372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
54472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        @Override
54572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
54672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (mCursor != null) {
54772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mCursor.close();
54872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
54972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
55072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (cursor != null) {
55172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                mCursor = cursor;
55272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                switch ((Integer) cookie) {
55372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    case THREAD_LIST_QUERY_TOKEN:
55472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        mListAdapter = new ConversationListAdapter(
55572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                ConversationList.this,
55672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                cursor,
55772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                true,  // simple (non-search)
55872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                mListAdapter,
55972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                mCachingNameStore);
56072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        break;
56172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    case SEARCH_TOKEN:
56272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        mListAdapter = new ConversationListAdapter(
56372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                ConversationList.this,
56472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                cursor,
56572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                false,  // non-simple (search)
56672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                mListAdapter,
56772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                                mCachingNameStore);
56872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        break;
56972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    default:
57072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        Log.e(TAG, "Bad query token: " + token);
57172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        break;
57272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
57372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
57472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ConversationList.this.setListAdapter(mListAdapter);
57572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
57672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Log.e(TAG, "Cannot init the cursor for the thread list.");
57772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                finish();
57872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
57972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
58072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            setTitle(mTitle);
58172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            setProgressBarIndeterminateVisibility(false);
58272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
58372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
58472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        @Override
58572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        protected void onDeleteComplete(int token, Object cookie, int result) {
58672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            switch (token) {
58772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case DELETE_CONVERSATION_TOKEN:
58872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Update the notification for new messages since they
58972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // may be deleted.
59072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                MessagingNotification.updateNewMessageIndicator(ConversationList.this);
59172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Update the notification for failed messages since they
59272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // may be deleted.
59372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                MessagingNotification.updateSendFailedNotification(ConversationList.this);
59472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
59572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Make sure the list reflects the delete
59672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                startAsyncQuery();
59772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
59872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                onContentChanged();
59972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
60072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
60172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
60272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
60372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
60472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    /**
60572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * This implements the CachingNameStore interface defined above
60672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * which we pass down to each newly-created ListAdapater, so they
60772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * share a common, reused cached between activity resumes, not
60872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     * having to hit the Contacts providers all the time.
60972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project     */
61072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final class CachingNameStoreImpl implements CachingNameStore {
61172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private static final String TAG = "ConversationList/CachingNameStoreImpl";
61272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private final ConcurrentHashMap<String, String> mCachedNames =
61372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                new ConcurrentHashMap<String, String>();
61472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private final ContentObserver mPhonesObserver;
61572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        private final Context mContext;
61672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
61772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public CachingNameStoreImpl(Context ctxt) {
61872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mContext = ctxt;
61972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mPhonesObserver = new ContentObserver(new Handler()) {
62072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    @Override
62172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    public void onChange(boolean selfUpdate) {
62272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        mCachedNames.clear();
62372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
62472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                };
62572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            ctxt.getContentResolver().registerContentObserver(
62672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    Contacts.Phones.CONTENT_URI,
62772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    true, mPhonesObserver);
62872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
62972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
63072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Returns comma-separated list of contact's display names
63172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // given a semicolon-delimited string of canonical phone
63272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // numbers, getting data either from cache or via a blocking
63372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // call to a provider.
63472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public String getContactNames(String addresses) {
63572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String value = mCachedNames.get(addresses);
63672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (value != null) {
63772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return value;
63872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
63972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            String[] values = addresses.split(";");
64072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (values.length < 2) {
64172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                if (DEBUG) Log.v(TAG, "Looking up name: " + addresses);
64272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ContactInfoCache cache = ContactInfoCache.getInstance();
64372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                value = (cache.getContactName(mContext, addresses)).replace(';', ',');
64472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            } else {
64572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                int length = 0;
64672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                for (int i = 0; i < values.length; ++i) {
64772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    values[i] = getContactNames(values[i]);
64872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    length += values[i].length() + 2;  // 2 for ", "
64972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
65072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                StringBuilder sb = new StringBuilder(length);
65172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                sb.append(values[0]);
65272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                for (int i = 1; i < values.length; ++i) {
65372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    sb.append(", ");
65472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    sb.append(values[i]);
65572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
65672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                value = sb.toString();
65772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
65872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            mCachedNames.put(addresses, value);
65972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return value;
66072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
66172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
66272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
66372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
664