1 package com.android.contacts.quickcontact;
2 
3 
4 import android.content.Context;
5 import android.content.Intent;
6 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
7 
8 import com.android.contacts.ContactSaveService;
9 import com.android.contacts.group.GroupMetaData;
10 import com.android.contacts.model.AccountTypeManager;
11 import com.android.contacts.model.Contact;
12 import com.android.contacts.model.RawContact;
13 import com.android.contacts.model.RawContactDelta;
14 import com.android.contacts.model.RawContactDeltaList;
15 import com.android.contacts.model.RawContactModifier;
16 import com.android.contacts.model.ValuesDelta;
17 import com.android.contacts.model.account.AccountType;
18 import com.android.contacts.model.dataitem.DataItem;
19 import com.android.contacts.model.dataitem.DataKind;
20 import com.android.contacts.model.dataitem.GroupMembershipDataItem;
21 
22 import com.google.common.collect.Iterables;
23 
24 import 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  */
30 public class InvisibleContactUtil {
31 
isInvisibleAndAddable(Contact contactData, Context context)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 
addToDefaultGroup(Contact contactData, Context context)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 
markAddToDefaultGroup(Contact contactData, RawContactDeltaList rawContactDeltaList, Context context)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 */
getDefaultGroupId(List<GroupMetaData> groups)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