• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EABService()88     public EABService() {
89         super();
90         logger.info("EAB Service constructed");
91     }
92 
93     @Override
onBind(Intent arg0)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 {
ContactChangedListener()157         public ContactChangedListener() {
158             super(null);
159         }
160 
161         @Override
deliverSelfNotifications()162         public boolean deliverSelfNotifications() {
163             return false;
164         }
165 
166         @Override
onChange(boolean selfChange)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 {
ContactProfileListener()175         public ContactProfileListener() {
176             super(null);
177         }
178 
179         @Override
deliverSelfNotifications()180         public boolean deliverSelfNotifications() {
181             return false;
182         }
183 
184         @Override
onChange(boolean selfChange)185         public void onChange(boolean selfChange) {
186             logger.debug("onChange for ContactProfileListener");
187             sendDelayedContactProfileMsg();
188         }
189     }
190 
191     @Override
onCreate()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
onDestroy()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 
initializeRcsInterfacer()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 
registerContentObservers()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 
unregisterContentObservers()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 
resetContentObservers()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 
startResetContentObserverAlarm()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 
cancelResetContentObserverAlarm()298     private void cancelResetContentObserverAlarm() {
299         ((AlarmManager) getSystemService(Context.ALARM_SERVICE)).cancel(
300                 mResetContentObserverListener);
301     }
302 
303     @Override
onStartCommand(Intent intent, int flags, int startId)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 {
ServiceHandler(Looper looper)320         public ServiceHandler(Looper looper) {
321             super(looper);
322         }
323 
324         @Override
handleMessage(Message msg)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.
validateAndSyncFromContactsDb()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.
validateAndSyncFromProfileDb()368     private synchronized void validateAndSyncFromProfileDb() {
369         logger.debug("Enter : validateAndSyncFromProfileDb()");
370         checkForProfileNumberChanges();
371         checkForDeletedProfileContacts();
372         logger.debug("Exit : validateAndSyncFromProfileDb()");
373     }
374 
ensureInitDone()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 
sendEABResetMessage()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 
sendDelayedContactChangeMsg()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 
sendDelayedContactProfileMsg()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 
checkForContactNumberChanges()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 
verifyInsertOrUpdateAction(Long dataId, Long contactId, Long rawContactId, String phoneNumber, String displayName)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 
checkForPhoneNumberDelete(ArrayList<Long> uniqueRawContactIds)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 
checkForDeletedContact()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 
checkForProfileNumberChanges()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 
checkForProfilePhoneNumberDelete(Long profileContactId, Long profileRawContactId, ArrayList<Long> profileDataIdList)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 
checkForDeletedProfileContacts()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 
handlePhoneNumberInsertion(Long dataId, Long contactId, Long rawContactId, String phoneNumber, String contactName)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 
handlePhoneNumberChanged(Long dataId, Long contactId, Long rawContactId, String oldPhoneNumber, String newPhoneNumber, String contactName)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 
handlePhoneNumbersDeleted(Long rawContactId, ArrayList <Long> contactDataIdList)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 
handlePhoneNameUpdate(Long dataId, Long contactId, Long rawContactId, String phoneNumber, String newDisplayName)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 
handleContactDeleted(Long contactId)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 
handleContactProfileDeleted()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 
isRcsProvisioned()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