private static List<ContactListFilter> loadAccountFilters(Context context) {
    final ArrayList<ContactListFilter> result = Lists.newArrayList();
    final ArrayList<ContactListFilter> accountFilters = Lists.newArrayList();
    final AccountTypeManager accountTypes = AccountTypeManager.getInstance(context);
    List<AccountWithDataSet> accounts = accountTypes.getAccounts(false);
    for (AccountWithDataSet account : accounts) {
      AccountType accountType = accountTypes.getAccountType(account.type, account.dataSet);
      if (accountType.isExtension() && !account.hasData(context)) {
        // Hide extensions with no raw_contacts.
        continue;
      }
      Drawable icon = accountType != null ? accountType.getDisplayIcon(context) : null;
      accountFilters.add(
          ContactListFilter.createAccountFilter(account.type, account.name, account.dataSet, icon));
    }

    // Always show "All", even when there's no accounts.  (We may have local contacts)
    result.add(ContactListFilter.createFilterWithType(ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS));

    final int count = accountFilters.size();
    if (count >= 1) {
      // If we only have one account, don't show it as "account", instead show it as "all"
      if (count > 1) {
        result.addAll(accountFilters);
      }
      result.add(ContactListFilter.createFilterWithType(ContactListFilter.FILTER_TYPE_CUSTOM));
    }
    return result;
  }
 /**
  * Posts a message to the contributing sync adapters that have opted-in, notifying them that the
  * contact has just been loaded
  */
 private void postViewNotificationToSyncAdapter() {
   Context context = getContext();
   for (RawContact rawContact : mContact.getRawContacts()) {
     final long rawContactId = rawContact.getId();
     if (mNotifiedRawContactIds.contains(rawContactId)) {
       continue; // Already notified for this raw contact.
     }
     mNotifiedRawContactIds.add(rawContactId);
     final AccountType accountType = rawContact.getAccountType(context);
     final String serviceName = accountType.getViewContactNotifyServiceClassName();
     final String servicePackageName = accountType.getViewContactNotifyServicePackageName();
     if (!TextUtils.isEmpty(serviceName) && !TextUtils.isEmpty(servicePackageName)) {
       final Uri uri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
       final Intent intent = new Intent();
       intent.setClassName(servicePackageName, serviceName);
       intent.setAction(Intent.ACTION_VIEW);
       intent.setDataAndType(uri, RawContacts.CONTENT_ITEM_TYPE);
       try {
         context.startService(intent);
       } catch (Exception e) {
         Log.e(TAG, "Error sending message to source-app", e);
       }
     }
   }
 }
 private void bindHeaderView(GroupListItem entry, GroupListItemViewCache viewCache) {
   AccountType accountType =
       mAccountTypeManager.getAccountType(entry.getAccountType(), entry.getDataSet());
   viewCache.accountType.setText(accountType.getDisplayLabel(mContext));
   // According to the UI SPEC, we will not show the account name for Phone account
   if (!PhoneAccountType.ACCOUNT_TYPE.equals(entry.getAccountType())) {
     viewCache.accountName.setText(entry.getAccountName());
   }
 }
    @Override
    public AccountSet loadInBackground() {
      Context context = getContext();
      final AccountTypeManager accountTypes = AccountTypeManager.getInstance(context);
      final ContentResolver resolver = context.getContentResolver();

      final AccountSet accounts = new AccountSet();
      for (AccountWithDataSet account : accountTypes.getAccounts(false)) {
        final AccountType accountType = accountTypes.getAccountTypeForAccount(account);
        if (accountType.isExtension() && !account.hasData(context)) {
          // Extension with no data -- skip.
          continue;
        }

        AccountDisplay accountDisplay =
            new AccountDisplay(resolver, account.name, account.type, account.dataSet);

        final Uri.Builder groupsUri =
            Groups.CONTENT_URI
                .buildUpon()
                .appendQueryParameter(Groups.ACCOUNT_NAME, account.name)
                .appendQueryParameter(Groups.ACCOUNT_TYPE, account.type);
        if (account.dataSet != null) {
          groupsUri.appendQueryParameter(Groups.DATA_SET, account.dataSet).build();
        }
        final Cursor cursor = resolver.query(groupsUri.build(), null, null, null, null);
        if (cursor == null) {
          continue;
        }
        android.content.EntityIterator iterator = ContactsContract.Groups.newEntityIterator(cursor);
        try {
          boolean hasGroups = false;

          // Create entries for each known group
          while (iterator.hasNext()) {
            final ContentValues values = iterator.next().getEntityValues();
            final GroupDelta group = GroupDelta.fromBefore(values);
            accountDisplay.addGroup(group);
            hasGroups = true;
          }
          // Create single entry handling ungrouped status
          accountDisplay.mUngrouped =
              GroupDelta.fromSettings(
                  resolver, account.name, account.type, account.dataSet, hasGroups);
          accountDisplay.addGroup(accountDisplay.mUngrouped);
        } finally {
          iterator.close();
        }

        accounts.add(accountDisplay);
      }

      return accounts;
    }
    @Override
    public View getGroupView(
        int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
      if (convertView == null) {
        convertView = mInflater.inflate(R.layout.custom_contact_list_filter_account, parent, false);
      }

      final TextView text1 = (TextView) convertView.findViewById(android.R.id.text1);
      final TextView text2 = (TextView) convertView.findViewById(android.R.id.text2);

      final AccountDisplay account = (AccountDisplay) this.getGroup(groupPosition);

      final AccountType accountType = mAccountTypes.getAccountType(account.mType, account.mDataSet);

      text1.setText(account.mName);
      text1.setVisibility(account.mName == null ? View.GONE : View.VISIBLE);
      text2.setText(accountType.getDisplayLabel(mContext));

      return convertView;
    }
  @Override
  protected void setUp() throws Exception {
    super.setUp();
    mMockContext = new ContactsMockContext(getContext());
    mContactsProvider = mMockContext.getContactsProvider();

    InjectedServices services = new InjectedServices();
    AccountType accountType =
        new BaseAccountType() {
          @Override
          public boolean areContactsWritable() {
            return false;
          }
        };
    accountType.accountType = "mockAccountType";

    AccountWithDataSet account = new AccountWithDataSet("mockAccountName", "mockAccountType", null);

    AccountTypeManager.setInstanceForTest(
        new MockAccountTypeManager(
            new AccountType[] {accountType}, new AccountWithDataSet[] {account}));
  }
  /** Sets up the editor based on the group's account name and type. */
  private void setupEditorForAccount() {
    final AccountType accountType = getAccountType();
    final boolean editable = isGroupMembershipEditable();
    boolean isNewEditor = false;
    mMemberListAdapter.setIsGroupMembershipEditable(editable);

    // Since this method can be called multiple time, remove old editor if the editor type
    // is different from the new one and mark the editor with a tag so it can be found for
    // removal if needed
    View editorView;
    int newGroupEditorId =
        editable ? R.layout.group_editor_view : R.layout.external_group_editor_view;
    if (newGroupEditorId != mLastGroupEditorId) {
      View oldEditorView = mRootView.findViewWithTag(CURRENT_EDITOR_TAG);
      if (oldEditorView != null) {
        mRootView.removeView(oldEditorView);
      }
      editorView = mLayoutInflater.inflate(newGroupEditorId, mRootView, false);
      editorView.setTag(CURRENT_EDITOR_TAG);
      mAutoCompleteAdapter = null;
      mLastGroupEditorId = newGroupEditorId;
      isNewEditor = true;
    } else {
      editorView = mRootView.findViewWithTag(CURRENT_EDITOR_TAG);
      if (editorView == null) {
        throw new IllegalStateException("Group editor view not found");
      }
    }

    mGroupNameView = (TextView) editorView.findViewById(R.id.group_name);
    mAutoCompleteTextView = (AutoCompleteTextView) editorView.findViewById(R.id.add_member_field);

    mListView = (ListView) editorView.findViewById(android.R.id.list);
    mListView.setAdapter(mMemberListAdapter);

    // Setup the account header, only when exists.
    if (editorView.findViewById(R.id.account_header) != null) {
      CharSequence accountTypeDisplayLabel = accountType.getDisplayLabel(mContext);
      ImageView accountIcon = (ImageView) editorView.findViewById(R.id.account_icon);
      TextView accountTypeTextView = (TextView) editorView.findViewById(R.id.account_type);
      TextView accountNameTextView = (TextView) editorView.findViewById(R.id.account_name);
      if (!TextUtils.isEmpty(mAccountName)) {
        accountNameTextView.setText(mContext.getString(R.string.from_account_format, mAccountName));
      }
      accountTypeTextView.setText(accountTypeDisplayLabel);
      accountIcon.setImageDrawable(accountType.getDisplayIcon(mContext));
    }

    // Setup the autocomplete adapter (for contacts to suggest to add to the group) based on the
    // account name and type. For groups that cannot have membership edited, there will be no
    // autocomplete text view.
    if (mAutoCompleteTextView != null) {
      mAutoCompleteAdapter =
          new SuggestedMemberListAdapter(mContext, android.R.layout.simple_dropdown_item_1line);
      mAutoCompleteAdapter.setContentResolver(mContentResolver);
      mAutoCompleteAdapter.setAccountType(mAccountType);
      mAutoCompleteAdapter.setAccountName(mAccountName);
      mAutoCompleteAdapter.setDataSet(mDataSet);
      mAutoCompleteTextView.setAdapter(mAutoCompleteAdapter);
      mAutoCompleteTextView.setOnItemClickListener(
          new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
              SuggestedMember member = (SuggestedMember) view.getTag();
              if (member == null) {
                return; // just in case
              }
              loadMemberToAddToGroup(
                  member.getRawContactId(), String.valueOf(member.getContactId()));

              // Update the autocomplete adapter so the contact doesn't get suggested again
              mAutoCompleteAdapter.addNewMember(member.getContactId());

              // Clear out the text field
              mAutoCompleteTextView.setText("");
            }
          });
      // Update the exempt list.  (mListToDisplay might have been restored from the saved
      // state.)
      mAutoCompleteAdapter.updateExistingMembersList(mListToDisplay);
    }

    // If the group name is ready only, don't let the user focus on the field.
    mGroupNameView.setFocusable(!mGroupNameIsReadOnly);
    if (isNewEditor) {
      mRootView.addView(editorView);
    }
    mStatus = Status.EDITING;
  }