Home | History | Annotate | Download | only in presence
      1 /*
      2  * Copyright (c) 2015, Motorola Mobility LLC
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *     - Redistributions of source code must retain the above copyright
      8  *       notice, this list of conditions and the following disclaimer.
      9  *     - Redistributions in binary form must reproduce the above copyright
     10  *       notice, this list of conditions and the following disclaimer in the
     11  *       documentation and/or other materials provided with the distribution.
     12  *     - Neither the name of Motorola Mobility nor the
     13  *       names of its contributors may be used to endorse or promote products
     14  *       derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
     26  * DAMAGE.
     27  */
     28 
     29 package com.android.service.ims.presence;
     30 
     31 import java.util.ArrayList;
     32 import java.util.Calendar;
     33 
     34 import android.app.Service;
     35 import android.app.AlarmManager;
     36 import android.content.BroadcastReceiver;
     37 import android.content.Context;
     38 import android.content.Intent;
     39 import android.content.IntentFilter;
     40 import android.database.ContentObserver;
     41 import android.database.Cursor;
     42 import android.net.Uri;
     43 import android.os.Handler;
     44 import android.os.HandlerThread;
     45 import android.os.IBinder;
     46 import android.os.Looper;
     47 import android.os.Message;
     48 import android.provider.ContactsContract;
     49 import android.provider.ContactsContract.CommonDataKinds.Phone;
     50 import android.telephony.PhoneNumberUtils;
     51 import android.text.TextUtils;
     52 
     53 import android.telephony.SubscriptionManager;
     54 import com.android.ims.internal.EABContract;
     55 
     56 import com.android.ims.ImsConfig;
     57 import com.android.ims.ImsManager;
     58 import com.android.ims.ImsException;
     59 
     60 import com.android.ims.RcsManager;
     61 import com.android.ims.RcsPresence;
     62 import com.android.ims.RcsException;
     63 import com.android.ims.internal.Logger;
     64 
     65 public class EABService extends Service {
     66 
     67     private Logger logger = Logger.getLogger(this.getClass().getName());
     68 
     69     private Context mContext;
     70     private Looper mServiceLooper = null;
     71     private ServiceHandler mServiceHandler = null;
     72     // Used to avoid any content observer processing during EABService
     73     // initialisation as anyways it will check for Contact db changes as part of boot-up.
     74     private boolean isEABServiceInitializing = true;
     75 
     76     private static final int BOOT_COMPLETED = 0;
     77     private static final int CONTACT_TABLE_MODIFIED = 1;
     78     private static final int CONTACT_PROFILE_TABLE_MODIFIED = 2;
     79     private static final int EAB_DATABASE_RESET = 3;
     80 
     81     private static final int SYNC_COMPLETE_DELAY_TIMER = 3 * 1000; // 3 seconds.
     82     private static final String TAG = "EABService";
     83 
     84     // Framework interface files.
     85     private RcsManager mRcsManager = null;
     86     private RcsPresence mRcsPresence = null;
     87 
     88     public EABService() {
     89         super();
     90         logger.info("EAB Service constructed");
     91     }
     92 
     93     @Override
     94     public IBinder onBind(Intent arg0) {
     95         return null;
     96     }
     97 
     98     /**
     99      * When "clear data" is done for contact storage in system settings, EAB
    100      * Provider must be cleared.
    101      */
    102     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    103         @Override
    104         public void onReceive(Context context, Intent intent) {
    105             String action = intent.getAction();
    106             logger.debug("onReceive intent: " + action);
    107 
    108             switch(action) {
    109                 case ContactsContract.Intents.CONTACTS_DATABASE_CREATED: {
    110                     logger.debug("Contacts database created.");
    111                     // Delete all entries from EAB Provider as it has to be re-synced with
    112                     // Contact db.
    113                     mContext.getContentResolver().delete(
    114                             EABContract.EABColumns.CONTENT_URI, null, null);
    115                     // Initialise EABProvider.
    116                     logger.debug("Resetting timestamp values in shared pref.");
    117                     SharedPrefUtil.resetEABSharedPref(mContext);
    118                     // init the EAB db after re-setting.
    119                     ensureInitDone();
    120                     break;
    121                 }
    122                 case Intent.ACTION_TIME_CHANGED:
    123                     // fall through
    124                 case Intent.ACTION_TIMEZONE_CHANGED: {
    125                     Calendar cal = Calendar.getInstance();
    126                     long currentTimestamp = cal.getTimeInMillis();
    127                     long lastChangedTimestamp = SharedPrefUtil.getLastContactChangedTimestamp(
    128                             mContext, currentTimestamp);
    129                     logger.debug("lastChangedTimestamp=" + lastChangedTimestamp +
    130                             " currentTimestamp=" + currentTimestamp);
    131                     // Changed time backwards.
    132                     if(lastChangedTimestamp > currentTimestamp) {
    133                         logger.debug("Resetting timestamp values in shared pref.");
    134                         SharedPrefUtil.resetEABSharedPref(mContext);
    135                         // Set Init done to true as only the contact sync timestamps are cleared and
    136                         // the EABProvider table data is not cleared.
    137                         SharedPrefUtil.setInitDone(mContext, true);
    138                         CapabilityPolling capabilityPolling = CapabilityPolling.getInstance(null);
    139                         if (capabilityPolling != null) {
    140                             capabilityPolling.enqueueDiscovery(
    141                                     CapabilityPolling.ACTION_POLLING_NORMAL);
    142                         }
    143                     }
    144                     break;
    145                 }
    146                 case Contacts.ACTION_EAB_DATABASE_RESET: {
    147                     logger.info("EAB Database Reset, Recreating...");
    148                     sendEABResetMessage();
    149                     break;
    150                 }
    151             }
    152         }
    153     };
    154 
    155     private  ContentObserver mContactChangedListener = null;
    156     private class ContactChangedListener extends ContentObserver {
    157         public ContactChangedListener() {
    158             super(null);
    159         }
    160 
    161         @Override
    162         public boolean deliverSelfNotifications() {
    163             return false;
    164         }
    165 
    166         @Override
    167         public void onChange(boolean selfChange) {
    168             logger.debug("onChange for ContactChangedListener");
    169             sendDelayedContactChangeMsg();
    170         }
    171     }
    172 
    173     private  ContentObserver mContactProfileListener = null;
    174     private class ContactProfileListener extends ContentObserver {
    175         public ContactProfileListener() {
    176             super(null);
    177         }
    178 
    179         @Override
    180         public boolean deliverSelfNotifications() {
    181             return false;
    182         }
    183 
    184         @Override
    185         public void onChange(boolean selfChange) {
    186             logger.debug("onChange for ContactProfileListener");
    187             sendDelayedContactProfileMsg();
    188         }
    189     }
    190 
    191     @Override
    192     public void onCreate() {
    193         logger.debug("Enter : onCreate");
    194         mContext = getApplicationContext();
    195         HandlerThread thread = new HandlerThread("EABServiceHandler");
    196         thread.start();
    197 
    198         mServiceLooper = thread.getLooper();
    199         if (mServiceLooper != null) {
    200             mServiceHandler = new ServiceHandler(mServiceLooper);
    201         } else {
    202             logger.debug("mServiceHandler could not be initialized since looper is null");
    203         }
    204 
    205         IntentFilter filter = new IntentFilter();
    206         filter.addAction(ContactsContract.Intents.CONTACTS_DATABASE_CREATED);
    207         filter.addAction(Intent.ACTION_TIME_CHANGED);
    208         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    209         filter.addAction(Contacts.ACTION_EAB_DATABASE_RESET);
    210         registerReceiver(mReceiver, filter);
    211 
    212         initializeRcsInterfacer();
    213 
    214         startResetContentObserverAlarm();
    215         super.onCreate();
    216     }
    217 
    218     @Override
    219     public void onDestroy() {
    220         cancelResetContentObserverAlarm();
    221         unregisterContentObservers();
    222         if (null != mReceiver) {
    223             unregisterReceiver(mReceiver);
    224         }
    225         if (null != mServiceHandler) {
    226             mServiceHandler = null;
    227         }
    228     }
    229 
    230     private void initializeRcsInterfacer() {
    231         // Get instance of mRcsManagr.
    232         if (null == mRcsManager) {
    233             mRcsManager = RcsManager.getInstance(this, 0);
    234         }
    235         try{
    236             if (null == mRcsPresence) {
    237                 mRcsPresence = mRcsManager.getRcsPresenceInterface();
    238                 logger.debug("mRcsManager : " + mRcsManager + " mRcsPresence : " + mRcsPresence);
    239             }
    240          }catch (RcsException e){
    241              logger.error("getRcsPresenceInterface() exception : ", e);
    242             mRcsPresence = null;
    243          } catch (Exception e) {
    244              logger.error("getRcsPresenceInterface() exception : ", e);
    245             mRcsPresence = null;
    246             mRcsManager = null;
    247          }
    248      }
    249 
    250     private void registerContentObservers() {
    251         logger.debug("Registering for Contact and Profile Change Listener.");
    252         mContactChangedListener = new ContactChangedListener();
    253         getContentResolver().registerContentObserver(
    254                 ContactsContract.Contacts.CONTENT_URI, true,
    255                 mContactChangedListener);
    256 
    257         mContactProfileListener = new ContactProfileListener();
    258         getContentResolver().registerContentObserver(
    259                 ContactsContract.Profile.CONTENT_URI, true,
    260                 mContactProfileListener);
    261     }
    262 
    263     private void unregisterContentObservers() {
    264         logger.debug("Un-registering for Contact and Profile Change Listener.");
    265         if (null != mContactChangedListener) {
    266             getContentResolver().unregisterContentObserver(
    267                     mContactChangedListener);
    268             mContactChangedListener = null;
    269         }
    270         if (null != mContactProfileListener) {
    271             getContentResolver().unregisterContentObserver(
    272                     mContactProfileListener);
    273             mContactProfileListener = null;
    274         }
    275     }
    276 
    277     private void resetContentObservers() {
    278         unregisterContentObservers();
    279         registerContentObservers();
    280     }
    281 
    282     private AlarmManager.OnAlarmListener mResetContentObserverListener = () -> {
    283         logger.debug("mResetContentObserverListener Callback Received");
    284 
    285         resetContentObservers();
    286         startResetContentObserverAlarm();
    287     };
    288 
    289     private void startResetContentObserverAlarm() {
    290         logger.debug("startResetContentObserverAlarm: content Observers reset every 12 hours");
    291         long startInterval = System.currentTimeMillis() + AlarmManager.INTERVAL_HALF_DAY;
    292 
    293         // Start the resetContentObservers Alarm on the ServiceHandler
    294         ((AlarmManager) getSystemService(Context.ALARM_SERVICE)).set(AlarmManager.RTC_WAKEUP,
    295                 startInterval, TAG, mResetContentObserverListener, mServiceHandler);
    296     }
    297 
    298     private void cancelResetContentObserverAlarm() {
    299         ((AlarmManager) getSystemService(Context.ALARM_SERVICE)).cancel(
    300                 mResetContentObserverListener);
    301     }
    302 
    303     @Override
    304     public int onStartCommand(Intent intent, int flags, int startId) {
    305         // As the return type is START_STICKY, check for null intent is not
    306         // needed as if this service's process is killed while it is started,
    307         // system will try to re-create the service with a null intent object if
    308         // there are not any pending start commands
    309         if (intent != null) {
    310             logger.debug("Enter : onStartCommand for intent : " + intent.getAction());
    311         }
    312         registerContentObservers();
    313         Message msg = mServiceHandler.obtainMessage(BOOT_COMPLETED);
    314         mServiceHandler.sendMessage(msg);
    315         // This service should be a always-on service.
    316         return START_STICKY;
    317     }
    318 
    319     private final class ServiceHandler extends Handler {
    320         public ServiceHandler(Looper looper) {
    321             super(looper);
    322         }
    323 
    324         @Override
    325         public void handleMessage(Message msg) {
    326             logger.debug("Enter: handleMessage");
    327 
    328             switch (msg.what) {
    329             case BOOT_COMPLETED:
    330                 logger.debug("case BOOT_COMPLETED");
    331                 ensureInitDone();
    332                 isEABServiceInitializing = false;
    333                 break;
    334             case CONTACT_TABLE_MODIFIED:
    335                 logger.debug("case CONTACT_TABLE_MODIFIED");
    336                 validateAndSyncFromContactsDb();
    337                 break;
    338             case CONTACT_PROFILE_TABLE_MODIFIED:
    339                 logger.debug("case CONTACT_PROFILE_TABLE_MODIFIED");
    340                 validateAndSyncFromProfileDb();
    341                 break;
    342             case EAB_DATABASE_RESET:
    343                 // Initialise EABProvider.
    344                 logger.debug("Resetting timestamp values in shared pref.");
    345                 SharedPrefUtil.resetEABSharedPref(mContext);
    346                 // init the EAB db after re-setting.
    347                 ensureInitDone();
    348                 break;
    349             default:
    350                 logger.debug("default usecase hit! Do nothing");
    351                 break;
    352             }
    353             logger.debug("Exit: handleMessage");
    354         }
    355     }
    356 
    357     // synchronized is used to prevent sync happening in parallel due to
    358     // multiple content change notifys from contacts observer.
    359     private synchronized void validateAndSyncFromContactsDb() {
    360         logger.debug("Enter : validateAndSyncFromContactsDb()");
    361         checkForContactNumberChanges();
    362         checkForDeletedContact();
    363         logger.debug("Exit : validateAndSyncFromContactsDb()");
    364     }
    365 
    366     // synchronized is used to prevent sync happening in parallel due to
    367     // multiple content change notify from contacts observer.
    368     private synchronized void validateAndSyncFromProfileDb() {
    369         logger.debug("Enter : validateAndSyncFromProfileDb()");
    370         checkForProfileNumberChanges();
    371         checkForDeletedProfileContacts();
    372         logger.debug("Exit : validateAndSyncFromProfileDb()");
    373     }
    374 
    375     private void ensureInitDone() {
    376         logger.debug("Enter : ensureInitDone()");
    377         if(SharedPrefUtil.isInitDone(mContext)) {
    378             logger.debug("EAB initialized already!!! Just Sync with Contacts db.");
    379             validateAndSyncFromContactsDb();
    380             validateAndSyncFromProfileDb();
    381             return;
    382         } else {
    383             logger.debug("Initializing EAB Provider.");
    384             // This API will sync the numbers from Contacts db to EAB db based on
    385             // contact last updated timestamp.
    386             EABDbUtil.validateAndSyncFromContactsDb(mContext);
    387             // This API's will sync the profile numbers from Contacts db to EAB db based on
    388             // contact last updated timestamp.
    389             validateAndSyncFromProfileDb();
    390             SharedPrefUtil.setInitDone(mContext, true);
    391         }
    392     }
    393 
    394     private void sendEABResetMessage() {
    395         logger.debug("Enter: sendEABResetMsg()");
    396         if (null != mServiceHandler) {
    397             if (mServiceHandler.hasMessages(EAB_DATABASE_RESET)) {
    398                 mServiceHandler.removeMessages(EAB_DATABASE_RESET);
    399                 logger.debug("Removed previous EAB_DATABASE_RESET msg.");
    400             }
    401 
    402             logger.debug("Sending new EAB_DATABASE_RESET msg.");
    403             Message msg = mServiceHandler.obtainMessage(EAB_DATABASE_RESET);
    404             mServiceHandler.sendMessage(msg);
    405         }
    406     }
    407 
    408     private void sendDelayedContactChangeMsg() {
    409         logger.debug("Enter: sendDelayedContactChangeMsg()");
    410         if (null != mServiceHandler && !isEABServiceInitializing) {
    411             // Remove any previous message for CONTACT_TABLE_MODIFIED.
    412             if (mServiceHandler.hasMessages(CONTACT_TABLE_MODIFIED)) {
    413                 mServiceHandler.removeMessages(CONTACT_TABLE_MODIFIED);
    414                 logger.debug("Removed previous CONTACT_TABLE_MODIFIED msg.");
    415             }
    416 
    417             logger.debug("Sending new CONTACT_TABLE_MODIFIED msg.");
    418             // Send a new delayed message for CONTACT_TABLE_MODIFIED.
    419             Message msg = mServiceHandler.obtainMessage(CONTACT_TABLE_MODIFIED);
    420             mServiceHandler.sendMessageDelayed(msg, SYNC_COMPLETE_DELAY_TIMER);
    421         }
    422     }
    423 
    424     private void sendDelayedContactProfileMsg() {
    425         logger.debug("Enter: sendDelayedContactProfileMsg()");
    426         if (null != mServiceHandler && !isEABServiceInitializing) {
    427             // Remove any previous message for CONTACT_PROFILE_TABLE_MODIFIED.
    428             if (mServiceHandler.hasMessages(CONTACT_PROFILE_TABLE_MODIFIED)) {
    429                 mServiceHandler.removeMessages(CONTACT_PROFILE_TABLE_MODIFIED);
    430                 logger.debug("Removed previous CONTACT_PROFILE_TABLE_MODIFIED msg.");
    431             }
    432 
    433             logger.debug("Sending new CONTACT_PROFILE_TABLE_MODIFIED msg.");
    434             // Send a new delayed message for CONTACT_PROFILE_TABLE_MODIFIED.
    435             Message msg = mServiceHandler.obtainMessage(CONTACT_PROFILE_TABLE_MODIFIED);
    436             mServiceHandler.sendMessageDelayed(msg, SYNC_COMPLETE_DELAY_TIMER);
    437         }
    438     }
    439 
    440     private void checkForContactNumberChanges() {
    441         logger.debug("Enter: checkForContactNumberChanges()");
    442         String[] projection = new String[] {
    443                 ContactsContract.Data._ID,
    444                 ContactsContract.Data.CONTACT_ID,
    445                 ContactsContract.Data.RAW_CONTACT_ID,
    446                 ContactsContract.Data.MIMETYPE,
    447                 ContactsContract.Data.DATA1,
    448                 ContactsContract.Data.DISPLAY_NAME,
    449                 ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP };
    450 
    451         long contactLastChange = SharedPrefUtil.getLastContactChangedTimestamp(mContext, 0);
    452         logger.debug("contactLastChange : " + contactLastChange);
    453 
    454         String selection = ContactsContract.Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE +
    455                 "' AND " + ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP  + " > '" +
    456                 contactLastChange + "'";
    457         String sortOrder = ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP + " desc";
    458         Cursor cursor = null;
    459         try {
    460             cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI,
    461                     projection, selection, null, sortOrder);
    462 
    463             if (null != cursor) {
    464                 int count = cursor.getCount();
    465                 logger.debug("cursor count : " + count);
    466                 if (count > 0) {
    467                     ArrayList<Long> uniqueRawContactIds = new ArrayList<Long>();
    468                     while (cursor.moveToNext()) {
    469                         Long dataId = Long.valueOf(cursor.getLong(cursor.getColumnIndex(
    470                                 ContactsContract.Data._ID)));
    471                         Long contactId = Long.valueOf(cursor.getLong(cursor.getColumnIndex(
    472                                 ContactsContract.Data.CONTACT_ID)));
    473                         Long rawContactId = Long.valueOf(cursor.getLong(cursor.getColumnIndex(
    474                                 ContactsContract.Data.RAW_CONTACT_ID)));
    475                         String phoneNumber = cursor.getString(cursor.getColumnIndex(
    476                                 ContactsContract.Data.DATA1));
    477                         String displayName = cursor.getString(cursor.getColumnIndex(
    478                                ContactsContract.Data.DISPLAY_NAME));
    479                         logger.debug("dataId : " + dataId + " rawContactId :"  + rawContactId +
    480                                " contactId : " + contactId
    481                                + " phoneNumber :" + phoneNumber + " displayName :" + displayName);
    482                         verifyInsertOrUpdateAction(dataId, contactId, rawContactId, phoneNumber,
    483                               displayName);
    484                         if (uniqueRawContactIds.isEmpty()) {
    485                             uniqueRawContactIds.add(rawContactId);
    486                         } else if (!uniqueRawContactIds.contains(rawContactId)) {
    487                             uniqueRawContactIds.add(rawContactId);
    488                         } else {
    489                             // Do nothing.
    490                             logger.debug("uniqueRawContactIds already contains rawContactId : " +
    491                                     rawContactId);
    492                         }
    493                     }
    494                     checkForPhoneNumberDelete(uniqueRawContactIds);
    495                     // Save the largest timestamp returned. Only need the first one due to
    496                     // the sort order.
    497                     cursor.moveToFirst();
    498                     long timestamp = cursor.getLong(cursor
    499                             .getColumnIndex(ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP));
    500                     if (timestamp > 0) {
    501                         SharedPrefUtil.saveLastContactChangedTimestamp(mContext, timestamp);
    502                     }
    503                 }
    504             } else {
    505                 logger.error("cursor is null!");
    506             }
    507         } catch (Exception e) {
    508             logger.error("checkForContactNumberChanges() exception:", e);
    509         } finally {
    510             if (null != cursor) {
    511                 cursor.close();
    512             }
    513         }
    514         logger.debug("Exit: checkForContactNumberChanges()");
    515     }
    516 
    517     private void verifyInsertOrUpdateAction(Long dataId, Long contactId,
    518             Long rawContactId, String phoneNumber, String displayName) {
    519         logger.debug("Enter: verifyInsertOrUpdateAction() phoneNumber : " + phoneNumber);
    520         if (null == phoneNumber){
    521             logger.error("Error: return as phoneNumber is null");
    522             return;
    523         }
    524         // Check if the contact is already available in EAB Provider.
    525         String[] eabProjection = new String[] {
    526                 EABContract.EABColumns.CONTACT_NUMBER,
    527                 EABContract.EABColumns.CONTACT_NAME };
    528         String eabWhereClause = EABContract.EABColumns.DATA_ID + " ='" + dataId.toString()
    529                 + "' AND " + EABContract.EABColumns.RAW_CONTACT_ID + " ='"
    530                 + rawContactId.toString() + "' AND " + EABContract.EABColumns.CONTACT_ID
    531                 + " ='" + contactId.toString() + "'";
    532         logger.debug("eabWhereClause : " + eabWhereClause);
    533 
    534         Cursor eabCursor = getContentResolver().query(EABContract.EABColumns.CONTENT_URI,
    535                 eabProjection, eabWhereClause, null, null);
    536         if (null != eabCursor) {
    537             int eabCursorCount = eabCursor.getCount();
    538             logger.debug("EAB cursor count : " + eabCursorCount);
    539             if (eabCursorCount > 0) {
    540                 while (eabCursor.moveToNext()) {
    541                     // EABProvider has entry for dataId & rawContactId. Try to
    542                     // match the contact number.
    543                     String eabPhoneNumber = eabCursor.getString(eabCursor
    544                                     .getColumnIndex(EABContract.EABColumns.CONTACT_NUMBER));
    545                     String eabDisplayName = eabCursor.getString(eabCursor
    546                             .getColumnIndex(EABContract.EABColumns.CONTACT_NAME));
    547                     logger.debug("phoneNumber : " + phoneNumber
    548                             + " eabPhoneNumber :" + eabPhoneNumber);
    549                     // If contact number do not match, then update EAB database with the new
    550                     // number. If contact name do not match, then update EAB database with the
    551                     // new name.
    552                     if (null != eabPhoneNumber) {
    553                         if (!phoneNumber.equals(eabPhoneNumber)) {
    554                             // Update use-case.
    555                             handlePhoneNumberChanged(dataId, contactId, rawContactId,
    556                                     eabPhoneNumber, phoneNumber, displayName);
    557                         } else if (!TextUtils.equals(displayName, eabDisplayName)) {
    558                             // Update name use-case.
    559                             handlePhoneNameUpdate(dataId, contactId, rawContactId,
    560                                     phoneNumber, displayName);
    561                         } else {
    562                             // Do nothing.
    563                             logger.debug("The contact name and number is already available " +
    564                                     "in EAB Provider.");
    565                         }
    566                     }
    567                 }
    568             } else {
    569                 // insert use-case.
    570                 handlePhoneNumberInsertion(dataId, contactId, rawContactId, phoneNumber,
    571                         displayName);
    572             }
    573         }
    574         if (null != eabCursor) {
    575             eabCursor.close();
    576         }
    577         logger.debug("Exit: verifyInsertOrUpdateAction()");
    578     }
    579 
    580     private void checkForPhoneNumberDelete(ArrayList<Long> uniqueRawContactIds) {
    581         logger.debug("Enter: checkForPhoneNumberDelete() ");
    582         if (null != uniqueRawContactIds && uniqueRawContactIds.size() > 0) {
    583             for (int i = 0; i < uniqueRawContactIds.size(); i++) {
    584                 Long rawContactId = uniqueRawContactIds.get(i);
    585                 int contactsDbCount = 0;
    586                 int eabDbCursorCount = 0;
    587 
    588                 // Find the total number of dataIds under the rawContactId in
    589                 // Contacts Provider DB.
    590                 String[] projection = new String[] { ContactsContract.Data._ID,
    591                         ContactsContract.Data.CONTACT_ID,
    592                         ContactsContract.Data.RAW_CONTACT_ID,
    593                         ContactsContract.Data.MIMETYPE,
    594                         ContactsContract.Data.DATA1,
    595                         ContactsContract.Data.DISPLAY_NAME };
    596 
    597                 // Get LastContactChangedTimestamp for knowing which contact
    598                 // number deleted from the contact id.
    599                 long contactLastChange = SharedPrefUtil.getLastContactChangedTimestamp(
    600                         mContext, 0);
    601 
    602                 String selection = ContactsContract.Data.MIMETYPE + " = '"
    603                         + Phone.CONTENT_ITEM_TYPE + "' AND " +
    604                         ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP
    605                         + " > '" + contactLastChange + "' AND " +
    606                         ContactsContract.Data.RAW_CONTACT_ID + " = '"
    607                         + rawContactId + "'";
    608 
    609                 String sortOrder = ContactsContract.Data.RAW_CONTACT_ID + " desc";
    610 
    611                 Cursor contactDbCursor = getContentResolver().query(
    612                         ContactsContract.Data.CONTENT_URI, projection,
    613                         selection, null, sortOrder);
    614 
    615                 if (null != contactDbCursor) {
    616                     contactsDbCount = contactDbCursor.getCount();
    617                     logger.debug("contactDbCursor count : " + contactsDbCount);
    618                 }
    619 
    620                 // Find the total number of dataIds under the rawContactId in
    621                 // EAB Provider DB.
    622                 String[] eabProjection = new String[] {
    623                         EABContract.EABColumns.CONTACT_ID,
    624                         EABContract.EABColumns.RAW_CONTACT_ID,
    625                         EABContract.EABColumns.DATA_ID,
    626                         EABContract.EABColumns.CONTACT_NUMBER,
    627                         EABContract.EABColumns.CONTACT_NAME };
    628 
    629                 String eabWhereClause = EABContract.EABColumns.RAW_CONTACT_ID
    630                         + " ='" + rawContactId.toString() + "'";
    631 
    632                 Cursor eabDbCursor = getContentResolver().query(
    633                         EABContract.EABColumns.CONTENT_URI, eabProjection,
    634                         eabWhereClause, null, null);
    635                 if (null != eabDbCursor) {
    636                     eabDbCursorCount = eabDbCursor.getCount();
    637                     logger.debug("eabDbCursor count : " + eabDbCursorCount);
    638                 }
    639                 if (0 == contactsDbCount && 0 == eabDbCursorCount) {
    640                     // Error scenario. Continue for checking the next rawContactId.
    641                     logger.error("Both cursor counts are 0. move to next rawContactId");
    642                 } else {
    643                     if (contactsDbCount == eabDbCursorCount) {
    644                         // Do nothing as both DB have the same number of contacts.
    645                         logger.debug("Both the databases have the same number of contacts." +
    646                                 " Do nothing.");
    647                     } else if (contactsDbCount > eabDbCursorCount) {
    648                         logger.error("EAB DB has less contacts then Contacts DB. Do nothing!");
    649                     } else if (contactsDbCount < eabDbCursorCount) {
    650                         // find and number and delete it from EAB Provider.
    651                         logger.debug("Delete usecase hit. Find and delete contact from EAB DB.");
    652                         ArrayList <Long> eabDataIdList = new ArrayList <Long>();
    653                         while (eabDbCursor.moveToNext()) {
    654                             String eabPhoneNumber = eabDbCursor.getString(eabDbCursor
    655                                     .getColumnIndex(EABContract.EABColumns.CONTACT_NUMBER));
    656                             logger.debug("eabPhoneNumber :" + eabPhoneNumber);
    657                             Long eabDataId = Long.valueOf(eabDbCursor.getLong(eabDbCursor
    658                                     .getColumnIndex(EABContract.EABColumns.DATA_ID)));
    659                             logger.debug("eabDataId :" + eabDataId);
    660                             if (eabDataIdList.isEmpty()) {
    661                                 eabDataIdList.add(eabDataId);
    662                             } else if (!eabDataIdList.contains(eabDataId) )  {
    663                                 eabDataIdList.add(eabDataId);
    664                             } else {
    665                                 // Something is wrong. There can not be duplicate numbers.
    666                                 logger.error("Duplicate entry for PhoneNumber :" + eabPhoneNumber
    667                                         + " with DataId : " + eabDataId + " found in EABProvider.");
    668                             }
    669                         }
    670                         logger.debug("Before computation eabDataIdList size :" +
    671                                 eabDataIdList.size());
    672                         while (contactDbCursor.moveToNext()) {
    673                             String contactPhoneNumber = contactDbCursor.getString(contactDbCursor
    674                                     .getColumnIndex(ContactsContract.Data.DATA1));
    675                             Long contactDataId = Long.valueOf(contactDbCursor.getLong(
    676                                     contactDbCursor
    677                                             .getColumnIndex(ContactsContract.Data._ID)));
    678                             logger.debug("contactPhoneNumber : " + contactPhoneNumber +
    679                                     " dataId : " + contactDataId);
    680                             if (eabDataIdList.contains(contactDataId) )  {
    681                                 eabDataIdList.remove(contactDataId);
    682                                 logger.debug("Number removed from eabDataIdList");
    683                             } else {
    684                                 // Something is wrong. There can not be new number in Contacts DB.
    685                                 logger.error("Number :" + contactPhoneNumber
    686                                         + " with DataId : " + contactDataId +
    687                                         " not found in EABProvider.");
    688                             }
    689                         }
    690                         logger.debug("After computation eabPhoneNumberList size :" +
    691                                 eabDataIdList.size());
    692                         if (eabDataIdList.size() > 0) {
    693                             handlePhoneNumbersDeleted(rawContactId, eabDataIdList);
    694                         }
    695                     }
    696                 }
    697                 if (null != contactDbCursor) {
    698                     contactDbCursor.close();
    699                 }
    700                 if (null != eabDbCursor) {
    701                     eabDbCursor.close();
    702                 }
    703             }
    704         } else {
    705             // Do nothing.
    706             logger.debug("uniqueRawContactIds is null or empty. Do nothing. ");
    707         }
    708         logger.debug("Exit: checkForPhoneNumberDelete() ");
    709     }
    710 
    711     private void checkForDeletedContact() {
    712         logger.debug("Enter: checkForDeletedContact()");
    713         String[] projection = new String[] {
    714                 ContactsContract.DeletedContacts.CONTACT_ID,
    715                 ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP };
    716 
    717         long contactLastDeleted = SharedPrefUtil.getLastContactDeletedTimestamp(mContext, 0);
    718         logger.debug("contactLastDeleted : " + contactLastDeleted);
    719 
    720         String selection = ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP
    721                 + " > '" + contactLastDeleted + "'";
    722 
    723         String sortOrder = ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP + " desc";
    724 
    725         Cursor cursor = getContentResolver().query(
    726                 ContactsContract.DeletedContacts.CONTENT_URI, projection,
    727                 selection, null, sortOrder);
    728         if (null != cursor) {
    729             int count = cursor.getCount();
    730             logger.debug("cursor count : " + count);
    731             if (count > 0) {
    732                 while (cursor.moveToNext()) {
    733                     Long contactId = Long.valueOf(cursor.getLong(cursor
    734                                     .getColumnIndex(ContactsContract.DeletedContacts.CONTACT_ID)));
    735                     logger.debug("contactId : " + contactId);
    736                     handleContactDeleted(contactId);
    737                 }
    738                 // Save the largest returned timestamp. Only need the first
    739                 // cursor element due to the sort order.
    740                 cursor.moveToFirst();
    741                 long timestamp = cursor.getLong(cursor
    742                         .getColumnIndex(
    743                         ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP));
    744                 if (timestamp > 0) {
    745                     SharedPrefUtil.saveLastContactDeletedTimestamp(mContext, timestamp);
    746                 }
    747             }
    748         }
    749         if (null != cursor) {
    750             cursor.close();
    751         }
    752         logger.debug("Exit: checkForDeletedContact()");
    753     }
    754 
    755     private void checkForProfileNumberChanges() {
    756         logger.debug("Enter: checkForProfileNumberChanges()");
    757         String[] projection = new String[] {
    758                 ContactsContract.Contacts.Entity.CONTACT_ID,
    759                 ContactsContract.Contacts.Entity.RAW_CONTACT_ID,
    760                 ContactsContract.Contacts.Entity.DATA_ID,
    761                 ContactsContract.Contacts.Entity.MIMETYPE,
    762                 ContactsContract.Contacts.Entity.DATA1,
    763                 ContactsContract.Contacts.Entity.DISPLAY_NAME,
    764                 ContactsContract.Contacts.Entity.CONTACT_LAST_UPDATED_TIMESTAMP};
    765 
    766         long profileContactLastChange = SharedPrefUtil.getLastProfileContactChangedTimestamp(
    767                 mContext, 0);
    768         logger.debug("profileContactLastChange : " + profileContactLastChange);
    769 
    770         String selection = ContactsContract.Contacts.Entity.MIMETYPE + " ='" +
    771                 Phone.CONTENT_ITEM_TYPE + "' AND "
    772                 + ContactsContract.Contacts.Entity.CONTACT_LAST_UPDATED_TIMESTAMP  + " > '" +
    773                 profileContactLastChange + "'";
    774         String sortOrder = ContactsContract.Contacts.Entity.CONTACT_LAST_UPDATED_TIMESTAMP +
    775                 " desc";
    776         // Construct the Uri to access Profile's Entity view.
    777         Uri profileUri = ContactsContract.Profile.CONTENT_URI;
    778         Uri entiryUri = Uri.withAppendedPath(profileUri,
    779                 ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);
    780 
    781         Cursor cursor = getContentResolver().query(entiryUri, projection, selection, null,
    782                 sortOrder);
    783         if (null != cursor) {
    784             int count = cursor.getCount();
    785             logger.debug("cursor count : " + count);
    786             if (count > 0) {
    787                 ArrayList <String> profileNumberList = new ArrayList <String>();
    788                 ArrayList <Long> profileDataIdList = new ArrayList <Long>();
    789                 Long contactId = null;
    790                 Long rawContactId = null;
    791                 while (cursor.moveToNext()) {
    792                     contactId = Long.valueOf(cursor.getLong(cursor.getColumnIndex(
    793                             ContactsContract.Contacts.Entity.CONTACT_ID)));
    794                     rawContactId = Long.valueOf(cursor.getLong(cursor.getColumnIndex(
    795                             ContactsContract.Contacts.Entity.RAW_CONTACT_ID)));
    796                     Long dataId = Long.valueOf(cursor.getLong(cursor.getColumnIndex(
    797                             ContactsContract.Contacts.Entity.DATA_ID)));
    798                     String contactNumber = cursor.getString(cursor.getColumnIndex(
    799                             ContactsContract.Contacts.Entity.DATA1));
    800                     String profileName = cursor.getString(cursor.getColumnIndex(
    801                             ContactsContract.Contacts.Entity.DISPLAY_NAME));
    802                     logger.debug("Profile Name : " + profileName
    803                             + " Profile Number : " + contactNumber
    804                             + " profile dataId : " + dataId
    805                             + " profile rawContactId : " + rawContactId
    806                             + " profile contactId : " + contactId);
    807                     if (profileDataIdList.isEmpty()) {
    808                         profileDataIdList.add(dataId);
    809                         profileNumberList.clear();
    810                         profileNumberList.add(contactNumber);
    811                     } else if (!profileDataIdList.contains(dataId)) {
    812                         profileDataIdList.add(dataId);
    813                         profileNumberList.add(contactNumber);
    814                     } else {
    815                         // There are duplicate entries in Profile's Table
    816                         logger.error("Duplicate entry in Profile's Table for contact :" +
    817                                 contactNumber + " dataId : " + dataId);
    818                     }
    819                     verifyInsertOrUpdateAction(dataId, contactId, rawContactId, contactNumber,
    820                             profileName);
    821                 }
    822                 checkForProfilePhoneNumberDelete(contactId, rawContactId, profileDataIdList);
    823                 // Save the largest timestamp returned. Only need the first cursor element
    824                 // due to sort order.
    825                 cursor.moveToFirst();
    826                 long timestamp = cursor.getLong(cursor.getColumnIndex(
    827                         ContactsContract.Contacts.Entity.CONTACT_LAST_UPDATED_TIMESTAMP));
    828                 if (timestamp > 0) {
    829                     SharedPrefUtil.saveLastProfileContactChangedTimestamp(mContext, timestamp);
    830                 }
    831             } else {
    832                 logger.error("cursor is zero. Do nothing.");
    833             }
    834         } else {
    835             logger.error("ContactsContract.Profile.CONTENT_URI cursor is null!");
    836         }
    837         if (null != cursor) {
    838             cursor.close();
    839         }
    840         logger.debug("Exit: checkForProfileNumberChanges()");
    841     }
    842 
    843     private void checkForProfilePhoneNumberDelete(Long profileContactId,
    844             Long profileRawContactId, ArrayList<Long> profileDataIdList) {
    845         logger.debug("Enter: checkForProfilePhoneNumberDelete()");
    846         if (!ContactsContract.isProfileId(profileContactId)) {
    847             logger.error("Not a Profile Contact Id : " + profileContactId);
    848             return;
    849         }
    850         int eabDbCursorCount = 0;
    851         int profileContactsDbCount = profileDataIdList.size();
    852         logger.error("profileContactsDbCount size : " + profileContactsDbCount);
    853         // Find the total number of dataIds under the rawContactId in EAB Provider DB.
    854         String[] eabProjection = new String[] {
    855                 EABContract.EABColumns.CONTACT_ID,
    856                 EABContract.EABColumns.DATA_ID,
    857                 EABContract.EABColumns.CONTACT_NUMBER};
    858         String eabWhereClause = EABContract.EABColumns.CONTACT_ID + " ='" +
    859                 profileContactId.toString() + "'";
    860 
    861         Cursor eabDbCursor = getContentResolver().query( EABContract.EABColumns.CONTENT_URI,
    862                 eabProjection,
    863                 eabWhereClause, null, null);
    864         if (null != eabDbCursor) {
    865             eabDbCursorCount = eabDbCursor.getCount();
    866             logger.debug("eabDbCursor count : " + eabDbCursorCount);
    867         }
    868         if (0 == profileContactsDbCount && 0 == eabDbCursorCount) {
    869             // Error scenario. Continue for checking the next rawContactId.
    870             logger.error("Both cursor counts are 0. Do nothing");
    871         } else {
    872             if (profileContactsDbCount == eabDbCursorCount) {
    873                 // Do nothing as both DB have the same number of contacts.
    874                 logger.debug("Both the databases have the same number of contacts. Do nothing.");
    875             } else if (profileContactsDbCount > eabDbCursorCount) {
    876                 logger.error("EAB DB has less contacts then Contacts DB. Do nothing!");
    877             } else if (profileContactsDbCount < eabDbCursorCount) {
    878                 // find and number and delete it from EAB Provider.
    879                 logger.debug("Delete usecase hit. Find and delete contact from EAB DB.");
    880                 ArrayList <Long> eabDataIdList = new ArrayList <Long>();
    881                 while (eabDbCursor.moveToNext()) {
    882                     Long eabDataId = Long.valueOf(eabDbCursor.getLong(eabDbCursor
    883                                     .getColumnIndex(EABContract.EABColumns.DATA_ID)));
    884                     logger.debug("eabDataId : " + eabDataId);
    885                     if (eabDataIdList.isEmpty()) {
    886                         eabDataIdList.add(eabDataId);
    887                     } else if (!eabDataIdList.contains(eabDataId) )  {
    888                         eabDataIdList.add(eabDataId);
    889                     } else {
    890                         // Something is wrong. There can not be duplicate numbers.
    891                         logger.error("Duplicate entry for eabDataId in EABProvider : " +
    892                                 eabDataId);
    893                     }
    894                 }
    895                 logger.debug("Before computation eabDataIdList size : " + eabDataIdList.size());
    896                 for (int i = 0; i < profileDataIdList.size(); i++) {
    897                     Long contactDataId = profileDataIdList.get(i);
    898                     logger.debug("Profile contactDataId : " + contactDataId);
    899                     if (eabDataIdList.contains(contactDataId) )  {
    900                         eabDataIdList.remove(contactDataId);
    901                         logger.debug("Number removed from eabDataIdList");
    902                     } else {
    903                         // Something is wrong. There can not be new number in Contacts DB.
    904                         logger.error("DataId : " + contactDataId +
    905                                 " not found in EAB Provider DB.");
    906                     }
    907                 }
    908                 logger.debug("After computation eabDataIdList size : " + eabDataIdList.size());
    909                 if (eabDataIdList.size() > 0) {
    910                     handlePhoneNumbersDeleted(profileRawContactId, eabDataIdList);
    911                 }
    912             }
    913         }
    914         if (null != eabDbCursor) {
    915             eabDbCursor.close();
    916         }
    917         logger.debug("Exit: checkForProfilePhoneNumberDelete() ");
    918     }
    919 
    920     private void checkForDeletedProfileContacts() {
    921         logger.debug("Enter: checkForDeletedProfileContacts()");
    922         String[] projection = new String[] {
    923                 ContactsContract.Contacts.Entity.DATA1,
    924                 ContactsContract.Contacts.Entity.DISPLAY_NAME,
    925                 ContactsContract.Contacts.Entity.CONTACT_LAST_UPDATED_TIMESTAMP};
    926 
    927         String selection = ContactsContract.Contacts.Entity.MIMETYPE + " ='" +
    928                 Phone.CONTENT_ITEM_TYPE + "'";
    929         // Construct the Uri to access Profile's Entity view.
    930         Uri profileUri = ContactsContract.Profile.CONTENT_URI;
    931         Uri entiryUri = Uri.withAppendedPath(profileUri,
    932                 ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);
    933 
    934         // Due to issue in AOSP contact profile db, table
    935         // ContactsContract.Profile.CONTENT_URI can not be checked for
    936         // selection = ContactsContract.Profile.HAS_PHONE_NUMBER + " = '" + 1 + "'".
    937         // This is resulting in 0 cursor count even when there are valid
    938         // contact numbers under contacts profile db.
    939         Cursor cursor = getContentResolver().query(entiryUri, projection, selection, null, null);
    940         if (null != cursor) {
    941             int count = cursor.getCount();
    942             logger.debug("Profile contact cursor count : " + count);
    943             if (count == 0) {
    944                 logger.debug("cursor count is Zero. There are no contacts in Contact Profile db.");
    945                 handleContactProfileDeleted();
    946             } else {
    947                 logger.debug("Profile is available. Do nothing");
    948             }
    949             cursor.close();
    950         }
    951         logger.debug("Exit: checkForDeletedProfileContacts()");
    952     }
    953 
    954     private void handlePhoneNumberInsertion(Long dataId, Long contactId,
    955             Long rawContactId, String phoneNumber, String contactName) {
    956 
    957         logger.debug("handlePhoneNumberInsertion() rawContactId : "
    958                 + rawContactId + " dataId :" + dataId + " contactId :"
    959                 + contactId + " phoneNumber :" + phoneNumber + " contactName :"
    960                 + contactName);
    961         if (!EABDbUtil.validateEligibleContact(mContext, phoneNumber)) {
    962             logger.debug("Return as number is not elegible for VT.");
    963             return;
    964         }
    965         String sRawContactId = null;
    966         String sDataId = null;
    967         String sContactId = null;
    968         if (null != rawContactId) {
    969             sRawContactId = rawContactId.toString();
    970         }
    971         if (null != dataId) {
    972             sDataId = dataId.toString();
    973         }
    974         if (null != contactId) {
    975             sContactId = contactId.toString();
    976         }
    977         String formattedNumber = EABDbUtil.formatNumber(phoneNumber);
    978         ArrayList<PresenceContact> contactListToInsert = new ArrayList<PresenceContact>();
    979         contactListToInsert.add(new PresenceContact(contactName, phoneNumber, formattedNumber,
    980                 sRawContactId, sContactId, sDataId));
    981 
    982         EABDbUtil.addContactsToEabDb(getApplicationContext(),
    983                 contactListToInsert);
    984     }
    985 
    986     private void handlePhoneNumberChanged(Long dataId, Long contactId,
    987             Long rawContactId, String oldPhoneNumber, String newPhoneNumber,
    988             String contactName) {
    989 
    990         logger.debug("handlePhoneNumberChanged() rawContactId : " + rawContactId
    991                 + " dataId :" + dataId + " oldPhoneNumber :" + oldPhoneNumber
    992                 + " newPhoneNumber :" + newPhoneNumber + " contactName :"
    993                 + contactName);
    994 
    995         if (null == oldPhoneNumber && null == newPhoneNumber) {
    996             logger.debug("Both old and new numbers are null.");
    997             return;
    998         }
    999 
   1000         ArrayList<PresenceContact> contactListToInsert = new ArrayList<PresenceContact>();
   1001         ArrayList<PresenceContact> contactListToDelete = new ArrayList<PresenceContact>();
   1002         String sRawContactId = null;
   1003         String sDataId = null;
   1004         String sContactId = null;
   1005         if (null != rawContactId) {
   1006             sRawContactId = rawContactId.toString();
   1007         }
   1008         if (null != dataId) {
   1009             sDataId = dataId.toString();
   1010         }
   1011         if (null != contactId) {
   1012             sContactId = contactId.toString();
   1013         }
   1014         String newFormattedNumber = EABDbUtil.formatNumber(newPhoneNumber);
   1015         logger.debug("newFormattedNumber : " + newFormattedNumber);
   1016         logger.debug("Removing old number and inserting new number in EABProvider.");
   1017         if (null != oldPhoneNumber) {
   1018             contactListToDelete.add(new PresenceContact(contactName,
   1019                     oldPhoneNumber, null /*formattedNumber*/, sRawContactId, sContactId, sDataId));
   1020             // Delete old number from EAB Presence Table
   1021             EABDbUtil.deleteNumbersFromEabDb(getApplicationContext(), contactListToDelete);
   1022         }
   1023         if (null != newPhoneNumber) {
   1024             if (EABDbUtil.validateEligibleContact(mContext, newPhoneNumber)) {
   1025                 contactListToInsert.add(new PresenceContact(contactName,
   1026                         newPhoneNumber, newFormattedNumber, sRawContactId, sContactId, sDataId));
   1027                 // Insert new number from EAB Presence Table
   1028                 EABDbUtil.addContactsToEabDb(getApplicationContext(), contactListToInsert);
   1029             } else {
   1030                 logger.debug("Return as number is not elegible for VT.");
   1031             }
   1032         }
   1033     }
   1034 
   1035     private void handlePhoneNumbersDeleted(Long rawContactId, ArrayList <Long> contactDataIdList) {
   1036         ArrayList<PresenceContact> phoneNumberToDeleteList = new ArrayList<PresenceContact>();
   1037         for (int v = 0; v < contactDataIdList.size(); v++) {
   1038             Long staleDataId = contactDataIdList.get(v);
   1039             if (null != staleDataId) {
   1040                 logger.debug("calling delete for staleNumber :" + staleDataId);
   1041                 String sRawContactId = null;
   1042                 if (null != rawContactId) {
   1043                     sRawContactId = rawContactId.toString();
   1044                 }
   1045                 phoneNumberToDeleteList.add(new PresenceContact(null, null, null,
   1046                         sRawContactId, null, staleDataId.toString()));
   1047             }
   1048         }
   1049         // Delete number from EAB Provider table.
   1050         EABDbUtil.deleteNumbersFromEabDb(getApplicationContext(), phoneNumberToDeleteList);
   1051     }
   1052 
   1053     private void handlePhoneNameUpdate(Long dataId, Long contactId,
   1054             Long rawContactId, String phoneNumber, String newDisplayName) {
   1055         logger.debug("handlePhoneNameUpdate() rawContactId : " + rawContactId
   1056                 + " dataId :" + dataId + " newDisplayName :" + newDisplayName);
   1057         String sRawContactId = null;
   1058         String sDataId = null;
   1059         String sContactId = null;
   1060         if (null != rawContactId) {
   1061             sRawContactId = rawContactId.toString();
   1062         }
   1063         if (null != dataId) {
   1064             sDataId = dataId.toString();
   1065         }
   1066         if (null != contactId) {
   1067             sContactId = contactId.toString();
   1068         }
   1069         ArrayList<PresenceContact> contactNameToUpdate = new ArrayList<PresenceContact>();
   1070         contactNameToUpdate.add(new PresenceContact(newDisplayName,
   1071                 phoneNumber, null /*formattedNumber */, sRawContactId, sContactId, sDataId));
   1072 
   1073         EABDbUtil.updateNamesInEabDb(getApplicationContext(), contactNameToUpdate);
   1074     }
   1075 
   1076     private void handleContactDeleted(Long contactId) {
   1077 
   1078         if (null == contactId) {
   1079             logger.debug("handleContactDeleted : contactId is null");
   1080         }
   1081         ArrayList<PresenceContact> contactListToDelete = new ArrayList<PresenceContact>();
   1082         contactListToDelete.add(new PresenceContact(null, null, null, null, contactId.toString(),
   1083                 null));
   1084 
   1085         //ContactDbUtil.deleteRawContact(getApplicationContext(), contactListToDelete);
   1086         EABDbUtil.deleteContactsFromEabDb(mContext, contactListToDelete);
   1087     }
   1088 
   1089     private void handleContactProfileDeleted() {
   1090         Long contactProfileMinId = Long.valueOf(ContactsContract.Profile.MIN_ID);
   1091         logger.debug("contactProfileMinId : " + contactProfileMinId);
   1092 
   1093         ArrayList<PresenceContact> contactListToDelete = new ArrayList<PresenceContact>();
   1094         contactListToDelete.add(new PresenceContact(null, null, null, null,
   1095                 contactProfileMinId.toString(), null));
   1096 
   1097         EABDbUtil.deleteContactsFromEabDb(mContext, contactListToDelete);
   1098     }
   1099 
   1100     private boolean isRcsProvisioned(){
   1101         boolean isVoLTEProvisioned = false;
   1102         boolean isLvcProvisioned = false;
   1103         boolean isEabProvisioned = false;
   1104         ImsManager imsManager = null;
   1105         ImsConfig imsConfig = null;
   1106 
   1107         // Get instance of imsManagr.
   1108         imsManager = ImsManager.getInstance(mContext,
   1109                 SubscriptionManager.getDefaultVoiceSubscriptionId());
   1110         try {
   1111             imsConfig = imsManager.getConfigInterface();
   1112             logger.debug("imsConfig initialized.");
   1113         } catch (Exception e) {
   1114             logger.error("getConfigInterface() exception:", e);
   1115             imsConfig = null;
   1116         }
   1117 
   1118         if (null != imsConfig) {
   1119             try {
   1120                 isVoLTEProvisioned = imsConfig.getProvisionedValue(
   1121                         ImsConfig.ConfigConstants.VLT_SETTING_ENABLED)
   1122                         == ImsConfig.FeatureValueConstants.ON;
   1123                 isLvcProvisioned = imsConfig.getProvisionedValue(
   1124                         ImsConfig.ConfigConstants.LVC_SETTING_ENABLED)
   1125                         == ImsConfig.FeatureValueConstants.ON;
   1126                 isEabProvisioned = imsConfig.getProvisionedValue(
   1127                         ImsConfig.ConfigConstants.EAB_SETTING_ENABLED)
   1128                         == ImsConfig.FeatureValueConstants.ON;
   1129             } catch (ImsException e) {
   1130                 logger.error("ImsException in isRcsProvisioned() : ", e);
   1131             }
   1132         } else {
   1133             logger.debug("isRcsProvisioned - imsConfig is null");
   1134         }
   1135         logger.debug("isVoLTEProvisioned : " + isVoLTEProvisioned + " isLvcProvisioned : " +
   1136                 isLvcProvisioned
   1137                 + " isEabProvisioned : " + isEabProvisioned);
   1138         return (isVoLTEProvisioned && isLvcProvisioned && isEabProvisioned);
   1139     }
   1140 }
   1141