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