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