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