AbstractSyncService.java revision 1b275b9408d5b856e2482fa3951827489e9585cc
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;
23ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
24ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.content.Context;
25ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.net.ConnectivityManager;
26ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.net.NetworkInfo;
27ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.net.NetworkInfo.DetailedState;
28ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport android.util.Log;
29ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
3067698e240187c902bed123bf18d342ff25ec75c7Marc Blankimport java.util.ArrayList;
3167698e240187c902bed123bf18d342ff25ec75c7Marc Blank
32ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank/**
33ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Base class for all protocol services SyncManager (extends Service, implements
34ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * Runnable) instantiates subclasses to run a sync (either timed, or push, or
35ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * mail placed in outbox, etc.) EasSyncService is currently implemented; my goal
36ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * would be to move IMAP to this structure when it comes time to introduce push
37ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank * functionality.
38ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank */
39ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankpublic abstract class AbstractSyncService implements Runnable {
40ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
41ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public String TAG = "ProtocolService";
42ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
43ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String SUMMARY_PROTOCOL = "_SUMMARY_";
44ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String SYNCED_PROTOCOL = "_SYNCING_";
45ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String MOVE_FAVORITES_PROTOCOL = "_MOVE_FAVORITES_";
46ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int CONNECT_TIMEOUT = 30000;
47ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int NETWORK_WAIT = 15000;
48ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int SECS = 1000;
49ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int MINS = 60 * SECS;
50ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int HRS = 60 * MINS;
51ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int DAYS = 24 * HRS;
52ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String IMAP_PROTOCOL = "imap";
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;
58ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
59ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Making SSL connections is so slow that I'd prefer that only one be
60ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // executed at a time
61ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Kindly subclasses will synchronize on this before making an SSL
62ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // connection
63ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static Object sslGovernorToken = new Object();
64ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Mailbox mMailbox;
65ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected long mMailboxId;
66ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected Thread mThread;
67ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected int mExitStatus = EXIT_EXCEPTION;
68ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected String mMailboxName;
69ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Account mAccount;
70ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected Context mContext;
71ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    public int mChangeCount = 0;
72ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    public int mSyncReason = 0;
731b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    protected volatile boolean mStop = false;
741b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    private Object mSynchronizer = new Object();
75ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
76d95115d72be6797835e1286fb8f0d2e5a01cf3a8Marc Blank    protected volatile long mRequestTime = 0;
77ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected ArrayList<PartRequest> mPartRequests = new ArrayList<PartRequest>();
78ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected PartRequest mPendingPartRequest = null;
79ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
80ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
81ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to request that the service stop itself cleanly
82ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
83ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void stop();
84ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
85ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
86ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to indicate a user request requiring service has been
87ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * added to the service's pending request queue
88ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
89ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void ping();
90ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
91ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
92ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Called to validate an account; abstract to allow each protocol to do what
93ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * is necessary. For consistency with the Email app's original
94ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * functionality, success is indicated by a failure to throw an Exception
95ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * (ugh). Parameters are self-explanatory
967c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank     *
97ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param host
98ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param userName
99ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param password
100ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param port
101ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param ssl
102ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param context
103ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @throws MessagingException
104ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
105ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void validateAccount(String host, String userName, String password, int port,
106ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            boolean ssl, Context context) throws MessagingException;
107ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
108ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
109ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to determine the state of a running sync This is
110ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * currently unused
1117c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank     *
112ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @return status code
113ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
114ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public int getSyncStatus() {
115ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return 0;
116ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
117ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
118ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(Context _context, Mailbox _mailbox) {
119ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mContext = _context;
120ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailbox = _mailbox;
121ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxId = _mailbox.mId;
122ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxName = _mailbox.mServerId;
123ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mAccount = Account.restoreAccountWithId(_context, _mailbox.mAccountKey);
124ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
125ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
126ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Will be required when subclasses are instantiated by name
127ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(String prefix) {
128ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
129ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
130ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
131ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * The UI can call this static method to perform account validation.  This method wraps each
132ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * protocol's validateAccount method.   Arguments are self-explanatory, except where noted.
1337c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank     *
134ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param klass the protocol class (EasSyncService.class for example)
135ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param host
136ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param userName
137ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param password
138ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param port
139ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param ssl
140ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param context
141ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @throws MessagingException
142ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
143ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    static public void validate(Class<? extends AbstractSyncService> klass, String host,
144ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            String userName, String password, int port, boolean ssl, Context context)
145ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throws MessagingException {
146ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        AbstractSyncService svc;
147ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        try {
148ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            svc = klass.newInstance();
149ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            svc.validateAccount(host, userName, password, port, ssl, context);
150ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (IllegalAccessException e) {
151ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throw new MessagingException("internal error", e);
152ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (InstantiationException e) {
153ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throw new MessagingException("internal error", e);
154ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
155ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
156ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
157ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static class ValidationResult {
158ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int NO_FAILURE = 0;
159ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int CONNECTION_FAILURE = 1;
160ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int VALIDATION_FAILURE = 2;
161ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int EXCEPTION = 3;
162ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
163ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final ValidationResult succeeded = new ValidationResult(true, NO_FAILURE, null);
164ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        boolean success;
165ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        int failure = NO_FAILURE;
166ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String reason = null;
167ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        Exception exception = null;
168ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
169ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success, int _failure, String _reason) {
170ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
171ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = _failure;
172ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            reason = _reason;
173ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
174ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
175ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success) {
176ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
177ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
178ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
179ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(Exception e) {
180ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = false;
181ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = EXCEPTION;
182ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            exception = e;
183ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
184ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
185ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public boolean isSuccess() {
186ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return success;
187ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
188ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
189ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public String getReason() {
190ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return reason;
191ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
192ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
193ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
1941b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    public boolean isStopped() {
1951b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        return mStop;
1961b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    }
1971b275b9408d5b856e2482fa3951827489e9585ccMarc Blank
1981b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    public Object getSynchronizer() {
1991b275b9408d5b856e2482fa3951827489e9585ccMarc Blank        return mSynchronizer;
2001b275b9408d5b856e2482fa3951827489e9585ccMarc Blank    }
2011b275b9408d5b856e2482fa3951827489e9585ccMarc Blank
202ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
203ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Asks SyncManager for a WaitLock for this sync
204ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
205ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public final void runAwake() {
206ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        //SyncManager.runAwake(mMailboxId);
207ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
208ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
209ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
210ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Asks SyncManager to release any WaitLock and schedule an alarm at a specified number
211ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * of milliseconds in the future
212ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
213ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param millis
214ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
215ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public final void runAsleep(long millis) {
216ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        //SyncManager.runAsleep(mMailboxId, millis);
217ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
218ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
219ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
220ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Convenience method to do user logging (i.e. connection activity).  Saves a bunch of
221ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * repetitive code.
222ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
223ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param str the String to log
224ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
225ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void userLog(String str) {
2267c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank        if (Eas.USER_LOG) {
227ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            Log.i(TAG, str);
228ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
229ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
230ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
231ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank    /**
232ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     * Error log is used for serious issues that should always be logged
233ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     * @param str the string to log
234ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank     */
235ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void errorLog(String str) {
236ed5b71376cb6fc3f54d63268afbd798e0b0c0a1bMarc Blank        Log.e(TAG, str);
237ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
238ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
239ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
240ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Implements a delay until there is some kind of network connectivity available. This method
241ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * may be supplanted by functionality in SyncManager.
242ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
243ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @return the type of network connected to
244ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
245ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public int waitForConnectivity() {
246ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ConnectivityManager cm = (ConnectivityManager)mContext
247ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                .getSystemService(Context.CONNECTIVITY_SERVICE);
248ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        while (true) {
249ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            NetworkInfo info = cm.getActiveNetworkInfo();
250ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            if (info != null && info.isConnected()) {
251ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                DetailedState state = info.getDetailedState();
252ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                if (state == DetailedState.CONNECTED) {
253ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    return info.getType();
254ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                } else {
255ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    // TODO Happens sometimes; find out why...
256ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    userLog("Not quite connected?  Pause 1 second");
257ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
258ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                pause(1000);
259ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            } else {
260ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                userLog("Not connected; waiting 15 seconds");
261ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                pause(NETWORK_WAIT);
262ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
263ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
264ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
265ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
266ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
267ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Convenience method to generate a small wait
268ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
269ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param ms time to wait in milliseconds
270ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
271ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    private void pause(int ms) {
272ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        try {
273ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            Thread.sleep(ms);
274ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (InterruptedException e) {
275ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
276ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
277ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
278ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // What's below here is temporary
279ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
2807c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank    /**
281ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * PartRequest handling (common functionality)
282ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Can be overridden if desired, but IMAP/EAS both use the next three methods as-is
283ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
2847c582a7fb883b3be728f270fbe5277676fe37cf9Marc Blank
285ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void addPartRequest(PartRequest req) {
286ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
287ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            mPartRequests.add(req);
288d95115d72be6797835e1286fb8f0d2e5a01cf3a8Marc Blank            mRequestTime = System.currentTimeMillis();
289ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
290ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
291ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
292ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void removePartRequest(PartRequest req) {
293ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
294ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            mPartRequests.remove(req);
295ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
296ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
297ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
298ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public PartRequest hasPartRequest(long emailId, String part) {
299ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
300ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            for (PartRequest pr : mPartRequests) {
301ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                if (pr.emailId == emailId && pr.loc.equals(part))
302ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    return pr;
303ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
304ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
305ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return null;
306ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
307ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
308ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // CancelPartRequest is sent in response to user input to stop a request
309ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // (attachment load at this point)
310ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // that is in progress. This will almost certainly require code overriding
311ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // the base functionality, as
312ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // sockets may need to be closed, etc. and this functionality will be
313ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // service dependent. This returns
314ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // the canceled PartRequest or null
315ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public PartRequest cancelPartRequest(long emailId, String part) {
316ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        synchronized (mPartRequests) {
317ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            PartRequest p = null;
318ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            for (PartRequest pr : mPartRequests) {
319ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                if (pr.emailId == emailId && pr.loc.equals(part)) {
320ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    p = pr;
321ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                    break;
322ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                }
323ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
324ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            if (p != null) {
325ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                mPartRequests.remove(p);
326ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank                return p;
327ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            }
328ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
329ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return null;
330ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
331ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank}
332