1dea198bb041754745c3b1522671fd31a79c7168cMarc Blank/*
2dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * Copyright (C) 2011 The Android Open Source Project
3dea198bb041754745c3b1522671fd31a79c7168cMarc Blank *
4dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * Licensed under the Apache License, Version 2.0 (the "License");
5dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * you may not use this file except in compliance with the License.
6dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * You may obtain a copy of the License at
7dea198bb041754745c3b1522671fd31a79c7168cMarc Blank *
8dea198bb041754745c3b1522671fd31a79c7168cMarc Blank *      http://www.apache.org/licenses/LICENSE-2.0
9dea198bb041754745c3b1522671fd31a79c7168cMarc Blank *
10dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * Unless required by applicable law or agreed to in writing, software
11dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * distributed under the License is distributed on an "AS IS" BASIS,
12dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * See the License for the specific language governing permissions and
14dea198bb041754745c3b1522671fd31a79c7168cMarc Blank * limitations under the License.
15dea198bb041754745c3b1522671fd31a79c7168cMarc Blank */
16dea198bb041754745c3b1522671fd31a79c7168cMarc Blank
17f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankpackage com.android.emailcommon.provider;
18f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
19f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.content.ContentProviderOperation;
20f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.content.ContentProviderResult;
21f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.content.ContentResolver;
22f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.content.ContentUris;
23f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.content.ContentValues;
24f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.content.Context;
25f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.content.OperationApplicationException;
26062f27fa370564d494260889c8141df50c07572fTony Mantlerimport android.database.ContentObserver;
27f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.database.Cursor;
280a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedyimport android.media.RingtoneManager;
29f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.net.Uri;
30f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.os.Parcel;
31f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.os.Parcelable;
32f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.os.RemoteException;
33f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
34f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport com.android.emailcommon.utility.Utility;
3582a207132b34377d532f19882f5bfc70bc657da0Tony Mantlerimport com.android.mail.utils.LogUtils;
369250f4787222f8bc3afe539a2f351fd8d9875fbaJames Lemieuximport com.google.common.annotations.VisibleForTesting;
3782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
3882a207132b34377d532f19882f5bfc70bc657da0Tony Mantlerimport org.json.JSONException;
3982a207132b34377d532f19882f5bfc70bc657da0Tony Mantlerimport org.json.JSONObject;
40f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
41f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport java.util.ArrayList;
42f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
433dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantlerpublic final class Account extends EmailContent implements Parcelable {
44f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String TABLE_NAME = "Account";
45f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
46f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Define all pseudo account IDs here to avoid conflict with one another.
47f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
48f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Pseudo account ID to represent a "combined account" that includes messages and mailboxes
49f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * from all defined accounts.
50f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
51f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * <em>IMPORTANT</em>: This must never be stored to the database.
52f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
53f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final long ACCOUNT_ID_COMBINED_VIEW = 0x1000000000000000L;
54f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
55f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Pseudo account ID to represent "no account". This may be used any time the account ID
56f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * may not be known or when we want to specifically select "no" account.
57f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
58f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * <em>IMPORTANT</em>: This must never be stored to the database.
59f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
60f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final long NO_ACCOUNT = -1L;
61f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
620a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    /**
630a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     * Whether or not the user has asked for notifications of new mail in this account
640a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     *
650a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     * @deprecated Used only for migration
660a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     */
670a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    @Deprecated
680a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    public final static int FLAGS_NOTIFY_NEW_MAIL = 1<<0;
690a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    /**
700a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     * Whether or not the user has asked for vibration notifications with all new mail
710a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     *
720a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     * @deprecated Used only for migration
730a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     */
740a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    @Deprecated
750a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    public final static int FLAGS_VIBRATE = 1<<1;
76f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Bit mask for the account's deletion policy (see DELETE_POLICY_x below)
77f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_DELETE_POLICY_MASK = 1<<2 | 1<<3;
78f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_DELETE_POLICY_SHIFT = 2;
79f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Whether the account is in the process of being created; any account reconciliation code
80f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // MUST ignore accounts with this bit set; in addition, ContentObservers for this data
81f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // SHOULD consider the state of this flag during operation
82f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_INCOMPLETE = 1<<4;
83f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Security hold is used when the device is not in compliance with security policies
84f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // required by the server; in this state, the user MUST be alerted to the need to update
85f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // security settings.  Sync adapters SHOULD NOT attempt to sync when this flag is set.
86f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_SECURITY_HOLD = 1<<5;
87f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Whether the account supports "smart forward" (i.e. the server appends the original
88f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // message along with any attachments to the outgoing message)
89f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_SUPPORTS_SMART_FORWARD = 1<<7;
90f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Whether the account should try to cache attachments in the background
91f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_BACKGROUND_ATTACHMENTS = 1<<8;
92f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Available to sync adapter
93f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_SYNC_ADAPTER = 1<<9;
94f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Sync disabled is a status commanded by the server; the sync adapter SHOULD NOT try to
95f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // sync mailboxes in this account automatically.  A manual sync request to sync a mailbox
96f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // with sync disabled SHOULD try to sync and report any failure result via the UI.
97f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_SYNC_DISABLED = 1<<10;
98e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    // Whether or not server-side search is supported by this account
99e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    public static final int FLAGS_SUPPORTS_SEARCH = 1<<11;
100e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    // Whether or not server-side search supports global search (i.e. all mailboxes); only valid
101e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    // if FLAGS_SUPPORTS_SEARCH is true
102e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    public static final int FLAGS_SUPPORTS_GLOBAL_SEARCH = 1<<12;
10326164054710375519ba7468987971a7a3340ba7eMarc Blank    // Whether or not the initial folder list has been loaded
10426164054710375519ba7468987971a7a3340ba7eMarc Blank    public static final int FLAGS_INITIAL_FOLDER_LIST_LOADED = 1<<13;
105f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
106f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Deletion policy (see FLAGS_DELETE_POLICY_MASK, above)
107f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int DELETE_POLICY_NEVER = 0;
108f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int DELETE_POLICY_7DAYS = 1<<0;        // not supported
109f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int DELETE_POLICY_ON_DELETE = 1<<1;
110f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
111f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Sentinel values for the mSyncInterval field of both Account records
112f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CHECK_INTERVAL_NEVER = -1;
113f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CHECK_INTERVAL_PUSH = -2;
114f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
115e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank    public static Uri CONTENT_URI;
116e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank    public static Uri RESET_NEW_MESSAGE_COUNT_URI;
117e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank    public static Uri NOTIFIER_URI;
118e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank
119e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank    public static void initAccount() {
120e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank        CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/account");
121e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank        RESET_NEW_MESSAGE_COUNT_URI = Uri.parse(EmailContent.CONTENT_URI + "/resetNewMessageCount");
122e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank        NOTIFIER_URI = Uri.parse(EmailContent.CONTENT_NOTIFIER_URI + "/account");
123e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank    }
12426164054710375519ba7468987971a7a3340ba7eMarc Blank
125f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mDisplayName;
126f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mEmailAddress;
127f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSyncKey;
128f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int mSyncLookback;
129f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int mSyncInterval;
130f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public long mHostAuthKeyRecv;
131f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public long mHostAuthKeySend;
132f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int mFlags;
133f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSenderName;
1340a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    /** @deprecated Used only for migration */
1350a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    @Deprecated
1360a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    private String mRingtoneUri;
137f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mProtocolVersion;
138f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSecuritySyncKey;
139f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSignature;
140f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public long mPolicyKey;
14152135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon    public long mPingDuration;
142f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
1439250f4787222f8bc3afe539a2f351fd8d9875fbaJames Lemieux    @VisibleForTesting
1449250f4787222f8bc3afe539a2f351fd8d9875fbaJames Lemieux    static final String JSON_TAG_HOST_AUTH_RECV = "hostAuthRecv";
1459250f4787222f8bc3afe539a2f351fd8d9875fbaJames Lemieux    @VisibleForTesting
1469250f4787222f8bc3afe539a2f351fd8d9875fbaJames Lemieux    static final String JSON_TAG_HOST_AUTH_SEND = "hostAuthSend";
14782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
148f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Convenience for creating/working with an account
149f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public transient HostAuth mHostAuthRecv;
150f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public transient HostAuth mHostAuthSend;
151f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public transient Policy mPolicy;
152f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
153994c282d804a635f783681ae314a6b4b244b476eTony Mantler    // Marks this account as being a temporary entry, so we know to use it directly and not go
154994c282d804a635f783681ae314a6b4b244b476eTony Mantler    // through the database or any caches
155994c282d804a635f783681ae314a6b4b244b476eTony Mantler    private transient boolean mTemporary;
156994c282d804a635f783681ae314a6b4b244b476eTony Mantler
157f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_ID_COLUMN = 0;
158f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_DISPLAY_NAME_COLUMN = 1;
159f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_EMAIL_ADDRESS_COLUMN = 2;
160f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SYNC_KEY_COLUMN = 3;
161f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SYNC_LOOKBACK_COLUMN = 4;
162f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SYNC_INTERVAL_COLUMN = 5;
163f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_HOST_AUTH_KEY_RECV_COLUMN = 6;
164f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_HOST_AUTH_KEY_SEND_COLUMN = 7;
165f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_FLAGS_COLUMN = 8;
1668518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_SENDER_NAME_COLUMN = 9;
1678518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_RINGTONE_URI_COLUMN = 10;
1688518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_PROTOCOL_VERSION_COLUMN = 11;
1698518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_SECURITY_SYNC_KEY_COLUMN = 12;
1708518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_SIGNATURE_COLUMN = 13;
1718518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_POLICY_KEY_COLUMN = 14;
1728518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_PING_DURATION_COLUMN = 15;
1738518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler    public static final int CONTENT_MAX_ATTACHMENT_SIZE_COLUMN = 16;
174f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
1753dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler    public static final String[] CONTENT_PROJECTION = {
1763dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler        AttachmentColumns._ID, AccountColumns.DISPLAY_NAME,
177f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.EMAIL_ADDRESS, AccountColumns.SYNC_KEY, AccountColumns.SYNC_LOOKBACK,
178f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.SYNC_INTERVAL, AccountColumns.HOST_AUTH_KEY_RECV,
179229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy        AccountColumns.HOST_AUTH_KEY_SEND, AccountColumns.FLAGS,
1802f97a7c658eb76ab9f388da8e73c1393b88d0defTony Mantler        AccountColumns.SENDER_NAME,
1810a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy        AccountColumns.RINGTONE_URI, AccountColumns.PROTOCOL_VERSION,
1828518665a04b0da5a6abbf06b2763f71ca78a979fTony Mantler        AccountColumns.SECURITY_SYNC_KEY,
183eba80c114e87346aeb64bbff91ef11b0ba566fd6Anthony Lee        AccountColumns.SIGNATURE, AccountColumns.POLICY_KEY, AccountColumns.PING_DURATION,
184eba80c114e87346aeb64bbff91ef11b0ba566fd6Anthony Lee        AccountColumns.MAX_ATTACHMENT_SIZE
185f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    };
186f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
187f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int ACCOUNT_FLAGS_COLUMN_ID = 0;
188f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int ACCOUNT_FLAGS_COLUMN_FLAGS = 1;
1893dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler    public static final String[] ACCOUNT_FLAGS_PROJECTION = {
1903dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler            AccountColumns._ID, AccountColumns.FLAGS};
191f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
192f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String SECURITY_NONZERO_SELECTION =
1933dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler        AccountColumns.POLICY_KEY + " IS NOT NULL AND " + AccountColumns.POLICY_KEY + "!=0";
194f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
195f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    private static final String FIND_INBOX_SELECTION =
196f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            MailboxColumns.TYPE + " = " + Mailbox.TYPE_INBOX +
197f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            " AND " + MailboxColumns.ACCOUNT_KEY + " =?";
198f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
199f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public Account() {
200f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mBaseUri = CONTENT_URI;
201f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
202f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // other defaults (policy)
2030a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy        mRingtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION).toString();
204f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = -1;
205f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = -1;
206b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy        mFlags = 0;
207f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
208f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
209f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static Account restoreAccountWithId(Context context, long id) {
210062f27fa370564d494260889c8141df50c07572fTony Mantler        return restoreAccountWithId(context, id, null);
211062f27fa370564d494260889c8141df50c07572fTony Mantler    }
212062f27fa370564d494260889c8141df50c07572fTony Mantler
213062f27fa370564d494260889c8141df50c07572fTony Mantler    public static Account restoreAccountWithId(Context context, long id, ContentObserver observer) {
214f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return EmailContent.restoreContentWithId(context, Account.class,
215062f27fa370564d494260889c8141df50c07572fTony Mantler                Account.CONTENT_URI, Account.CONTENT_PROJECTION, id, observer);
216f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
217f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
21806415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler    public static Account restoreAccountWithAddress(Context context, String emailAddress) {
21906415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler        return restoreAccountWithAddress(context, emailAddress, null);
22006415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler    }
22106415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler
22206415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler    public static Account restoreAccountWithAddress(Context context, String emailAddress,
22306415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler            ContentObserver observer) {
22406415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler        final Cursor c = context.getContentResolver().query(CONTENT_URI,
22506415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler                new String[] {AccountColumns._ID},
22606415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler                AccountColumns.EMAIL_ADDRESS + "=?", new String[] {emailAddress},
22706415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler                null);
228123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon        try {
229123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon            if (c == null || !c.moveToFirst()) {
230123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon                return null;
231123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon            }
232123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon            final long id = c.getLong(c.getColumnIndex(AccountColumns._ID));
233123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon            return restoreAccountWithId(context, id, observer);
234123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon        } finally {
235123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon            if (c != null) {
236123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon                c.close();
237123d40283e1411dcb5fa5def656ad352c101e5d0Martin Hibdon            }
23806415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler        }
23906415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler    }
24006415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler
2410f8d16f56ad3aa1c2d3cd20b1ca0c24b486035caTony Mantler    @Override
2420f8d16f56ad3aa1c2d3cd20b1ca0c24b486035caTony Mantler    protected Uri getContentNotificationUri() {
2430f8d16f56ad3aa1c2d3cd20b1ca0c24b486035caTony Mantler        return Account.CONTENT_URI;
2440f8d16f56ad3aa1c2d3cd20b1ca0c24b486035caTony Mantler    }
2450f8d16f56ad3aa1c2d3cd20b1ca0c24b486035caTony Mantler
246f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
247f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Refresh an account that has already been loaded.  This is slightly less expensive
248f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * that generating a brand-new account object.
249f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
250f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void refresh(Context context) {
251f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        Cursor c = context.getContentResolver().query(getUri(), Account.CONTENT_PROJECTION,
252f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                null, null, null);
253f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        try {
254f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            c.moveToFirst();
255f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            restore(c);
256f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } finally {
257f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (c != null) {
258f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                c.close();
259f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
260f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
261f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
262f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
263f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
264f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void restore(Cursor cursor) {
265f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mId = cursor.getLong(CONTENT_ID_COLUMN);
266f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mBaseUri = CONTENT_URI;
267f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mDisplayName = cursor.getString(CONTENT_DISPLAY_NAME_COLUMN);
268f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mEmailAddress = cursor.getString(CONTENT_EMAIL_ADDRESS_COLUMN);
269f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncKey = cursor.getString(CONTENT_SYNC_KEY_COLUMN);
270f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = cursor.getInt(CONTENT_SYNC_LOOKBACK_COLUMN);
271f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = cursor.getInt(CONTENT_SYNC_INTERVAL_COLUMN);
272f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeyRecv = cursor.getLong(CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
273f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeySend = cursor.getLong(CONTENT_HOST_AUTH_KEY_SEND_COLUMN);
274f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
275f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSenderName = cursor.getString(CONTENT_SENDER_NAME_COLUMN);
2760a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy        mRingtoneUri = cursor.getString(CONTENT_RINGTONE_URI_COLUMN);
277f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mProtocolVersion = cursor.getString(CONTENT_PROTOCOL_VERSION_COLUMN);
278f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSecuritySyncKey = cursor.getString(CONTENT_SECURITY_SYNC_KEY_COLUMN);
279f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSignature = cursor.getString(CONTENT_SIGNATURE_COLUMN);
28052135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon        mPolicyKey = cursor.getLong(CONTENT_POLICY_KEY_COLUMN);
28152135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon        mPingDuration = cursor.getLong(CONTENT_PING_DURATION_COLUMN);
282f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
283f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
284994c282d804a635f783681ae314a6b4b244b476eTony Mantler    public boolean isTemporary() {
285994c282d804a635f783681ae314a6b4b244b476eTony Mantler        return mTemporary;
286994c282d804a635f783681ae314a6b4b244b476eTony Mantler    }
287994c282d804a635f783681ae314a6b4b244b476eTony Mantler
288994c282d804a635f783681ae314a6b4b244b476eTony Mantler    public void setTemporary(boolean temporary) {
289994c282d804a635f783681ae314a6b4b244b476eTony Mantler        mTemporary = temporary;
290994c282d804a635f783681ae314a6b4b244b476eTony Mantler    }
291994c282d804a635f783681ae314a6b4b244b476eTony Mantler
2921b8e0fa23f6e9957f0b8753dd3f5b95d3f5d98eaScott Kennedy    private static long getId(Uri u) {
293f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return Long.parseLong(u.getPathSegments().get(1));
294f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
295f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
2966d24534804ddf54cd353ed46c4cbd6d23152f899Tony Mantler    public long getId() {
2976d24534804ddf54cd353ed46c4cbd6d23152f899Tony Mantler        return mId;
2986d24534804ddf54cd353ed46c4cbd6d23152f899Tony Mantler    }
2996d24534804ddf54cd353ed46c4cbd6d23152f899Tony Mantler
300f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
301c3404cca71b3451e0bf79afe2abca45522738873Régis Décamps     * Returns the user-visible name for the account, eg. "My work address"
302c3404cca71b3451e0bf79afe2abca45522738873Régis Décamps     * or "foo@exemple.com".
303c3404cca71b3451e0bf79afe2abca45522738873Régis Décamps     * @return the user-visible name for the account.
304f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
305f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getDisplayName() {
306f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mDisplayName;
307f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
308f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
309f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
310f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the description.  Be sure to call save() to commit to database.
311f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param description the new description
312f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
313f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setDisplayName(String description) {
314f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mDisplayName = description;
315f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
316f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
317f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
318f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the email address for this account
319f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
320f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getEmailAddress() {
321f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mEmailAddress;
322f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
323f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
324f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
325f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the Email address for this account.  Be sure to call save() to commit to database.
326f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param emailAddress the new email address for this account
327f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
328f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setEmailAddress(String emailAddress) {
329f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mEmailAddress = emailAddress;
330f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
331f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
332f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
333f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the sender's name for this account
334f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
335f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getSenderName() {
336f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSenderName;
337f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
338f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
339f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
340f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the sender's name.  Be sure to call save() to commit to database.
341f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param name the new sender name
342f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
343f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSenderName(String name) {
344f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSenderName = name;
345f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
346f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
347f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getSignature() {
348f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSignature;
349f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
350f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
35106415a635f5f01d8e1620b29f44d68dc4dfdf435Tony Mantler    @VisibleForTesting
352f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSignature(String signature) {
353f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSignature = signature;
354f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
355f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
356f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
357f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the minutes per check (for polling)
358f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "never", "push", etc.  See Account.java
359f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
360f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getSyncInterval() {
361f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSyncInterval;
362f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
363f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
364f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
365f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the minutes per check (for polling).  Be sure to call save() to commit to database.
366f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "never", "push", etc.  See Account.java
367f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param minutes the number of minutes between polling checks
368f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
369f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSyncInterval(int minutes) {
370f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = minutes;
371f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
372f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
373f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
374f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return One of the {@code Account.SYNC_WINDOW_*} constants that represents the sync
375f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *     lookback window.
376f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "all", "1 month", etc.  See Account.java
377f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
378f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getSyncLookback() {
379f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSyncLookback;
380f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
381f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
382f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
383f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the sync lookback window.  Be sure to call save() to commit to database.
384f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "all", "1 month", etc.  See Account.java
385025d29fd4b9dd8351fe2e0428a585cf327ddaca4Ben Komalo     * @param value One of the {@link com.android.emailcommon.service.SyncWindow} constants
386f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
387f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSyncLookback(int value) {
388f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = value;
389f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
390f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
391f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
39252135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon     * @return the current ping duration.
39352135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon     */
39452135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon    public long getPingDuration() {
39552135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon        return mPingDuration;
39652135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon    }
39752135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon
39852135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon    /**
39952135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon     * Set the ping duration.  Be sure to call save() to commit to database.
40052135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon     */
40152135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon    public void setPingDuration(long value) {
40252135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon        mPingDuration = value;
40352135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon    }
40452135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon
40552135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon    /**
406f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the flags for this account
407f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
408f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getFlags() {
409f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mFlags;
410f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
411f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
412f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
413f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the flags for this account
414f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param newFlags the new value for the flags
415f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
416f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setFlags(int newFlags) {
417f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags = newFlags;
418f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
419f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
420f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
4210a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     * @return the ringtone Uri for this account
4220a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     * @deprecated Used only for migration
4230a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy     */
4240a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    @Deprecated
4250a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    public String getRingtone() {
4260a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy        return mRingtoneUri;
4270a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    }
4280a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy
4290a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy    /**
430f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the "delete policy" as a simple 0,1,2 value set.
431f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param newPolicy the new delete policy
432f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
433f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setDeletePolicy(int newPolicy) {
434f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags &= ~FLAGS_DELETE_POLICY_MASK;
435f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags |= (newPolicy << FLAGS_DELETE_POLICY_SHIFT) & FLAGS_DELETE_POLICY_MASK;
436f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
437f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
438f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
439f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the "delete policy" as a simple 0,1,2 value set.
440f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the current delete policy
441f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
442f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getDeletePolicy() {
443f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return (mFlags & FLAGS_DELETE_POLICY_MASK) >> FLAGS_DELETE_POLICY_SHIFT;
444f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
445f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
446f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public HostAuth getOrCreateHostAuthSend(Context context) {
447f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthSend == null) {
448f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (mHostAuthKeySend != 0) {
449f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthSend = HostAuth.restoreHostAuthWithId(context, mHostAuthKeySend);
450f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            } else {
451f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthSend = new HostAuth();
452f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
453f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
454f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mHostAuthSend;
455f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
456f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
457f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public HostAuth getOrCreateHostAuthRecv(Context context) {
458f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv == null) {
459f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (mHostAuthKeyRecv != 0) {
460f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthRecv = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
461f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            } else {
462f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthRecv = new HostAuth();
463f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
464f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
465f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mHostAuthRecv;
466f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
467f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
468f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
469229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy     * Return the id of the default account. If one hasn't been explicitly specified, return the
470229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy     * first one in the database. If no account exists, returns {@link #NO_ACCOUNT}.
471229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy     *
472f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
473229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy     * @param lastUsedAccountId the last used account id, which is the basis of the default account
474f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
475229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy    public static long getDefaultAccountId(final Context context, final long lastUsedAccountId) {
476229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy        final Cursor cursor = context.getContentResolver().query(
477229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                CONTENT_URI, ID_PROJECTION, null, null, null);
478229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy
479229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy        long firstAccount = NO_ACCOUNT;
480229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy
4816e418aa41a17136be0dddb816d843428a0a1e722Marc Blank        try {
482229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy            if (cursor != null && cursor.moveToFirst()) {
483229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                do {
484229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                    final long accountId = cursor.getLong(Account.ID_PROJECTION_COLUMN);
485229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy
486229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                    if (accountId == lastUsedAccountId) {
487229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                        return accountId;
488229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                    }
489229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy
490229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                    if (firstAccount == NO_ACCOUNT) {
491229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                        firstAccount = accountId;
492229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                    }
493229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                } while (cursor.moveToNext());
4946e418aa41a17136be0dddb816d843428a0a1e722Marc Blank            }
4956e418aa41a17136be0dddb816d843428a0a1e722Marc Blank        } finally {
496229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy            if (cursor != null) {
497229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy                cursor.close();
498156163cceb5f56bb53e88e68d4e79bd5c076797fPaul Westbrook            }
499f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
500229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy
501229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy        return firstAccount;
502f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
503f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
504f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
505f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Given an account id, return the account's protocol
506f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
507f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param accountId the id of the account to be examined
508f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account's protocol (or null if the Account or HostAuth do not exist)
509f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
510f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static String getProtocol(Context context, long accountId) {
511f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        Account account = Account.restoreAccountWithId(context, accountId);
512f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (account != null) {
513f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return account.getProtocol(context);
514f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank         }
515f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
516f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
517f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
518f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
519f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the account's protocol
520f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
521f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account's protocol (or null if the HostAuth doesn't not exist)
522f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
523f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getProtocol(Context context) {
524062f27fa370564d494260889c8141df50c07572fTony Mantler        HostAuth hostAuth = getOrCreateHostAuthRecv(context);
525f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (hostAuth != null) {
526f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return hostAuth.mProtocol;
527f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
528f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
529f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
530f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
531f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
532840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler     * Return a corresponding account manager object using the passed in type
533840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler     *
534840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler     * @param type We can't look up the account type from here, so pass it in
535840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler     * @return system account object
536840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler     */
537840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler    public android.accounts.Account getAccountManagerAccount(String type) {
538840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler        return new android.accounts.Account(mEmailAddress, type);
539840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler    }
540840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler
541840408c41cfc95ffa491aaf11f1c3f4075eae9c9Tony Mantler    /**
542f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the account ID for a message with a given id
543f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
544f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
545f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param messageId the id of the message
546f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account ID, or -1 if the account doesn't exist
547f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
548f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static long getAccountIdForMessageId(Context context, long messageId) {
549f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return Message.getKeyColumnLong(context, messageId, MessageColumns.ACCOUNT_KEY);
550f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
551f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
552f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
553f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the account for a message with a given id
554f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
555f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param messageId the id of the message
556f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account, or null if the account doesn't exist
557f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
558f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static Account getAccountForMessageId(Context context, long messageId) {
559f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        long accountId = getAccountIdForMessageId(context, messageId);
560f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (accountId != -1) {
561f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return Account.restoreAccountWithId(context, accountId);
562f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
563f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
564f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
565f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
566f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
567f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return true if an {@code accountId} is assigned to any existing account.
568f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
569f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static boolean isValidId(Context context, long accountId) {
570f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null != Utility.getFirstRowLong(context, CONTENT_URI, ID_PROJECTION,
571f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ID_SELECTION, new String[] {Long.toString(accountId)}, null,
572f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ID_PROJECTION_COLUMN);
573f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
574f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
575f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
576f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Check a single account for security hold status.
577f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
578f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static boolean isSecurityHold(Context context, long accountId) {
579f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return (Utility.getFirstRowLong(context,
580f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ContentUris.withAppendedId(Account.CONTENT_URI, accountId),
581f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ACCOUNT_FLAGS_PROJECTION, null, null, null, ACCOUNT_FLAGS_COLUMN_FLAGS, 0L)
582f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                & Account.FLAGS_SECURITY_HOLD) != 0;
583f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
584f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
585f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
586f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return id of the "inbox" mailbox, or -1 if not found.
587f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
588f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static long getInboxId(Context context, long accountId) {
589f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return Utility.getFirstRowLong(context, Mailbox.CONTENT_URI, ID_PROJECTION,
590f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                FIND_INBOX_SELECTION, new String[] {Long.toString(accountId)}, null,
591f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ID_PROJECTION_COLUMN, -1L);
592f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
593f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
594f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
595f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Clear all account hold flags that are set.
596f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
597f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * (This will trigger watchers, and in particular will cause EAS to try and resync the
598f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * account(s).)
599f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
600f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static void clearSecurityHoldOnAllAccounts(Context context) {
601f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentResolver resolver = context.getContentResolver();
602f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        Cursor c = resolver.query(Account.CONTENT_URI, ACCOUNT_FLAGS_PROJECTION,
603f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                SECURITY_NONZERO_SELECTION, null, null);
604f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        try {
605f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            while (c.moveToNext()) {
606f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                int flags = c.getInt(ACCOUNT_FLAGS_COLUMN_FLAGS);
607f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
608f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                if (0 != (flags & FLAGS_SECURITY_HOLD)) {
609f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    ContentValues cv = new ContentValues();
610f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    cv.put(AccountColumns.FLAGS, flags & ~FLAGS_SECURITY_HOLD);
611f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    long accountId = c.getLong(ACCOUNT_FLAGS_COLUMN_ID);
612f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
613f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    resolver.update(uri, cv, null, null);
614f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                }
615f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
616f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } finally {
617f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            c.close();
618f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
619f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
620f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
621f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /*
622f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Override this so that we can store the HostAuth's first and link them to the Account
623f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * (non-Javadoc)
624f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see com.android.email.provider.EmailContent#save(android.content.Context)
625f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
626f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
627f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public Uri save(Context context) {
628f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (isSaved()) {
629f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            throw new UnsupportedOperationException();
630f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
631f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // This logic is in place so I can (a) short circuit the expensive stuff when
632f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // possible, and (b) override (and throw) if anyone tries to call save() or update()
633f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // directly for Account, which are unsupported.
634229c070b0b177793032ce9249cb77f6ca98e5aa4Scott Kennedy        if (mHostAuthRecv == null && mHostAuthSend == null && mPolicy != null) {
635f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return super.save(context);
636f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
637f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
638f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        int index = 0;
639f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        int recvIndex = -1;
6400b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon        int recvCredentialsIndex = -1;
641f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        int sendIndex = -1;
6420b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon        int sendCredentialsIndex = -1;
643f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
6440b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon        // Create operations for saving the send and recv hostAuths, and their credentials.
645f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Also, remember which operation in the array they represent
646f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
647f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv != null) {
648e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon            if (mHostAuthRecv.mCredential != null) {
649e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                recvCredentialsIndex = index++;
650e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mCredential.mBaseUri)
651e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                        .withValues(mHostAuthRecv.mCredential.toContentValues())
652e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                    .build());
653e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon            }
654f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            recvIndex = index++;
6550b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            final ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(
6560b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon                    mHostAuthRecv.mBaseUri);
6570b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            b.withValues(mHostAuthRecv.toContentValues());
6580b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            if (recvCredentialsIndex >= 0) {
6590b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon                final ContentValues cv = new ContentValues();
6603dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler                cv.put(HostAuthColumns.CREDENTIAL_KEY, recvCredentialsIndex);
6610b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon                b.withValueBackReferences(cv);
6620b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            }
6630b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            ops.add(b.build());
664f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
665f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthSend != null) {
666e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon            if (mHostAuthSend.mCredential != null) {
667e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                if (mHostAuthRecv.mCredential != null &&
668e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                        mHostAuthRecv.mCredential.equals(mHostAuthSend.mCredential)) {
6690b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon                    // These two credentials are identical, use the same row.
670e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                    sendCredentialsIndex = recvCredentialsIndex;
671e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                } else {
672e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                    sendCredentialsIndex = index++;
673e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                    ops.add(ContentProviderOperation.newInsert(mHostAuthSend.mCredential.mBaseUri)
674e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                            .withValues(mHostAuthSend.mCredential.toContentValues())
675e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                            .build());
676e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon                }
677e8eb6e659b5914eb7deab451c583e906010d0457Martin Hibdon            }
678f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            sendIndex = index++;
6790b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            final ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(
6800b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon                    mHostAuthSend.mBaseUri);
6810b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            b.withValues(mHostAuthSend.toContentValues());
6820b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            if (sendCredentialsIndex >= 0) {
6830b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon                final ContentValues cv = new ContentValues();
6843dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler                cv.put(HostAuthColumns.CREDENTIAL_KEY, sendCredentialsIndex);
6850b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon                b.withValueBackReferences(cv);
6860b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            }
6870b25179dab10dc7dfb91210cabfe637f3067d777Martin Hibdon            ops.add(b.build());
688f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
689f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
690f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Now do the Account
691f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentValues cv = null;
692f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        if (recvIndex >= 0 || sendIndex >= 0) {
693f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            cv = new ContentValues();
694f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (recvIndex >= 0) {
6953dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler                cv.put(AccountColumns.HOST_AUTH_KEY_RECV, recvIndex);
696f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
697f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (sendIndex >= 0) {
6983dd85723a1af5537e23e4b05bdc361cce9cd42beTony Mantler                cv.put(AccountColumns.HOST_AUTH_KEY_SEND, sendIndex);
699f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
700f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
701f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
702f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(mBaseUri);
703f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        b.withValues(toContentValues());
704f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (cv != null) {
705f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            b.withValueBackReferences(cv);
706f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
707f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ops.add(b.build());
708f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
709f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        try {
710f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ContentProviderResult[] results =
711e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank                context.getContentResolver().applyBatch(EmailContent.AUTHORITY, ops);
712f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // If saving, set the mId's of the various saved objects
713f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (recvIndex >= 0) {
714f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                long newId = getId(results[recvIndex].uri);
715f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthKeyRecv = newId;
716f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthRecv.mId = newId;
717f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
718f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (sendIndex >= 0) {
719f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                long newId = getId(results[sendIndex].uri);
720f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthKeySend = newId;
721f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthSend.mId = newId;
722f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
723f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            Uri u = results[index].uri;
724f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mId = getId(u);
725f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return u;
726f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } catch (RemoteException e) {
727f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // There is nothing to be done here; fail by returning null
728f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } catch (OperationApplicationException e) {
729f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // There is nothing to be done here; fail by returning null
730f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
731f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
732f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
733f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
734f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
735f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public ContentValues toContentValues() {
736f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentValues values = new ContentValues();
737f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.DISPLAY_NAME, mDisplayName);
738f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.EMAIL_ADDRESS, mEmailAddress);
739f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SYNC_KEY, mSyncKey);
740f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SYNC_LOOKBACK, mSyncLookback);
741f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SYNC_INTERVAL, mSyncInterval);
742f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.HOST_AUTH_KEY_RECV, mHostAuthKeyRecv);
743f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.HOST_AUTH_KEY_SEND, mHostAuthKeySend);
744f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.FLAGS, mFlags);
745f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SENDER_NAME, mSenderName);
7460a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy        values.put(AccountColumns.RINGTONE_URI, mRingtoneUri);
747f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.PROTOCOL_VERSION, mProtocolVersion);
748f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SECURITY_SYNC_KEY, mSecuritySyncKey);
749f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SIGNATURE, mSignature);
750f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.POLICY_KEY, mPolicyKey);
75152135c6e8750f19084695cdda78ffe34719c4b6cMartin Hibdon        values.put(AccountColumns.PING_DURATION, mPingDuration);
752f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return values;
753f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
754f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
75582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    public String toJsonString(final Context context) {
75682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        ensureLoaded(context);
75782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        final JSONObject json = toJson();
75882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        if (json != null) {
75982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            return json.toString();
76082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        }
76182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        return null;
76282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    }
76382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
76482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    protected JSONObject toJson() {
76582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        try {
76682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            final JSONObject json = new JSONObject();
76782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.putOpt(AccountColumns.DISPLAY_NAME, mDisplayName);
76882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.put(AccountColumns.EMAIL_ADDRESS, mEmailAddress);
76982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.put(AccountColumns.SYNC_LOOKBACK, mSyncLookback);
77082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.put(AccountColumns.SYNC_INTERVAL, mSyncInterval);
77182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            final JSONObject recvJson = mHostAuthRecv.toJson();
77282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.put(JSON_TAG_HOST_AUTH_RECV, recvJson);
77382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            if (mHostAuthSend != null) {
77482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler                final JSONObject sendJson = mHostAuthSend.toJson();
77582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler                json.put(JSON_TAG_HOST_AUTH_SEND, sendJson);
77682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            }
77782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.put(AccountColumns.FLAGS, mFlags);
77882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.putOpt(AccountColumns.SENDER_NAME, mSenderName);
77982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.putOpt(AccountColumns.PROTOCOL_VERSION, mProtocolVersion);
78082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.putOpt(AccountColumns.SIGNATURE, mSignature);
78182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            json.put(AccountColumns.PING_DURATION, mPingDuration);
78282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            return json;
78382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        } catch (final JSONException e) {
78482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            LogUtils.d(LogUtils.TAG, e, "Exception while serializing Account");
78582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        }
78682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        return null;
78782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    }
78882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
78982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    public static Account fromJsonString(final String jsonString) {
79082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        try {
79182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            final JSONObject json = new JSONObject(jsonString);
79282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            return fromJson(json);
79382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        } catch (final JSONException e) {
79482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            LogUtils.d(LogUtils.TAG, e, "Could not parse json for account");
79582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        }
79682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        return null;
79782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    }
79882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
79982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    protected static Account fromJson(final JSONObject json) {
80082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        try {
80182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            final Account a = new Account();
80282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mDisplayName = json.optString(AccountColumns.DISPLAY_NAME);
80382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mEmailAddress = json.getString(AccountColumns.EMAIL_ADDRESS);
80482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            // SYNC_KEY is not stored
80582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mSyncLookback = json.getInt(AccountColumns.SYNC_LOOKBACK);
80682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mSyncInterval = json.getInt(AccountColumns.SYNC_INTERVAL);
80782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            final JSONObject recvJson = json.getJSONObject(JSON_TAG_HOST_AUTH_RECV);
80882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mHostAuthRecv = HostAuth.fromJson(recvJson);
80982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            final JSONObject sendJson = json.optJSONObject(JSON_TAG_HOST_AUTH_SEND);
81082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            if (sendJson != null) {
81182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler                a.mHostAuthSend = HostAuth.fromJson(sendJson);
81282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            }
81382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mFlags = json.getInt(AccountColumns.FLAGS);
81482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mSenderName = json.optString(AccountColumns.SENDER_NAME);
81582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mProtocolVersion = json.optString(AccountColumns.PROTOCOL_VERSION);
81682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            // SECURITY_SYNC_KEY is not stored
81782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mSignature = json.optString(AccountColumns.SIGNATURE);
81882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            // POLICY_KEY is not stored
81982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            a.mPingDuration = json.optInt(AccountColumns.PING_DURATION, 0);
82082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            return a;
82182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        } catch (final JSONException e) {
82282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            LogUtils.d(LogUtils.TAG, e, "Exception while deserializing Account");
82382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        }
82482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        return null;
82582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    }
82682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
82782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    /**
82882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler     * Ensure that all optionally-loaded fields are populated from the provider.
82982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler     * @param context for provider loads
83082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler     */
83182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    public void ensureLoaded(final Context context) {
83282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        if (mHostAuthKeyRecv == 0 && mHostAuthRecv == null) {
83382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            throw new IllegalStateException("Trying to load incomplete Account object");
83482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        }
83582a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        getOrCreateHostAuthRecv(context).ensureLoaded(context);
83682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
83782a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        if (mHostAuthKeySend != 0) {
83882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            getOrCreateHostAuthSend(context);
83982a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            if (mHostAuthSend != null) {
84082a207132b34377d532f19882f5bfc70bc657da0Tony Mantler                mHostAuthSend.ensureLoaded(context);
84182a207132b34377d532f19882f5bfc70bc657da0Tony Mantler            }
84282a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        }
84382a207132b34377d532f19882f5bfc70bc657da0Tony Mantler    }
84482a207132b34377d532f19882f5bfc70bc657da0Tony Mantler
845f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
846f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
847f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
848f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
849f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int describeContents() {
850f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return 0;
851f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
852f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
853f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
854f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
855f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
856f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final Parcelable.Creator<Account> CREATOR
857f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            = new Parcelable.Creator<Account>() {
858f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        @Override
859f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        public Account createFromParcel(Parcel in) {
860f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return new Account(in);
861f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
862f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
863f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        @Override
864f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        public Account[] newArray(int size) {
865f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return new Account[size];
866f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
867f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    };
868f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
869f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
870f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
871f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
872f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
873f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void writeToParcel(Parcel dest, int flags) {
874f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // mBaseUri is not parceled
875f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mId);
876f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mDisplayName);
877f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mEmailAddress);
878f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSyncKey);
879f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeInt(mSyncLookback);
880f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeInt(mSyncInterval);
881f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mHostAuthKeyRecv);
882f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mHostAuthKeySend);
883f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeInt(mFlags);
8842f97a7c658eb76ab9f388da8e73c1393b88d0defTony Mantler        dest.writeString("" /* mCompatibilityUuid */);
885f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSenderName);
8860a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy        dest.writeString(mRingtoneUri);
887f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mProtocolVersion);
88882a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        dest.writeInt(0 /* mNewMessageCount */);
889f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSecuritySyncKey);
890f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSignature);
891f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mPolicyKey);
892f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
893f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv != null) {
894f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)1);
895f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthRecv.writeToParcel(dest, flags);
896f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } else {
897f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)0);
898f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
899f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
900f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthSend != null) {
901f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)1);
902f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthSend.writeToParcel(dest, flags);
903f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } else {
904f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)0);
905f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
906f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
907f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
908f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
909f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
910f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
911f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public Account(Parcel in) {
912f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mBaseUri = Account.CONTENT_URI;
913f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mId = in.readLong();
914f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mDisplayName = in.readString();
915f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mEmailAddress = in.readString();
916f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncKey = in.readString();
917f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = in.readInt();
918f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = in.readInt();
919f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeyRecv = in.readLong();
920f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeySend = in.readLong();
921f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags = in.readInt();
9222f97a7c658eb76ab9f388da8e73c1393b88d0defTony Mantler        /* mCompatibilityUuid = */ in.readString();
923f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSenderName = in.readString();
9240a710bde6817354211525b0f3176a1e294d1cd79Scott Kennedy        mRingtoneUri = in.readString();
925f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mProtocolVersion = in.readString();
92682a207132b34377d532f19882f5bfc70bc657da0Tony Mantler        /* mNewMessageCount = */ in.readInt();
927f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSecuritySyncKey = in.readString();
928f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSignature = in.readString();
929f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mPolicyKey = in.readLong();
930f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
931f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthRecv = null;
932f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (in.readByte() == 1) {
933f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthRecv = new HostAuth(in);
934f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
935f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
936f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthSend = null;
937f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (in.readByte() == 1) {
938f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthSend = new HostAuth(in);
939f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
940f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
941f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
942f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
943f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * For debugger support only - DO NOT use for code.
944f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
945f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
946f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String toString() {
9472f97a7c658eb76ab9f388da8e73c1393b88d0defTony Mantler        StringBuilder sb = new StringBuilder("[");
948f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv != null && mHostAuthRecv.mProtocol != null) {
949f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            sb.append(mHostAuthRecv.mProtocol);
950f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            sb.append(':');
951f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
952f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mDisplayName != null)   sb.append(mDisplayName);
953f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        sb.append(':');
954f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mEmailAddress != null)  sb.append(mEmailAddress);
955f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        sb.append(':');
956f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mSenderName != null)    sb.append(mSenderName);
957f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        sb.append(']');
958f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return sb.toString();
959f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
96073101f3a7bc1e735199a7c2c18358e9db9af0bcaTony Mantler}
961