1c5afb16430a145f20d7c887e45f47b38687054daMarc Blank/*
2c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * Copyright (C) 2008-2009 Marc Blank
3c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * Licensed to The Android Open Source Project.
4c5afb16430a145f20d7c887e45f47b38687054daMarc Blank *
5c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * Licensed under the Apache License, Version 2.0 (the "License");
6c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * you may not use this file except in compliance with the License.
7c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * You may obtain a copy of the License at
8c5afb16430a145f20d7c887e45f47b38687054daMarc Blank *
9c5afb16430a145f20d7c887e45f47b38687054daMarc Blank *      http://www.apache.org/licenses/LICENSE-2.0
10c5afb16430a145f20d7c887e45f47b38687054daMarc Blank *
11c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * Unless required by applicable law or agreed to in writing, software
12c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * distributed under the License is distributed on an "AS IS" BASIS,
13c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * See the License for the specific language governing permissions and
15c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * limitations under the License.
16c5afb16430a145f20d7c887e45f47b38687054daMarc Blank */
17c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
18c5afb16430a145f20d7c887e45f47b38687054daMarc Blankpackage com.android.emailsync;
19c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
20c5afb16430a145f20d7c887e45f47b38687054daMarc Blankimport android.content.Context;
21c5afb16430a145f20d7c887e45f47b38687054daMarc Blankimport android.net.ConnectivityManager;
22c5afb16430a145f20d7c887e45f47b38687054daMarc Blankimport android.net.NetworkInfo;
23c5afb16430a145f20d7c887e45f47b38687054daMarc Blankimport android.os.Bundle;
24d1bae6c1e83bf4907096d4c2c16baaba330ca5b1Yu Ping Huimport android.text.format.DateUtils;
25c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
26e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport com.android.emailcommon.provider.Account;
27e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport com.android.emailcommon.provider.HostAuth;
28e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blankimport com.android.emailcommon.provider.Mailbox;
29560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils;
30e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank
31c5afb16430a145f20d7c887e45f47b38687054daMarc Blankimport java.util.concurrent.LinkedBlockingQueue;
32c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
33c5afb16430a145f20d7c887e45f47b38687054daMarc Blank/**
34c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * Base class for all protocol services SyncManager (extends Service, implements
35c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * Runnable) instantiates subclasses to run a sync (either timed, or push, or
36c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * mail placed in outbox, etc.) EasSyncService is currently implemented; my goal
37c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * would be to move IMAP to this structure when it comes time to introduce push
38c5afb16430a145f20d7c887e45f47b38687054daMarc Blank * functionality.
39c5afb16430a145f20d7c887e45f47b38687054daMarc Blank */
40c5afb16430a145f20d7c887e45f47b38687054daMarc Blankpublic abstract class AbstractSyncService implements Runnable {
41c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
42c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public String TAG = "AbstractSyncService";
43c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
44c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static final int EXIT_DONE = 0;
45c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static final int EXIT_IO_ERROR = 1;
46c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static final int EXIT_LOGIN_FAILURE = 2;
47c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static final int EXIT_EXCEPTION = 3;
48c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static final int EXIT_SECURITY_FAILURE = 4;
49c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static final int EXIT_ACCESS_DENIED = 5;
50c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
51c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public Mailbox mMailbox;
52c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    protected long mMailboxId;
53c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    protected int mExitStatus = EXIT_EXCEPTION;
54dba0b20d955d88831ce94d96dbdadc49dba4761aMarc Blank    protected String mExitReason;
55c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    protected String mMailboxName;
56c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public Account mAccount;
57c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public Context mContext;
58c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public int mChangeCount = 0;
59c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public volatile int mSyncReason = 0;
60c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    protected volatile boolean mStop = false;
61c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public volatile Thread mThread;
62c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    protected final Object mSynchronizer = new Object();
63c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    // Whether or not the sync service is valid (usable)
64c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public boolean mIsValid = true;
65c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
66c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public boolean mUserLog = true; // STOPSHIP
67c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public boolean mFileLog = false;
68c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
69c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    protected volatile long mRequestTime = 0;
70c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    protected LinkedBlockingQueue<Request> mRequestQueue = new LinkedBlockingQueue<Request>();
71c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
72c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
73c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Sent by SyncManager to request that the service stop itself cleanly
74c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
75c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public abstract void stop();
76c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
77c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
78c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Sent by SyncManager to indicate that an alarm has fired for this service, and that its
79c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * pending (network) operation has timed out. The service is NOT automatically stopped,
80c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * although the behavior is service dependent.
81c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     *
82c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @return true if the operation was stopped normally; false if the thread needed to be
83c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * interrupted.
84c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
85c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public abstract boolean alarm();
86c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
87c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
88c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Sent by SyncManager to request that the service reset itself cleanly; the meaning of this
89c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * operation is service dependent.
90c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
91c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public abstract void reset();
92c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
93c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
94c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Called to validate an account; abstract to allow each protocol to do what
95c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * is necessary. For consistency with the Email app's original
96c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * functionality, success is indicated by a failure to throw an Exception
97c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * (ugh). Parameters are self-explanatory
98c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     *
99c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @param hostAuth
100c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @return a Bundle containing a result code and, depending on the result, a PolicySet or an
101c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * error message
102c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
103c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public abstract Bundle validateAccount(HostAuth hostAuth, Context context);
104c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
105c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
106c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Called to clear the syncKey for the calendar associated with this service; this is necessary
107c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * because changes to calendar sync state cause a reset of data.
108c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
109c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public abstract void resetCalendarSyncKey();
110c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
111c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public AbstractSyncService(Context _context, Mailbox _mailbox) {
112c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        mContext = _context;
113c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        mMailbox = _mailbox;
114c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        mMailboxId = _mailbox.mId;
115c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        mMailboxName = _mailbox.mServerId;
116c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        mAccount = Account.restoreAccountWithId(_context, _mailbox.mAccountKey);
117c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
118c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
119c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    // Will be required when subclasses are instantiated by name
120c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public AbstractSyncService(String prefix) {
121c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
122c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
123c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
124c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * The UI can call this static method to perform account validation.  This method wraps each
125c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * protocol's validateAccount method.   Arguments are self-explanatory, except where noted.
126c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     *
127c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @param klass the protocol class (EasSyncService.class for example)
128c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @param hostAuth
129c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @param context
130c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @return a Bundle containing a result code and, depending on the result, a PolicySet or an
131c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * error message
132c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
133c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static Bundle validate(Class<? extends AbstractSyncService> klass,
134c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            HostAuth hostAuth, Context context) {
135c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        AbstractSyncService svc;
136c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        try {
137c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            svc = klass.newInstance();
138c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            return svc.validateAccount(hostAuth, context);
139c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        } catch (IllegalAccessException e) {
140c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        } catch (InstantiationException e) {
141c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
142c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        return null;
143c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
144c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
145c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public static class ValidationResult {
146c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        static final int NO_FAILURE = 0;
147c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        static final int CONNECTION_FAILURE = 1;
148c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        static final int VALIDATION_FAILURE = 2;
149c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        static final int EXCEPTION = 3;
150c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
151c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        static final ValidationResult succeeded = new ValidationResult(true, NO_FAILURE, null);
152c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        boolean success;
153c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        int failure = NO_FAILURE;
154c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        String reason = null;
155c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        Exception exception = null;
156c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
157c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        ValidationResult(boolean _success, int _failure, String _reason) {
158c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            success = _success;
159c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            failure = _failure;
160c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            reason = _reason;
161c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
162c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
163c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        ValidationResult(boolean _success) {
164c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            success = _success;
165c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
166c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
167c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        ValidationResult(Exception e) {
168c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            success = false;
169c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            failure = EXCEPTION;
170c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            exception = e;
171c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
172c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
173c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        public boolean isSuccess() {
174c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            return success;
175c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
176c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
177c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        public String getReason() {
178c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            return reason;
179c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
180c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
181c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
182c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public boolean isStopped() {
183c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        return mStop;
184c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
185c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
186c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public Object getSynchronizer() {
187c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        return mSynchronizer;
188c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
189c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
190c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
191c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Convenience methods to do user logging (i.e. connection activity).  Saves a bunch of
192c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * repetitive code.
193c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
194c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void userLog(String string, int code, String string2) {
195c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        if (mUserLog) {
196c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            userLog(string + code + string2);
197c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
198c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
199c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
200c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void userLog(String string, int code) {
201c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        if (mUserLog) {
202c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            userLog(string + code);
203c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
204c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
205c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
206c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void userLog(String str, Exception e) {
207c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        if (mUserLog) {
208560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy            LogUtils.e(TAG, str, e);
209c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        } else {
210560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy            LogUtils.e(TAG, str + e);
211c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
212c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        if (mFileLog) {
213c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            FileLogger.log(e);
214c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
215c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
216c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
217c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
218c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Standard logging for EAS.
219560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy     * If user logging is active, we concatenate any arguments and log them using LogUtils.d
220c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * We also check for file logging, and log appropriately
221c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @param strings strings to concatenate and log
222c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
223c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void userLog(String ...strings) {
224c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        if (mUserLog) {
225c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            String logText;
226c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            if (strings.length == 1) {
227c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                logText = strings[0];
228c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            } else {
229c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                StringBuilder sb = new StringBuilder(64);
230c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                for (String string: strings) {
231c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                    sb.append(string);
232c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                }
233c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                logText = sb.toString();
234c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            }
235560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy            LogUtils.d(TAG, logText);
236c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            if (mFileLog) {
237c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                FileLogger.log(TAG, logText);
238c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            }
239c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
240c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
241c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
242c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
243c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Error log is used for serious issues that should always be logged
244c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @param str the string to log
245c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
246c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void errorLog(String str) {
247560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy        LogUtils.e(TAG, str);
248c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        if (mFileLog) {
249c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            FileLogger.log(TAG, str);
250c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
251c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
252c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
253c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
254c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Waits for up to 10 seconds for network connectivity; returns whether or not there is
255c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * network connectivity.
256c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     *
257c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * @return whether there is network connectivity
258c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
259c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public boolean hasConnectivity() {
260c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        ConnectivityManager cm =
261c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
262c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        int tries = 0;
263c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        while (tries++ < 1) {
264c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            // Use the same test as in ExchangeService#waitForConnectivity
265c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            // TODO: Create common code for this test in emailcommon
266c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            NetworkInfo info = cm.getActiveNetworkInfo();
267c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            if (info != null) {
268c5afb16430a145f20d7c887e45f47b38687054daMarc Blank                return true;
269c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            }
270c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            try {
271d1bae6c1e83bf4907096d4c2c16baaba330ca5b1Yu Ping Hu                Thread.sleep(10 * DateUtils.SECOND_IN_MILLIS);
272c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            } catch (InterruptedException e) {
273c5afb16430a145f20d7c887e45f47b38687054daMarc Blank            }
274c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        }
275c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        return false;
276c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
277c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
278c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    /**
279c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Request handling (common functionality)
280c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     * Can be overridden if desired
281c5afb16430a145f20d7c887e45f47b38687054daMarc Blank     */
282c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
283c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void addRequest(Request req) {
284e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank        if (!mRequestQueue.contains(req)) {
285e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank            mRequestQueue.offer(req);
286e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank        }
287c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
288c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
289c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void removeRequest(Request req) {
290c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        mRequestQueue.remove(req);
291c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
292c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
293c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public boolean hasPendingRequests() {
294c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        return !mRequestQueue.isEmpty();
295c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
296c5afb16430a145f20d7c887e45f47b38687054daMarc Blank
297c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    public void clearRequests() {
298c5afb16430a145f20d7c887e45f47b38687054daMarc Blank        mRequestQueue.clear();
299c5afb16430a145f20d7c887e45f47b38687054daMarc Blank    }
300c5afb16430a145f20d7c887e45f47b38687054daMarc Blank}
301