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
202426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylorimport android.app.ActionBar;
2172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.AlertDialog;
2272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.app.ListActivity;
23136fe3767b8cb5dc0575992f2f6951c8451ee5e2Tom Taylorimport android.app.SearchManager;
24e131a53620fff000a08cf53d29313a3922328dc0Mark Wagnerimport android.app.SearchableInfo;
25d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.content.ActivityNotFoundException;
2672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.AsyncQueryHandler;
2778e2f412983f8f3732b87bfd794e04d3b20233bbJake Hambyimport android.content.ComponentName;
2872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.ContentResolver;
293e10898d774b0005fc776865216651346503024bTom Taylorimport android.content.Context;
3072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.DialogInterface;
31d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.content.DialogInterface.OnClickListener;
3272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.Intent;
33f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylorimport android.content.SharedPreferences;
34a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport android.content.pm.ApplicationInfo;
35d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.content.pm.PackageManager;
36a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport android.content.pm.PackageManager.NameNotFoundException;
3772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.content.res.Configuration;
3872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.Cursor;
3972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.database.sqlite.SQLiteException;
40d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.database.sqlite.SqliteWrapper;
41a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport android.graphics.drawable.Drawable;
4272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.os.Bundle;
43f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylorimport android.os.Handler;
44f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylorimport android.preference.PreferenceManager;
45923c4c7e9afb8e364d4a93afa0eb6394485d3637Dmitri Plotnikovimport android.provider.ContactsContract;
46923c4c7e9afb8e364d4a93afa0eb6394485d3637Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
47a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport android.provider.Telephony;
48f7e8281a223af6228e6399055a6197a1edd9bc3aTom Taylorimport android.provider.Telephony.Mms;
492426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylorimport android.provider.Telephony.Threads;
5072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.util.Log;
51b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylorimport android.view.ActionMode;
5272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.ContextMenu;
53d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.view.ContextMenu.ContextMenuInfo;
549995f7fda121bbd84a2a8a3c5edfd9d2d60870e8Tom Taylorimport android.view.Gravity;
5572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.KeyEvent;
5672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.LayoutInflater;
5772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.Menu;
58b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylorimport android.view.MenuInflater;
5972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.MenuItem;
6072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.View;
6172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.View.OnCreateContextMenuListener;
6272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.view.View.OnKeyListener;
63d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport android.view.ViewGroup;
6472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.AdapterView;
6585fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylorimport android.widget.CheckBox;
66a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport android.widget.ImageView;
6772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Projectimport android.widget.ListView;
68e131a53620fff000a08cf53d29313a3922328dc0Mark Wagnerimport android.widget.SearchView;
6985fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylorimport android.widget.TextView;
70a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport android.widget.Toast;
7172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
72d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.LogTag;
73991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braunimport com.android.mms.MmsConfig;
74d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.R;
75d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.Contact;
76d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.ContactList;
77d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.Conversation;
78d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.data.Conversation.ConversationQueryHandler;
79d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.transaction.MessagingNotification;
80d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.transaction.SmsRejectedReceiver;
81d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.util.DraftCache;
82d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.android.mms.util.Recycler;
83cee64965b033733a494df675892267e109a23dd6Roger Chenimport com.android.mms.widget.MmsWidgetProvider;
84d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chenimport com.google.android.mms.pdu.PduHeaders;
85d64419030e1fec1e751695dab3bd7236e2fb0214Roger Chen
86a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport java.util.ArrayList;
87a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport java.util.Collection;
88a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braunimport java.util.HashSet;
89a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun
9072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project/**
9172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project * This activity provides a list view of existing conversations.
9272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project */
93e131a53620fff000a08cf53d29313a3922328dc0Mark Wagnerpublic class ConversationList extends ListActivity implements DraftCache.OnDraftChangedListener {
94ab845dee6565a8dfc384186bc8f2e801a2b087e1Ye Wen    private static final String TAG = LogTag.TAG;
9572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private static final boolean DEBUG = false;
9699f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor    private static final boolean DEBUGCLEANUP = true;
9772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
9863e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor    private static final int THREAD_LIST_QUERY_TOKEN       = 1701;
992426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor    private static final int UNREAD_THREADS_QUERY_TOKEN    = 1702;
10063e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor    public static final int DELETE_CONVERSATION_TOKEN      = 1801;
10163e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor    public static final int HAVE_LOCKED_MESSAGES_TOKEN     = 1802;
10263e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor    private static final int DELETE_OBSOLETE_THREADS_TOKEN = 1803;
10333a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick
10472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    // IDs of the context menu items for the list of conversations.
10548da875f1beea835c6771977e5bd8a9aa3d4bc10Tom Taylor    public static final int MENU_DELETE               = 0;
10648da875f1beea835c6771977e5bd8a9aa3d4bc10Tom Taylor    public static final int MENU_VIEW                 = 1;
10748da875f1beea835c6771977e5bd8a9aa3d4bc10Tom Taylor    public static final int MENU_VIEW_CONTACT         = 2;
10848da875f1beea835c6771977e5bd8a9aa3d4bc10Tom Taylor    public static final int MENU_ADD_TO_CONTACTS      = 3;
10933a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick
11072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ThreadListQueryHandler mQueryHandler;
11172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private ConversationListAdapter mListAdapter;
112f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    private SharedPreferences mPrefs;
113f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    private Handler mHandler;
114d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor    private boolean mDoOnceAfterFirstQuery;
1152426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor    private TextView mUnreadConvCount;
116e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner    private MenuItem mSearchItem;
117e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner    private SearchView mSearchView;
118991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun    private View mSmsPromoBannerView;
1196019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    private int mSavedFirstVisiblePosition = AdapterView.INVALID_POSITION;
1206019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    private int mSavedFirstItemOffset;
1216019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor
1226019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    // keys for extras and icicles
1236019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    private final static String LAST_LIST_POS = "last_list_pos";
1246019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    private final static String LAST_LIST_OFFSET = "last_list_offset";
125f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor
126f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    static private final String CHECKED_MESSAGE_LIMITS = "checked_message_limits";
12772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
128991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun    // Whether or not we are currently enabled for SMS. This field is updated in onResume to make
129991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun    // sure we notice if the user has changed the default SMS app.
130991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun    private boolean mIsSmsEnabled;
131a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun    private Toast mComposeDisabledToast;
132991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun
13372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
13472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onCreate(Bundle savedInstanceState) {
13572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onCreate(savedInstanceState);
13672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
13772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        setContentView(R.layout.conversation_list_screen);
13872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
139991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        mSmsPromoBannerView = findViewById(R.id.banner_sms_promo);
140991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun
14172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        mQueryHandler = new ThreadListQueryHandler(getContentResolver());
14272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
14372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        ListView listView = getListView();
14472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        listView.setOnCreateContextMenuListener(mConvListOnCreateContextMenuListener);
14572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        listView.setOnKeyListener(mThreadListKeyListener);
146b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
147b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        listView.setMultiChoiceModeListener(new ModeCallback());
14872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
149ebb3227c391ec7fd4686aadd3cb18d5f427fc17bTom Taylor        // Tell the list view which view to display when the list is empty
150e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor        listView.setEmptyView(findViewById(R.id.empty));
151ebb3227c391ec7fd4686aadd3cb18d5f427fc17bTom Taylor
15259cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick        initListAdapter();
15333a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick
1542426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        setupActionBar();
1552426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
15664989ecb6d0e4bea59487bade662915317b6b54bTodor Kalaydjiev        setTitle(R.string.app_label);
157f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor
158f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        mHandler = new Handler();
159f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
160f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        boolean checkedMessageLimits = mPrefs.getBoolean(CHECKED_MESSAGE_LIMITS, false);
161f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        if (DEBUG) Log.v(TAG, "checkedMessageLimits: " + checkedMessageLimits);
1626af6c0c78aa684221f43d297e6d1ea52afa7093aRoger Chen        if (!checkedMessageLimits) {
163f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            runOneTimeStorageLimitCheckForLegacyMessages();
164f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        }
1656019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor
1666019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        if (savedInstanceState != null) {
1676019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor            mSavedFirstVisiblePosition = savedInstanceState.getInt(LAST_LIST_POS,
1686019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor                    AdapterView.INVALID_POSITION);
1696019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor            mSavedFirstItemOffset = savedInstanceState.getInt(LAST_LIST_OFFSET, 0);
1706019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        } else {
1716019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor            mSavedFirstVisiblePosition = AdapterView.INVALID_POSITION;
1726019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor            mSavedFirstItemOffset = 0;
1736019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        }
1746019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    }
1756019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor
1766019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    @Override
1776019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    public void onSaveInstanceState(Bundle outState) {
1786019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        super.onSaveInstanceState(outState);
1796019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor
1806019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        outState.putInt(LAST_LIST_POS, mSavedFirstVisiblePosition);
1816019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        outState.putInt(LAST_LIST_OFFSET, mSavedFirstItemOffset);
1826019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    }
1836019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor
1846019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    @Override
1856019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor    public void onPause() {
1866019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        super.onPause();
1876019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor
188f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor        // Don't listen for changes while we're paused.
189f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor        mListAdapter.setOnContentChangedListener(null);
190f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor
1916019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        // Remember where the list is scrolled to so we can restore the scroll position
1926019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        // when we come back to this activity and *after* we complete querying for the
1936019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        // conversations.
1946019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        ListView listView = getListView();
1956019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        mSavedFirstVisiblePosition = listView.getFirstVisiblePosition();
1966019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        View firstChild = listView.getChildAt(0);
1976019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor        mSavedFirstItemOffset = (firstChild == null) ? 0 : firstChild.getTop();
19872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
19972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
200f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor    @Override
201f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor    protected void onResume() {
202f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor        super.onResume();
203991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        boolean isSmsEnabled = MmsConfig.isSmsEnabled(this);
204991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        if (isSmsEnabled != mIsSmsEnabled) {
205991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            mIsSmsEnabled = isSmsEnabled;
206991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            invalidateOptionsMenu();
207991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        }
208991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun
209991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        // Multi-select is used to delete conversations. It is disabled if we are not the sms app.
210991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        ListView listView = getListView();
211991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        if (mIsSmsEnabled) {
212991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
213991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        } else {
214991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            listView.setChoiceMode(ListView.CHOICE_MODE_NONE);
215991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        }
216991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun
217991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        // Show or hide the SMS promo banner
218991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        if (mIsSmsEnabled || MmsConfig.isSmsPromoDismissed(this)) {
219991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            mSmsPromoBannerView.setVisibility(View.GONE);
220991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        } else {
221a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            initSmsPromoBanner();
222991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            mSmsPromoBannerView.setVisibility(View.VISIBLE);
223991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        }
224f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor
225f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor        mListAdapter.setOnContentChangedListener(mContentChangedListener);
226f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor    }
227f794f8cf5bdf72165bbed1fb3dc7f3e98b49150eTom Taylor
2282426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor    private void setupActionBar() {
2292426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        ActionBar actionBar = getActionBar();
2302426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
2312426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        ViewGroup v = (ViewGroup)LayoutInflater.from(this)
2322426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            .inflate(R.layout.conversation_list_actionbar, null);
2339995f7fda121bbd84a2a8a3c5edfd9d2d60870e8Tom Taylor        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
2349995f7fda121bbd84a2a8a3c5edfd9d2d60870e8Tom Taylor                ActionBar.DISPLAY_SHOW_CUSTOM);
2352426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        actionBar.setCustomView(v,
2369995f7fda121bbd84a2a8a3c5edfd9d2d60870e8Tom Taylor                new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,
2379995f7fda121bbd84a2a8a3c5edfd9d2d60870e8Tom Taylor                        ActionBar.LayoutParams.WRAP_CONTENT,
2389995f7fda121bbd84a2a8a3c5edfd9d2d60870e8Tom Taylor                        Gravity.CENTER_VERTICAL | Gravity.RIGHT));
2392426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
2402426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        mUnreadConvCount = (TextView)v.findViewById(R.id.unread_conv_count);
2412426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor    }
2422426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
24367b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor    private final ConversationListAdapter.OnContentChangedListener mContentChangedListener =
24467b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor        new ConversationListAdapter.OnContentChangedListener() {
245ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
24667b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor        public void onContentChanged(ConversationListAdapter adapter) {
24767b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor            startAsyncQuery();
24867b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor        }
24967b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor    };
25067b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor
25159cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick    private void initListAdapter() {
2521d98ae0b203e01034ddead4214d1520ce863a23bFicus Kirkpatrick        mListAdapter = new ConversationListAdapter(this, null);
25367b794480aaad0e1958df2988671b78ea03b76e1Tom Taylor        mListAdapter.setOnContentChangedListener(mContentChangedListener);
25459cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick        setListAdapter(mListAdapter);
255d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        getListView().setRecyclerListener(mListAdapter);
25659cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick    }
25733a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick
258991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun    private void initSmsPromoBanner() {
259a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        final PackageManager packageManager = getPackageManager();
260a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        final String smsAppPackage = Telephony.Sms.getDefaultSmsPackage(this);
261a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun
262a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        // Get all the data we need about the default app to properly render the promo banner. We
263a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        // try to show the icon and name of the user's selected SMS app and have the banner link
264a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        // to that app. If we can't read that information for any reason we leave the fallback
265a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        // text that links to Messaging settings where the user can change the default.
266a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        Drawable smsAppIcon = null;
267a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        ApplicationInfo smsAppInfo = null;
268a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        try {
269a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            smsAppIcon = packageManager.getApplicationIcon(smsAppPackage);
270a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            smsAppInfo = packageManager.getApplicationInfo(smsAppPackage, 0);
271a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        } catch (NameNotFoundException e) {
272a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        }
273a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        final Intent smsAppIntent = packageManager.getLaunchIntentForPackage(smsAppPackage);
274a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun
275a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        // If we got all the info we needed
276a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        if (smsAppIcon != null && smsAppInfo != null && smsAppIntent != null) {
277a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            ImageView defaultSmsAppIconImageView =
278a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    (ImageView)mSmsPromoBannerView.findViewById(R.id.banner_sms_default_app_icon);
279a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            defaultSmsAppIconImageView.setImageDrawable(smsAppIcon);
280a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            TextView smsPromoBannerTitle =
281a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    (TextView)mSmsPromoBannerView.findViewById(R.id.banner_sms_promo_title);
282a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            String message = getResources().getString(R.string.banner_sms_promo_title_application,
283a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    smsAppInfo.loadLabel(packageManager));
284a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            smsPromoBannerTitle.setText(message);
285a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun
286a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            mSmsPromoBannerView.setOnClickListener(new View.OnClickListener() {
287a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                @Override
288a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                public void onClick(View v) {
289a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    startActivity(smsAppIntent);
290a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                }
291a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            });
292a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        } else {
293a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            // Otherwise the banner will be left alone and will launch settings
294a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            mSmsPromoBannerView.setOnClickListener(new View.OnClickListener() {
295a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                @Override
296a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                public void onClick(View v) {
297a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    // Launch settings
298a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    Intent settingsIntent = new Intent(ConversationList.this,
299a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                            MessagingPreferenceActivity.class);
300a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    startActivityIfNeeded(settingsIntent, -1);
301a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                }
302a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            });
303a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun        }
304991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun    }
305991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun
306f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    /**
307f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     * Checks to see if the number of MMS and SMS messages are under the limits for the
308f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     * recycler. If so, it will automatically turn on the recycler setting. If not, it
309f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     * will prompt the user with a message and point them to the setting to manually
310f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     * turn on the recycler.
311f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     */
312f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    public synchronized void runOneTimeStorageLimitCheckForLegacyMessages() {
313f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        if (Recycler.isAutoDeleteEnabled(this)) {
314f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            if (DEBUG) Log.v(TAG, "recycler is already turned on");
315f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            // The recycler is already turned on. We don't need to check anything or warn
316f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            // the user, just remember that we've made the check.
317f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            markCheckedMessageLimit();
318f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            return;
319f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        }
320f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        new Thread(new Runnable() {
321ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev            @Override
322f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            public void run() {
323f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                if (Recycler.checkForThreadsOverLimit(ConversationList.this)) {
324f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    if (DEBUG) Log.v(TAG, "checkForThreadsOverLimit TRUE");
325f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    // Dang, one or more of the threads are over the limit. Show an activity
326f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    // that'll encourage the user to manually turn on the setting. Delay showing
327f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    // this activity until a couple of seconds after the conversation list appears.
328f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    mHandler.postDelayed(new Runnable() {
329ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev                        @Override
330f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                        public void run() {
331f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                            Intent intent = new Intent(ConversationList.this,
332f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                                    WarnOfStorageLimitsActivity.class);
333f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                            startActivity(intent);
334f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                        }
335f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    }, 2000);
336f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                } else {
337f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    if (DEBUG) Log.v(TAG, "checkForThreadsOverLimit silently turning on recycler");
338f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    // No threads were over the limit. Turn on the recycler by default.
339f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    runOnUiThread(new Runnable() {
340ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev                        @Override
341f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                        public void run() {
342f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                            SharedPreferences.Editor editor = mPrefs.edit();
343f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                            editor.putBoolean(MessagingPreferenceActivity.AUTO_DELETE, true);
344d4ab73b7483ba8a92a96235474070fbf5c10244cBrad Fitzpatrick                            editor.apply();
345f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                        }
346f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    });
347f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                }
348f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                // Remember that we don't have to do the check anymore when starting MMS.
349f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                runOnUiThread(new Runnable() {
350ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev                    @Override
351f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    public void run() {
352f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                        markCheckedMessageLimit();
353f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                    }
354f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor                });
355f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor            }
356ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        }, "ConversationList.runOneTimeStorageLimitCheckForLegacyMessages").start();
357f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    }
358f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor
359f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    /**
360f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     * Mark in preferences that we've checked the user's message limits. Once checked, we'll
361f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     * never check them again, unless the user wipe-data or resets the device.
362f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor     */
363f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    private void markCheckedMessageLimit() {
364f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        if (DEBUG) Log.v(TAG, "markCheckedMessageLimit");
365f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        SharedPreferences.Editor editor = mPrefs.edit();
366f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor        editor.putBoolean(CHECKED_MESSAGE_LIMITS, true);
367d4ab73b7483ba8a92a96235474070fbf5c10244cBrad Fitzpatrick        editor.apply();
368f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor    }
369f766f33b774cfb6dd4100a6522ffa23c0a0dae35Tom Taylor
37072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
37172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onNewIntent(Intent intent) {
37272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // Handle intents that occur after the activity has already been created.
37363e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor        startAsyncQuery();
37472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
37572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
376d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang    @Override
377d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang    protected void onStart() {
378d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        super.onStart();
379dc58429bf08e9d5ba8c43f0ac21e7cd18ea8cb06Tom Taylor
380a1af734418c5578483f3387e5e0bf6128c963dfaTom Taylor        MessagingNotification.cancelNotification(getApplicationContext(),
381a1af734418c5578483f3387e5e0bf6128c963dfaTom Taylor                SmsRejectedReceiver.SMS_REJECTED_NOTIFICATION_ID);
382b530437ceaad97151be691067191f48e1e93b87eFicus Kirkpatrick
383d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        DraftCache.getInstance().addOnDraftChangedListener(this);
384812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang
385d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor        mDoOnceAfterFirstQuery = true;
38663e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor
38763e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor        startAsyncQuery();
38863e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor
389d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // We used to refresh the DraftCache here, but
390d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // refreshing the DraftCache each time we go to the ConversationList seems overly
391d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // aggressive. We already update the DraftCache when leaving CMA in onStop() and
392d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // onNewIntent(), and when we delete threads or delete all in CMA or this activity.
393d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // I hope we don't have to do such a heavy operation each time we enter here.
394598ca14f5d7d26d6d5125d8fe0d07e50f066ff98Ficus Kirkpatrick
395d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // we invalidate the contact cache here because we want to get updated presence
396d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // and any contact changes. We don't invalidate the cache by observing presence and contact
397d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // changes (since that's too untargeted), so as a tradeoff we do it here.
398445fb5abf8804279e591d1c35657c9162625135eTom Taylor        // If we're in the middle of the app initialization where we're loading the conversation
399445fb5abf8804279e591d1c35657c9162625135eTom Taylor        // threads, don't invalidate the cache because we're in the process of building it.
400d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // TODO: think of a better way to invalidate cache more surgically or based on actual
401d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        // TODO: changes we care about
402445fb5abf8804279e591d1c35657c9162625135eTom Taylor        if (!Conversation.loadingThreads()) {
403445fb5abf8804279e591d1c35657c9162625135eTom Taylor            Contact.invalidateCache();
404445fb5abf8804279e591d1c35657c9162625135eTom Taylor        }
40572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
40672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
40772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
40872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onStop() {
40972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onStop();
41072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
41181f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang        stopAsyncQuery();
41281f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang
413d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang        DraftCache.getInstance().removeOnDraftChangedListener(this);
414f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor
4158e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang        unbindListeners(null);
416f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor        // Simply setting the choice mode causes the previous choice mode to finish and we exit
417f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor        // multi-select mode (if we're in it) and remove all the selections.
418f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
419f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor
4206f82efcfc934f13b7774a05c8d5ed9fafa2c4fcaRoger Chen        // Close the cursor in the ListAdapter if the activity stopped.
4216f82efcfc934f13b7774a05c8d5ed9fafa2c4fcaRoger Chen        Cursor cursor = mListAdapter.getCursor();
4226f82efcfc934f13b7774a05c8d5ed9fafa2c4fcaRoger Chen
4236f82efcfc934f13b7774a05c8d5ed9fafa2c4fcaRoger Chen        if (cursor != null && !cursor.isClosed()) {
4246f82efcfc934f13b7774a05c8d5ed9fafa2c4fcaRoger Chen            cursor.close();
4256f82efcfc934f13b7774a05c8d5ed9fafa2c4fcaRoger Chen        }
4266f82efcfc934f13b7774a05c8d5ed9fafa2c4fcaRoger Chen
42759cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick        mListAdapter.changeCursor(null);
42872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
42972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
4308e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang    private void unbindListeners(final Collection<Long> threadIds) {
4318e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang        for (int i = 0; i < getListView().getChildCount(); i++) {
4328e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang            View view = getListView().getChildAt(i);
4338e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang            if (view instanceof ConversationListItem) {
4348e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                ConversationListItem item = (ConversationListItem)view;
4358e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                if (threadIds == null) {
4368e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                    item.unbind();
4378e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                } else if (threadIds.contains(item.getConversation().getThreadId())) {
4388e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                    item.unbind();
4398e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                }
4408e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang            }
4418e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang        }
4428e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang    }
4438e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang
444ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev    @Override
445d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang    public void onDraftChanged(final long threadId, final boolean hasDraft) {
44659cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick        // Run notifyDataSetChanged() on the main thread.
44759cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick        mQueryHandler.post(new Runnable() {
448ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev            @Override
44959cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick            public void run() {
450d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang                if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
451d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang                    log("onDraftChanged: threadId=" + threadId + ", hasDraft=" + hasDraft);
452d9d7479a8c9e10b7b3f39137e28ed0f283e4a257Wei Huang                }
45359cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick                mListAdapter.notifyDataSetChanged();
45459cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick            }
45559cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick        });
456b530437ceaad97151be691067191f48e1e93b87eFicus Kirkpatrick    }
45733a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick
45872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void startAsyncQuery() {
45972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        try {
460e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor            ((TextView)(getListView().getEmptyView())).setText(R.string.loading_conversations);
46172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
46270c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick            Conversation.startQueryForAll(mQueryHandler, THREAD_LIST_QUERY_TOKEN);
4632426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            Conversation.startQuery(mQueryHandler, UNREAD_THREADS_QUERY_TOKEN, Threads.READ + "=0");
46472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        } catch (SQLiteException e) {
46572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            SqliteWrapper.checkSQLiteException(this, e);
46672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
46772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
46872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
46981f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang    private void stopAsyncQuery() {
47081f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang        if (mQueryHandler != null) {
47181f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang            mQueryHandler.cancelOperation(THREAD_LIST_QUERY_TOKEN);
47281f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang            mQueryHandler.cancelOperation(UNREAD_THREADS_QUERY_TOKEN);
47381f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang        }
47481f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang    }
47581f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang
476e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner    SearchView.OnQueryTextListener mQueryTextListener = new SearchView.OnQueryTextListener() {
477ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
478e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        public boolean onQueryTextSubmit(String query) {
479e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            Intent intent = new Intent();
480e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            intent.setClass(ConversationList.this, SearchActivity.class);
481e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            intent.putExtra(SearchManager.QUERY, query);
482e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            startActivity(intent);
483e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            mSearchItem.collapseActionView();
484e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            return true;
485e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        }
486e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner
487ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
488e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        public boolean onQueryTextChange(String newText) {
489e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            return false;
490e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        }
491e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner    };
492b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor
49372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
494136fe3767b8cb5dc0575992f2f6951c8451ee5e2Tom Taylor    public boolean onCreateOptionsMenu(Menu menu) {
495b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor        getMenuInflater().inflate(R.menu.conversation_list_menu, menu);
496b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor
497e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        mSearchItem = menu.findItem(R.id.search);
498e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        mSearchView = (SearchView) mSearchItem.getActionView();
499b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor
500e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        mSearchView.setOnQueryTextListener(mQueryTextListener);
501e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        mSearchView.setQueryHint(getString(R.string.search_hint));
502e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        mSearchView.setIconifiedByDefault(true);
503e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
504136fe3767b8cb5dc0575992f2f6951c8451ee5e2Tom Taylor
505e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        if (searchManager != null) {
506e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            SearchableInfo info = searchManager.getSearchableInfo(this.getComponentName());
507e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner            mSearchView.setSearchableInfo(info);
508e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        }
509e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner
51078e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby        MenuItem cellBroadcastItem = menu.findItem(R.id.action_cell_broadcasts);
51178e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby        if (cellBroadcastItem != null) {
51278e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            // Enable link to Cell broadcast activity depending on the value in config.xml.
51378e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
51478e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                    com.android.internal.R.bool.config_cellBroadcastAppLinks);
51578e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            try {
51678e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                if (isCellBroadcastAppLinkEnabled) {
51778e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                    PackageManager pm = getPackageManager();
51878e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                    if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
51978e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
52078e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                        isCellBroadcastAppLinkEnabled = false;  // CMAS app disabled
52178e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                    }
52278e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                }
52378e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            } catch (IllegalArgumentException ignored) {
52478e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                isCellBroadcastAppLinkEnabled = false;  // CMAS app not installed
52578e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            }
52678e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            if (!isCellBroadcastAppLinkEnabled) {
52778e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                cellBroadcastItem.setVisible(false);
52878e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            }
52978e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby        }
53078e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby
531e131a53620fff000a08cf53d29313a3922328dc0Mark Wagner        return true;
532136fe3767b8cb5dc0575992f2f6951c8451ee5e2Tom Taylor    }
533136fe3767b8cb5dc0575992f2f6951c8451ee5e2Tom Taylor
534136fe3767b8cb5dc0575992f2f6951c8451ee5e2Tom Taylor    @Override
53572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onPrepareOptionsMenu(Menu menu) {
536b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor        MenuItem item = menu.findItem(R.id.action_delete_all);
537b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor        if (item != null) {
538991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            item.setVisible((mListAdapter.getCount() > 0) && mIsSmsEnabled);
539991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        }
540991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        item = menu.findItem(R.id.action_compose_new);
541991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun        if (item != null ){
542a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            // Dim compose if SMS is disabled because it will not work (will show a toast)
543a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun            item.getIcon().setAlpha(mIsSmsEnabled ? 255 : 127);
54472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
545b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor        if (!LogTag.DEBUG_DUMP) {
546b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor            item = menu.findItem(R.id.action_debug_dump);
547b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor            if (item != null) {
548b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor                item.setVisible(false);
549b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor            }
550b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor        }
551331864544ec51ba6807fc5471cc6d537b7fef198Mark Wagner        return true;
552331864544ec51ba6807fc5471cc6d537b7fef198Mark Wagner    }
553331864544ec51ba6807fc5471cc6d537b7fef198Mark Wagner
554331864544ec51ba6807fc5471cc6d537b7fef198Mark Wagner    @Override
555331864544ec51ba6807fc5471cc6d537b7fef198Mark Wagner    public boolean onSearchRequested() {
5564a0d14c517c1968c0f1e59544a54277ede9a8fa4Tom Taylor        if (mSearchItem != null) {
5574a0d14c517c1968c0f1e59544a54277ede9a8fa4Tom Taylor            mSearchItem.expandActionView();
5584a0d14c517c1968c0f1e59544a54277ede9a8fa4Tom Taylor        }
55972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return true;
56072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
56172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
56272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
56372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onOptionsItemSelected(MenuItem item) {
56472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        switch(item.getItemId()) {
565b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor            case R.id.action_compose_new:
566a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                if (mIsSmsEnabled) {
567a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    createNewMessage();
568a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                } else {
569a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    // Display a toast letting the user know they can not compose.
570a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    if (mComposeDisabledToast == null) {
571a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                        mComposeDisabledToast = Toast.makeText(this,
572a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                                R.string.compose_disabled_toast, Toast.LENGTH_SHORT);
573a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    }
574a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                    mComposeDisabledToast.show();
575a8ec27f7ab554745e1e1c4700455fdfd6a1048e9David Braun                }
57672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
577b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor            case R.id.action_delete_all:
5783e10898d774b0005fc776865216651346503024bTom Taylor                // The invalid threadId of -1 means all threads here.
5793e10898d774b0005fc776865216651346503024bTom Taylor                confirmDeleteThread(-1L, mQueryHandler);
58072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
581b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor            case R.id.action_settings:
58272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                Intent intent = new Intent(this, MessagingPreferenceActivity.class);
58372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                startActivityIfNeeded(intent, -1);
58472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
585b31f9b5666f424d4fe8551696f480be0c1f51926Tom Taylor            case R.id.action_debug_dump:
586b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor                LogTag.dumpInternalTables(this);
587b3217a6ddcd9455968de7078bfbc0a901b4ff705Tom Taylor                break;
58878e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby            case R.id.action_cell_broadcasts:
58978e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                Intent cellBroadcastIntent = new Intent(Intent.ACTION_MAIN);
59078e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                cellBroadcastIntent.setComponent(new ComponentName(
59178e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                        "com.android.cellbroadcastreceiver",
59278e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                        "com.android.cellbroadcastreceiver.CellBroadcastListActivity"));
59378e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                cellBroadcastIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
59478e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                try {
59578e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                    startActivity(cellBroadcastIntent);
59678e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                } catch (ActivityNotFoundException ignored) {
59778e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                    Log.e(TAG, "ActivityNotFoundException for CellBroadcastListActivity");
59878e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                }
59978e2f412983f8f3732b87bfd794e04d3b20233bbJake Hamby                return true;
60072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            default:
60172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                return true;
60272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
60372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return false;
60472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
60572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
60672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
60772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    protected void onListItemClick(ListView l, View v, int position, long id) {
6082426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        // Note: don't read the thread id data from the ConversationListItem view passed in.
6092426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        // It's unreliable to read the cached data stored in the view because the ListItem
6102426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        // can be recycled, and the same view could be assigned to a different position
6112426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        // if you click the list item fast enough. Instead, get the cursor at the position
6122426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        // clicked and load the data from the cursor.
6132426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        // (ConversationListAdapter extends CursorAdapter, so getItemAtPosition() should
6142426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        // return the cursor object, which is moved to the position passed in)
6152426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        Cursor cursor  = (Cursor) getListView().getItemAtPosition(position);
6162426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        Conversation conv = Conversation.from(this, cursor);
6172426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        long tid = conv.getThreadId();
6182426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
6192426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        if (LogTag.VERBOSE) {
6202426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            Log.d(TAG, "onListItemClick: pos=" + position + ", view=" + v + ", tid=" + tid);
62172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
6222426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
6232426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor        openThread(tid);
62472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
62572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
62672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private void createNewMessage() {
627812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang        startActivity(ComposeMessageActivity.createIntent(this, 0));
62872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
62972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
630ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick    private void openThread(long threadId) {
631812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang        startActivity(ComposeMessageActivity.createIntent(this, threadId));
63272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
63372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
6347d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor    public static Intent createAddContactIntent(String address) {
6357d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        // address must be a single recipient
6361bb6975b0a9a5a4b38aef689305b1e7eb5b61b08Tom Taylor        Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
637923c4c7e9afb8e364d4a93afa0eb6394485d3637Dmitri Plotnikov        intent.setType(Contacts.CONTENT_ITEM_TYPE);
63820b79e068c8aebff46f24fd3803cf7697df4eac4Ficus Kirkpatrick        if (Mms.isEmailAddress(address)) {
639923c4c7e9afb8e364d4a93afa0eb6394485d3637Dmitri Plotnikov            intent.putExtra(ContactsContract.Intents.Insert.EMAIL, address);
64020b79e068c8aebff46f24fd3803cf7697df4eac4Ficus Kirkpatrick        } else {
641923c4c7e9afb8e364d4a93afa0eb6394485d3637Dmitri Plotnikov            intent.putExtra(ContactsContract.Intents.Insert.PHONE, address);
642012970b3d50851d147318527a9a872108b0ab9c7Tom Taylor            intent.putExtra(ContactsContract.Intents.Insert.PHONE_TYPE,
643012970b3d50851d147318527a9a872108b0ab9c7Tom Taylor                    ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
6447d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        }
645dc58429bf08e9d5ba8c43f0ac21e7cd18ea8cb06Tom Taylor        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
64633a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick
6477d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor        return intent;
6487d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor    }
6497d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor
65072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final OnCreateContextMenuListener mConvListOnCreateContextMenuListener =
65172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        new OnCreateContextMenuListener() {
652ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
65372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public void onCreateContextMenu(ContextMenu menu, View v,
65472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                ContextMenuInfo menuInfo) {
65559cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick            Cursor cursor = mListAdapter.getCursor();
656f899bce945a70990c9511ce4d26f856d8adf1e04Tom Taylor            if (cursor == null || cursor.getPosition() < 0) {
657e64a39148677dfae433185af5a63f9a9f8687b48Tom Taylor                return;
658e64a39148677dfae433185af5a63f9a9f8687b48Tom Taylor            }
65970c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick            Conversation conv = Conversation.from(ConversationList.this, cursor);
66033a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick            ContactList recipients = conv.getRecipients();
66133a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick            menu.setHeaderTitle(recipients.formatNames(","));
66270c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick
66370c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick            AdapterView.AdapterContextMenuInfo info =
66470c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick                (AdapterView.AdapterContextMenuInfo) menuInfo;
6652426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            menu.add(0, MENU_VIEW, 0, R.string.menu_view);
6662426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
6672426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            // Only show if there's a single recipient
6682426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            if (recipients.size() == 1) {
6692426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor                // do we have this recipient in contacts?
6702426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor                if (recipients.get(0).existsInDatabase()) {
6712426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor                    menu.add(0, MENU_VIEW_CONTACT, 0, R.string.menu_view_contact);
6722426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor                } else {
6732426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor                    menu.add(0, MENU_ADD_TO_CONTACTS, 0, R.string.menu_add_to_contacts);
67472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
67572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
676991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            if (mIsSmsEnabled) {
677991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun                menu.add(0, MENU_DELETE, 0, R.string.menu_delete);
678991a1f3a31bd749573b4d780a3e4d01e6c1c293fDavid Braun            }
67972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
68072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    };
68172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
68272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    @Override
68372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public boolean onContextItemSelected(MenuItem item) {
68459cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick        Cursor cursor = mListAdapter.getCursor();
685f899bce945a70990c9511ce4d26f856d8adf1e04Tom Taylor        if (cursor != null && cursor.getPosition() >= 0) {
686e64a39148677dfae433185af5a63f9a9f8687b48Tom Taylor            Conversation conv = Conversation.from(ConversationList.this, cursor);
687e64a39148677dfae433185af5a63f9a9f8687b48Tom Taylor            long threadId = conv.getThreadId();
688e64a39148677dfae433185af5a63f9a9f8687b48Tom Taylor            switch (item.getItemId()) {
68972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_DELETE: {
6903e10898d774b0005fc776865216651346503024bTom Taylor                confirmDeleteThread(threadId, mQueryHandler);
69172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
69272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
69372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_VIEW: {
694ab6141d9c98f1a6024fac52fe3c897076d8549c0Ficus Kirkpatrick                openThread(threadId);
69572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
69672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
69772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case MENU_VIEW_CONTACT: {
69833a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick                Contact contact = conv.getRecipients().get(0);
69933a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick                Intent intent = new Intent(Intent.ACTION_VIEW, contact.getUri());
700dc58429bf08e9d5ba8c43f0ac21e7cd18ea8cb06Tom Taylor                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
70133a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick                startActivity(intent);
70272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
70372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
7047d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor            case MENU_ADD_TO_CONTACTS: {
70533a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick                String address = conv.getRecipients().get(0).getNumber();
7067d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                startActivity(createAddContactIntent(address));
7077d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor                break;
7087d3e1caa6000b0bbab0716b1815c2c7177d67948Tom Taylor            }
70972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            default:
71072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
711e64a39148677dfae433185af5a63f9a9f8687b48Tom Taylor            }
71272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
71372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        return super.onContextItemSelected(item);
71472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
71572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
716923c4c7e9afb8e364d4a93afa0eb6394485d3637Dmitri Plotnikov    @Override
71772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    public void onConfigurationChanged(Configuration newConfig) {
71872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // We override this method to avoid restarting the entire
71972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // activity when the keyboard is opened (declared in
72072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // AndroidManifest.xml).  Because the only translatable text
72172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // in this activity is "New Message", which has the full width
72272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // of phone to work with, localization shouldn't be a problem:
72372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // no abbreviated alternate words should be needed even in
72472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        // 'wide' languages like German or Russian.
72572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
72672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        super.onConfigurationChanged(newConfig);
72772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        if (DEBUG) Log.v(TAG, "onConfigurationChanged: " + newConfig);
72872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
72972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7303e10898d774b0005fc776865216651346503024bTom Taylor    /**
7313e10898d774b0005fc776865216651346503024bTom Taylor     * Start the process of putting up a dialog to confirm deleting a thread,
7323e10898d774b0005fc776865216651346503024bTom Taylor     * but first start a background query to see if any of the threads or thread
7333e10898d774b0005fc776865216651346503024bTom Taylor     * contain locked messages so we'll know how detailed of a UI to display.
7343e10898d774b0005fc776865216651346503024bTom Taylor     * @param threadId id of the thread to delete or -1 for all threads
7353e10898d774b0005fc776865216651346503024bTom Taylor     * @param handler query handler to do the background locked query
7363e10898d774b0005fc776865216651346503024bTom Taylor     */
7373e10898d774b0005fc776865216651346503024bTom Taylor    public static void confirmDeleteThread(long threadId, AsyncQueryHandler handler) {
738b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        ArrayList<Long> threadIds = null;
739b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        if (threadId != -1) {
740b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            threadIds = new ArrayList<Long>();
741b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            threadIds.add(threadId);
742b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        }
743b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        confirmDeleteThreads(threadIds, handler);
744b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor    }
745b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
746b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor    /**
747b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor     * Start the process of putting up a dialog to confirm deleting threads,
748b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor     * but first start a background query to see if any of the threads
749b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor     * contain locked messages so we'll know how detailed of a UI to display.
750b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor     * @param threadIds list of threadIds to delete or null for all threads
751b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor     * @param handler query handler to do the background locked query
752b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor     */
753b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor    public static void confirmDeleteThreads(Collection<Long> threadIds, AsyncQueryHandler handler) {
754b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        Conversation.startQueryHaveLockedMessages(handler, threadIds,
7553e10898d774b0005fc776865216651346503024bTom Taylor                HAVE_LOCKED_MESSAGES_TOKEN);
75685fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor    }
75785fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor
7583e10898d774b0005fc776865216651346503024bTom Taylor    /**
7593e10898d774b0005fc776865216651346503024bTom Taylor     * Build and show the proper delete thread dialog. The UI is slightly different
7603e10898d774b0005fc776865216651346503024bTom Taylor     * depending on whether there are locked messages in the thread(s) and whether we're
761b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor     * deleting single/multiple threads or all threads.
7623e10898d774b0005fc776865216651346503024bTom Taylor     * @param listener gets called when the delete button is pressed
763ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev     * @param threadIds the thread IDs to be deleted (pass null for all threads)
7643e10898d774b0005fc776865216651346503024bTom Taylor     * @param hasLockedMessages whether the thread(s) contain locked messages
7653e10898d774b0005fc776865216651346503024bTom Taylor     * @param context used to load the various UI elements
7663e10898d774b0005fc776865216651346503024bTom Taylor     */
7673e10898d774b0005fc776865216651346503024bTom Taylor    public static void confirmDeleteThreadDialog(final DeleteThreadListener listener,
768b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            Collection<Long> threadIds,
7693e10898d774b0005fc776865216651346503024bTom Taylor            boolean hasLockedMessages,
7703e10898d774b0005fc776865216651346503024bTom Taylor            Context context) {
7713e10898d774b0005fc776865216651346503024bTom Taylor        View contents = View.inflate(context, R.layout.delete_thread_dialog_view, null);
77285fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor        TextView msg = (TextView)contents.findViewById(R.id.message);
773b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
774b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        if (threadIds == null) {
775b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            msg.setText(R.string.confirm_delete_all_conversations);
776b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        } else {
777b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            // Show the number of threads getting deleted in the confirmation dialog.
778b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            int cnt = threadIds.size();
779b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            msg.setText(context.getResources().getQuantityString(
780b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                R.plurals.confirm_delete_conversation, cnt, cnt));
781b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        }
782b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
78385fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor        final CheckBox checkbox = (CheckBox)contents.findViewById(R.id.delete_locked);
78485fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor        if (!hasLockedMessages) {
78585fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor            checkbox.setVisibility(View.GONE);
78685fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor        } else {
7873e10898d774b0005fc776865216651346503024bTom Taylor            listener.setDeleteLockedMessage(checkbox.isChecked());
78885fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor            checkbox.setOnClickListener(new View.OnClickListener() {
789ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev                @Override
79085fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor                public void onClick(View v) {
7913e10898d774b0005fc776865216651346503024bTom Taylor                    listener.setDeleteLockedMessage(checkbox.isChecked());
79285fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor                }
79385fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor            });
79485fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor        }
79572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
7963e10898d774b0005fc776865216651346503024bTom Taylor        AlertDialog.Builder builder = new AlertDialog.Builder(context);
79785fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor        builder.setTitle(R.string.confirm_dialog_title)
79818d29eb95b2e692974b53655d4953accb6968570Tom Taylor            .setIconAttribute(android.R.attr.alertDialogIcon)
7992426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            .setCancelable(true)
8002426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            .setPositiveButton(R.string.delete, listener)
8012426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            .setNegativeButton(R.string.no, null)
8022426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            .setView(contents)
8032426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            .show();
80472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
80572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
80672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    private final OnKeyListener mThreadListKeyListener = new OnKeyListener() {
807ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
80872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public boolean onKey(View v, int keyCode, KeyEvent event) {
80972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            if (event.getAction() == KeyEvent.ACTION_DOWN) {
81072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                switch (keyCode) {
81172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    case KeyEvent.KEYCODE_DEL: {
81272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        long id = getListView().getSelectedItemId();
81372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        if (id > 0) {
8143e10898d774b0005fc776865216651346503024bTom Taylor                            confirmDeleteThread(id, mQueryHandler);
81572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        }
81672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                        return true;
81772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    }
81872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
81972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
82072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            return false;
82172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
82272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    };
82372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8243e10898d774b0005fc776865216651346503024bTom Taylor    public static class DeleteThreadListener implements OnClickListener {
825b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor        private final Collection<Long> mThreadIds;
8266bbfdd3cc9cbe6b31dc64f122f3308563d19e077Tom Taylor        private final ConversationQueryHandler mHandler;
8273e10898d774b0005fc776865216651346503024bTom Taylor        private final Context mContext;
8283e10898d774b0005fc776865216651346503024bTom Taylor        private boolean mDeleteLockedMessages;
82972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8306bbfdd3cc9cbe6b31dc64f122f3308563d19e077Tom Taylor        public DeleteThreadListener(Collection<Long> threadIds, ConversationQueryHandler handler,
831b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                Context context) {
832b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            mThreadIds = threadIds;
8333e10898d774b0005fc776865216651346503024bTom Taylor            mHandler = handler;
8343e10898d774b0005fc776865216651346503024bTom Taylor            mContext = context;
8353e10898d774b0005fc776865216651346503024bTom Taylor        }
8363e10898d774b0005fc776865216651346503024bTom Taylor
8373e10898d774b0005fc776865216651346503024bTom Taylor        public void setDeleteLockedMessage(boolean deleteLockedMessages) {
8383e10898d774b0005fc776865216651346503024bTom Taylor            mDeleteLockedMessages = deleteLockedMessages;
83972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
84072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
841ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
842475d780550e0034379ed821a90fdbc96d810b72dTom Taylor        public void onClick(DialogInterface dialog, final int whichButton) {
843b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            MessageUtils.handleReadReport(mContext, mThreadIds,
84472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                    PduHeaders.READ_STATUS__DELETED_WITHOUT_BEING_READ, new Runnable() {
845ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev                @Override
84672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                public void run() {
84770c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick                    int token = DELETE_CONVERSATION_TOKEN;
8488e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                    if (mContext instanceof ConversationList) {
8498e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                        ((ConversationList)mContext).unbindListeners(mThreadIds);
8508e317f9f98cdcfc4955c483e20b5a620849ff2dcGuobin Zhang                    }
851b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    if (mThreadIds == null) {
8523e10898d774b0005fc776865216651346503024bTom Taylor                        Conversation.startDeleteAll(mHandler, token, mDeleteLockedMessages);
8537542864dfb78a58d056e26c9f12e48842324a849Wei Huang                        DraftCache.getInstance().refresh();
85470c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick                    } else {
8558cc338d324dc4c92b686029064882147e9054f17Tom Taylor                        Conversation.startDelete(mHandler, token, mDeleteLockedMessages,
8568cc338d324dc4c92b686029064882147e9054f17Tom Taylor                                mThreadIds);
85770c73e05a792832aa28da751cdaf3fa83a7b8113Ficus Kirkpatrick                    }
85872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                }
85972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            });
860c4a34a0ccd414e2bba937e8abd105a0383afff35Tom Taylor            dialog.dismiss();
86172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
86272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
86372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
8645fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor    private final Runnable mDeleteObsoleteThreadsRunnable = new Runnable() {
865ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
8665fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor        public void run() {
8675fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor            if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
8685fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                LogTag.debug("mDeleteObsoleteThreadsRunnable getSavingDraft(): " +
8695fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                        DraftCache.getInstance().getSavingDraft());
8705fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor            }
8715fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor            if (DraftCache.getInstance().getSavingDraft()) {
8725fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                // We're still saving a draft. Try again in a second. We don't want to delete
8735fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                // any threads out from under the draft.
87499f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                if (DEBUGCLEANUP) {
87599f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                    LogTag.debug("mDeleteObsoleteThreadsRunnable saving draft, trying again");
87699f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                }
8775fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                mHandler.postDelayed(mDeleteObsoleteThreadsRunnable, 1000);
8785fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor            } else {
87999f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                if (DEBUGCLEANUP) {
88099f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                    LogTag.debug("mDeleteObsoleteThreadsRunnable calling " +
88199f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                            "asyncDeleteObsoleteThreads");
88299f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                }
8835fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                Conversation.asyncDeleteObsoleteThreads(mQueryHandler,
8845fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                        DELETE_OBSOLETE_THREADS_TOKEN);
8855fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor            }
8865fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor        }
8875fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor    };
8885fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor
8896bbfdd3cc9cbe6b31dc64f122f3308563d19e077Tom Taylor    private final class ThreadListQueryHandler extends ConversationQueryHandler {
89072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        public ThreadListQueryHandler(ContentResolver contentResolver) {
89172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            super(contentResolver);
89272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
89372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
894e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor        // Test code used for various scenarios where its desirable to insert a delay in
895e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor        // responding to query complete. To use, uncomment out the block below and then
896e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor        // comment out the @Override and onQueryComplete line.
897e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//        @Override
898e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//        protected void onQueryComplete(final int token, final Object cookie, final Cursor cursor) {
899e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//            mHandler.postDelayed(new Runnable() {
900e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//                public void run() {
901e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//                    myonQueryComplete(token, cookie, cursor);
902e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//                    }
903e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//            }, 2000);
904e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//        }
905e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//
906e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor//        protected void myonQueryComplete(int token, Object cookie, Cursor cursor) {
907e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor
90872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        @Override
90972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
91059cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick            switch (token) {
91159cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick            case THREAD_LIST_QUERY_TOKEN:
91259cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick                mListAdapter.changeCursor(cursor);
913627007213deb59ef938c80353c8f3598b01478b3Wei Huang
914e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor                if (mListAdapter.getCount() == 0) {
915e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor                    ((TextView)(getListView().getEmptyView())).setText(R.string.no_conversations);
916e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor                }
917e0dccd0713d9349dadef5f0b41ce7da5e970f541Tom Taylor
918d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                if (mDoOnceAfterFirstQuery) {
919d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    mDoOnceAfterFirstQuery = false;
920d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    // Delay doing a couple of DB operations until we've initially queried the DB
921d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    // for the list of conversations to display. We don't want to slow down showing
922d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    // the initial UI.
923d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor
924d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    // 1. Delete any obsolete threads. Obsolete threads are threads that aren't
925d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    // referenced by at least one message in the pdu or sms tables.
9265fd2543851375fc764495584ddd319f5e7d13cb9Tom Taylor                    mHandler.post(mDeleteObsoleteThreadsRunnable);
927d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor
928d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    // 2. Mark all the conversations as seen.
929d645c8b53ae904bc059ee1ca7232916637c223e5Tom Taylor                    Conversation.markAllConversationsAsSeen(getApplicationContext());
93063e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor                }
9316019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor                if (mSavedFirstVisiblePosition != AdapterView.INVALID_POSITION) {
9326019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor                    // Restore the list to its previous position.
9336019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor                    getListView().setSelectionFromTop(mSavedFirstVisiblePosition,
9346019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor                            mSavedFirstItemOffset);
9356019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor                    mSavedFirstVisiblePosition = AdapterView.INVALID_POSITION;
9366019ec8bfc8df57e95ca1ca36cf76c77ca84818eTom Taylor                }
93759cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick                break;
93885fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor
9392426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor            case UNREAD_THREADS_QUERY_TOKEN:
94028af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                int count = 0;
94128af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                if (cursor != null) {
94228af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                    count = cursor.getCount();
94328af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                    cursor.close();
94428af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                }
9452426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor                mUnreadConvCount.setText(count > 0 ? Integer.toString(count) : null);
9462426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor                break;
9472426db8887f7f1c0c93dbab5a10663cb22575ccdTom Taylor
94885fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor            case HAVE_LOCKED_MESSAGES_TOKEN:
94981f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang                if (ConversationList.this.isFinishing()) {
95081f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang                    Log.w(TAG, "ConversationList is finished, do nothing ");
95181f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang                    if (cursor != null) {
95281f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang                        cursor.close();
95381f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang                    }
95481f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang                    return ;
95581f9cd868c04636de44ac3c09d5ab70abbe5ab42Bin Yang                }
956ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev                @SuppressWarnings("unchecked")
957b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor                Collection<Long> threadIds = (Collection<Long>)cookie;
958b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                confirmDeleteThreadDialog(new DeleteThreadListener(threadIds, mQueryHandler,
959b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                        ConversationList.this), threadIds,
9603e10898d774b0005fc776865216651346503024bTom Taylor                        cursor != null && cursor.getCount() > 0,
9613e10898d774b0005fc776865216651346503024bTom Taylor                        ConversationList.this);
96228af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                if (cursor != null) {
96328af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                    cursor.close();
96428af0405f300b050bed3b4649ad777bde8f28971Tom Taylor                }
96585fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor                break;
96685fbc94e34688455c3f2f36271ba65b90ceb2542Tom Taylor
96759cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick            default:
96859cd1f499645badf8df9e2820b29d28fc1835e79Ficus Kirkpatrick                Log.e(TAG, "onQueryComplete called with unknown token " + token);
96972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
97072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
97172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project
97272735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        @Override
97372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        protected void onDeleteComplete(int token, Object cookie, int result) {
9746bbfdd3cc9cbe6b31dc64f122f3308563d19e077Tom Taylor            super.onDeleteComplete(token, cookie, result);
97572735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            switch (token) {
97672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            case DELETE_CONVERSATION_TOKEN:
9771b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                long threadId = cookie != null ? (Long)cookie : -1;     // default to all threads
9782ddc2c0585fec6fca59acc115e26dc51f69aacc5Tom Taylor
9791b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                if (threadId == -1) {
9801b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    // Rebuild the contacts cache now that all threads and their associated unique
9811b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    // recipients have been deleted.
9821b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    Contact.init(ConversationList.this);
9831b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                } else {
9841b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    // Remove any recipients referenced by this single thread from the
9851b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    // contacts cache. It's possible for two or more threads to reference
9861b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    // the same contact. That's ok if we remove it. We'll recreate that contact
9871b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    // when we init all Conversations below.
9881b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    Conversation conv = Conversation.get(ConversationList.this, threadId, false);
9891b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    if (conv != null) {
9901b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                        ContactList recipients = conv.getRecipients();
9911b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                        for (Contact contact : recipients) {
9921b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                            contact.removeFromCache();
9931b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                        }
9941b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                    }
9951b1af7c751218e380bd119629ff9a652157fbb21Tom Taylor                }
99607ce1878a36d2df1707dd4bbd9cd7235679bdc94Tom Taylor                // Make sure the conversation cache reflects the threads in the DB.
99707ce1878a36d2df1707dd4bbd9cd7235679bdc94Tom Taylor                Conversation.init(ConversationList.this);
99807ce1878a36d2df1707dd4bbd9cd7235679bdc94Tom Taylor
99972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Update the notification for new messages since they
100072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // may be deleted.
10013b21f6ab04db5936d73e9f53032f1587389380ffTom Taylor                MessagingNotification.nonBlockingUpdateNewMessageIndicator(ConversationList.this,
1002c8d727902ff6976c45285a12aab176545a7848bbTodor Kalaydjiev                        MessagingNotification.THREAD_NONE, false);
100372735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Update the notification for failed messages since they
100472735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // may be deleted.
1005b0ef8fc2738b210a2bb0490e75eedc1e7b7b491fTom Taylor                MessagingNotification.nonBlockingUpdateSendFailedNotification(ConversationList.this);
100633a87f96f8c625aa10131a77a3968c97c4ec5a62Ficus Kirkpatrick
100772735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                // Make sure the list reflects the delete
100872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                startAsyncQuery();
1009cee64965b033733a494df675892267e109a23dd6Roger Chen
1010cee64965b033733a494df675892267e109a23dd6Roger Chen                MmsWidgetProvider.notifyDatasetChanged(getApplicationContext());
101172735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project                break;
101263e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor
101363e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor            case DELETE_OBSOLETE_THREADS_TOKEN:
101499f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                if (DEBUGCLEANUP) {
101599f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                    LogTag.debug("onQueryComplete finished DELETE_OBSOLETE_THREADS_TOKEN");
101699f719d1cb0c6ed68373d73427a816c4e56eb5baTom Taylor                }
101763e395258ae33a101b9634a68b55ec89fac8b580Tom Taylor                break;
101872735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project            }
101972735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project        }
102072735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project    }
1021812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang
1022b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor    private class ModeCallback implements ListView.MultiChoiceModeListener {
1023b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        private View mMultiSelectActionBarView;
1024b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        private TextView mSelectedConvCount;
1025b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor        private HashSet<Long> mSelectedThreadIds;
1026b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1027ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
1028b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
1029b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            MenuInflater inflater = getMenuInflater();
1030b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            mSelectedThreadIds = new HashSet<Long>();
1031b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            inflater.inflate(R.menu.conversation_multi_select_menu, menu);
1032b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1033b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            if (mMultiSelectActionBarView == null) {
1034ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev                mMultiSelectActionBarView = LayoutInflater.from(ConversationList.this)
1035b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    .inflate(R.layout.conversation_list_multi_select_actionbar, null);
1036b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1037b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                mSelectedConvCount =
1038b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    (TextView)mMultiSelectActionBarView.findViewById(R.id.selected_conv_count);
1039b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            }
1040b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            mode.setCustomView(mMultiSelectActionBarView);
1041b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            ((TextView)mMultiSelectActionBarView.findViewById(R.id.title))
1042b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                .setText(R.string.select_conversations);
1043b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            return true;
1044b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        }
1045b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1046ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
1047b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
1048b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            if (mMultiSelectActionBarView == null) {
1049b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                ViewGroup v = (ViewGroup)LayoutInflater.from(ConversationList.this)
1050b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    .inflate(R.layout.conversation_list_multi_select_actionbar, null);
1051b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                mode.setCustomView(v);
1052b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1053b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                mSelectedConvCount = (TextView)v.findViewById(R.id.selected_conv_count);
1054b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            }
1055b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            return true;
1056b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        }
1057b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1058ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
1059b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
1060b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            switch (item.getItemId()) {
1061b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                case R.id.delete:
1062b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor                    if (mSelectedThreadIds.size() > 0) {
1063b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor                        confirmDeleteThreads(mSelectedThreadIds, mQueryHandler);
1064b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    }
1065b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    mode.finish();
1066b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    break;
1067b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1068b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                default:
1069b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                    break;
1070b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            }
1071b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            return true;
1072b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        }
1073b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1074ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
1075b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        public void onDestroyActionMode(ActionMode mode) {
1076f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor            ConversationListAdapter adapter = (ConversationListAdapter)getListView().getAdapter();
1077f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor            adapter.uncheckAll();
1078b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            mSelectedThreadIds = null;
1079b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        }
1080b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1081ddd31c4011b4191035bdfbba05a8edb1785f71afTodor Kalaydjiev        @Override
1082b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        public void onItemCheckedStateChanged(ActionMode mode,
1083b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor                int position, long id, boolean checked) {
1084f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor            ListView listView = getListView();
1085f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor            final int checkedCount = listView.getCheckedItemCount();
1086b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor            mSelectedConvCount.setText(Integer.toString(checkedCount));
1087f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor
1088f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor            Cursor cursor  = (Cursor)listView.getItemAtPosition(position);
1089f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor            Conversation conv = Conversation.from(ConversationList.this, cursor);
1090f9d706cfd0c46a74ba3d79e5543f13a225328d30Tom Taylor            conv.setIsChecked(checked);
1091b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            long threadId = conv.getThreadId();
1092b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor
1093b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            if (checked) {
1094b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor                mSelectedThreadIds.add(threadId);
1095b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            } else {
1096b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor                mSelectedThreadIds.remove(threadId);
1097b04236e2977ac69e63cc0fa123399a584b606945Tom Taylor            }
1098b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor        }
1099b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1100b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor    }
1101b51ea8318ca2e4019b666d938e3e7efdf6e643b3Tom Taylor
1102812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang    private void log(String format, Object... args) {
1103812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang        String s = String.format(format, args);
1104812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang        Log.d(TAG, "[" + Thread.currentThread().getId() + "] " + s);
1105812391ad832f3fdac054ad3a50af563da16e99b5Wei Huang    }
110672735c62aba8fd2a9420a0f9f83d22543e3c164fThe Android Open Source Project}
1107