AbstractSyncService.java revision 67698e240187c902bed123bf18d342ff25ec75c7
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.Email;
21ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blankimport com.android.email.mail.MessagingException;
2267698e240187c902bed123bf18d342ff25ec75c7Marc Blankimport com.android.email.provider.EmailContent.Account;
2367698e240187c902bed123bf18d342ff25ec75c7Marc Blankimport com.android.email.provider.EmailContent.Mailbox;
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
42ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public String TAG = "ProtocolService";
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_";
47ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int CONNECT_TIMEOUT = 30000;
48ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int NETWORK_WAIT = 15000;
49ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int SECS = 1000;
50ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int MINS = 60 * SECS;
51ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int HRS = 60 * MINS;
52ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int DAYS = 24 * HRS;
53ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String IMAP_PROTOCOL = "imap";
54ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final String EAS_PROTOCOL = "eas";
55ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_DONE = 0;
56ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_IO_ERROR = 1;
57ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_LOGIN_FAILURE = 2;
58ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static final int EXIT_EXCEPTION = 3;
59ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
60ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Making SSL connections is so slow that I'd prefer that only one be
61ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // executed at a time
62ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Kindly subclasses will synchronize on this before making an SSL
63ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // connection
64ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static Object sslGovernorToken = new Object();
65ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Mailbox mMailbox;
66ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected long mMailboxId;
67ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected Thread mThread;
68ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected int mExitStatus = EXIT_EXCEPTION;
69ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected String mMailboxName;
70ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public Account mAccount;
71ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected Context mContext;
72ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
73d95115d72be6797835e1286fb8f0d2e5a01cf3a8Marc Blank    protected volatile long mRequestTime = 0;
74ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected ArrayList<PartRequest> mPartRequests = new ArrayList<PartRequest>();
75ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected PartRequest mPendingPartRequest = null;
76ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
77ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
78ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to request that the service stop itself cleanly
79ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
80ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void stop();
81ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
82ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
83ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to indicate a user request requiring service has been
84ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * added to the service's pending request queue
85ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
86ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void ping();
87ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
88ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
89ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Called to validate an account; abstract to allow each protocol to do what
90ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * is necessary. For consistency with the Email app's original
91ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * functionality, success is indicated by a failure to throw an Exception
92ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * (ugh). Parameters are self-explanatory
93ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
94ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param host
95ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param userName
96ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param password
97ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param port
98ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param ssl
99ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param context
100ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @throws MessagingException
101ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
102ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public abstract void validateAccount(String host, String userName, String password, int port,
103ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            boolean ssl, Context context) throws MessagingException;
104ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
105ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
106ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Sent by SyncManager to determine the state of a running sync This is
107ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * currently unused
108ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
109ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @return status code
110ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
111ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public int getSyncStatus() {
112ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        return 0;
113ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
114ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
115ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(Context _context, Mailbox _mailbox) {
116ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mContext = _context;
117ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailbox = _mailbox;
118ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxId = _mailbox.mId;
119ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mMailboxName = _mailbox.mServerId;
120ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        mAccount = Account.restoreAccountWithId(_context, _mailbox.mAccountKey);
121ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
122ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
123ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    // Will be required when subclasses are instantiated by name
124ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public AbstractSyncService(String prefix) {
125ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
126ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
127ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
128ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * The UI can call this static method to perform account validation.  This method wraps each
129ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * protocol's validateAccount method.   Arguments are self-explanatory, except where noted.
130ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
131ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param klass the protocol class (EasSyncService.class for example)
132ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param host
133ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param userName
134ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param password
135ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param port
136ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param ssl
137ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param context
138ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @throws MessagingException
139ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
140ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    static public void validate(Class<? extends AbstractSyncService> klass, String host,
141ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            String userName, String password, int port, boolean ssl, Context context)
142ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throws MessagingException {
143ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        AbstractSyncService svc;
144ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        try {
145ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            svc = klass.newInstance();
146ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            svc.validateAccount(host, userName, password, port, ssl, context);
147ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (IllegalAccessException e) {
148ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throw new MessagingException("internal error", e);
149ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        } catch (InstantiationException e) {
150ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            throw new MessagingException("internal error", e);
151ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
152ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
153ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
154ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public static class ValidationResult {
155ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int NO_FAILURE = 0;
156ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int CONNECTION_FAILURE = 1;
157ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int VALIDATION_FAILURE = 2;
158ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final int EXCEPTION = 3;
159ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
160ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        static final ValidationResult succeeded = new ValidationResult(true, NO_FAILURE, null);
161ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        boolean success;
162ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        int failure = NO_FAILURE;
163ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        String reason = null;
164ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        Exception exception = null;
165ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
166ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success, int _failure, String _reason) {
167ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
168ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = _failure;
169ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            reason = _reason;
170ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
171ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
172ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(boolean _success) {
173ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = _success;
174ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
175ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
176ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        ValidationResult(Exception e) {
177ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            success = false;
178ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            failure = EXCEPTION;
179ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            exception = e;
180ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
181ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
182ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public boolean isSuccess() {
183ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return success;
184ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
185ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
186ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        public String getReason() {
187ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            return reason;
188ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
189ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
190ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
191ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
192ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Asks SyncManager for a WaitLock for this sync
193ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
194ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public final void runAwake() {
195ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        //SyncManager.runAwake(mMailboxId);
196ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
197ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
198ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
199ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Asks SyncManager to release any WaitLock and schedule an alarm at a specified number
200ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * of milliseconds in the future
201ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
202ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param millis
203ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
204ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public final void runAsleep(long millis) {
205ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        //SyncManager.runAsleep(mMailboxId, millis);
206ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
207ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
208ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
209ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Convenience method to do user logging (i.e. connection activity).  Saves a bunch of
210ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * repetitive code.
211ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
212ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param str the String to log
213ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
214ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void userLog(String str) {
215ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        if (Eas.USER_DEBUG) {
216ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            Log.i(TAG, str);
217ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
218ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
219ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
220ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    public void errorLog(String str) {
221ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        if (Eas.USER_DEBUG) {
222ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            Log.e(TAG, str);
223ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
224ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    }
225ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank
226ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    /**
227ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Convenience method to do test logging.  Saves a bunch of repetitive code.
228ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * Unlike user logging, TEST_DEBUG is declared final, so that testLog calls should get
229ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * "compiled out" for non-debug builds.
230ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     *
231ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     * @param str the String to log
232ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank     */
233ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank    protected void testLog(String str) {
234ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        if (Eas.TEST_DEBUG) {
235ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank            Log.v(Email.LOG_TAG, str);
236ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc Blank        }
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
280ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc 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     */
284ab30d429e0c6069604aead9b5e6845b6b91b6a02Marc 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