public void onAllContactListsLoaded() {
   mAllContactsLoaded = true;
   handleDelayedContactChanges();
   removeObsoleteContactsAndLists();
   final int N = mRemoteContactListeners.beginBroadcast();
   for (int i = 0; i < N; i++) {
     IContactListListener listener = mRemoteContactListeners.getBroadcastItem(i);
     try {
       listener.onAllContactListsLoaded();
     } catch (RemoteException e) {
       // The RemoteCallbackList will take care of removing the
       // dead listeners.
     }
   }
   mRemoteContactListeners.finishBroadcast();
 }
 public void onContactError(
     final int errorType,
     final ImErrorInfo error,
     final String listName,
     final Contact contact) {
   final int N = mRemoteContactListeners.beginBroadcast();
   for (int i = 0; i < N; i++) {
     IContactListListener listener = mRemoteContactListeners.getBroadcastItem(i);
     try {
       listener.onContactError(errorType, error, listName, contact);
     } catch (RemoteException e) {
       // The RemoteCallbackList will take care of removing the
       // dead listeners.
     }
   }
   mRemoteContactListeners.finishBroadcast();
 }
    public void onContactsPresenceUpdate(final Contact[] contacts) {
      // The client listens only to presence updates for now. Update
      // the avatars first to ensure it can get the new avatar when
      // presence updated.
      // TODO: Don't update avatar now since none of the server supports it
      // updateAvatarsContent(contacts);
      updatePresenceContent(contacts);

      final int N = mRemoteContactListeners.beginBroadcast();
      for (int i = 0; i < N; i++) {
        IContactListListener listener = mRemoteContactListeners.getBroadcastItem(i);
        try {
          listener.onContactsPresenceUpdate(contacts);
        } catch (RemoteException e) {
          // The RemoteCallbackList will take care of removing the
          // dead listeners.
        }
      }
      mRemoteContactListeners.finishBroadcast();
    }
    public void onContactChange(final int type, final ContactList list, final Contact contact) {
      ContactListAdapter removed = null;
      String notificationText = null;

      switch (type) {
        case LIST_LOADED:
        case LIST_CREATED:
          addContactListContent(list);
          break;

        case LIST_DELETED:
          removed = removeContactListFromDataBase(list.getName());
          // handle case where a list is deleted before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a cached contact list is deleted before the actual contact list is
            // downloaded from the server, we will have to remove the list again once
            // once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        case LIST_CONTACT_ADDED:
          long listId = getContactListAdapter(list.getAddress()).getDataBaseId();
          String contactAddress = contact.getAddress().getFullName();
          if (isTemporary(contactAddress)) {
            moveTemporaryContactToList(contactAddress, listId);
          } else {
            insertContactContent(contact, listId);
          }
          notificationText =
              mContext.getResources().getString(R.string.add_contact_success, contact.getName());
          // handle case where a contact is added before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact is added to a cached contact list before the actual contact
            // list is downloaded from the server, we will have to add the contact to
            // the contact list once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        case LIST_CONTACT_REMOVED:
          deleteContactFromDataBase(contact, list);
          // handle case where a contact is removed before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact is added to a cached contact list before the actual contact
            // list is downloaded from the server, we will have to add the contact to
            // the contact list once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }

          // Clear ChatSession if any.
          String address = contact.getAddress().getFullName();
          closeChatSession(address);

          notificationText =
              mContext.getResources().getString(R.string.delete_contact_success, contact.getName());
          break;

        case LIST_RENAMED:
          updateListNameInDataBase(list);
          // handle case where a list is renamed before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact list name is updated before the actual contact list is
            // downloaded from the server, we will have to update the list name again
            // once mAllContactsLoaded is true
            if (!mValidatedContactLists.contains(list.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        case CONTACT_BLOCKED:
          insertBlockedContactToDataBase(contact);
          address = contact.getAddress().getFullName();
          updateContactType(address, Imps.Contacts.TYPE_BLOCKED);
          closeChatSession(address);
          notificationText =
              mContext.getResources().getString(R.string.block_contact_success, contact.getName());
          break;

        case CONTACT_UNBLOCKED:
          removeBlockedContactFromDataBase(contact);
          notificationText =
              mContext
                  .getResources()
                  .getString(R.string.unblock_contact_success, contact.getName());
          // handle case where a contact is unblocked before mAllContactsLoaded
          if (!mAllContactsLoaded) {
            // if a contact list name is updated before the actual contact list is
            // downloaded from the server, we will have to update the list name again
            // once mAllContactsLoaded is true
            if (!mValidatedBlockedContacts.contains(contact.getName())) {
              mDelayedContactChanges.add(new StoredContactChange(type, list, contact));
            }
          }
          break;

        default:
          Log.e(TAG, "Unknown list update event!");
          break;
      }

      final ContactListAdapter listAdapter;
      if (type == LIST_DELETED) {
        listAdapter = removed;
      } else {
        listAdapter = (list == null) ? null : getContactListAdapter(list.getAddress());
      }
      final int N = mRemoteContactListeners.beginBroadcast();
      for (int i = 0; i < N; i++) {
        IContactListListener listener = mRemoteContactListeners.getBroadcastItem(i);
        try {
          listener.onContactChange(type, listAdapter, contact);
        } catch (RemoteException e) {
          // The RemoteCallbackList will take care of removing the
          // dead listeners.
        }
      }
      mRemoteContactListeners.finishBroadcast();

      if (mAllContactsLoaded && notificationText != null) {
        mContext.showToast(notificationText, Toast.LENGTH_SHORT);
      }
    }