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