AbstractSyncService.java revision 1403386ebffa1b6093a506a6a24db4523acdc315
1ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/*
2ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Copyright (C) 2008-2009 Marc Blank
3ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Licensed to The Android Open Source Project.
4ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *
5ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Licensed under the Apache License, Version 2.0 (the "License");
6ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * you may not use this file except in compliance with the License.
7ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * You may obtain a copy of the License at
8ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *
9ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *      http://www.apache.org/licenses/LICENSE-2.0
10ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank *
11ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Unless required by applicable law or agreed to in writing, software
12ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * distributed under the License is distributed on an "AS IS" BASIS,
13ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * See the License for the specific language governing permissions and
15ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * limitations under the License.
16ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank */
17ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
18ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankpackage com.android.exchange;
19ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
20ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.email.mail.MessagingException;
2167698e240187c902bed123bf18d342ff25ec75c7Marc Blankimport com.android.email.provider.EmailContent.Account;
2267698e240187c902bed123bf18d342ff25ec75c7Marc Blankimport com.android.email.provider.EmailContent.Mailbox;
2377424af660458104b732bdcb718874b17d0cab3aMarc Blankimport com.android.exchange.utility.FileLogger;
24ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
25ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.content.Context;
26ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.net.ConnectivityManager;
27ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.net.NetworkInfo;
28ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.net.NetworkInfo.DetailedState;
29ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.util.Log;
30ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
3167698e240187c902bed123bf18d342ff25ec75c7Marc Blankimport java.util.ArrayList;
3267698e240187c902bed123bf18d342ff25ec75c7Marc Blank
33ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/**
34ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Base class for all protocol services SyncManager (extends Service, implements
35ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Runnable) instantiates subclasses to run a sync (either timed, or push, or
36ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * mail placed in outbox, etc.) EasSyncService is currently implemented; my goal
37ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * would be to move IMAP to this structure when it comes time to introduce push
38ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * functionality.
39ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank */
40ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankpublic abstract class AbstractSyncService implements Runnable {
41ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
421b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    public String TAG = "AbstractSyncService";
43ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
44ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String SUMMARY_PROTOCOL = "_SUMMARY_";
45ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String SYNCED_PROTOCOL = "_SYNCING_";
46ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String MOVE_FAVORITES_PROTOCOL = "_MOVE_FAVORITES_";
47c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int SECONDS = 1000;
48c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int MINUTES = 60*SECONDS;
49c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int HOURS = 60*MINUTES;
50c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int DAYS = 24*HOURS;
51c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank
52c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int CONNECT_TIMEOUT = 30*SECONDS;
53c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int NETWORK_WAIT = 15*SECONDS;
54c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank
55ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String IMAP_PROTOCOL = "imap";
56ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String EAS_PROTOCOL = "eas";
57ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_DONE = 0;
58ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_IO_ERROR = 1;
59ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_LOGIN_FAILURE = 2;
60ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_EXCEPTION = 3;
61ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
62ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Mailbox mMailbox;
63ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected long mMailboxId;
64ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected Thread mThread;
65ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected int mExitStatus = EXIT_EXCEPTION;
66ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected String mMailboxName;
67ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Account mAccount;
681b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    public Context mContext;
69ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    public int mChangeCount = 0;
70ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    public int mSyncReason = 0;
711b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    protected volatile boolean mStop = false;
72c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    protected Object mSynchronizer = new Object();
73ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
74d95115d72be6797835e1286fb8f0d2e5a01cf3a8Marc Blank    protected volatile long mRequestTime = 0;
75ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected ArrayList<PartRequest> mPartRequests = new ArrayList<PartRequest>();
76ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected PartRequest mPendingPartRequest = null;
77ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
78ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
79ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to request that the service stop itself cleanly
80ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
81ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void stop();
82ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
83ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
84ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to indicate a user request requiring service has been
85ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * added to the service's pending request queue
86ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
87ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void ping();
88ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
89ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
90ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Called to validate an account; abstract to allow each protocol to do what
91ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * is necessary. For consistency with the Email app's original
92ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * functionality, success is indicated by a failure to throw an Exception
93ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * (ugh). Parameters are self-explanatory
947c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank     *
95ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param host
96ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param userName
97ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param password
98ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param port
99ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param ssl
100ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param context
101ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @throws MessagingException
102ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
103ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void validateAccount(String host, String userName, String password, int port,
104ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            boolean ssl, Context context) throws MessagingException;
105ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
106ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(Context _context, Mailbox _mailbox) {
107ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mContext = _context;
108ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailbox = _mailbox;
109ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxId = _mailbox.mId;
110ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxName = _mailbox.mServerId;
111ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mAccount = Account.restoreAccountWithId(_context, _mailbox.mAccountKey);
112ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
113ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
114ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Will be required when subclasses are instantiated by name
115ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(String prefix) {
116ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
117ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
118ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
119ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * The UI can call this static method to perform account validation.  This method wraps each
120ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * protocol's validateAccount method.   Arguments are self-explanatory, except where noted.
1217c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank     *
122ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param klass the protocol class (EasSyncService.class for example)
123ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param host
124ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param userName
125ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param password
126ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param port
127ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param ssl
128ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param context
129ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @throws MessagingException
130ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
131ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    static public void validate(Class<? extends AbstractSyncService> klass, String host,
132ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            String userName, String password, int port, boolean ssl, Context context)
133ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throws MessagingException {
134ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        AbstractSyncService svc;
135ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        try {
136ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            svc = klass.newInstance();
137ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            svc.validateAccount(host, userName, password, port, ssl, context);
138ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (IllegalAccessException e) {
139ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throw new MessagingException("internal error", e);
140ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (InstantiationException e) {
141ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throw new MessagingException("internal error", e);
142ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
143ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
144ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
145ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static class ValidationResult {
146ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int NO_FAILURE = 0;
147ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int CONNECTION_FAILURE = 1;
148ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int VALIDATION_FAILURE = 2;
149ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int EXCEPTION = 3;
150ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
151ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final ValidationResult succeeded = new ValidationResult(true, NO_FAILURE, null);
152ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        boolean success;
153ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        int failure = NO_FAILURE;
154ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String reason = null;
155ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        Exception exception = null;
156ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
157ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success, int _failure, String _reason) {
158ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
159ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = _failure;
160ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            reason = _reason;
161ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
162ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
163ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success) {
164ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
165ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
166ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
167ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(Exception e) {
168ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = false;
169ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = EXCEPTION;
170ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            exception = e;
171ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
172ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
173ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public boolean isSuccess() {
174ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return success;
175ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
176ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
177ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public String getReason() {
178ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return reason;
179ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
180ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
181ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1821b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    public boolean isStopped() {
1831b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        return mStop;
1841b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    }
1851b275b9408d5b856e2482fa3951827489e9585ccMarc Blank
1861b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    public Object getSynchronizer() {
1871b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        return mSynchronizer;
1881b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    }
1891b275b9408d5b856e2482fa3951827489e9585ccMarc Blank
190ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
1910a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * Convenience methods to do user logging (i.e. connection activity).  Saves a bunch of
192ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * repetitive code.
193ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
1940a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void userLog(String string, int code, String string2) {
1950a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        if (Eas.USER_LOG) {
1960a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            userLog(string + code + string2);
1970a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        }
1980a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    }
1990a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank
2000a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void userLog(String string, int code) {
2010a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        if (Eas.USER_LOG) {
2020a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            userLog(string + code);
2030a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        }
2040a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    }
2050a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank
2061403386ebffa1b6093a506a6a24db4523acdc315Marc Blank    public void userLog(Exception e) {
2071403386ebffa1b6093a506a6a24db4523acdc315Marc Blank        if (Eas.FILE_LOG) {
2081403386ebffa1b6093a506a6a24db4523acdc315Marc Blank            FileLogger.log(e);
2091403386ebffa1b6093a506a6a24db4523acdc315Marc Blank        }
2101403386ebffa1b6093a506a6a24db4523acdc315Marc Blank    }
2111403386ebffa1b6093a506a6a24db4523acdc315Marc Blank
2120a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    /**
2130a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * Standard logging for EAS.
2140a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * If user logging is active, we concatenate any arguments and log them using Log.d
2150a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * We also check for file logging, and log appropriately
2160a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * @param strings strings to concatenate and log
2170a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     */
2180a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void userLog(String ...strings) {
2197c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        if (Eas.USER_LOG) {
2200a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            String logText;
2210a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            if (strings.length == 1) {
2220a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                logText = strings[0];
2230a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            } else {
2240a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                StringBuilder sb = new StringBuilder(64);
2250a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                for (String string: strings) {
2260a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                    sb.append(string);
2270a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                }
2280a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                logText = sb.toString();
2290a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            }
2300a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            Log.d(TAG, logText);
23177424af660458104b732bdcb718874b17d0cab3aMarc Blank            if (Eas.FILE_LOG) {
2320a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                FileLogger.log(TAG, logText);
23377424af660458104b732bdcb718874b17d0cab3aMarc Blank            }
234ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
235ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
236ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
237ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    /**
238ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     * Error log is used for serious issues that should always be logged
239ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     * @param str the string to log
240ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     */
241ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void errorLog(String str) {
242ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank        Log.e(TAG, str);
24377424af660458104b732bdcb718874b17d0cab3aMarc Blank        if (Eas.FILE_LOG) {
24477424af660458104b732bdcb718874b17d0cab3aMarc Blank            FileLogger.log(TAG, str);
24577424af660458104b732bdcb718874b17d0cab3aMarc Blank        }
246ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
247ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
248ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
2491b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank     * Waits for up to 10 seconds for network connectivity; returns whether or not there is
2501b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank     * network connectivity.
251ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
2521b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank     * @return whether there is network connectivity
253ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
2541b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    public boolean hasConnectivity() {
2551b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        ConnectivityManager cm =
2561b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank            (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
2571b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        int tries = 0;
2581b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        while (tries++ < 1) {
259ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            NetworkInfo info = cm.getActiveNetworkInfo();
260ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            if (info != null && info.isConnected()) {
261ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                DetailedState state = info.getDetailedState();
262ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                if (state == DetailedState.CONNECTED) {
2631b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank                    return true;
264ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
2651b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank            }
2661b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank            try {
2671b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank                Thread.sleep(10*SECONDS);
2681b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank            } catch (InterruptedException e) {
269ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
270ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
2711b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        return false;
272ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
273ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
274ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
275ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * PartRequest handling (common functionality)
276ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Can be overridden if desired, but IMAP/EAS both use the next three methods as-is
277ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
2787c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank
279ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void addPartRequest(PartRequest req) {
280ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
281ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            mPartRequests.add(req);
282d95115d72be6797835e1286fb8f0d2e5a01cf3a8Marc Blank            mRequestTime = System.currentTimeMillis();
283ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
284ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
285ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
286ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void removePartRequest(PartRequest req) {
287ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
288ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            mPartRequests.remove(req);
289ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
290ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
291ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
292ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public PartRequest hasPartRequest(long emailId, String part) {
293ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
294ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            for (PartRequest pr : mPartRequests) {
295ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                if (pr.emailId == emailId && pr.loc.equals(part))
296ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    return pr;
297ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
298ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
299ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return null;
300ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
301ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
3021b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    // cancelPartRequest is sent in response to user input to stop an attachment load
3031b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    // that is in progress. This will almost certainly require code overriding the base
3041b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    // functionality, as sockets may need to be closed, etc. and this functionality will be
3051b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    // service dependent. This returns the canceled PartRequest or null
306ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public PartRequest cancelPartRequest(long emailId, String part) {
307ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
308ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            PartRequest p = null;
309ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            for (PartRequest pr : mPartRequests) {
310ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                if (pr.emailId == emailId && pr.loc.equals(part)) {
311ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    p = pr;
312ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
313ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
314ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
315ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            if (p != null) {
316ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                mPartRequests.remove(p);
317ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                return p;
318ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
319ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
320ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return null;
321ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
322ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank}
323