1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.contacts.model.account;
18
19import android.content.ContentValues;
20import android.content.Context;
21import android.provider.ContactsContract.CommonDataKinds.Email;
22import android.provider.ContactsContract.CommonDataKinds.Event;
23import android.provider.ContactsContract.CommonDataKinds.Phone;
24import android.provider.ContactsContract.CommonDataKinds.Relation;
25import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
26
27import com.android.contacts.R;
28import com.android.contacts.model.dataitem.DataKind;
29import com.android.contacts.util.CommonDateUtils;
30import com.android.contactsbind.FeedbackHelper;
31
32import com.google.common.collect.Lists;
33
34import java.util.Locale;
35
36/**
37 * A writable account type that can be used to support samsung contacts. This may not perfectly
38 * match Samsung's latest intended account schema.
39 *
40 * This is only used to partially support Samsung accounts. The DataKind labels & fields are
41 * setup to support the values used by Samsung. But, not everything in the Samsung account type is
42 * supported. The Samsung account type includes a "Message Type" mimetype that we have no intention
43 * of showing inside the Contact editor. Similarly, we don't handle the "Ringtone" mimetype here
44 * since managing ringtones is handled in a different flow.
45 */
46public class SamsungAccountType extends BaseAccountType {
47    private static final String TAG = "KnownExternalAccount";
48    private static final String ACCOUNT_TYPE_SAMSUNG = "com.osp.app.signin";
49
50    public SamsungAccountType(Context context, String authenticatorPackageName, String type) {
51        this.accountType = type;
52        this.resourcePackageName = null;
53        this.syncAdapterPackageName = authenticatorPackageName;
54
55        try {
56            addDataKindStructuredName(context);
57            addDataKindName(context);
58            addDataKindPhoneticName(context);
59            addDataKindNickname(context);
60            addDataKindPhone(context);
61            addDataKindEmail(context);
62            addDataKindStructuredPostal(context);
63            addDataKindIm(context);
64            addDataKindOrganization(context);
65            addDataKindPhoto(context);
66            addDataKindNote(context);
67            addDataKindWebsite(context);
68            addDataKindGroupMembership(context);
69            addDataKindRelation(context);
70            addDataKindEvent(context);
71
72            mIsInitialized = true;
73        } catch (DefinitionException e) {
74            FeedbackHelper.sendFeedback(context, TAG, "Failed to build samsung account type", e);
75        }
76    }
77
78    /**
79     * Returns {@code TRUE} if this is samsung's account type and Samsung hasn't bothered to
80     * define a contacts.xml to provide a more accurate definition than ours.
81     */
82    public static boolean isSamsungAccountType(Context context, String type,
83            String packageName) {
84        return ACCOUNT_TYPE_SAMSUNG.equals(type)
85                && !ExternalAccountType.hasContactsXml(context, packageName);
86    }
87
88    @Override
89    protected DataKind addDataKindStructuredPostal(Context context) throws DefinitionException {
90        final DataKind kind = super.addDataKindStructuredPostal(context);
91
92        final boolean useJapaneseOrder =
93                Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage());
94        kind.typeColumn = StructuredPostal.TYPE;
95        kind.typeList = Lists.newArrayList();
96        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK).setSpecificMax(1));
97        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME).setSpecificMax(1));
98        kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER).setSpecificMax(1));
99
100        kind.fieldList = Lists.newArrayList();
101        if (useJapaneseOrder) {
102            kind.fieldList.add(new EditField(StructuredPostal.COUNTRY,
103                    R.string.postal_country, FLAGS_POSTAL).setOptional(true));
104            kind.fieldList.add(new EditField(StructuredPostal.POSTCODE,
105                    R.string.postal_postcode, FLAGS_POSTAL));
106            kind.fieldList.add(new EditField(StructuredPostal.REGION,
107                    R.string.postal_region, FLAGS_POSTAL));
108            kind.fieldList.add(new EditField(StructuredPostal.CITY,
109                    R.string.postal_city,FLAGS_POSTAL));
110            kind.fieldList.add(new EditField(StructuredPostal.STREET,
111                    R.string.postal_street, FLAGS_POSTAL));
112        } else {
113            kind.fieldList.add(new EditField(StructuredPostal.STREET,
114                    R.string.postal_street, FLAGS_POSTAL));
115            kind.fieldList.add(new EditField(StructuredPostal.CITY,
116                    R.string.postal_city,FLAGS_POSTAL));
117            kind.fieldList.add(new EditField(StructuredPostal.REGION,
118                    R.string.postal_region, FLAGS_POSTAL));
119            kind.fieldList.add(new EditField(StructuredPostal.POSTCODE,
120                    R.string.postal_postcode, FLAGS_POSTAL));
121            kind.fieldList.add(new EditField(StructuredPostal.COUNTRY,
122                    R.string.postal_country, FLAGS_POSTAL).setOptional(true));
123        }
124
125        return kind;
126    }
127
128    @Override
129    protected DataKind addDataKindPhone(Context context) throws DefinitionException {
130        final DataKind kind = super.addDataKindPhone(context);
131
132        kind.typeColumn = Phone.TYPE;
133        kind.typeList = Lists.newArrayList();
134        kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
135        kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
136        kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
137        kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN));
138        kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
139        kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
140        kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
141        kind.typeList.add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true));
142        kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));
143        kind.typeList.add(buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true)
144                .setCustomColumn(Phone.LABEL));
145
146        kind.fieldList = Lists.newArrayList();
147        kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
148
149        return kind;
150    }
151
152    @Override
153    protected DataKind addDataKindEmail(Context context) throws DefinitionException {
154        final DataKind kind = super.addDataKindEmail(context);
155
156        kind.typeColumn = Email.TYPE;
157        kind.typeList = Lists.newArrayList();
158        kind.typeList.add(buildEmailType(Email.TYPE_HOME));
159        kind.typeList.add(buildEmailType(Email.TYPE_WORK));
160        kind.typeList.add(buildEmailType(Email.TYPE_OTHER));
161        kind.typeList.add(buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(
162                Email.LABEL));
163
164        kind.fieldList = Lists.newArrayList();
165        kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL));
166
167        return kind;
168    }
169
170    private DataKind addDataKindRelation(Context context) throws DefinitionException {
171        DataKind kind = addKind(new DataKind(Relation.CONTENT_ITEM_TYPE,
172                R.string.relationLabelsGroup, 160, true));
173        kind.actionHeader = new RelationActionInflater();
174        kind.actionBody = new SimpleInflater(Relation.NAME);
175
176        kind.typeColumn = Relation.TYPE;
177        kind.typeList = Lists.newArrayList();
178        kind.typeList.add(buildRelationType(Relation.TYPE_ASSISTANT));
179        kind.typeList.add(buildRelationType(Relation.TYPE_BROTHER));
180        kind.typeList.add(buildRelationType(Relation.TYPE_CHILD));
181        kind.typeList.add(buildRelationType(Relation.TYPE_DOMESTIC_PARTNER));
182        kind.typeList.add(buildRelationType(Relation.TYPE_FATHER));
183        kind.typeList.add(buildRelationType(Relation.TYPE_FRIEND));
184        kind.typeList.add(buildRelationType(Relation.TYPE_MANAGER));
185        kind.typeList.add(buildRelationType(Relation.TYPE_MOTHER));
186        kind.typeList.add(buildRelationType(Relation.TYPE_PARENT));
187        kind.typeList.add(buildRelationType(Relation.TYPE_PARTNER));
188        kind.typeList.add(buildRelationType(Relation.TYPE_REFERRED_BY));
189        kind.typeList.add(buildRelationType(Relation.TYPE_RELATIVE));
190        kind.typeList.add(buildRelationType(Relation.TYPE_SISTER));
191        kind.typeList.add(buildRelationType(Relation.TYPE_SPOUSE));
192        kind.typeList.add(buildRelationType(Relation.TYPE_CUSTOM).setSecondary(true)
193                .setCustomColumn(Relation.LABEL));
194
195        kind.defaultValues = new ContentValues();
196        kind.defaultValues.put(Relation.TYPE, Relation.TYPE_SPOUSE);
197
198        kind.fieldList = Lists.newArrayList();
199        kind.fieldList.add(new EditField(Relation.DATA, R.string.relationLabelsGroup,
200                FLAGS_RELATION));
201
202        return kind;
203    }
204
205    private DataKind addDataKindEvent(Context context) throws DefinitionException {
206        DataKind kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE,
207                R.string.eventLabelsGroup, 150, true));
208        kind.actionHeader = new EventActionInflater();
209        kind.actionBody = new SimpleInflater(Event.START_DATE);
210
211        kind.typeColumn = Event.TYPE;
212        kind.typeList = Lists.newArrayList();
213        kind.dateFormatWithoutYear = CommonDateUtils.NO_YEAR_DATE_FORMAT;
214        kind.dateFormatWithYear = CommonDateUtils.FULL_DATE_FORMAT;
215        kind.typeList.add(buildEventType(Event.TYPE_BIRTHDAY, true).setSpecificMax(1));
216        kind.typeList.add(buildEventType(Event.TYPE_ANNIVERSARY, false));
217        kind.typeList.add(buildEventType(Event.TYPE_OTHER, false));
218        kind.typeList.add(buildEventType(Event.TYPE_CUSTOM, false).setSecondary(true)
219                .setCustomColumn(Event.LABEL));
220
221        kind.defaultValues = new ContentValues();
222        kind.defaultValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
223
224        kind.fieldList = Lists.newArrayList();
225        kind.fieldList.add(new EditField(Event.DATA, R.string.eventLabelsGroup, FLAGS_EVENT));
226
227        return kind;
228    }
229
230    @Override
231    public boolean isGroupMembershipEditable() {
232        return true;
233    }
234
235    @Override
236    public boolean areContactsWritable() {
237        return true;
238    }
239}
240