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