1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.datamodel; 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ContentValues; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.ContentObserver; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.DatabaseUtils; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Color; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.ContactsContract.CommonDataKinds.Phone; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.v4.util.ArrayMap; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.telephony.SubscriptionInfo; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.TextUtils; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.Factory; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseHelper.ConversationColumns; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseHelper.ConversationParticipantsColumns; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ParticipantData.ParticipantsQuery; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.UIIntents; 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.ContactUtil; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil; 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.OsUtil; 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.PhoneUtils; 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.SafeAsyncTask; 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.annotations.VisibleForTesting; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.base.Joiner; 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.ArrayList; 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.HashSet; 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List; 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.Locale; 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.Set; 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.concurrent.atomic.AtomicBoolean; 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Utility class for refreshing participant information based on matching contact. This updates 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1. name, photo_uri, matching contact_id of participants. 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 2. generated_name of conversations. 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * There are two kinds of participant refreshes, 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1. Full refresh, this is triggered at application start or activity resumes after contact 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * change is detected. 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 2. Partial refresh, this is triggered when a participant is added to a conversation. This 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * normally happens during SMS sync. 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd@VisibleForTesting 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class ParticipantRefresh { 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG; 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Refresh all participants including ones that were resolved before. 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int REFRESH_MODE_FULL = 0; 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Refresh all unresolved participants. 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int REFRESH_MODE_INCREMENTAL = 1; 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Force refresh all self participants. 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int REFRESH_MODE_SELF_ONLY = 2; 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class ConversationParticipantsQuery { 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final String[] PROJECTION = new String[] { 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ConversationParticipantsColumns._ID, 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ConversationParticipantsColumns.CONVERSATION_ID, 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ConversationParticipantsColumns.PARTICIPANT_ID 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_ID = 0; 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_CONVERSATION_ID = 1; 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static final int INDEX_PARTICIPANT_ID = 2; 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Track whether observer is initialized or not. 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static volatile boolean sObserverInitialized = false; 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final Object sLock = new Object(); 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final AtomicBoolean sFullRefreshScheduled = new AtomicBoolean(false); 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final Runnable sFullRefreshRunnable = new Runnable() { 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void run() { 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean oldScheduled = sFullRefreshScheduled.getAndSet(false); 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.isTrue(oldScheduled); 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd refreshParticipants(REFRESH_MODE_FULL); 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final Runnable sSelfOnlyRefreshRunnable = new Runnable() { 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void run() { 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd refreshParticipants(REFRESH_MODE_SELF_ONLY); 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * A customized content resolver to track contact changes. 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static class ContactContentObserver extends ContentObserver { 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private volatile boolean mContactChanged = false; 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ContactContentObserver() { 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(null); 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void onChange(final boolean selfChange) { 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super.onChange(selfChange); 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Contacts changed"); 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactChanged = true; 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean getContactChanged() { 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return mContactChanged; 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void resetContactChanged() { 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactChanged = false; 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void initialize() { 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: Handle enterprise contacts post M once contacts provider supports it 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Factory.get().getApplicationContext().getContentResolver().registerContentObserver( 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Phone.CONTENT_URI, true, this); 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactChanged = true; // Force a full refresh on initialization. 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Refresh participants only if needed, i.e., application start or contact changed. 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void refreshParticipantsIfNeeded() { 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (ParticipantRefresh.getNeedFullRefresh() && 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sFullRefreshScheduled.compareAndSet(false, true)) { 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Started full participant refresh"); 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SafeAsyncTask.executeOnThreadPool(sFullRefreshRunnable); 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Skipped full participant refresh"); 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Refresh self participants on subscription or settings change. 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void refreshSelfParticipants() { 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SafeAsyncTask.executeOnThreadPool(sSelfOnlyRefreshRunnable); 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static boolean getNeedFullRefresh() { 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContactContentObserver observer = Factory.get().getContactContentObserver(); 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (observer == null) { 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If there is no observer (for unittest cases), we don't need to refresh participants. 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!sObserverInitialized) { 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd synchronized (sLock) { 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!sObserverInitialized) { 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd observer.initialize(); 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sObserverInitialized = true; 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return observer.getContactChanged(); 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void resetNeedFullRefresh() { 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContactContentObserver observer = Factory.get().getContactContentObserver(); 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (observer != null) { 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd observer.resetContactChanged(); 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * This class is totally static. Make constructor to be private so that an instance 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * of this class would not be created by by mistake. 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ParticipantRefresh() { 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Refresh participants in Bugle. 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param refreshMode the refresh mode desired. See {@link #REFRESH_MODE_FULL}, 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * {@link #REFRESH_MODE_INCREMENTAL}, and {@link #REFRESH_MODE_SELF_ONLY} 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @VisibleForTesting 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static void refreshParticipants(final int refreshMode) { 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.inRange(refreshMode, REFRESH_MODE_FULL, REFRESH_MODE_SELF_ONLY); 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd switch (refreshMode) { 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case REFRESH_MODE_FULL: 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Start full participant refresh"); 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case REFRESH_MODE_INCREMENTAL: 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Start partial participant refresh"); 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case REFRESH_MODE_SELF_ONLY: 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Start self participant refresh"); 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!ContactUtil.hasReadContactsPermission() || !OsUtil.hasPhonePermission()) { 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Skipping participant referesh because of permissions"); 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (refreshMode == REFRESH_MODE_FULL) { 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // resetNeedFullRefresh right away so that we will skip duplicated full refresh 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // requests. 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd resetNeedFullRefresh(); 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (refreshMode == REFRESH_MODE_FULL || refreshMode == REFRESH_MODE_SELF_ONLY) { 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd refreshSelfParticipantList(); 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ArrayList<String> changedParticipants = new ArrayList<String>(); 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String selection = null; 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String[] selectionArgs = null; 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (refreshMode == REFRESH_MODE_INCREMENTAL) { 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // In case of incremental refresh, filter out participants that are already resolved. 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selection = ParticipantColumns.CONTACT_ID + "=?"; 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selectionArgs = new String[] { 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String.valueOf(ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED) }; 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (refreshMode == REFRESH_MODE_SELF_ONLY) { 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // In case of self-only refresh, filter out non-self participants. 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selection = SELF_PARTICIPANTS_CLAUSE; 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selectionArgs = null; 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor cursor = null; 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean selfUpdated = false; 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE, 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ParticipantsQuery.PROJECTION, selection, selectionArgs, null, null, null); 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (cursor.moveToNext()) { 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData participantData = 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ParticipantData.getFromCursor(cursor); 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (refreshParticipant(db, participantData)) { 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (participantData.isSelf()) { 273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selfUpdated = true; 274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateParticipant(db, participantData); 276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String id = participantData.getId(); 277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd changedParticipants.add(id); 278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final Exception exception) { 280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Failure to update one participant shouldn't cancel the entire refresh. 281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Log the failure so we know what's going on and resume the loop. 282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "ParticipantRefresh: Failed to " + 283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "update participant", exception); 284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.close(); 290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) { 294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.v(TAG, "Number of participants refreshed:" + changedParticipants.size()); 295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Refresh conversations for participants that are changed. 298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (changedParticipants.size() > 0) { 299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.refreshConversationsForParticipants(changedParticipants); 300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (selfUpdated) { 302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Boom 303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyAllParticipantsChanged(); 304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyAllMessagesChanged(); 305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String SELF_PARTICIPANTS_CLAUSE = ParticipantColumns.SUB_ID 309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " NOT IN ( " 310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + ParticipantData.OTHER_THAN_SELF_SUB_ID 311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " )"; 312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final Set<Integer> getExistingSubIds() { 314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final HashSet<Integer> existingSubIds = new HashSet<Integer>(); 316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor cursor = null; 318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE, 320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ParticipantsQuery.PROJECTION, 321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SELF_PARTICIPANTS_CLAUSE, null, null, null, null); 322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (cursor.moveToNext()) { 325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int subId = cursor.getInt(ParticipantsQuery.INDEX_SUB_ID); 326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd existingSubIds.add(subId); 327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.close(); 332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return existingSubIds; 335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final String UPDATE_SELF_PARTICIPANT_SUBSCRIPTION_SQL = 338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "UPDATE " + DatabaseHelper.PARTICIPANTS_TABLE + " SET " 339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + ParticipantColumns.SIM_SLOT_ID + " = %d, " 340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + ParticipantColumns.SUBSCRIPTION_COLOR + " = %d, " 341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + ParticipantColumns.SUBSCRIPTION_NAME + " = %s " 342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd + " WHERE %s"; 343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static String getUpdateSelfParticipantSubscriptionInfoSql(final int slotId, 345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int subscriptionColor, final String subscriptionName, final String where) { 346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return String.format((Locale) null /* construct SQL string without localization */, 347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd UPDATE_SELF_PARTICIPANT_SUBSCRIPTION_SQL, 348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd slotId, subscriptionColor, subscriptionName, where); 349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Ensure that there is a self participant corresponding to every active SIM. Also, ensure 353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * that any other older SIM self participants are marked as inactive. 354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void refreshSelfParticipantList() { 356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!OsUtil.isAtLeastL_MR1()) { 357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<SubscriptionInfo> subInfoRecords = 363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneUtils.getDefault().toLMr1().getActiveSubscriptionInfoList(); 364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ArrayMap<Integer, SubscriptionInfo> activeSubscriptionIdToRecordMap = 365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new ArrayMap<Integer, SubscriptionInfo>(); 366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.beginTransaction(); 367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Set<Integer> existingSubIds = getExistingSubIds(); 368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (subInfoRecords != null) { 371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final SubscriptionInfo subInfoRecord : subInfoRecords) { 372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int subId = subInfoRecord.getSubscriptionId(); 373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If its a new subscription, add it to the database. 374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!existingSubIds.contains(subId)) { 375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.execSQL(DatabaseHelper.getCreateSelfParticipantSql(subId)); 376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Add it to the local set to guard against duplicated entries returned 377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // by subscription manager. 378d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd existingSubIds.add(subId); 379d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 380d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd activeSubscriptionIdToRecordMap.put(subId, subInfoRecord); 381d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 382d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (subId == PhoneUtils.getDefault().getDefaultSmsSubscriptionId()) { 383d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This is the system default subscription, so update the default self. 384d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd activeSubscriptionIdToRecordMap.put(ParticipantData.DEFAULT_SELF_SUB_ID, 385d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subInfoRecord); 386d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 387d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 388d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 389d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 390d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // For subscriptions already in the database, refresh ParticipantColumns.SIM_SLOT_ID. 391d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final Integer subId : activeSubscriptionIdToRecordMap.keySet()) { 392d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final SubscriptionInfo record = activeSubscriptionIdToRecordMap.get(subId); 393d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String displayName = 394d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DatabaseUtils.sqlEscapeString(record.getDisplayName().toString()); 395d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.execSQL(getUpdateSelfParticipantSubscriptionInfoSql(record.getSimSlotIndex(), 396d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd record.getIconTint(), displayName, 397d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ParticipantColumns.SUB_ID + " = " + subId)); 398d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 399d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.execSQL(getUpdateSelfParticipantSubscriptionInfoSql( 400d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ParticipantData.INVALID_SLOT_ID, Color.TRANSPARENT, "''", 401d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ParticipantColumns.SUB_ID + " NOT IN (" + 402d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Joiner.on(", ").join(activeSubscriptionIdToRecordMap.keySet()) + ")")); 403d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.setTransactionSuccessful(); 404d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 405d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.endTransaction(); 406d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 407d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Fix up conversation self ids by reverting to default self for conversations whose self 408d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // ids are no longer active. 409d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd refreshConversationSelfIds(); 410d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 411d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 412d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 413d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Refresh one participant. 414d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return true if the ParticipantData was changed 415d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 416d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static boolean refreshParticipant(final DatabaseWrapper db, 417d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData participantData) { 418d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean updated = false; 419d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 420d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (participantData.isSelf()) { 421d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int selfChange = refreshFromSelfProfile(db, participantData); 422d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 423d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (selfChange == SELF_PROFILE_EXISTS) { 424d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If a self-profile exists, it takes precedence over Contacts data. So we are done. 425d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 426d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 427d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 428d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updated = (selfChange == SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED); 429d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 430d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Fall-through and try to update based on Contacts data 431d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 432d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 433d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updated |= refreshFromContacts(db, participantData); 434d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return updated; 435d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 436d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 437d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED = 1; 438d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final int SELF_PROFILE_EXISTS = 2; 439d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 440d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static int refreshFromSelfProfile(final DatabaseWrapper db, 441d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData participantData) { 442d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int changed = 0; 443d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Refresh the phone number based on information from telephony 444d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (participantData.updatePhoneNumberForSelfIfChanged()) { 445d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd changed = SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED; 446d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 447d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 448d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (OsUtil.isAtLeastL_MR1()) { 449d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Refresh the subscription info based on information from SubscriptionManager. 450d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final SubscriptionInfo subscriptionInfo = 451d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd PhoneUtils.get(participantData.getSubId()).toLMr1().getActiveSubscriptionInfo(); 452d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (participantData.updateSubscriptionInfoForSelfIfChanged(subscriptionInfo)) { 453d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd changed = SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED; 454d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 455d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 456d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 457d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // For self participant, try getting name/avatar from self profile in CP2 first. 458d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: in case of multi-sim, profile would not be able to be used for 459d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // different numbers. Need to figure out that. 460d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor selfCursor = null; 461d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 462d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selfCursor = ContactUtil.getSelf(db.getContext()).performSynchronousQuery(); 463d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (selfCursor != null && selfCursor.getCount() > 0) { 464d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selfCursor.moveToNext(); 465d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long selfContactId = selfCursor.getLong(ContactUtil.INDEX_CONTACT_ID); 466d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setContactId(selfContactId); 467d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setFullName(selfCursor.getString( 468d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_DISPLAY_NAME)); 469d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setFirstName( 470d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.lookupFirstName(db.getContext(), selfContactId)); 471d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setProfilePhotoUri(selfCursor.getString( 472d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_PHOTO_URI)); 473d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setLookupKey(selfCursor.getString( 474d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_SELF_QUERY_LOOKUP_KEY)); 475d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return SELF_PROFILE_EXISTS; 476d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 477d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final Exception exception) { 478d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // It's possible for contact query to fail and we don't want that to crash our app. 479d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // However, we need to at least log the exception so we know something was wrong. 480d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "Participant refresh: failed to refresh " + 481d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "participant. exception=" + exception); 482d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 483d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (selfCursor != null) { 484d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selfCursor.close(); 485d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 486d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 487d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return changed; 488d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 489d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 490d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static boolean refreshFromContacts(final DatabaseWrapper db, 491d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData participantData) { 492d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String normalizedDestination = participantData.getNormalizedDestination(); 493d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long currentContactId = participantData.getContactId(); 494d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String currentDisplayName = participantData.getFullName(); 495d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String currentFirstName = participantData.getFirstName(); 496d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String currentPhotoUri = participantData.getProfilePhotoUri(); 497d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String currentContactDestination = participantData.getContactDestination(); 498d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 499d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor matchingContactCursor = null; 500d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd long matchingContactId = -1; 501d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String matchingDisplayName = null; 502d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String matchingFirstName = null; 503d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String matchingPhotoUri = null; 504d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String matchingLookupKey = null; 505d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String matchingDestination = null; 506d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean updated = false; 507d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 508d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (TextUtils.isEmpty(normalizedDestination)) { 509d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // The normalized destination can be "" for the self id if we can't get it from the 510d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // SIM. Some contact providers throw an IllegalArgumentException if you lookup "", 511d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // so we early out. 512d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 513d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 514d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 515d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 516d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingContactCursor = ContactUtil.lookupDestination(db.getContext(), 517d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd normalizedDestination).performSynchronousQuery(); 518d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (matchingContactCursor == null || matchingContactCursor.getCount() == 0) { 519d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If there is no match, mark the participant as contact not found. 520d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (currentContactId != ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND) { 521d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setContactId(ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND); 522d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setFullName(null); 523d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setFirstName(null); 524d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setProfilePhotoUri(null); 525d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setLookupKey(null); 526d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updated = true; 527d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 528d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return updated; 529d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 530d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 531d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (matchingContactCursor.moveToNext()) { 532d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final long contactId = matchingContactCursor.getLong(ContactUtil.INDEX_CONTACT_ID); 533d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Pick either the first contact or the contact with same id as previous matched 534d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // contact id. 535d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (matchingContactId == -1 || currentContactId == contactId) { 536d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingContactId = contactId; 537d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingDisplayName = matchingContactCursor.getString( 538d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_DISPLAY_NAME); 539d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingFirstName = ContactUtil.lookupFirstName(db.getContext(), contactId); 540d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingPhotoUri = matchingContactCursor.getString( 541d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_PHOTO_URI); 542d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingLookupKey = matchingContactCursor.getString( 543d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_LOOKUP_KEY); 544d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingDestination = matchingContactCursor.getString( 545d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ContactUtil.INDEX_PHONE_EMAIL); 546d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 547d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 548d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // There is no need to try other contacts if the current contactId was not filled... 549d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (currentContactId < 0 550d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // or we found the matching contact id 551d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || currentContactId == contactId) { 552d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 553d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 554d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 555d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } catch (final Exception exception) { 556d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // It's possible for contact query to fail and we don't want that to crash our app. 557d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // However, we need to at least log the exception so we know something was wrong. 558d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "Participant refresh: failed to refresh " + 559d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd "participant. exception=" + exception); 560d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 561d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 562d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (matchingContactCursor != null) { 563d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matchingContactCursor.close(); 564d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 565d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 566d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 567d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update participant only if something changed. 568d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isContactIdChanged = (matchingContactId != currentContactId); 569d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isDisplayNameChanged = 570d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd !TextUtils.equals(matchingDisplayName, currentDisplayName); 571d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isFirstNameChanged = !TextUtils.equals(matchingFirstName, currentFirstName); 572d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isPhotoUrlChanged = !TextUtils.equals(matchingPhotoUri, currentPhotoUri); 573d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isDestinationChanged = !TextUtils.equals(matchingDestination, 574d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd currentContactDestination); 575d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 576d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isContactIdChanged || isDisplayNameChanged || isFirstNameChanged || isPhotoUrlChanged 577d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || isDestinationChanged) { 578d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setContactId(matchingContactId); 579d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setFullName(matchingDisplayName); 580d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setFirstName(matchingFirstName); 581d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setProfilePhotoUri(matchingPhotoUri); 582d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setLookupKey(matchingLookupKey); 583d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setContactDestination(matchingDestination); 584d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isDestinationChanged) { 585d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update the send destination to the new one entered by user in Contacts. 586d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.setSendDestination(matchingDestination); 587d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 588d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updated = true; 589d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 590d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 591d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return updated; 592d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 593d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 594d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 595d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Update participant with matching contact's contactId, displayName and photoUri. 596d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 597d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void updateParticipant(final DatabaseWrapper db, 598d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData participantData) { 599d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ContentValues values = new ContentValues(); 600d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (participantData.isSelf()) { 601d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Self participants can refresh their normalized phone numbers 602d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.NORMALIZED_DESTINATION, 603d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.getNormalizedDestination()); 604d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.DISPLAY_DESTINATION, 605d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd participantData.getDisplayDestination()); 606d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 607d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.CONTACT_ID, participantData.getContactId()); 608d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.LOOKUP_KEY, participantData.getLookupKey()); 609d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.FULL_NAME, participantData.getFullName()); 610d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.FIRST_NAME, participantData.getFirstName()); 611d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.PROFILE_PHOTO_URI, participantData.getProfilePhotoUri()); 612d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.CONTACT_DESTINATION, participantData.getContactDestination()); 613d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd values.put(ParticipantColumns.SEND_DESTINATION, participantData.getSendDestination()); 614d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 615d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.beginTransaction(); 616d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 617d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.update(DatabaseHelper.PARTICIPANTS_TABLE, values, ParticipantColumns._ID + "=?", 618d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new String[] { participantData.getId() }); 619d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.setTransactionSuccessful(); 620d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 621d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.endTransaction(); 622d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 623d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 624d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 625d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 626d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Get a list of inactive self ids in the participants table. 627d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 628d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static List<String> getInactiveSelfParticipantIds() { 629d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 630d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<String> inactiveSelf = new ArrayList<String>(); 631d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 632d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String selection = ParticipantColumns.SIM_SLOT_ID + "=? AND " + 633d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SELF_PARTICIPANTS_CLAUSE; 634d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor cursor = null; 635d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 636d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE, 637d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new String[] { ParticipantColumns._ID }, 638d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selection, new String[] { String.valueOf(ParticipantData.INVALID_SLOT_ID) }, 639d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, null, null); 640d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 641d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 642d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (cursor.moveToNext()) { 643d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String participantId = cursor.getString(0); 644d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd inactiveSelf.add(participantId); 645d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 646d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 647d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 648d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 649d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.close(); 650d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 651d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 652d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 653d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return inactiveSelf; 654d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 655d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 656d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 657d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Gets a list of conversations with the given self ids. 658d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 659d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static List<String> getConversationsWithSelfParticipantIds(final List<String> selfIds) { 660d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 661d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<String> conversationIds = new ArrayList<String>(); 662d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 663d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Cursor cursor = null; 664d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 665d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final StringBuilder selectionList = new StringBuilder(); 666d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < selfIds.size(); i++) { 667d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selectionList.append('?'); 668d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (i < selfIds.size() - 1) { 669d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selectionList.append(','); 670d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 671d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 672d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String selection = 673d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ConversationColumns.CURRENT_SELF_ID + " IN (" + selectionList + ")"; 674d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor = db.query(DatabaseHelper.CONVERSATIONS_TABLE, 675d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new String[] { ConversationColumns._ID }, 676d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selection, selfIds.toArray(new String[0]), 677d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd null, null, null); 678d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 679d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 680d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (cursor.moveToNext()) { 681d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String conversationId = cursor.getString(0); 682d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd conversationIds.add(conversationId); 683d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 684d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 685d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 686d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (cursor != null) { 687d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd cursor.close(); 688d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 689d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 690d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return conversationIds; 691d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 692d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 693d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 694d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Refresh one conversation's self id. 695d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 696d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void updateConversationSelfId(final String conversationId, 697d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String selfId) { 698d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 699d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 700d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.beginTransaction(); 701d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 702d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.updateConversationSelfIdInTransaction(db, conversationId, 703d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selfId); 704d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.setTransactionSuccessful(); 705d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 706d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd db.endTransaction(); 707d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 708d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 709d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyMessagesChanged(conversationId); 710d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagingContentProvider.notifyConversationMetadataChanged(conversationId); 711d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd UIIntents.get().broadcastConversationSelfIdChange(db.getContext(), conversationId, selfId); 712d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 713d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 714d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 715d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * After refreshing the self participant list, find all conversations with inactive self ids, 716d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * and switch them back to system default. 717d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 718d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static void refreshConversationSelfIds() { 719d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<String> inactiveSelfs = getInactiveSelfParticipantIds(); 720d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (inactiveSelfs.size() == 0) { 721d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 722d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 723d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<String> conversationsToRefresh = 724d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd getConversationsWithSelfParticipantIds(inactiveSelfs); 725d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (conversationsToRefresh.size() == 0) { 726d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return; 727d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 728d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DatabaseWrapper db = DataModel.get().getDatabase(); 729d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ParticipantData defaultSelf = 730d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd BugleDatabaseOperations.getOrCreateSelf(db, ParticipantData.DEFAULT_SELF_SUB_ID); 731d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 732d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (defaultSelf != null) { 733d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final String conversationId : conversationsToRefresh) { 734d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateConversationSelfId(conversationId, defaultSelf.getId()); 735d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 736d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 737d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 738d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 739