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;
26f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport android.database.Cursor;
27dea198bb041754745c3b1522671fd31a79c7168cMarc Blankimport android.net.ConnectivityManager;
28dea198bb041754745c3b1522671fd31a79c7168cMarc Blankimport android.net.NetworkInfo;
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.provider.EmailContent.AccountColumns;
35f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport com.android.emailcommon.utility.Utility;
36f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
37f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport java.util.ArrayList;
38f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport java.util.List;
39f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport java.util.UUID;
40f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
41f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankpublic final class Account extends EmailContent implements AccountColumns, Parcelable {
42f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String TABLE_NAME = "Account";
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @SuppressWarnings("hiding")
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final Uri CONTENT_URI = Uri.parse(EmailContent.CONTENT_URI + "/account");
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final Uri ADD_TO_FIELD_URI =
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Uri.parse(EmailContent.CONTENT_URI + "/accountIdAddToField");
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final Uri RESET_NEW_MESSAGE_COUNT_URI =
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Uri.parse(EmailContent.CONTENT_URI + "/resetNewMessageCount");
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final Uri NOTIFIER_URI =
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Uri.parse(EmailContent.CONTENT_NOTIFIER_URI + "/account");
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final Uri DEFAULT_ACCOUNT_ID_URI =
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Uri.parse(EmailContent.CONTENT_URI + "/account/default");
53f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
54f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Define all pseudo account IDs here to avoid conflict with one another.
55f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
56f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Pseudo account ID to represent a "combined account" that includes messages and mailboxes
57f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * from all defined accounts.
58f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
59f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * <em>IMPORTANT</em>: This must never be stored to the database.
60f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
61f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final long ACCOUNT_ID_COMBINED_VIEW = 0x1000000000000000L;
62f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
63f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Pseudo account ID to represent "no account". This may be used any time the account ID
64f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * may not be known or when we want to specifically select "no" account.
65f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
66f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * <em>IMPORTANT</em>: This must never be stored to the database.
67f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
68f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final long NO_ACCOUNT = -1L;
69f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
70f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Whether or not the user has asked for notifications of new mail in this account
71f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public final static int FLAGS_NOTIFY_NEW_MAIL = 1<<0;
72f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Whether or not the user has asked for vibration notifications with all new mail
73f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public final static int FLAGS_VIBRATE_ALWAYS = 1<<1;
74f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Bit mask for the account's deletion policy (see DELETE_POLICY_x below)
75f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_DELETE_POLICY_MASK = 1<<2 | 1<<3;
76f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_DELETE_POLICY_SHIFT = 2;
77f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Whether the account is in the process of being created; any account reconciliation code
78f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // MUST ignore accounts with this bit set; in addition, ContentObservers for this data
79f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // SHOULD consider the state of this flag during operation
80f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_INCOMPLETE = 1<<4;
81f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Security hold is used when the device is not in compliance with security policies
82f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // required by the server; in this state, the user MUST be alerted to the need to update
83f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // security settings.  Sync adapters SHOULD NOT attempt to sync when this flag is set.
84f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_SECURITY_HOLD = 1<<5;
85f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Whether or not the user has asked for vibration notifications when the ringer is silent
86f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int FLAGS_VIBRATE_WHEN_SILENT = 1<<6;
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;
103f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
104f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Deletion policy (see FLAGS_DELETE_POLICY_MASK, above)
105f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int DELETE_POLICY_NEVER = 0;
106f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int DELETE_POLICY_7DAYS = 1<<0;        // not supported
107f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int DELETE_POLICY_ON_DELETE = 1<<1;
108f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
109f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Sentinel values for the mSyncInterval field of both Account records
110f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CHECK_INTERVAL_NEVER = -1;
111f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CHECK_INTERVAL_PUSH = -2;
112f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
113f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mDisplayName;
114f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mEmailAddress;
115f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSyncKey;
116f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int mSyncLookback;
117f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int mSyncInterval;
118f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public long mHostAuthKeyRecv;
119f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public long mHostAuthKeySend;
120f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int mFlags;
121f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public boolean mIsDefault;          // note: callers should use getDefaultAccountId()
122f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mCompatibilityUuid;
123f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSenderName;
124f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mRingtoneUri;
125f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mProtocolVersion;
126f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int mNewMessageCount;
127f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSecuritySyncKey;
128f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String mSignature;
129f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public long mPolicyKey;
130f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // For compatibility with Email1
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public long mNotifiedMessageId;
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int mNotifiedMessageCount;
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
135f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Convenience for creating/working with an account
136f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public transient HostAuth mHostAuthRecv;
137f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public transient HostAuth mHostAuthSend;
138f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public transient Policy mPolicy;
139f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    // Might hold the corresponding AccountManager account structure
140f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public transient android.accounts.Account mAmAccount;
141f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
142f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_ID_COLUMN = 0;
143f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_DISPLAY_NAME_COLUMN = 1;
144f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_EMAIL_ADDRESS_COLUMN = 2;
145f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SYNC_KEY_COLUMN = 3;
146f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SYNC_LOOKBACK_COLUMN = 4;
147f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SYNC_INTERVAL_COLUMN = 5;
148f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_HOST_AUTH_KEY_RECV_COLUMN = 6;
149f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_HOST_AUTH_KEY_SEND_COLUMN = 7;
150f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_FLAGS_COLUMN = 8;
151f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_IS_DEFAULT_COLUMN = 9;
152f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_COMPATIBILITY_UUID_COLUMN = 10;
153f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SENDER_NAME_COLUMN = 11;
154f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_RINGTONE_URI_COLUMN = 12;
155f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_PROTOCOL_VERSION_COLUMN = 13;
156f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_NEW_MESSAGE_COUNT_COLUMN = 14;
157f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SECURITY_SYNC_KEY_COLUMN = 15;
158f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_SIGNATURE_COLUMN = 16;
159f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_POLICY_KEY = 17;
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int CONTENT_NOTIFIED_MESSAGE_ID_COLUMN = 18;
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int CONTENT_NOTIFIED_MESSAGE_COUNT_COLUMN = 19;
162f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
163f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String[] CONTENT_PROJECTION = new String[] {
164f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        RECORD_ID, AccountColumns.DISPLAY_NAME,
165f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.EMAIL_ADDRESS, AccountColumns.SYNC_KEY, AccountColumns.SYNC_LOOKBACK,
166f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.SYNC_INTERVAL, AccountColumns.HOST_AUTH_KEY_RECV,
167f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.HOST_AUTH_KEY_SEND, AccountColumns.FLAGS, AccountColumns.IS_DEFAULT,
168f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.COMPATIBILITY_UUID, AccountColumns.SENDER_NAME,
169f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.RINGTONE_URI, AccountColumns.PROTOCOL_VERSION,
170f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        AccountColumns.NEW_MESSAGE_COUNT, AccountColumns.SECURITY_SYNC_KEY,
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        AccountColumns.SIGNATURE, AccountColumns.POLICY_KEY,
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        AccountColumns.NOTIFIED_MESSAGE_ID, AccountColumns.NOTIFIED_MESSAGE_COUNT
173f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    };
174f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
175f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int CONTENT_MAILBOX_TYPE_COLUMN = 1;
176f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
177f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
178f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * This projection is for listing account id's only
179f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
180f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String[] ID_TYPE_PROJECTION = new String[] {
181f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        RECORD_ID, MailboxColumns.TYPE
182f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    };
183f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
184f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int ACCOUNT_FLAGS_COLUMN_ID = 0;
185f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final int ACCOUNT_FLAGS_COLUMN_FLAGS = 1;
186f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String[] ACCOUNT_FLAGS_PROJECTION = new String[] {
187f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            AccountColumns.ID, AccountColumns.FLAGS};
188f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
189f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String MAILBOX_SELECTION =
190f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        MessageColumns.MAILBOX_KEY + " =?";
191f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
192f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String UNREAD_COUNT_SELECTION =
193f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        MessageColumns.MAILBOX_KEY + " =? and " + MessageColumns.FLAG_READ + "= 0";
194f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
195f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    private static final String UUID_SELECTION = AccountColumns.COMPATIBILITY_UUID + " =?";
196f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
197f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final String SECURITY_NONZERO_SELECTION =
198f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        Account.POLICY_KEY + " IS NOT NULL AND " + Account.POLICY_KEY + "!=0";
199f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
200f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    private static final String FIND_INBOX_SELECTION =
201f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            MailboxColumns.TYPE + " = " + Mailbox.TYPE_INBOX +
202f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            " AND " + MailboxColumns.ACCOUNT_KEY + " =?";
203f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
204f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This projection is for searching for the default account
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String[] DEFAULT_ID_PROJECTION = new String[] {
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        RECORD_ID, IS_DEFAULT
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    };
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
212f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * no public constructor since this is a utility class
213f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
214f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public Account() {
215f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mBaseUri = CONTENT_URI;
216f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
217f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // other defaults (policy)
218f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mRingtoneUri = "content://settings/system/notification_sound";
219f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = -1;
220f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = -1;
221f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags = FLAGS_NOTIFY_NEW_MAIL;
222f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mCompatibilityUuid = UUID.randomUUID().toString();
223f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
224f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
225f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static Account restoreAccountWithId(Context context, long id) {
226f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return EmailContent.restoreContentWithId(context, Account.class,
227f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                Account.CONTENT_URI, Account.CONTENT_PROJECTION, id);
228f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
229f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
230f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
231f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Returns {@code true} if the given account ID is a "normal" account. Normal accounts
232f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * always have an ID greater than {@code 0} and not equal to any pseudo account IDs
233f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * (such as {@link #ACCOUNT_ID_COMBINED_VIEW})
234f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
235f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static boolean isNormalAccount(long accountId) {
236f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return (accountId > 0L) && (accountId != ACCOUNT_ID_COMBINED_VIEW);
237f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
238f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
239f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
240f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Refresh an account that has already been loaded.  This is slightly less expensive
241f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * that generating a brand-new account object.
242f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
243f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void refresh(Context context) {
244f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        Cursor c = context.getContentResolver().query(getUri(), Account.CONTENT_PROJECTION,
245f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                null, null, null);
246f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        try {
247f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            c.moveToFirst();
248f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            restore(c);
249f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } finally {
250f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (c != null) {
251f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                c.close();
252f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
253f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
254f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
255f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
256f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
257f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void restore(Cursor cursor) {
258f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mId = cursor.getLong(CONTENT_ID_COLUMN);
259f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mBaseUri = CONTENT_URI;
260f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mDisplayName = cursor.getString(CONTENT_DISPLAY_NAME_COLUMN);
261f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mEmailAddress = cursor.getString(CONTENT_EMAIL_ADDRESS_COLUMN);
262f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncKey = cursor.getString(CONTENT_SYNC_KEY_COLUMN);
263f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = cursor.getInt(CONTENT_SYNC_LOOKBACK_COLUMN);
264f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = cursor.getInt(CONTENT_SYNC_INTERVAL_COLUMN);
265f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeyRecv = cursor.getLong(CONTENT_HOST_AUTH_KEY_RECV_COLUMN);
266f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeySend = cursor.getLong(CONTENT_HOST_AUTH_KEY_SEND_COLUMN);
267f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags = cursor.getInt(CONTENT_FLAGS_COLUMN);
268f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mIsDefault = cursor.getInt(CONTENT_IS_DEFAULT_COLUMN) == 1;
269f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mCompatibilityUuid = cursor.getString(CONTENT_COMPATIBILITY_UUID_COLUMN);
270f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSenderName = cursor.getString(CONTENT_SENDER_NAME_COLUMN);
271f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mRingtoneUri = cursor.getString(CONTENT_RINGTONE_URI_COLUMN);
272f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mProtocolVersion = cursor.getString(CONTENT_PROTOCOL_VERSION_COLUMN);
273f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mNewMessageCount = cursor.getInt(CONTENT_NEW_MESSAGE_COUNT_COLUMN);
274f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSecuritySyncKey = cursor.getString(CONTENT_SECURITY_SYNC_KEY_COLUMN);
275f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSignature = cursor.getString(CONTENT_SIGNATURE_COLUMN);
276f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mPolicyKey = cursor.getLong(CONTENT_POLICY_KEY);
277bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mNotifiedMessageId = cursor.getLong(CONTENT_NOTIFIED_MESSAGE_ID_COLUMN);
278bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mNotifiedMessageCount = cursor.getInt(CONTENT_NOTIFIED_MESSAGE_COUNT_COLUMN);
279f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
280f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
281f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    private long getId(Uri u) {
282f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return Long.parseLong(u.getPathSegments().get(1));
283f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
284f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
285f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
286f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the user-visible name for the account
287f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
288f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getDisplayName() {
289f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mDisplayName;
290f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
291f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
292f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
293f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the description.  Be sure to call save() to commit to database.
294f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param description the new description
295f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
296f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setDisplayName(String description) {
297f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mDisplayName = description;
298f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
299f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
300f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
301f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the email address for this account
302f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
303f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getEmailAddress() {
304f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mEmailAddress;
305f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
306f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
307f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
308f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the Email address for this account.  Be sure to call save() to commit to database.
309f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param emailAddress the new email address for this account
310f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
311f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setEmailAddress(String emailAddress) {
312f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mEmailAddress = emailAddress;
313f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
314f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
315f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
316f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the sender's name for this account
317f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
318f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getSenderName() {
319f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSenderName;
320f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
321f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
322f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
323f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the sender's name.  Be sure to call save() to commit to database.
324f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param name the new sender name
325f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
326f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSenderName(String name) {
327f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSenderName = name;
328f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
329f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
330f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getSignature() {
331f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSignature;
332f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
333f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
334f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSignature(String signature) {
335f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSignature = signature;
336f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
337f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
338f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
339f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the minutes per check (for polling)
340f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "never", "push", etc.  See Account.java
341f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
342f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getSyncInterval() {
343f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSyncInterval;
344f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
345f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
346f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
347f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the minutes per check (for polling).  Be sure to call save() to commit to database.
348f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "never", "push", etc.  See Account.java
349f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param minutes the number of minutes between polling checks
350f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
351f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSyncInterval(int minutes) {
352f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = minutes;
353f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
354f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
355f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
356f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return One of the {@code Account.SYNC_WINDOW_*} constants that represents the sync
357f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *     lookback window.
358f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "all", "1 month", etc.  See Account.java
359f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
360f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getSyncLookback() {
361f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mSyncLookback;
362f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
363f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
364f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
365f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the sync lookback window.  Be sure to call save() to commit to database.
366f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * TODO define sentinel values for "all", "1 month", etc.  See Account.java
367025d29fd4b9dd8351fe2e0428a585cf327ddaca4Ben Komalo     * @param value One of the {@link com.android.emailcommon.service.SyncWindow} constants
368f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
369f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setSyncLookback(int value) {
370f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = value;
371f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
372f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
373f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
374f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the flags for this account
375f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see #FLAGS_NOTIFY_NEW_MAIL
376f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see #FLAGS_VIBRATE_ALWAYS
377f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see #FLAGS_VIBRATE_WHEN_SILENT
378f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
379f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getFlags() {
380f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mFlags;
381f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
382f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
383f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
384f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the flags for this account
385f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see #FLAGS_NOTIFY_NEW_MAIL
386f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see #FLAGS_VIBRATE_ALWAYS
387f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see #FLAGS_VIBRATE_WHEN_SILENT
388f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param newFlags the new value for the flags
389f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
390f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setFlags(int newFlags) {
391f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags = newFlags;
392f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
393f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
394f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
395f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the ringtone Uri for this account
396f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
397f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getRingtone() {
398f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mRingtoneUri;
399f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
400f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
401f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
402f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the ringtone Uri for this account
403f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param newUri the new URI string for the ringtone for this account
404f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
405f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setRingtone(String newUri) {
406f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mRingtoneUri = newUri;
407f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
408f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
409f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
410f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the "delete policy" as a simple 0,1,2 value set.
411f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param newPolicy the new delete policy
412f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
413f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setDeletePolicy(int newPolicy) {
414f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags &= ~FLAGS_DELETE_POLICY_MASK;
415f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags |= (newPolicy << FLAGS_DELETE_POLICY_SHIFT) & FLAGS_DELETE_POLICY_MASK;
416f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
417f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
418f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
419f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the "delete policy" as a simple 0,1,2 value set.
420f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the current delete policy
421f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
422f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int getDeletePolicy() {
423f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return (mFlags & FLAGS_DELETE_POLICY_MASK) >> FLAGS_DELETE_POLICY_SHIFT;
424f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
425f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
426f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
427f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the Uuid associated with this account.  This is primarily for compatibility
428f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * with accounts set up by previous versions, because there are externals references
429f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * to the Uuid (e.g. desktop shortcuts).
430f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
431f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getUuid() {
432f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mCompatibilityUuid;
433f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
434f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
435f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public HostAuth getOrCreateHostAuthSend(Context context) {
436f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthSend == null) {
437f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (mHostAuthKeySend != 0) {
438f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthSend = HostAuth.restoreHostAuthWithId(context, mHostAuthKeySend);
439f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            } else {
440f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthSend = new HostAuth();
441f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
442f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
443f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mHostAuthSend;
444f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
445f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
446f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public HostAuth getOrCreateHostAuthRecv(Context context) {
447f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv == null) {
448f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (mHostAuthKeyRecv != 0) {
449f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthRecv = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
450f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            } else {
451f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthRecv = new HostAuth();
452f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
453f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
454f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return mHostAuthRecv;
455f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
456f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
457f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
458f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * For compatibility while converting to provider model, generate a "local store URI"
459f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
460f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return a string in the form of a Uri, as used by the other parts of the email app
461f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
462f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getLocalStoreUri(Context context) {
463f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return "local://localhost/" + context.getDatabasePath(getUuid() + ".db");
464f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
465f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
466f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
467bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return true if the instance is of an EAS account.
468bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
469bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * NOTE This method accesses the DB if {@link #mHostAuthRecv} hasn't been restored yet.
470bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Use caution when you use this on the main thread.
471bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
472bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean isEasAccount(Context context) {
473bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return "eas".equals(getProtocol(context));
474bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
475bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
476bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean supportsMoveMessages(Context context) {
477bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        String protocol = getProtocol(context);
478bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return "eas".equals(protocol) || "imap".equals(protocol);
479bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
480bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
481bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
482e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank     * @return true if the account supports "search".
483e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank     */
484e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    public static boolean supportsServerSearch(Context context, long accountId) {
485e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank        Account account = Account.restoreAccountWithId(context, accountId);
486e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank        if (account == null) return false;
487e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank        return (account.mFlags & Account.FLAGS_SUPPORTS_SEARCH) != 0;
488e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    }
489e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank
490e57a83d39a1414bd44eef7376f3a091264fce5d9Marc Blank    /**
491f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Set the account to be the default account.  If this is set to "true", when the account
492f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * is saved, all other accounts will have the same value set to "false".
493f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param newDefaultState the new default state - if true, others will be cleared.
494f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
495f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void setDefaultAccount(boolean newDefaultState) {
496f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mIsDefault = newDefaultState;
497f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
498f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
499f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
500f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return {@link Uri} to this {@link Account} in the
501f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * {@code content://com.android.email.provider/account/UUID} format, which is safe to use
502f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * for desktop shortcuts.
503f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
504f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * <p>We don't want to store _id in shortcuts, because
505f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * {@link com.android.email.provider.AccountBackupRestore} won't preserve it.
506f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
507f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public Uri getShortcutSafeUri() {
508f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return getShortcutSafeUriFromUuid(mCompatibilityUuid);
509f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
510f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
511f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
512f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return {@link Uri} to an {@link Account} with a {@code uuid}.
513f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
514f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static Uri getShortcutSafeUriFromUuid(String uuid) {
515f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return CONTENT_URI.buildUpon().appendEncodedPath(uuid).build();
516f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
517f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
518f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
519f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Parse {@link Uri} in the {@code content://com.android.email.provider/account/ID} format
520f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * where ID = account id (used on Eclair, Android 2.0-2.1) or UUID, and return _id of
521f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * the {@link Account} associated with it.
522f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
523f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context context to access DB
524f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param uri URI of interest
525f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return _id of the {@link Account} associated with ID, or -1 if none found.
526f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
527f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static long getAccountIdFromShortcutSafeUri(Context context, Uri uri) {
528f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Make sure the URI is in the correct format.
529f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (!"content".equals(uri.getScheme())
530bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                || !AUTHORITY.equals(uri.getAuthority())) {
531f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return -1;
532f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
533f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
534f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        final List<String> ps = uri.getPathSegments();
535f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (ps.size() != 2 || !"account".equals(ps.get(0))) {
536f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return -1;
537f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
538f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
539f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Now get the ID part.
540f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        final String id = ps.get(1);
541f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
542f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // First, see if ID can be parsed as long.  (Eclair-style)
543f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // (UUIDs have '-' in them, so they are always non-parsable.)
544f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        try {
545f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return Long.parseLong(id);
546f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } catch (NumberFormatException ok) {
547f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // OK, it's not a long.  Continue...
548f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
549f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
550f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Now id is a UUId.
551f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return getAccountIdFromUuid(context, id);
552f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
553f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
554f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
555f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return ID of the account with the given UUID.
556f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
557f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static long getAccountIdFromUuid(Context context, String uuid) {
558f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return Utility.getFirstRowLong(context,
559f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                CONTENT_URI, ID_PROJECTION,
560f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                UUID_SELECTION, new String[] {uuid}, null, 0, -1L);
561f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
562f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
563f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
564f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the id of the default account.  If one hasn't been explicitly specified, return
5656e418aa41a17136be0dddb816d843428a0a1e722Marc Blank     * the first one in the database (the logic is provided within EmailProvider)
566f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
5674de538be2d17545fb63e781412b8565f0d0d97d4Ben Komalo     * @return the id of the default account, or Account.NO_ACCOUNT if there are no accounts
568f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
569f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    static public long getDefaultAccountId(Context context) {
5706e418aa41a17136be0dddb816d843428a0a1e722Marc Blank        Cursor c = context.getContentResolver().query(
5716e418aa41a17136be0dddb816d843428a0a1e722Marc Blank                Account.DEFAULT_ACCOUNT_ID_URI, Account.ID_PROJECTION, null, null, null);
5726e418aa41a17136be0dddb816d843428a0a1e722Marc Blank        try {
5736e418aa41a17136be0dddb816d843428a0a1e722Marc Blank            if (c != null && c.moveToFirst()) {
5746e418aa41a17136be0dddb816d843428a0a1e722Marc Blank                return c.getLong(Account.ID_PROJECTION_COLUMN);
5756e418aa41a17136be0dddb816d843428a0a1e722Marc Blank            }
5766e418aa41a17136be0dddb816d843428a0a1e722Marc Blank        } finally {
5776e418aa41a17136be0dddb816d843428a0a1e722Marc Blank            c.close();
578f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
5794de538be2d17545fb63e781412b8565f0d0d97d4Ben Komalo        return Account.NO_ACCOUNT;
580f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
581f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
582f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
583f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Given an account id, return the account's protocol
584f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
585f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param accountId the id of the account to be examined
586f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account's protocol (or null if the Account or HostAuth do not exist)
587f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
588f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static String getProtocol(Context context, long accountId) {
589f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        Account account = Account.restoreAccountWithId(context, accountId);
590f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (account != null) {
591f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return account.getProtocol(context);
592f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank         }
593f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
594f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
595f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
596f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
597f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the account's protocol
598f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
599f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account's protocol (or null if the HostAuth doesn't not exist)
600f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
601f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String getProtocol(Context context) {
602f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        HostAuth hostAuth = HostAuth.restoreHostAuthWithId(context, mHostAuthKeyRecv);
603f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (hostAuth != null) {
604f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return hostAuth.mProtocol;
605f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
606f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
607f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
608f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
609f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
610f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the account ID for a message with a given id
611f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
612f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
613f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param messageId the id of the message
614f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account ID, or -1 if the account doesn't exist
615f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
616f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static long getAccountIdForMessageId(Context context, long messageId) {
617f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return Message.getKeyColumnLong(context, messageId, MessageColumns.ACCOUNT_KEY);
618f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
619f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
620f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
621f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Return the account for a message with a given id
622f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param context the caller's context
623f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @param messageId the id of the message
624f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return the account, or null if the account doesn't exist
625f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
626f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static Account getAccountForMessageId(Context context, long messageId) {
627f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        long accountId = getAccountIdForMessageId(context, messageId);
628f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (accountId != -1) {
629f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return Account.restoreAccountWithId(context, accountId);
630f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
631f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
632f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
633f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
634f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
635f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return true if an {@code accountId} is assigned to any existing account.
636f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
637f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static boolean isValidId(Context context, long accountId) {
638f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null != Utility.getFirstRowLong(context, CONTENT_URI, ID_PROJECTION,
639f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ID_SELECTION, new String[] {Long.toString(accountId)}, null,
640f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ID_PROJECTION_COLUMN);
641f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
642f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
643f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
644f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Check a single account for security hold status.
645f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
646f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static boolean isSecurityHold(Context context, long accountId) {
647f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return (Utility.getFirstRowLong(context,
648f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ContentUris.withAppendedId(Account.CONTENT_URI, accountId),
649f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ACCOUNT_FLAGS_PROJECTION, null, null, null, ACCOUNT_FLAGS_COLUMN_FLAGS, 0L)
650f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                & Account.FLAGS_SECURITY_HOLD) != 0;
651f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
652f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
653f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
654f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @return id of the "inbox" mailbox, or -1 if not found.
655f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
656f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static long getInboxId(Context context, long accountId) {
657f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return Utility.getFirstRowLong(context, Mailbox.CONTENT_URI, ID_PROJECTION,
658f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                FIND_INBOX_SELECTION, new String[] {Long.toString(accountId)}, null,
659f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                ID_PROJECTION_COLUMN, -1L);
660f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
661f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
662f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
663f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Clear all account hold flags that are set.
664f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     *
665f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * (This will trigger watchers, and in particular will cause EAS to try and resync the
666f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * account(s).)
667f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
668f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static void clearSecurityHoldOnAllAccounts(Context context) {
669f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentResolver resolver = context.getContentResolver();
670f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        Cursor c = resolver.query(Account.CONTENT_URI, ACCOUNT_FLAGS_PROJECTION,
671f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                SECURITY_NONZERO_SELECTION, null, null);
672f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        try {
673f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            while (c.moveToNext()) {
674f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                int flags = c.getInt(ACCOUNT_FLAGS_COLUMN_FLAGS);
675f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
676f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                if (0 != (flags & FLAGS_SECURITY_HOLD)) {
677f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    ContentValues cv = new ContentValues();
678f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    cv.put(AccountColumns.FLAGS, flags & ~FLAGS_SECURITY_HOLD);
679f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    long accountId = c.getLong(ACCOUNT_FLAGS_COLUMN_ID);
680f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, accountId);
681f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    resolver.update(uri, cv, null, null);
682f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                }
683f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
684f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } finally {
685f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            c.close();
686f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
687f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
688f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
689f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
690dea198bb041754745c3b1522671fd31a79c7168cMarc Blank     * Given an account id, determine whether the account is currently prohibited from automatic
691dea198bb041754745c3b1522671fd31a79c7168cMarc Blank     * sync, due to roaming while the account's policy disables this
692dea198bb041754745c3b1522671fd31a79c7168cMarc Blank     * @param context the caller's context
693dea198bb041754745c3b1522671fd31a79c7168cMarc Blank     * @param accountId the account id
694dea198bb041754745c3b1522671fd31a79c7168cMarc Blank     * @return true if the account can't automatically sync due to roaming; false otherwise
695dea198bb041754745c3b1522671fd31a79c7168cMarc Blank     */
696dea198bb041754745c3b1522671fd31a79c7168cMarc Blank    public static boolean isAutomaticSyncDisabledByRoaming(Context context, long accountId) {
697dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        Account account = Account.restoreAccountWithId(context, accountId);
698dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        // Account being deleted; just return
699dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        if (account == null) return false;
700dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        long policyKey = account.mPolicyKey;
701dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        // If no security policy, we're good
702dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        if (policyKey <= 0) return false;
703dea198bb041754745c3b1522671fd31a79c7168cMarc Blank
704dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        ConnectivityManager cm =
705dea198bb041754745c3b1522671fd31a79c7168cMarc Blank            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
706dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        NetworkInfo info = cm.getActiveNetworkInfo();
707dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        // If we're not on mobile, we're good
708dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        if (info == null || (info.getType() != ConnectivityManager.TYPE_MOBILE)) return false;
709dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        // If we're not roaming, we're good
710dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        if (!info.isRoaming()) return false;
711dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        Policy policy = Policy.restorePolicyWithId(context, policyKey);
712dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        // Account being deleted; just return
713dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        if (policy == null) return false;
714dea198bb041754745c3b1522671fd31a79c7168cMarc Blank        return policy.mRequireManualSyncWhenRoaming;
715dea198bb041754745c3b1522671fd31a79c7168cMarc Blank    }
716dea198bb041754745c3b1522671fd31a79c7168cMarc Blank
717dea198bb041754745c3b1522671fd31a79c7168cMarc Blank    /**
718f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Override update to enforce a single default account, and do it atomically
719f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
720f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
721f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int update(Context context, ContentValues cv) {
722f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (cv.containsKey(AccountColumns.IS_DEFAULT) &&
723f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                cv.getAsBoolean(AccountColumns.IS_DEFAULT)) {
724f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
725f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ContentValues cv1 = new ContentValues();
726f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            cv1.put(AccountColumns.IS_DEFAULT, false);
727f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // Clear the default flag in all accounts
728f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ops.add(ContentProviderOperation.newUpdate(CONTENT_URI).withValues(cv1).build());
729f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // Update this account
730f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ops.add(ContentProviderOperation
731f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    .newUpdate(ContentUris.withAppendedId(CONTENT_URI, mId))
732f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    .withValues(cv).build());
733f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            try {
734bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                context.getContentResolver().applyBatch(AUTHORITY, ops);
735f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                return 1;
736f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            } catch (RemoteException e) {
737f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                // There is nothing to be done here; fail by returning 0
738f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            } catch (OperationApplicationException e) {
739f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                // There is nothing to be done here; fail by returning 0
740f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
741f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return 0;
742f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
743f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return super.update(context, cv);
744f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
745f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
746f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /*
747f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Override this so that we can store the HostAuth's first and link them to the Account
748f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * (non-Javadoc)
749f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * @see com.android.email.provider.EmailContent#save(android.content.Context)
750f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
751f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
752f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public Uri save(Context context) {
753f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (isSaved()) {
754f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            throw new UnsupportedOperationException();
755f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
756f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // This logic is in place so I can (a) short circuit the expensive stuff when
757f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // possible, and (b) override (and throw) if anyone tries to call save() or update()
758f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // directly for Account, which are unsupported.
759f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv == null && mHostAuthSend == null && mIsDefault == false &&
760f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mPolicy != null) {
761f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return super.save(context);
762f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
763f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
764f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        int index = 0;
765f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        int recvIndex = -1;
766f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        int sendIndex = -1;
767f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
768f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Create operations for saving the send and recv hostAuths
769f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Also, remember which operation in the array they represent
770f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
771f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv != null) {
772f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            recvIndex = index++;
773f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mBaseUri)
774f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    .withValues(mHostAuthRecv.toContentValues())
775f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    .build());
776f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
777f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthSend != null) {
778f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            sendIndex = index++;
779f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ops.add(ContentProviderOperation.newInsert(mHostAuthSend.mBaseUri)
780f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    .withValues(mHostAuthSend.toContentValues())
781f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                    .build());
782f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
783f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
784f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Create operations for making this the only default account
785f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Note, these are always updates because they change existing accounts
786f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mIsDefault) {
787f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            index++;
788f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ContentValues cv1 = new ContentValues();
789f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            cv1.put(AccountColumns.IS_DEFAULT, 0);
790f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ops.add(ContentProviderOperation.newUpdate(CONTENT_URI).withValues(cv1).build());
791f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
792f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
793f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // Now do the Account
794f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentValues cv = null;
795f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank        if (recvIndex >= 0 || sendIndex >= 0) {
796f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            cv = new ContentValues();
797f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (recvIndex >= 0) {
798f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                cv.put(Account.HOST_AUTH_KEY_RECV, recvIndex);
799f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
800f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (sendIndex >= 0) {
801f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                cv.put(Account.HOST_AUTH_KEY_SEND, sendIndex);
802f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
803f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
804f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
805f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(mBaseUri);
806f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        b.withValues(toContentValues());
807f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (cv != null) {
808f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            b.withValueBackReferences(cv);
809f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
810f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ops.add(b.build());
811f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
812f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        try {
813f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            ContentProviderResult[] results =
814bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                context.getContentResolver().applyBatch(AUTHORITY, ops);
815f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // If saving, set the mId's of the various saved objects
816f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (recvIndex >= 0) {
817f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                long newId = getId(results[recvIndex].uri);
818f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthKeyRecv = newId;
819f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthRecv.mId = newId;
820f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
821f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            if (sendIndex >= 0) {
822f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                long newId = getId(results[sendIndex].uri);
823f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthKeySend = newId;
824f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank                mHostAuthSend.mId = newId;
825f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            }
826f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            Uri u = results[index].uri;
827f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mId = getId(u);
828f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return u;
829f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } catch (RemoteException e) {
830f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // There is nothing to be done here; fail by returning null
831f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } catch (OperationApplicationException e) {
832f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            // There is nothing to be done here; fail by returning null
833f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
834f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return null;
835f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
836f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
837f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
838f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public ContentValues toContentValues() {
839f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        ContentValues values = new ContentValues();
840f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.DISPLAY_NAME, mDisplayName);
841f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.EMAIL_ADDRESS, mEmailAddress);
842f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SYNC_KEY, mSyncKey);
843f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SYNC_LOOKBACK, mSyncLookback);
844f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SYNC_INTERVAL, mSyncInterval);
845f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.HOST_AUTH_KEY_RECV, mHostAuthKeyRecv);
846f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.HOST_AUTH_KEY_SEND, mHostAuthKeySend);
847f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.FLAGS, mFlags);
848f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.IS_DEFAULT, mIsDefault);
849f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.COMPATIBILITY_UUID, mCompatibilityUuid);
850f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SENDER_NAME, mSenderName);
851f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.RINGTONE_URI, mRingtoneUri);
852f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.PROTOCOL_VERSION, mProtocolVersion);
853f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.NEW_MESSAGE_COUNT, mNewMessageCount);
854f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SECURITY_SYNC_KEY, mSecuritySyncKey);
855f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.SIGNATURE, mSignature);
856f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        values.put(AccountColumns.POLICY_KEY, mPolicyKey);
857bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        values.put(AccountColumns.NOTIFIED_MESSAGE_ID, mNotifiedMessageId);
858bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        values.put(AccountColumns.NOTIFIED_MESSAGE_COUNT, mNotifiedMessageCount);
859f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return values;
860f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
861f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
862f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
863f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
864f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
865f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
866f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public int describeContents() {
867f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return 0;
868f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
869f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
870f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
871f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
872f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
873f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public static final Parcelable.Creator<Account> CREATOR
874f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            = new Parcelable.Creator<Account>() {
875f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        @Override
876f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        public Account createFromParcel(Parcel in) {
877f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return new Account(in);
878f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
879f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
880f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        @Override
881f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        public Account[] newArray(int size) {
882f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            return new Account[size];
883f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
884f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    };
885f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
886f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
887f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
888f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
889f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
890f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public void writeToParcel(Parcel dest, int flags) {
891f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        // mBaseUri is not parceled
892f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mId);
893f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mDisplayName);
894f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mEmailAddress);
895f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSyncKey);
896f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeInt(mSyncLookback);
897f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeInt(mSyncInterval);
898f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mHostAuthKeyRecv);
899f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mHostAuthKeySend);
900f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeInt(mFlags);
901f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeByte(mIsDefault ? (byte)1 : (byte)0);
902f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mCompatibilityUuid);
903f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSenderName);
904f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mRingtoneUri);
905f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mProtocolVersion);
906f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeInt(mNewMessageCount);
907f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSecuritySyncKey);
908f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeString(mSignature);
909f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        dest.writeLong(mPolicyKey);
910f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
911f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv != null) {
912f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)1);
913f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthRecv.writeToParcel(dest, flags);
914f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } else {
915f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)0);
916f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
917f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
918f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthSend != null) {
919f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)1);
920f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthSend.writeToParcel(dest, flags);
921f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        } else {
922f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            dest.writeByte((byte)0);
923f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
924f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
925f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
926f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
927f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * Supports Parcelable
928f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
929f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public Account(Parcel in) {
930f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mBaseUri = Account.CONTENT_URI;
931f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mId = in.readLong();
932f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mDisplayName = in.readString();
933f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mEmailAddress = in.readString();
934f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncKey = in.readString();
935f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncLookback = in.readInt();
936f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSyncInterval = in.readInt();
937f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeyRecv = in.readLong();
938f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthKeySend = in.readLong();
939f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mFlags = in.readInt();
940f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mIsDefault = in.readByte() == 1;
941f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mCompatibilityUuid = in.readString();
942f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSenderName = in.readString();
943f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mRingtoneUri = in.readString();
944f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mProtocolVersion = in.readString();
945f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mNewMessageCount = in.readInt();
946f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSecuritySyncKey = in.readString();
947f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mSignature = in.readString();
948f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mPolicyKey = in.readLong();
949f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
950f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthRecv = null;
951f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (in.readByte() == 1) {
952f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthRecv = new HostAuth(in);
953f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
954f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
955f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        mHostAuthSend = null;
956f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (in.readByte() == 1) {
957f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            mHostAuthSend = new HostAuth(in);
958f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
959f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
960f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank
961f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    /**
962f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     * For debugger support only - DO NOT use for code.
963f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank     */
964f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    @Override
965f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    public String toString() {
966f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        StringBuilder sb = new StringBuilder('[');
967f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mHostAuthRecv != null && mHostAuthRecv.mProtocol != null) {
968f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            sb.append(mHostAuthRecv.mProtocol);
969f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank            sb.append(':');
970f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        }
971f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mDisplayName != null)   sb.append(mDisplayName);
972f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        sb.append(':');
973f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mEmailAddress != null)  sb.append(mEmailAddress);
974f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        sb.append(':');
975f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        if (mSenderName != null)    sb.append(mSenderName);
976f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        sb.append(']');
977f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank        return sb.toString();
978f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank    }
979f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blank}