1package com.android.contacts.quickcontact;
2
3
4import android.content.Context;
5import android.content.Intent;
6import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
7
8import com.android.contacts.ContactSaveService;
9import com.android.contacts.group.GroupMetaData;
10import com.android.contacts.model.AccountTypeManager;
11import com.android.contacts.model.Contact;
12import com.android.contacts.model.RawContact;
13import com.android.contacts.model.RawContactDelta;
14import com.android.contacts.model.RawContactDeltaList;
15import com.android.contacts.model.RawContactModifier;
16import com.android.contacts.model.ValuesDelta;
17import com.android.contacts.model.account.AccountType;
18import com.android.contacts.model.dataitem.DataItem;
19import com.android.contacts.model.dataitem.DataKind;
20import com.android.contacts.model.dataitem.GroupMembershipDataItem;
21
22import com.google.common.collect.Iterables;
23
24import java.util.List;
25
26/**
27 * Utility class to support adding invisible contacts. Ie, contacts that don't belong to the
28 * default group.
29 */
30public class InvisibleContactUtil {
31
32    public static boolean isInvisibleAndAddable(Contact contactData, Context context) {
33        // Only local contacts
34        if (contactData == null || contactData.isDirectoryEntry()) return false;
35
36        // User profile cannot be added to contacts
37        if (contactData.isUserProfile()) return false;
38
39        // Only if exactly one raw contact
40        if (contactData.getRawContacts().size() != 1) return false;
41
42        // test if the default group is assigned
43        final List<GroupMetaData> groups = contactData.getGroupMetaData();
44
45        // For accounts without group support, groups is null
46        if (groups == null) return false;
47
48        // remember the default group id. no default group? bail out early
49        final long defaultGroupId = getDefaultGroupId(groups);
50        if (defaultGroupId == -1) return false;
51
52        final RawContact rawContact = (RawContact) contactData.getRawContacts().get(0);
53        final AccountType type = rawContact.getAccountType(context);
54        // Offline or non-writeable account? Nothing to fix
55        if (type == null || !type.areContactsWritable()) return false;
56
57        // Check whether the contact is in the default group
58        boolean isInDefaultGroup = false;
59        for (DataItem dataItem : Iterables.filter(
60                rawContact.getDataItems(), GroupMembershipDataItem.class)) {
61            GroupMembershipDataItem groupMembership = (GroupMembershipDataItem) dataItem;
62            final Long groupId = groupMembership.getGroupRowId();
63            if (groupId != null && groupId == defaultGroupId) {
64                isInDefaultGroup = true;
65                break;
66            }
67        }
68
69        return !isInDefaultGroup;
70    }
71
72    public static void addToDefaultGroup(Contact contactData, Context context) {
73        final RawContactDeltaList contactDeltaList = contactData.createRawContactDeltaList();
74        if (markAddToDefaultGroup(contactData, contactDeltaList, context)) {
75            // Fire off the intent. we don't need a callback, as the database listener
76            // should update the ui
77            final Intent intent = ContactSaveService.createSaveContactIntent(
78                    context,
79                    contactDeltaList, "", 0, false, QuickContactActivity.class,
80                    Intent.ACTION_VIEW, null, /* joinContactIdExtraKey =*/ null,
81                /* joinContactId =*/ null);
82            ContactSaveService.startService(context, intent);
83        }
84    }
85
86    public static boolean markAddToDefaultGroup(Contact contactData,
87            RawContactDeltaList rawContactDeltaList, Context context) {
88        final long defaultGroupId = getDefaultGroupId(contactData.getGroupMetaData());
89        // there should always be a default group (otherwise the button would be invisible),
90        // but let's be safe here
91        if (defaultGroupId == -1) return false;
92
93        // add the group membership to the current state
94        final RawContactDelta rawContactEntityDelta = rawContactDeltaList.get(0);
95
96        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
97                context);
98        final AccountType type = rawContactEntityDelta.getAccountType(accountTypes);
99        final DataKind groupMembershipKind = type.getKindForMimetype(
100                GroupMembership.CONTENT_ITEM_TYPE);
101        final ValuesDelta entry = RawContactModifier.insertChild(rawContactEntityDelta,
102                groupMembershipKind);
103        if (entry == null) return false;
104        entry.setGroupRowId(defaultGroupId);
105        return true;
106    }
107
108    /** return default group id or -1 if no group or several groups are marked as default */
109    private static long getDefaultGroupId(List<GroupMetaData> groups) {
110        long defaultGroupId = -1;
111        for (GroupMetaData group : groups) {
112            if (group.defaultGroup) {
113                // two default groups? return neither
114                if (defaultGroupId != -1) return -1;
115                defaultGroupId = group.groupId;
116            }
117        }
118        return defaultGroupId;
119    }
120}
121