1 /**
2  * Copyright (c) 2012, Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.mail.providers;
18 
19 import android.database.Cursor;
20 import android.net.Uri;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.text.TextUtils;
24 
25 import com.android.mail.providers.UIProvider.AccountColumns.SettingsColumns;
26 import com.android.mail.providers.UIProvider.AutoAdvance;
27 import com.android.mail.providers.UIProvider.ConversationListIcon;
28 import com.android.mail.providers.UIProvider.DefaultReplyBehavior;
29 import com.android.mail.providers.UIProvider.SnapHeaderValue;
30 import com.android.mail.providers.UIProvider.Swipe;
31 import com.android.mail.utils.LogTag;
32 import com.android.mail.utils.LogUtils;
33 import com.android.mail.utils.Utils;
34 import com.google.android.mail.common.base.Strings;
35 import com.google.common.base.Objects;
36 
37 import org.json.JSONException;
38 import org.json.JSONObject;
39 
40 import java.util.HashMap;
41 import java.util.Map;
42 
43 /**
44  * Model to hold Settings for an account.
45  */
46 public class Settings implements Parcelable {
47     private static final String LOG_TAG = LogTag.getLogTag();
48 
49     static final Settings EMPTY_SETTINGS = new Settings();
50 
51     // Max size for attachments (5 megs). Will be overridden by an account
52     // setting, if found.
53     private static final int DEFAULT_MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024;
54 
55     public static final int SWIPE_SETTING_ARCHIVE = 0;
56     public static final int SWIPE_SETTING_DELETE = 1;
57     public static final int SWIPE_SETTING_DISABLED = 2;
58 
59     private static final int DEFAULT = SWIPE_SETTING_ARCHIVE;
60 
61     public interface ShowImages {
62         public static final int ALWAYS = 0;
63         public static final int ASK_FIRST = 1;
64     }
65 
66     public final String signature;
67     /**
68      * Auto advance setting for this account.
69      * Integer, one of {@link AutoAdvance#LIST}, {@link AutoAdvance#NEWER},
70      * {@link AutoAdvance#OLDER} or  {@link AutoAdvance#UNSET}
71      */
72     private final int mAutoAdvance;
73     private Integer mTransientAutoAdvance = null;
74     public final int snapHeaders;
75     public final int replyBehavior;
76     public final int convListIcon;
77     public final boolean confirmDelete;
78     public final boolean confirmArchive;
79     public final boolean confirmSend;
80     public final int conversationViewMode;
81     public final Uri defaultInbox;
82     /**
83      * The name of the default inbox: "Inbox" or "Priority Inbox", internationalized...
84      */
85     public final String defaultInboxName;
86     // If you find the need for more default Inbox information: ID or capabilities, then
87     // ask viki to replace the above two members with a single JSON object representing the default
88     // folder.  That should make all the information about the folder available without an
89     // explosion in the number of members.
90 
91     public final boolean forceReplyFromDefault;
92     public final int maxAttachmentSize;
93     public final int swipe;
94     /** True if the yellow label indicating importance should be shown. */
95     public final boolean importanceMarkersEnabled;
96     /**
97      * true if personal level indicators should be shown:
98      * an arrow ( › ) by messages sent to my address (not a mailing list),
99      * and a double arrow ( » ) by messages sent only to me.
100      */
101     public final boolean showChevronsEnabled;
102     public final Uri setupIntentUri;
103     public final String veiledAddressPattern;
104     public final int showImages;
105     public final int welcomeTourShownVersion;
106 
107     /**
108      * The {@link Uri} to use when moving a conversation to the inbox. May
109      * differ from {@link #defaultInbox}.
110      */
111     public final Uri moveToInbox;
112 
113     /** Cached value of hashCode */
114     private int mHashCode;
115 
116     /** Safe defaults to be used if some values are unspecified. */
117     private static final Settings sDefault = EMPTY_SETTINGS;
118 
Settings()119     private Settings() {
120         signature = "";
121         mAutoAdvance = AutoAdvance.LIST;
122         snapHeaders = SnapHeaderValue.ALWAYS;
123         replyBehavior = DefaultReplyBehavior.REPLY;
124         convListIcon = ConversationListIcon.SENDER_IMAGE;
125         confirmDelete = false;
126         confirmArchive = false;
127         confirmSend = false;
128         defaultInbox = Uri.EMPTY;
129         defaultInboxName = "";
130         forceReplyFromDefault = false;
131         maxAttachmentSize = 0;
132         swipe = DEFAULT;
133         importanceMarkersEnabled = false;
134         showChevronsEnabled = false;
135         setupIntentUri = Uri.EMPTY;
136         conversationViewMode = UIProvider.ConversationViewMode.UNDEFINED;
137         veiledAddressPattern = null;
138         moveToInbox = Uri.EMPTY;
139         showImages = ShowImages.ASK_FIRST;
140         welcomeTourShownVersion = -1;
141     }
142 
Settings(Parcel inParcel)143     public Settings(Parcel inParcel) {
144         signature = inParcel.readString();
145         mAutoAdvance = inParcel.readInt();
146         snapHeaders = inParcel.readInt();
147         replyBehavior = inParcel.readInt();
148         convListIcon = inParcel.readInt();
149         confirmDelete = inParcel.readInt() != 0;
150         confirmArchive = inParcel.readInt() != 0;
151         confirmSend = inParcel.readInt() != 0;
152         defaultInbox = Utils.getValidUri(inParcel.readString());
153         defaultInboxName = inParcel.readString();
154         forceReplyFromDefault = inParcel.readInt() != 0;
155         maxAttachmentSize = inParcel.readInt();
156         swipe = inParcel.readInt();
157         importanceMarkersEnabled = inParcel.readInt() != 0;
158         showChevronsEnabled = inParcel.readInt() != 0;
159         setupIntentUri = Utils.getValidUri(inParcel.readString());
160         conversationViewMode = inParcel.readInt();
161         veiledAddressPattern = inParcel.readString();
162         moveToInbox = Utils.getValidUri(inParcel.readString());
163         showImages = inParcel.readInt();
164         welcomeTourShownVersion = inParcel.readInt();
165     }
166 
Settings(Cursor cursor)167     public Settings(Cursor cursor) {
168         signature = Strings.nullToEmpty(
169                 cursor.getString(cursor.getColumnIndex(SettingsColumns.SIGNATURE)));
170         mAutoAdvance = cursor.getInt(cursor.getColumnIndex(SettingsColumns.AUTO_ADVANCE));
171         snapHeaders = cursor.getInt(cursor.getColumnIndex(SettingsColumns.SNAP_HEADERS));
172         replyBehavior = cursor.getInt(cursor.getColumnIndex(SettingsColumns.REPLY_BEHAVIOR));
173         convListIcon = cursor.getInt(cursor.getColumnIndex(SettingsColumns.CONV_LIST_ICON));
174         confirmDelete = cursor.getInt(cursor.getColumnIndex(SettingsColumns.CONFIRM_DELETE)) != 0;
175         confirmArchive = cursor.getInt(cursor.getColumnIndex(SettingsColumns.CONFIRM_ARCHIVE)) != 0;
176         confirmSend = cursor.getInt(cursor.getColumnIndex(SettingsColumns.CONFIRM_SEND)) != 0;
177         defaultInbox = Utils.getValidUri(
178                 cursor.getString(cursor.getColumnIndex(SettingsColumns.DEFAULT_INBOX)));
179         defaultInboxName = Strings.nullToEmpty(
180                 cursor.getString(cursor.getColumnIndex(SettingsColumns.DEFAULT_INBOX_NAME)));
181         forceReplyFromDefault = cursor.getInt(
182                 cursor.getColumnIndex(SettingsColumns.FORCE_REPLY_FROM_DEFAULT)) != 0;
183         maxAttachmentSize =
184                 cursor.getInt(cursor.getColumnIndex(SettingsColumns.MAX_ATTACHMENT_SIZE));
185         swipe = cursor.getInt(cursor.getColumnIndex(SettingsColumns.SWIPE));
186         importanceMarkersEnabled = cursor.getInt(
187                 cursor.getColumnIndex(SettingsColumns.IMPORTANCE_MARKERS_ENABLED)) != 0;
188         showChevronsEnabled = cursor.getInt(
189                 cursor.getColumnIndex(SettingsColumns.SHOW_CHEVRONS_ENABLED)) != 0;
190         setupIntentUri = Utils.getValidUri(
191                 cursor.getString(cursor.getColumnIndex(SettingsColumns.SETUP_INTENT_URI)));
192         conversationViewMode =
193                 cursor.getInt(cursor.getColumnIndex(SettingsColumns.CONVERSATION_VIEW_MODE));
194         veiledAddressPattern = Strings.nullToEmpty(
195                 cursor.getString(cursor.getColumnIndex(SettingsColumns.VEILED_ADDRESS_PATTERN)));
196         moveToInbox = Utils.getValidUri(
197                 cursor.getString(cursor.getColumnIndex(SettingsColumns.MOVE_TO_INBOX)));
198         showImages = cursor.getInt(cursor.getColumnIndex(SettingsColumns.SHOW_IMAGES));
199         welcomeTourShownVersion = cursor.getInt(
200                 cursor.getColumnIndex(SettingsColumns.WELCOME_TOUR_SHOWN_VERSION));
201     }
202 
Settings(JSONObject json)203     private Settings(JSONObject json) {
204         signature = json.optString(SettingsColumns.SIGNATURE, sDefault.signature);
205         mAutoAdvance = json.optInt(SettingsColumns.AUTO_ADVANCE, sDefault.getAutoAdvanceSetting());
206         snapHeaders = json.optInt(SettingsColumns.SNAP_HEADERS, sDefault.snapHeaders);
207         replyBehavior = json.optInt(SettingsColumns.REPLY_BEHAVIOR, sDefault.replyBehavior);
208         convListIcon = json.optInt(SettingsColumns.CONV_LIST_ICON, sDefault.convListIcon);
209         confirmDelete = json.optBoolean(SettingsColumns.CONFIRM_DELETE, sDefault.confirmDelete);
210         confirmArchive = json.optBoolean(SettingsColumns.CONFIRM_ARCHIVE, sDefault.confirmArchive);
211         confirmSend = json.optBoolean(SettingsColumns.CONFIRM_SEND, sDefault.confirmSend);
212         defaultInbox = Utils.getValidUri(json.optString(SettingsColumns.DEFAULT_INBOX));
213         defaultInboxName = json.optString(SettingsColumns.DEFAULT_INBOX_NAME,
214                 sDefault.defaultInboxName);
215         forceReplyFromDefault = json.optBoolean(SettingsColumns.FORCE_REPLY_FROM_DEFAULT,
216                 sDefault.forceReplyFromDefault);
217         maxAttachmentSize =
218                 json.optInt(SettingsColumns.MAX_ATTACHMENT_SIZE, sDefault.maxAttachmentSize);
219         swipe = json.optInt(SettingsColumns.SWIPE, sDefault.swipe);
220         importanceMarkersEnabled = json.optBoolean(SettingsColumns.IMPORTANCE_MARKERS_ENABLED,
221                 sDefault.importanceMarkersEnabled);
222         showChevronsEnabled = json.optBoolean(SettingsColumns.SHOW_CHEVRONS_ENABLED,
223                 sDefault.showChevronsEnabled);
224         setupIntentUri = Utils.getValidUri(json.optString(SettingsColumns.SETUP_INTENT_URI));
225         conversationViewMode = json.optInt(SettingsColumns.CONVERSATION_VIEW_MODE,
226                 UIProvider.ConversationViewMode.UNDEFINED);
227         veiledAddressPattern = json.optString(SettingsColumns.VEILED_ADDRESS_PATTERN, null);
228         moveToInbox = Utils.getValidUri(json.optString(SettingsColumns.MOVE_TO_INBOX));
229         showImages = json.optInt(SettingsColumns.SHOW_IMAGES, sDefault.showImages);
230         welcomeTourShownVersion = json.optInt(
231                 SettingsColumns.WELCOME_TOUR_SHOWN_VERSION, sDefault.welcomeTourShownVersion);
232     }
233 
234     /**
235      * Return a serialized String for these settings.
236      */
serialize()237     public synchronized String serialize() {
238         final JSONObject json = toJSON();
239         return json.toString();
240     }
241 
getNonNull(Object candidate, Object fallback)242     private static Object getNonNull(Object candidate, Object fallback){
243         if (candidate == null)
244             return fallback;
245         return candidate;
246     }
247 
248     /**
249      * Return a JSONObject for these settings.
250      */
toJSON()251     public synchronized JSONObject toJSON() {
252         final JSONObject json = new JSONObject();
253         try {
254             json.put(SettingsColumns.SIGNATURE, getNonNull(signature, sDefault.signature));
255             json.put(SettingsColumns.AUTO_ADVANCE, getAutoAdvanceSetting());
256             json.put(SettingsColumns.SNAP_HEADERS, snapHeaders);
257             json.put(SettingsColumns.REPLY_BEHAVIOR, replyBehavior);
258             json.put(SettingsColumns.CONV_LIST_ICON, convListIcon);
259             json.put(SettingsColumns.CONFIRM_DELETE, confirmDelete);
260             json.put(SettingsColumns.CONFIRM_ARCHIVE, confirmArchive);
261             json.put(SettingsColumns.CONFIRM_SEND, confirmSend);
262             json.put(SettingsColumns.DEFAULT_INBOX,
263                     getNonNull(defaultInbox, sDefault.defaultInbox));
264             json.put(SettingsColumns.DEFAULT_INBOX_NAME,
265                     getNonNull(defaultInboxName, sDefault.defaultInboxName));
266             json.put(SettingsColumns.FORCE_REPLY_FROM_DEFAULT, forceReplyFromDefault);
267             json.put(SettingsColumns.MAX_ATTACHMENT_SIZE,  maxAttachmentSize);
268             json.put(SettingsColumns.SWIPE, swipe);
269             json.put(SettingsColumns.IMPORTANCE_MARKERS_ENABLED, importanceMarkersEnabled);
270             json.put(SettingsColumns.SHOW_CHEVRONS_ENABLED, showChevronsEnabled);
271             json.put(SettingsColumns.SETUP_INTENT_URI, setupIntentUri);
272             json.put(SettingsColumns.CONVERSATION_VIEW_MODE, conversationViewMode);
273             json.put(SettingsColumns.VEILED_ADDRESS_PATTERN, veiledAddressPattern);
274             json.put(SettingsColumns.MOVE_TO_INBOX,
275                     getNonNull(moveToInbox, sDefault.moveToInbox));
276             json.put(SettingsColumns.SHOW_IMAGES, showImages);
277             json.put(SettingsColumns.WELCOME_TOUR_SHOWN_VERSION, welcomeTourShownVersion);
278         } catch (JSONException e) {
279             LogUtils.wtf(LOG_TAG, e, "Could not serialize settings");
280         }
281         return json;
282     }
283 
284     /**
285      * Creates a {@link Map} where the column name is the key and the value is the value.
286      * @param map map to insert values into or null
287      * @return the resulting map
288      */
getValueMap(Map<String, Object> map)289     public Map<String, Object> getValueMap(Map<String, Object> map) {
290         if (map == null) {
291             map = new HashMap<String, Object>();
292         }
293 
294         map.put(SettingsColumns.SIGNATURE, signature);
295         map.put(SettingsColumns.AUTO_ADVANCE, getAutoAdvanceSetting());
296         map.put(SettingsColumns.SNAP_HEADERS, snapHeaders);
297         map.put(SettingsColumns.REPLY_BEHAVIOR, replyBehavior);
298         map.put(SettingsColumns.CONV_LIST_ICON, convListIcon);
299         map.put(SettingsColumns.CONFIRM_DELETE, confirmDelete ? 1 : 0);
300         map.put(SettingsColumns.CONFIRM_ARCHIVE, confirmArchive ? 1 : 0);
301         map.put(SettingsColumns.CONFIRM_SEND, confirmSend ? 1 : 0);
302         map.put(SettingsColumns.DEFAULT_INBOX, defaultInbox);
303         map.put(SettingsColumns.DEFAULT_INBOX_NAME, defaultInboxName);
304         map.put(SettingsColumns.FORCE_REPLY_FROM_DEFAULT, forceReplyFromDefault ? 1 : 0);
305         map.put(SettingsColumns.MAX_ATTACHMENT_SIZE, maxAttachmentSize);
306         map.put(SettingsColumns.SWIPE, swipe);
307         map.put(SettingsColumns.IMPORTANCE_MARKERS_ENABLED, importanceMarkersEnabled ? 1 : 0);
308         map.put(SettingsColumns.SHOW_CHEVRONS_ENABLED, showChevronsEnabled ? 1 : 0);
309         map.put(SettingsColumns.SETUP_INTENT_URI, setupIntentUri);
310         map.put(SettingsColumns.CONVERSATION_VIEW_MODE, conversationViewMode);
311         map.put(SettingsColumns.VEILED_ADDRESS_PATTERN, veiledAddressPattern);
312         map.put(SettingsColumns.MOVE_TO_INBOX, moveToInbox);
313         map.put(SettingsColumns.SHOW_IMAGES, showImages);
314         map.put(SettingsColumns.WELCOME_TOUR_SHOWN_VERSION, welcomeTourShownVersion);
315 
316         return map;
317     }
318 
319     /**
320      * Create a new instance of an Settings object using a JSONObject  instance created previously
321      * using {@link #toJSON()}. This returns null if the serialized instance was invalid or does
322      * not represent a valid account object.
323      *
324      * @param json Serialized object
325      * @return New settings object or null
326      */
newInstance(JSONObject json)327     public static Settings newInstance(JSONObject json) {
328         if (json == null) {
329             return null;
330         }
331         return new Settings(json);
332     }
333 
334     @Override
describeContents()335     public int describeContents() {
336         return 0;
337     }
338 
339     @Override
writeToParcel(Parcel dest, int flags)340     public void writeToParcel(Parcel dest, int flags) {
341         dest.writeString((String) getNonNull(signature, sDefault.signature));
342         dest.writeInt(getAutoAdvanceSetting());
343         dest.writeInt(snapHeaders);
344         dest.writeInt(replyBehavior);
345         dest.writeInt(convListIcon);
346         dest.writeInt(confirmDelete ? 1 : 0);
347         dest.writeInt(confirmArchive? 1 : 0);
348         dest.writeInt(confirmSend? 1 : 0);
349         dest.writeString(getNonNull(defaultInbox, sDefault.defaultInbox).toString());
350         dest.writeString((String) getNonNull(defaultInboxName, sDefault.defaultInboxName));
351         dest.writeInt(forceReplyFromDefault ? 1 : 0);
352         dest.writeInt(maxAttachmentSize);
353         dest.writeInt(swipe);
354         dest.writeInt(importanceMarkersEnabled ? 1 : 0);
355         dest.writeInt(showChevronsEnabled ? 1 : 0);
356         dest.writeString(getNonNull(setupIntentUri, sDefault.setupIntentUri).toString());
357         dest.writeInt(conversationViewMode);
358         dest.writeString(veiledAddressPattern);
359         dest.writeString(getNonNull(moveToInbox, sDefault.moveToInbox).toString());
360         dest.writeInt(showImages);
361         dest.writeInt(welcomeTourShownVersion);
362     }
363 
364     /**
365      * Returns the URI of the current account's default inbox if available, otherwise
366      * returns the empty URI {@link Uri#EMPTY}
367      * @param settings a settings object, possibly null.
368      * @return a valid default Inbox URI, or {@link Uri#EMPTY} if settings are null or no default
369      * is specified.
370      */
getDefaultInboxUri(Settings settings)371     public static Uri getDefaultInboxUri(Settings settings) {
372         if (settings == null) {
373             return sDefault.defaultInbox;
374         }
375         return (Uri) getNonNull(settings.defaultInbox, sDefault.defaultInbox);
376     }
377 
378     /**
379      * Gets the autoadvance setting for this object, which may have changed since the settings were
380      * initially loaded.
381      */
getAutoAdvanceSetting()382     public int getAutoAdvanceSetting() {
383         if (mTransientAutoAdvance != null) {
384             return mTransientAutoAdvance;
385         }
386 
387         return mAutoAdvance;
388     }
389 
390     /**
391      * Sets the transient autoadvance setting, which will override the initial autoadvance setting.
392      */
setAutoAdvanceSetting(final int autoAdvance)393     public void setAutoAdvanceSetting(final int autoAdvance) {
394         mTransientAutoAdvance = autoAdvance;
395     }
396 
397     /**
398      * @return true if {@link UIProvider.ConversationViewMode#OVERVIEW} mode is set. In the event
399      * that the setting is not yet set, fall back to
400      * {@link UIProvider.ConversationViewMode#DEFAULT}.
401      */
isOverviewMode()402     public boolean isOverviewMode() {
403         final int val = (conversationViewMode != UIProvider.ConversationViewMode.UNDEFINED) ?
404                 conversationViewMode : UIProvider.ConversationViewMode.DEFAULT;
405         return (val == UIProvider.ConversationViewMode.OVERVIEW);
406     }
407 
408     /**
409      * Return the swipe setting for the settings provided. It is safe to pass this method
410      * a null object. It always returns a valid {@link Swipe} setting.
411      * @return the auto advance setting, a constant from {@link Swipe}
412      */
getSwipeSetting(Settings settings)413     public static int getSwipeSetting(Settings settings) {
414         return settings != null ? settings.swipe : sDefault.swipe;
415     }
416 
417     @SuppressWarnings("hiding")
418     public static final Creator<Settings> CREATOR = new Creator<Settings>() {
419         @Override
420         public Settings createFromParcel(Parcel source) {
421             return new Settings(source);
422         }
423 
424         @Override
425         public Settings[] newArray(int size) {
426             return new Settings[size];
427         }
428     };
429 
430     /**
431      *  Get the maximum size in bytes for attachments.
432      */
getMaxAttachmentSize()433     public int getMaxAttachmentSize() {
434         return maxAttachmentSize <= 0 ? DEFAULT_MAX_ATTACHMENT_SIZE : maxAttachmentSize;
435     }
436 
437     @Override
equals(final Object aThat)438     public boolean equals(final Object aThat) {
439         LogUtils.d(LOG_TAG, "Settings.equals(%s)", aThat);
440         if (this == aThat) {
441             return true;
442         }
443         if ((aThat == null) || (aThat.getClass() != this.getClass())) {
444             return false;
445         }
446         final Settings that = (Settings) aThat;
447         final boolean autoAdvanceEquals = mTransientAutoAdvance != null
448                 ? mTransientAutoAdvance.equals(that.mTransientAutoAdvance)
449                 : that.mTransientAutoAdvance == null;
450         return (TextUtils.equals(signature, that.signature)
451                 && mAutoAdvance == that.mAutoAdvance
452                 && autoAdvanceEquals
453                 && snapHeaders == that.snapHeaders
454                 && replyBehavior == that.replyBehavior
455                 && convListIcon == that.convListIcon
456                 && confirmDelete == that.confirmDelete
457                 && confirmArchive == that.confirmArchive
458                 && confirmSend == that.confirmSend
459                 && Objects.equal(defaultInbox, that.defaultInbox)
460                 // Not checking default Inbox name, since is is identical to the URI check above.
461                 && forceReplyFromDefault == that.forceReplyFromDefault
462                 && maxAttachmentSize == that.maxAttachmentSize
463                 && swipe == that.swipe
464                 && importanceMarkersEnabled == that.importanceMarkersEnabled
465                 && showChevronsEnabled == that.showChevronsEnabled
466                 && setupIntentUri == that.setupIntentUri
467                 && conversationViewMode == that.conversationViewMode
468                 && TextUtils.equals(veiledAddressPattern, that.veiledAddressPattern))
469                 && Objects.equal(moveToInbox, that.moveToInbox)
470                 && welcomeTourShownVersion == that.welcomeTourShownVersion;
471     }
472 
473     @Override
hashCode()474     public int hashCode() {
475         if (mHashCode == 0) {
476             mHashCode = super.hashCode()
477                     ^ Objects.hashCode(signature, mAutoAdvance, mTransientAutoAdvance,
478                     snapHeaders, replyBehavior, convListIcon, confirmDelete, confirmArchive,
479                     confirmSend, defaultInbox, forceReplyFromDefault, maxAttachmentSize, swipe,
480                     importanceMarkersEnabled, showChevronsEnabled, setupIntentUri,
481                     conversationViewMode, veiledAddressPattern, moveToInbox,
482                     welcomeTourShownVersion);
483         }
484         return mHashCode;
485     }
486 }
487