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
207372782488977df778a33d990401ce9e397f646bMarc Blankimport com.android.emailcommon.provider.Account;
2191e6d2a4ff733417090b06f8644615a0fb9160c0Ben Komaloimport com.android.emailcommon.provider.HostAuth;
224d8774462ace9a45154b2df418b9f2fe7a9c685dBen Komaloimport com.android.emailcommon.provider.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;
297b4c3ab965df57afdcddc5bce109467458c409f4Marc Blankimport android.os.Bundle;
30ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.util.Log;
31ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
32b20a744b01fef0082b106f44612a3d0fec361800Marc Blankimport java.util.concurrent.LinkedBlockingQueue;
3367698e240187c902bed123bf18d342ff25ec75c7Marc Blank
34ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/**
35ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Base class for all protocol services SyncManager (extends Service, implements
36ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Runnable) instantiates subclasses to run a sync (either timed, or push, or
37ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * mail placed in outbox, etc.) EasSyncService is currently implemented; my goal
38ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * would be to move IMAP to this structure when it comes time to introduce push
39ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * functionality.
40ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank */
41ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankpublic abstract class AbstractSyncService implements Runnable {
42ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
431b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    public String TAG = "AbstractSyncService";
44ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
45c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int SECONDS = 1000;
46c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int MINUTES = 60*SECONDS;
47c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int HOURS = 60*MINUTES;
48c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int DAYS = 24*HOURS;
49c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank
50c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int CONNECT_TIMEOUT = 30*SECONDS;
51c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank    public static final int NETWORK_WAIT = 15*SECONDS;
52c1e79c036cd2a40e8a6e66b8ea4d37d121d355baMarc Blank
53ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String EAS_PROTOCOL = "eas";
54ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_DONE = 0;
55ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_IO_ERROR = 1;
56ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_LOGIN_FAILURE = 2;
57ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_EXCEPTION = 3;
5820da011530088036d2bf45d3836d6986a4b5d423Marc Blank    public static final int EXIT_SECURITY_FAILURE = 4;
5977186bb1a174432ef272584374942d8b9228e39cMarc Blank    public static final int EXIT_ACCESS_DENIED = 5;
60ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
61ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Mailbox mMailbox;
62ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected long mMailboxId;
63ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected int mExitStatus = EXIT_EXCEPTION;
64ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected String mMailboxName;
65ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Account mAccount;
661b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    public Context mContext;
67ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    public int mChangeCount = 0;
68feb60882fdf4ea57d65717b55c265e91dae9f9ceMarc Blank    public volatile int mSyncReason = 0;
691b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    protected volatile boolean mStop = false;
70d0bb59f5d1c7e1d8b6c2350d3ad769a2073a0230Marc Blank    protected volatile Thread mThread;
71d0bb59f5d1c7e1d8b6c2350d3ad769a2073a0230Marc Blank    protected final Object mSynchronizer = new Object();
72ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
73d95115d72be6797835e1286fb8f0d2e5a01cf3a8Marc Blank    protected volatile long mRequestTime = 0;
74b20a744b01fef0082b106f44612a3d0fec361800Marc Blank    protected LinkedBlockingQueue<Request> mRequestQueue = new LinkedBlockingQueue<Request>();
75ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
76ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
77ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to request that the service stop itself cleanly
78ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
79ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void stop();
80ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
81ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
825b4baf900a589e0ed00289631f6d0e1f85a95ecdMarc Blank     * Sent by SyncManager to indicate that an alarm has fired for this service, and that its
835b4baf900a589e0ed00289631f6d0e1f85a95ecdMarc Blank     * pending (network) operation has timed out. The service is NOT automatically stopped,
845b4baf900a589e0ed00289631f6d0e1f85a95ecdMarc Blank     * although the behavior is service dependent.
855b4baf900a589e0ed00289631f6d0e1f85a95ecdMarc Blank     *
865b4baf900a589e0ed00289631f6d0e1f85a95ecdMarc Blank     * @return true if the operation was stopped normally; false if the thread needed to be
875b4baf900a589e0ed00289631f6d0e1f85a95ecdMarc Blank     * interrupted.
88ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
895b4baf900a589e0ed00289631f6d0e1f85a95ecdMarc Blank    public abstract boolean alarm();
90e8ea6833e0541f0a0a3ceb1d78c84ac9ce359210Marc Blank
91e8ea6833e0541f0a0a3ceb1d78c84ac9ce359210Marc Blank    /**
92e8ea6833e0541f0a0a3ceb1d78c84ac9ce359210Marc Blank     * Sent by SyncManager to request that the service reset itself cleanly; the meaning of this
93e8ea6833e0541f0a0a3ceb1d78c84ac9ce359210Marc Blank     * operation is service dependent.
94e8ea6833e0541f0a0a3ceb1d78c84ac9ce359210Marc Blank     */
95e8ea6833e0541f0a0a3ceb1d78c84ac9ce359210Marc Blank    public abstract void reset();
96ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
97ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
98ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Called to validate an account; abstract to allow each protocol to do what
99ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * is necessary. For consistency with the Email app's original
100ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * functionality, success is indicated by a failure to throw an Exception
101ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * (ugh). Parameters are self-explanatory
1027c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank     *
10391e6d2a4ff733417090b06f8644615a0fb9160c0Ben Komalo     * @param hostAuth
1047b4c3ab965df57afdcddc5bce109467458c409f4Marc Blank     * @return a Bundle containing a result code and, depending on the result, a PolicySet or an
1057b4c3ab965df57afdcddc5bce109467458c409f4Marc Blank     * error message
106ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
10791e6d2a4ff733417090b06f8644615a0fb9160c0Ben Komalo    public abstract Bundle validateAccount(HostAuth hostAuth, Context context);
108ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
109ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(Context _context, Mailbox _mailbox) {
110ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mContext = _context;
111ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailbox = _mailbox;
112ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxId = _mailbox.mId;
113ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxName = _mailbox.mServerId;
114ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mAccount = Account.restoreAccountWithId(_context, _mailbox.mAccountKey);
115ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
116ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
117ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Will be required when subclasses are instantiated by name
118ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(String prefix) {
119ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
120ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
121ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
122ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * The UI can call this static method to perform account validation.  This method wraps each
123ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * protocol's validateAccount method.   Arguments are self-explanatory, except where noted.
1247c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank     *
125ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param klass the protocol class (EasSyncService.class for example)
12691e6d2a4ff733417090b06f8644615a0fb9160c0Ben Komalo     * @param hostAuth
127ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param context
1287b4c3ab965df57afdcddc5bce109467458c409f4Marc Blank     * @return a Bundle containing a result code and, depending on the result, a PolicySet or an
1297b4c3ab965df57afdcddc5bce109467458c409f4Marc Blank     * error message
130ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
13191e6d2a4ff733417090b06f8644615a0fb9160c0Ben Komalo    public static Bundle validate(Class<? extends AbstractSyncService> klass,
13291e6d2a4ff733417090b06f8644615a0fb9160c0Ben Komalo            HostAuth hostAuth, Context context) {
133ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        AbstractSyncService svc;
134ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        try {
135ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            svc = klass.newInstance();
13691e6d2a4ff733417090b06f8644615a0fb9160c0Ben Komalo            return svc.validateAccount(hostAuth, context);
137ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (IllegalAccessException e) {
138ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (InstantiationException e) {
139ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
1407b4c3ab965df57afdcddc5bce109467458c409f4Marc Blank        return null;
141ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
142ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
143ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static class ValidationResult {
144ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int NO_FAILURE = 0;
145ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int CONNECTION_FAILURE = 1;
146ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int VALIDATION_FAILURE = 2;
147ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int EXCEPTION = 3;
148ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
149ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final ValidationResult succeeded = new ValidationResult(true, NO_FAILURE, null);
150ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        boolean success;
151ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        int failure = NO_FAILURE;
152ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String reason = null;
153ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        Exception exception = null;
154ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
155ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success, int _failure, String _reason) {
156ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
157ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = _failure;
158ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            reason = _reason;
159ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
160ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
161ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success) {
162ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
163ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
164ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
165ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(Exception e) {
166ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = false;
167ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = EXCEPTION;
168ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            exception = e;
169ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
170ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
171ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public boolean isSuccess() {
172ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return success;
173ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
174ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
175ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public String getReason() {
176ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return reason;
177ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
178ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
179ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1801b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    public boolean isStopped() {
1811b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        return mStop;
1821b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    }
1831b275b9408d5b856e2482fa3951827489e9585ccMarc Blank
1841b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    public Object getSynchronizer() {
1851b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        return mSynchronizer;
1861b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    }
1871b275b9408d5b856e2482fa3951827489e9585ccMarc Blank
188ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
1890a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * Convenience methods to do user logging (i.e. connection activity).  Saves a bunch of
190ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * repetitive code.
191ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
1920a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void userLog(String string, int code, String string2) {
1930a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        if (Eas.USER_LOG) {
1940a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            userLog(string + code + string2);
1950a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        }
1960a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    }
1970a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank
1980a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void userLog(String string, int code) {
1990a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        if (Eas.USER_LOG) {
2000a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            userLog(string + code);
2010a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank        }
2020a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    }
2030a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank
2041431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank    public void userLog(String str, Exception e) {
2051431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank        if (Eas.USER_LOG) {
2061431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank            Log.e(TAG, str, e);
2071431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank        } else {
2081431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank            Log.e(TAG, str + e);
2091431215b5fc40d0d6498b0fe602ad4d1b8a66ff3Marc Blank        }
2101403386ebffa1b6093a506a6a24db4523acdc315Marc Blank        if (Eas.FILE_LOG) {
2111403386ebffa1b6093a506a6a24db4523acdc315Marc Blank            FileLogger.log(e);
2121403386ebffa1b6093a506a6a24db4523acdc315Marc Blank        }
2131403386ebffa1b6093a506a6a24db4523acdc315Marc Blank    }
2141403386ebffa1b6093a506a6a24db4523acdc315Marc Blank
2150a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    /**
2160a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * Standard logging for EAS.
2170a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * If user logging is active, we concatenate any arguments and log them using Log.d
2180a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * We also check for file logging, and log appropriately
2190a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     * @param strings strings to concatenate and log
2200a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank     */
2210a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank    public void userLog(String ...strings) {
2227c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        if (Eas.USER_LOG) {
2230a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            String logText;
2240a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            if (strings.length == 1) {
2250a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                logText = strings[0];
2260a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            } else {
2270a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                StringBuilder sb = new StringBuilder(64);
2280a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                for (String string: strings) {
2290a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                    sb.append(string);
2300a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                }
2310a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                logText = sb.toString();
2320a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            }
2330a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank            Log.d(TAG, logText);
23477424af660458104b732bdcb718874b17d0cab3aMarc Blank            if (Eas.FILE_LOG) {
2350a4d05f0d8753c67364f7167e62cea82aef9a81eMarc Blank                FileLogger.log(TAG, logText);
23677424af660458104b732bdcb718874b17d0cab3aMarc Blank            }
237ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
238ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
239ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
240ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    /**
241ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     * Error log is used for serious issues that should always be logged
242ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     * @param str the string to log
243ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     */
244ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void errorLog(String str) {
245ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank        Log.e(TAG, str);
24677424af660458104b732bdcb718874b17d0cab3aMarc Blank        if (Eas.FILE_LOG) {
24777424af660458104b732bdcb718874b17d0cab3aMarc Blank            FileLogger.log(TAG, str);
24877424af660458104b732bdcb718874b17d0cab3aMarc Blank        }
249ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
250ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
251ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
2521b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank     * Waits for up to 10 seconds for network connectivity; returns whether or not there is
2531b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank     * network connectivity.
254ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
2551b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank     * @return whether there is network connectivity
256ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
2571b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank    public boolean hasConnectivity() {
2581b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        ConnectivityManager cm =
25991e5c5bfa6a12679c7611160ad848d4fa2fc73adMarc Blank                (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
2601b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        int tries = 0;
2611b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        while (tries++ < 1) {
26291e5c5bfa6a12679c7611160ad848d4fa2fc73adMarc Blank            // Use the same test as in ExchangeService#waitForConnectivity
26391e5c5bfa6a12679c7611160ad848d4fa2fc73adMarc Blank            // TODO: Create common code for this test in emailcommon
264ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            NetworkInfo info = cm.getActiveNetworkInfo();
26591e5c5bfa6a12679c7611160ad848d4fa2fc73adMarc Blank            if (info != null) {
26691e5c5bfa6a12679c7611160ad848d4fa2fc73adMarc Blank                return true;
2671b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank            }
2681b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank            try {
2691b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank                Thread.sleep(10*SECONDS);
2701b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank            } catch (InterruptedException e) {
271ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
272ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
2731b06024587a4499bcf3f9005337e8f7cae5ffa26Marc Blank        return false;
274ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
275ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
276ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
2777531be7774769c84b499b1de5dc46da3a9468316Marc Blank     * Request handling (common functionality)
2787531be7774769c84b499b1de5dc46da3a9468316Marc Blank     * Can be overridden if desired
279ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
2807c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank
2817531be7774769c84b499b1de5dc46da3a9468316Marc Blank    public void addRequest(Request req) {
282b20a744b01fef0082b106f44612a3d0fec361800Marc Blank        mRequestQueue.offer(req);
283ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
284ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
2857531be7774769c84b499b1de5dc46da3a9468316Marc Blank    public void removeRequest(Request req) {
286b20a744b01fef0082b106f44612a3d0fec361800Marc Blank        mRequestQueue.remove(req);
287ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
288b20a744b01fef0082b106f44612a3d0fec361800Marc Blank
289b20a744b01fef0082b106f44612a3d0fec361800Marc Blank    public boolean hasPendingRequests() {
290b20a744b01fef0082b106f44612a3d0fec361800Marc Blank        return !mRequestQueue.isEmpty();
291057faf66b737bbc7df2eaf77ee7a63827785e1b9Marc Blank    }
292b20a744b01fef0082b106f44612a3d0fec361800Marc Blank
293057faf66b737bbc7df2eaf77ee7a63827785e1b9Marc Blank    public void clearRequests() {
294057faf66b737bbc7df2eaf77ee7a63827785e1b9Marc Blank        mRequestQueue.clear();
295057faf66b737bbc7df2eaf77ee7a63827785e1b9Marc Blank    }
296ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank}
297