diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7216f25f6..5dda66ca3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -289,7 +289,7 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
Mark as read on server
IMAP path prefix
- Optional
+ (Automatic using NAMESPACE if available)
Drafts folder name
Sent folder name
diff --git a/src/com/android/email/Account.java b/src/com/android/email/Account.java
index 6c374caec..3bf731413 100644
--- a/src/com/android/email/Account.java
+++ b/src/com/android/email/Account.java
@@ -831,6 +831,12 @@ public class Account implements Serializable
}
return super.equals(o);
}
+
+ @Override
+ public int hashCode()
+ {
+ return mUuid.hashCode();
+ }
public FolderMode getFolderDisplayMode()
{
diff --git a/src/com/android/email/MessagingController.java b/src/com/android/email/MessagingController.java
index eb989ece1..5a23f6e13 100644
--- a/src/com/android/email/MessagingController.java
+++ b/src/com/android/email/MessagingController.java
@@ -3995,147 +3995,15 @@ public class MessagingController implements Runnable
return pushers.values();
}
- public Pusher setupPushing(final Account account)
+ public boolean setupPushing(final Account account)
{
- Pusher pusher = pushers.get(account);
- if (pusher != null)
- {
- return pusher;
- }
- Store store = null;
try
{
- store = Store.getInstance(account.getStoreUri(), mApplication);
- if (store.isPushCapable() == false)
+ Pusher previousPusher = pushers.remove(account);
+ if (previousPusher != null)
{
- Log.i(Email.LOG_TAG, "Account " + account.getDescription() + " is not push capable, skipping");
- return null;
+ previousPusher.stop();
}
- }
- catch (Exception e)
- {
- Log.e(Email.LOG_TAG, "Could not get remote store", e);
- return null;
- }
- final MessagingController controller = this;
- PushReceiver receiver = new PushReceiver()
- {
- ThreadLocal threadWakeLock = new ThreadLocal();
- public void acquireWakeLock()
- {
- WakeLock wakeLock = threadWakeLock.get();
- if (wakeLock == null)
- {
- PowerManager pm = (PowerManager) mApplication.getSystemService(Context.POWER_SERVICE);
- wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Email");
- wakeLock.setReferenceCounted(false);
- threadWakeLock.set(wakeLock);
- }
- wakeLock.acquire(Email.PUSH_WAKE_LOCK_TIMEOUT);
- if (Email.DEBUG)
- {
- Log.d(Email.LOG_TAG, "Acquired WakeLock for Pushing for thread " + Thread.currentThread().getName());
- }
- }
-
- public void releaseWakeLock()
- {
- if (Email.DEBUG)
- {
- Log.d(Email.LOG_TAG, "Considering releasing WakeLock for Pushing");
- }
- WakeLock wakeLock = threadWakeLock.get();
- if (wakeLock != null)
- {
-
- if (Email.DEBUG)
- {
- Log.d(Email.LOG_TAG, "Releasing WakeLock for Pushing for thread " + Thread.currentThread().getName());
- }
- wakeLock.release();
- }
- else
- {
- Log.e(Email.LOG_TAG, "No WakeLock waiting to be released for thread " + Thread.currentThread().getName());
- }
- }
-
- public void messagesFlagsChanged(Folder folder,
- List messages)
- {
- controller.messagesArrived(account, folder, messages, true);
-
- }
- public void messagesArrived(Folder folder, List messages)
- {
- controller.messagesArrived(account, folder, messages, false);
- }
-
- public void sleep(long millis)
- {
- SleepService.sleep(mApplication, millis, threadWakeLock.get(), Email.PUSH_WAKE_LOCK_TIMEOUT);
- }
-
- public void pushError(String errorMessage, Exception e)
- {
- String errMess = errorMessage;
- String body = null;
-
- if (errMess == null && e != null)
- {
- errMess = e.getMessage();
- }
- body = errMess;
- if (e != null)
- {
- body = e.toString();
- }
- controller.addErrorMessage(account, errMess, body);
- }
-
- public String getPushState(String folderName)
- {
- LocalFolder localFolder = null;
- try
- {
- LocalStore localStore = (LocalStore) Store.getInstance(account.getLocalStoreUri(), mApplication);
- localFolder= (LocalFolder) localStore.getFolder(folderName);
- localFolder.open(OpenMode.READ_WRITE);
- return localFolder.getPushState();
- }
- catch (Exception e)
- {
- Log.e(Email.LOG_TAG, "Unable to get push state from account " + account.getDescription()
- + ", folder " + folderName, e);
- return null;
- }
- finally
- {
- if (localFolder != null)
- {
- try
- {
- localFolder.close(false);
- }
- catch (Exception e)
- {
- Log.e(Email.LOG_TAG, "Unable to close folder '" + folderName + "' in account " + account.getDescription(), e);
- }
- }
- }
- }
-
- public void setPushActive(String folderName, boolean enabled)
- {
- for (MessagingListener l : getListeners())
- {
- l.setPushActive(account, folderName, enabled);
- }
- }
-
- };
- try
- {
Preferences prefs = Preferences.getPreferences(mApplication);
Account.FolderMode aDisplayMode = account.getFolderDisplayMode();
@@ -4178,19 +4046,46 @@ public class MessagingController implements Runnable
Log.i(Email.LOG_TAG, "Starting pusher for " + account.getDescription() + ":" + folder.getName());
names.add(folder.getName());
}
+
if (names.size() > 0)
{
- pusher = store.getPusher(receiver, names);
- if (pusher != null)
+ PushReceiver receiver = new MessagingControllerPushReceiver(mApplication, account, this);
+
+ try
{
- pushers.put(account, pusher);
+ Store store = Store.getInstance(account.getStoreUri(), mApplication);
+ if (store.isPushCapable() == false)
+ {
+ Log.i(Email.LOG_TAG, "Account " + account.getDescription() + " is not push capable, skipping");
+ return false;
+ }
+ Pusher pusher = store.getPusher(receiver);
+ Pusher oldPusher = null;
+ if (pusher != null)
+ {
+ oldPusher = pushers.putIfAbsent(account, pusher);
+ }
+ if (oldPusher != null)
+ {
+ pusher = oldPusher;
+ }
+ else
+ {
+ pusher.start(names);
+ }
}
- return pusher;
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Could not get remote store", e);
+ return false;
+ }
+
+ return true;
}
else
{
Log.i(Email.LOG_TAG, "No folders are configured for pushing in account " + account.getDescription());
- return null;
+ return false;
}
}
@@ -4198,16 +4093,7 @@ public class MessagingController implements Runnable
{
Log.e(Email.LOG_TAG, "Got exception while setting up pushing", e);
}
- return null;
- }
-
- public void stopPushing(Account account)
- {
- Pusher pusher = pushers.remove(account);
- if (pusher != null)
- {
- pusher.stop();
- }
+ return false;
}
public void stopAllPushing()
@@ -4220,7 +4106,6 @@ public class MessagingController implements Runnable
iter.remove();
pusher.stop();
}
-
}
public void messagesArrived(final Account account, final Folder remoteFolder, final List messages, final boolean flagSyncOnly)
@@ -4239,7 +4124,6 @@ public class MessagingController implements Runnable
LocalStore localStore = (LocalStore) Store.getInstance(account.getLocalStoreUri(), mApplication);
localFolder= (LocalFolder) localStore.getFolder(remoteFolder.getName());
localFolder.open(OpenMode.READ_WRITE);
- remoteFolder.open(OpenMode.READ_WRITE);
int newCount = downloadMessages(account, remoteFolder, localFolder, messages, flagSyncOnly);
setLocalUnreadCountToRemote(localFolder, remoteFolder, messages.size());
diff --git a/src/com/android/email/MessagingControllerPushReceiver.java b/src/com/android/email/MessagingControllerPushReceiver.java
new file mode 100644
index 000000000..d9d96cdde
--- /dev/null
+++ b/src/com/android/email/MessagingControllerPushReceiver.java
@@ -0,0 +1,145 @@
+package com.android.email;
+
+import java.util.List;
+
+import android.app.Application;
+import android.content.Context;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.util.Log;
+
+import com.android.email.mail.Folder;
+import com.android.email.mail.Message;
+import com.android.email.mail.PushReceiver;
+import com.android.email.mail.Store;
+import com.android.email.mail.Folder.OpenMode;
+import com.android.email.mail.store.LocalStore;
+import com.android.email.mail.store.LocalStore.LocalFolder;
+import com.android.email.service.SleepService;
+
+public class MessagingControllerPushReceiver implements PushReceiver
+{
+ final Account account;
+ final MessagingController controller;
+ final Application mApplication;
+
+ public MessagingControllerPushReceiver(Application nApplication, Account nAccount, MessagingController nController)
+ {
+ account = nAccount;
+ controller = nController;
+ mApplication = nApplication;
+ }
+ ThreadLocal threadWakeLock = new ThreadLocal();
+ public void acquireWakeLock()
+ {
+ WakeLock wakeLock = threadWakeLock.get();
+ if (wakeLock == null)
+ {
+ PowerManager pm = (PowerManager) mApplication.getSystemService(Context.POWER_SERVICE);
+ wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Email");
+ wakeLock.setReferenceCounted(false);
+ threadWakeLock.set(wakeLock);
+ }
+ wakeLock.acquire(Email.PUSH_WAKE_LOCK_TIMEOUT);
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Acquired WakeLock for Pushing for thread " + Thread.currentThread().getName());
+ }
+ }
+
+ public void releaseWakeLock()
+ {
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Considering releasing WakeLock for Pushing");
+ }
+ WakeLock wakeLock = threadWakeLock.get();
+ if (wakeLock != null)
+ {
+
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Releasing WakeLock for Pushing for thread " + Thread.currentThread().getName());
+ }
+ wakeLock.release();
+ }
+ else
+ {
+ Log.e(Email.LOG_TAG, "No WakeLock waiting to be released for thread " + Thread.currentThread().getName());
+ }
+ }
+
+ public void messagesFlagsChanged(Folder folder,
+ List messages)
+ {
+ controller.messagesArrived(account, folder, messages, true);
+
+ }
+ public void messagesArrived(Folder folder, List messages)
+ {
+ controller.messagesArrived(account, folder, messages, false);
+ }
+
+ public void sleep(long millis)
+ {
+ SleepService.sleep(mApplication, millis, threadWakeLock.get(), Email.PUSH_WAKE_LOCK_TIMEOUT);
+ }
+
+ public void pushError(String errorMessage, Exception e)
+ {
+ String errMess = errorMessage;
+ String body = null;
+
+ if (errMess == null && e != null)
+ {
+ errMess = e.getMessage();
+ }
+ body = errMess;
+ if (e != null)
+ {
+ body = e.toString();
+ }
+ controller.addErrorMessage(account, errMess, body);
+ }
+
+ public String getPushState(String folderName)
+ {
+ LocalFolder localFolder = null;
+ try
+ {
+ LocalStore localStore = (LocalStore) Store.getInstance(account.getLocalStoreUri(), mApplication);
+ localFolder= (LocalFolder) localStore.getFolder(folderName);
+ localFolder.open(OpenMode.READ_WRITE);
+ return localFolder.getPushState();
+ }
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Unable to get push state from account " + account.getDescription()
+ + ", folder " + folderName, e);
+ return null;
+ }
+ finally
+ {
+ if (localFolder != null)
+ {
+ try
+ {
+ localFolder.close(false);
+ }
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Unable to close folder '" + folderName + "' in account " + account.getDescription(), e);
+ }
+ }
+ }
+ }
+
+ public void setPushActive(String folderName, boolean enabled)
+ {
+ for (MessagingListener l : controller.getListeners())
+ {
+ l.setPushActive(account, folderName, enabled);
+ }
+ }
+
+}
diff --git a/src/com/android/email/mail/Pusher.java b/src/com/android/email/mail/Pusher.java
index e2f942558..37d095b88 100644
--- a/src/com/android/email/mail/Pusher.java
+++ b/src/com/android/email/mail/Pusher.java
@@ -1,9 +1,11 @@
package com.android.email.mail;
+import java.util.List;
+
public interface Pusher
{
- public void start();
+ public void start(List folderNames);
public void refresh();
public void stop();
/**
diff --git a/src/com/android/email/mail/Store.java b/src/com/android/email/mail/Store.java
index 6411ba419..db47dc9f1 100644
--- a/src/com/android/email/mail/Store.java
+++ b/src/com/android/email/mail/Store.java
@@ -113,7 +113,7 @@ public abstract class Store
{
}
- public Pusher getPusher(PushReceiver receiver, List names)
+ public Pusher getPusher(PushReceiver receiver)
{
return null;
}
diff --git a/src/com/android/email/mail/store/ImapStore.java b/src/com/android/email/mail/store/ImapStore.java
index 082cb2bcb..280758bdc 100644
--- a/src/com/android/email/mail/store/ImapStore.java
+++ b/src/com/android/email/mail/store/ImapStore.java
@@ -33,6 +33,7 @@ import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -99,14 +100,20 @@ public class ImapStore extends Store
private static final int IDLE_REFRESH_INTERVAL = 20 * 60 * 1000; // 20 minutes
private static final Flag[] PERMANENT_FLAGS = { Flag.DELETED, Flag.SEEN };
+
+ private static final String CAPABILITY_IDLE = "IDLE";
+ private static final String COMMAND_IDLE = "IDLE";
+ private static final String CAPABILITY_NAMESPACE = "NAMESPACE";
+ private static final String COMMAND_NAMESPACE = "NAMESPACE";
private String mHost;
private int mPort;
private String mUsername;
private String mPassword;
private int mConnectionSecurity;
- private String mPathPrefix;
- private String mPathDelimeter;
+ private volatile String mPathPrefix;
+ private volatile String mCombinedPrefix = null;
+ private volatile String mPathDelimeter;
private LinkedList mConnections =
new LinkedList();
@@ -196,6 +203,10 @@ public class ImapStore extends Store
if ((uri.getPath() != null) && (uri.getPath().length() > 0))
{
mPathPrefix = uri.getPath().substring(1);
+ if (mPathPrefix != null && mPathPrefix.trim().length() == 0)
+ {
+ mPathPrefix = null;
+ }
}
mModifiedUtf7Charset = new CharsetProvider().charsetForName("X-RFC-3501");
@@ -217,6 +228,34 @@ public class ImapStore extends Store
return folder;
}
+ private String getCombinedPrefix()
+ {
+ if (mCombinedPrefix == null)
+ {
+ if (mPathPrefix != null)
+ {
+ String tmpPrefix = mPathPrefix.trim();
+ String tmpDelim = (mPathDelimeter != null ? mPathDelimeter.trim() : "");
+ if (tmpPrefix.endsWith(tmpDelim))
+ {
+ mCombinedPrefix = tmpPrefix;
+ }
+ else if (tmpPrefix.length() > 0)
+ {
+ mCombinedPrefix = tmpPrefix + tmpDelim;
+ }
+ else
+ {
+ mCombinedPrefix = "";
+ }
+ }
+ else
+ {
+ mCombinedPrefix = "";
+ }
+ }
+ return mCombinedPrefix;
+ }
@Override
public Folder[] getPersonalNamespaces() throws MessagingException
@@ -225,13 +264,10 @@ public class ImapStore extends Store
try
{
ArrayList folders = new ArrayList();
- if (mPathPrefix == null)
- {
- mPathPrefix = "";
- }
+
List responses =
connection.executeSimpleCommand(String.format("LIST \"\" \"%s*\"",
- mPathPrefix));
+ getCombinedPrefix()));
for (ImapResponse response : responses)
{
@@ -243,6 +279,7 @@ public class ImapStore extends Store
if (mPathDelimeter == null)
{
mPathDelimeter = response.getString(2);
+ mCombinedPrefix = null;
}
if (folder.equalsIgnoreCase(Email.INBOX))
@@ -251,13 +288,14 @@ public class ImapStore extends Store
}
else
{
- if (mPathPrefix.length() > 0)
+
+ if (getCombinedPrefix().length() > 0)
{
- if (folder.length() >= mPathPrefix.length() + 1)
+ if (folder.length() >= getCombinedPrefix().length())
{
- folder = folder.substring(mPathPrefix.length() + 1);
+ folder = folder.substring(getCombinedPrefix().length());
}
- if (!decodeFolderName(response.getString(3)).equals(mPathPrefix + mPathDelimeter + folder))
+ if (!decodeFolderName(response.getString(3)).equals(getCombinedPrefix() + folder))
{
includeFolder = false;
}
@@ -406,12 +444,7 @@ public class ImapStore extends Store
return true;
}
- @Override
- public Pusher getPusher(PushReceiver receiver, List names)
- {
- return new ImapPusher(this, receiver, names);
- }
-
+
class ImapFolder extends Folder
{
private String mName;
@@ -433,18 +466,7 @@ public class ImapStore extends Store
String prefixedName = "";
if (!Email.INBOX.equalsIgnoreCase(mName))
{
- String prefix = mPathPrefix;
- String delim = mPathDelimeter;
-
- if (prefix != null && delim != null)
- {
- prefix = prefix.trim();
- delim = delim.trim();
- if (prefix.length() > 0 && delim.length() > 0)
- {
- prefixedName += mPathPrefix + mPathDelimeter;
- }
- }
+ prefixedName = getCombinedPrefix();
}
prefixedName += mName;
@@ -503,7 +525,7 @@ public class ImapStore extends Store
// 2 OK [READ-WRITE] Select completed.
try
{
-
+
if (mPathDelimeter == null)
{
List nameResponses =
@@ -512,7 +534,7 @@ public class ImapStore extends Store
{
if (response.get(0).equals("LIST"))
{
- mPathDelimeter = nameResponses.get(0).getString(2);
+ mPathDelimeter = response.getString(2);
if (Email.DEBUG)
{
Log.d(Email.LOG_TAG, "Got path delimeter '" + mPathDelimeter + "' for " + getLogId());
@@ -1168,6 +1190,37 @@ public class ImapStore extends Store
}
return responses;
}
+
+ protected void handlePossibleUidNext(ImapResponse response)
+ {
+ if (response.get(0).equals("OK") && response.size() > 1)
+ {
+ Object bracketedObj = response.get(1);
+ if (bracketedObj instanceof ImapList)
+ {
+ ImapList bracketed = (ImapList)bracketedObj;
+
+ if (bracketed.size() > 1)
+ {
+ Object keyObj = bracketed.get(0);
+ if (keyObj instanceof String)
+ {
+ String key = (String)keyObj;
+ if ("UIDNEXT".equals(key))
+ {
+ uidNext = bracketed.getNumber(1);
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Got UidNext = " + uidNext + " for " + getLogId());
+ }
+ }
+ }
+ }
+
+
+ }
+ }
+ }
/**
* Handle an untagged response that the caller doesn't care to handle themselves.
@@ -1186,34 +1239,9 @@ public class ImapStore extends Store
Log.d(Email.LOG_TAG, "Got untagged EXISTS with value " + mMessageCount + " for " + getLogId());
}
}
- if (response.get(0).equals("OK") && response.size() > 1)
- {
- Object bracketedObj = response.get(1);
- if (bracketedObj instanceof ImapList)
- {
- ImapList bracketed = (ImapList)bracketedObj;
-
- if (bracketed.size() > 1)
- {
- Object keyObj = bracketed.get(0);
- if (keyObj instanceof String)
- {
- String key = (String)keyObj;
- if ("UIDNEXT".equals(key))
- {
- uidNext = bracketed.getNumber(1);
- if (Email.DEBUG)
- {
- Log.d(Email.LOG_TAG, "Got UidNext = " + uidNext + " for " + getLogId());
- }
- }
- }
- }
-
-
- }
- }
- else if (response.get(1).equals("EXPUNGE") && mMessageCount > 0)
+ handlePossibleUidNext(response);
+
+ if (response.get(1).equals("EXPUNGE") && mMessageCount > 0)
{
mMessageCount--;
if (Email.DEBUG)
@@ -1873,6 +1901,61 @@ public class ImapStore extends Store
{
throw new AuthenticationFailedException(null, me);
}
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "NAMESPACE = " + hasCapability(CAPABILITY_NAMESPACE)
+ + ", mPathPrefix = " + mPathPrefix);
+ }
+ if (mPathPrefix == null)
+ {
+ if (hasCapability(CAPABILITY_NAMESPACE))
+ {
+ Log.i(Email.LOG_TAG, "mPathPrefix is unset and server has NAMESPACE capability");
+ List namespaceResponses =
+ executeSimpleCommand(COMMAND_NAMESPACE);
+ for (ImapResponse response : namespaceResponses)
+ {
+ if (response.get(0).equals(COMMAND_NAMESPACE))
+ {
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Got NAMESPACE response " + response + " on " + getLogId());
+ }
+
+ Object personalNamespaces = response.get(1);
+ if (personalNamespaces != null && personalNamespaces instanceof ImapList)
+ {
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Got personal namespaces: " + personalNamespaces);
+ }
+ ImapList bracketed = (ImapList)personalNamespaces;
+ Object firstNamespace = bracketed.get(0);
+ if (firstNamespace != null && firstNamespace instanceof ImapList)
+ {
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Got first personal namespaces: " + firstNamespace);
+ }
+ bracketed = (ImapList)firstNamespace;
+ mPathPrefix = bracketed.getString(0);
+ mPathDelimeter = bracketed.getString(1);
+ mCombinedPrefix = null;
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Got path '" + mPathPrefix + "' and separator '" + mPathDelimeter + "'");
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Log.i(Email.LOG_TAG, "mPathPrefix is unset but server does not have NAMESPACE capability");
+ mPathPrefix = "";
+ }
+ }
}
catch (SSLException e)
{
@@ -1922,7 +2005,12 @@ public class ImapStore extends Store
// Log.v(Email.LOG_TAG, "Have capability '" + capability + "' for " + getLogId());
// }
}
- return capabilities.contains("IDLE");
+ return capabilities.contains(CAPABILITY_IDLE);
+ }
+
+ protected boolean hasCapability(String capability)
+ {
+ return capabilities.contains(capability);
}
private boolean isOpen()
@@ -2287,7 +2375,7 @@ public class ImapStore extends Store
}
}
- public void start() throws MessagingException
+ public void start()
{
Runnable runner = new Runnable()
{
@@ -2297,7 +2385,6 @@ public class ImapStore extends Store
Log.i(Email.LOG_TAG, "Pusher starting for " + getLogId());
while (stop.get() != true)
{
-
try
{
int oldUidNext = -1;
@@ -2332,17 +2419,17 @@ public class ImapStore extends Store
{
handleUntaggedResponses(responses);
}
- if (uidNext > oldUidNext)
+ int startUid = oldUidNext;
+ if (startUid < uidNext - 10)
+ {
+ startUid = uidNext - 10;
+ }
+ if (startUid < 1)
+ {
+ startUid = 1;
+ }
+ if (uidNext > startUid)
{
- int startUid = oldUidNext;
- if (startUid < uidNext - 100)
- {
- startUid = uidNext - 100;
- }
- if (startUid < 1)
- {
- startUid = 1;
- }
Log.i(Email.LOG_TAG, "Needs sync from uid " + startUid + " to " + uidNext + " for " + getLogId());
List messages = new ArrayList();
@@ -2359,7 +2446,7 @@ public class ImapStore extends Store
}
else
{
- if (stop.get() != true)
+ if (stop.get() == false)
{
List untaggedResponses = null;
if (storedUntaggedResponses.size() > 0)
@@ -2378,8 +2465,11 @@ public class ImapStore extends Store
idling.set(false);
}
- storedUntaggedResponses.clear();
- processUntaggedResponses(untaggedResponses);
+ if (stop.get() == false)
+ {
+ storedUntaggedResponses.clear();
+ processUntaggedResponses(untaggedResponses);
+ }
delayTime.set(NORMAL_DELAY_TIME);
}
}
@@ -2404,6 +2494,7 @@ public class ImapStore extends Store
}
else
{
+ receiver.pushError("Push error: " + e.getMessage(), null);
Log.e(Email.LOG_TAG, "Got exception while idling for " + getLogId(), e);
int delayTimeInt = delayTime.get();
receiver.sleep(delayTimeInt);
@@ -2453,25 +2544,34 @@ public class ImapStore extends Store
}
storedUntaggedResponses.add(response);
}
+ handlePossibleUidNext(response);
}
}
protected void processUntaggedResponses(List responses)
{
+ boolean skipSync = false;
int oldMessageCount = mMessageCount;
+ if (oldMessageCount == -1)
+ {
+ skipSync = true;
+ }
List flagSyncMsgSeqs = new ArrayList();
for (ImapResponse response : responses)
{
oldMessageCount += processUntaggedResponse(oldMessageCount, response, flagSyncMsgSeqs);
}
- if (oldMessageCount < 0)
+ if (skipSync == false)
{
- oldMessageCount = 0;
- }
- if (mMessageCount > oldMessageCount)
- {
- syncMessages(oldMessageCount + 1, mMessageCount, true);
+ if (oldMessageCount < 0)
+ {
+ oldMessageCount = 0;
+ }
+ if (mMessageCount > oldMessageCount)
+ {
+ syncMessages(oldMessageCount + 1, mMessageCount, true);
+ }
}
if (Email.DEBUG)
{
@@ -2610,10 +2710,13 @@ public class ImapStore extends Store
}
}
- public void stop() throws MessagingException
+ public void stop()
{
stop.set(true);
-
+ if (listeningThread != null)
+ {
+ listeningThread.interrupt();
+ }
if (mConnection != null)
{
if (Email.DEBUG)
@@ -2634,109 +2737,143 @@ public class ImapStore extends Store
{
Log.v(Email.LOG_TAG, "Got async response: " + response);
}
- if (response.mTag == null)
+ if (stop.get() == true)
{
- if (response.size() > 1)
+ if (Email.DEBUG)
{
- boolean started = false;
- Object responseType = response.get(1);
- if ("EXISTS".equals(responseType) || "EXPUNGE".equals(responseType) ||
- "FETCH".equals(responseType))
+ Log.d(Email.LOG_TAG, "Got async untagged response: " + response + ", but stop is set for " + getLogId());
+ }
+ try
+ {
+ sendDone();
+ }
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Exception while sending DONE for " + getLogId(), e);
+ }
+ }
+ else
+ {
+ if (response.mTag == null)
+ {
+ if (response.size() > 1)
{
- if (started == false)
+ boolean started = false;
+ Object responseType = response.get(1);
+ if ("EXISTS".equals(responseType) || "EXPUNGE".equals(responseType) ||
+ "FETCH".equals(responseType))
{
- receiver.acquireWakeLock();
- started = true;
- }
- if (Email.DEBUG)
- {
- Log.d(Email.LOG_TAG, "Got useful async untagged response: " + response + " for " + getLogId());
- }
- try
- {
- sendDone();
- }
- catch (Exception e)
- {
- Log.e(Email.LOG_TAG, "Exception while sending DONE for " + getLogId(), e);
+ if (started == false)
+ {
+ receiver.acquireWakeLock();
+ started = true;
+ }
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Got useful async untagged response: " + response + " for " + getLogId());
+ }
+ try
+ {
+ sendDone();
+ }
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Exception while sending DONE for " + getLogId(), e);
+ }
}
}
- }
- else if (response.size() > 0)
- {
- if ("idling".equals(response.get(0)))
+ else if (response.size() > 0)
{
- if (Email.DEBUG)
+ if ("idling".equals(response.get(0)))
{
- Log.d(Email.LOG_TAG, "Idling " + getLogId());
+ if (Email.DEBUG)
+ {
+ Log.d(Email.LOG_TAG, "Idling " + getLogId());
+ }
+ receiver.releaseWakeLock();
}
- receiver.releaseWakeLock();
}
}
}
}
}
+ @Override
+ public Pusher getPusher(PushReceiver receiver)
+ {
+ return new ImapPusher(this, receiver);
+ }
public class ImapPusher implements Pusher
{
- List folderPushers = new ArrayList();
+ final ImapStore mStore;
+ final PushReceiver mReceiver;
+
+ HashMap folderPushers = new HashMap();
- public ImapPusher(ImapStore store, PushReceiver receiver, List folderNames)
+ public ImapPusher(ImapStore store, PushReceiver receiver)
{
- for (String folderName : folderNames)
+ mStore = store;
+ mReceiver = receiver;
+ }
+
+ @Override
+ public void start(List folderNames)
+ {
+ stop();
+ synchronized(folderPushers)
{
- ImapFolderPusher pusher = new ImapFolderPusher(store, folderName, receiver);
- folderPushers.add(pusher);
+ for (String folderName : folderNames)
+ {
+ ImapFolderPusher pusher = folderPushers.get(folderName);
+ if (pusher == null)
+ {
+ pusher = new ImapFolderPusher(mStore, folderName, mReceiver);
+ folderPushers.put(folderName, pusher);
+ pusher.start();
+ }
+ }
}
}
+ @Override
public void refresh()
{
- for (ImapFolderPusher folderPusher : folderPushers)
+ synchronized(folderPushers)
{
- try
+ for (ImapFolderPusher folderPusher : folderPushers.values())
{
- folderPusher.refresh();
- }
- catch (Exception e)
- {
- Log.e(Email.LOG_TAG, "Got exception while refreshing for " + folderPusher.getName(), e);
- }
- }
-
- }
-
- public void start()
- {
- for (ImapFolderPusher folderPusher : folderPushers)
- {
- try
- {
- folderPusher.start();
- }
- catch (Exception e)
- {
- Log.e(Email.LOG_TAG, "Got exception while starting " + folderPusher.getName(), e);
+ try
+ {
+ folderPusher.refresh();
+ }
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Got exception while refreshing for " + folderPusher.getName(), e);
+ }
}
}
}
-
+
+ @Override
public void stop()
{
Log.i(Email.LOG_TAG, "Requested stop of IMAP pusher");
- for (ImapFolderPusher folderPusher : folderPushers)
+ synchronized(folderPushers)
{
- try
+ for (ImapFolderPusher folderPusher : folderPushers.values())
{
- Log.i(Email.LOG_TAG, "Requesting stop of IMAP folderPusher " + folderPusher.getName());
- folderPusher.stop();
- }
- catch (Exception e)
- {
- Log.e(Email.LOG_TAG, "Got exception while stopping " + folderPusher.getName(), e);
+ try
+ {
+ Log.i(Email.LOG_TAG, "Requesting stop of IMAP folderPusher " + folderPusher.getName());
+ folderPusher.stop();
+ }
+ catch (Exception e)
+ {
+ Log.e(Email.LOG_TAG, "Got exception while stopping " + folderPusher.getName(), e);
+ }
}
+ folderPushers.clear();
}
- folderPushers.clear();
}
public int getRefreshInterval()
diff --git a/src/com/android/email/service/BootReceiver.java b/src/com/android/email/service/BootReceiver.java
index 740179ba6..5339e7188 100644
--- a/src/com/android/email/service/BootReceiver.java
+++ b/src/com/android/email/service/BootReceiver.java
@@ -69,8 +69,8 @@ public class BootReceiver extends BroadcastReceiver
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()))
{
- Email.setServicesEnabled(context, tmpWakeLockId);
- tmpWakeLockId = null;
+ //Email.setServicesEnabled(context, tmpWakeLockId);
+ //tmpWakeLockId = null;
}
else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(intent.getAction()))
{
diff --git a/src/com/android/email/service/MailService.java b/src/com/android/email/service/MailService.java
index 5c54d9217..092b19e26 100644
--- a/src/com/android/email/service/MailService.java
+++ b/src/com/android/email/service/MailService.java
@@ -361,13 +361,7 @@ public class MailService extends CoreService
for (Account account : Preferences.getPreferences(MailService.this).getAccounts())
{
Log.i(Email.LOG_TAG, "Setting up pushers for account " + account.getDescription());
- Pusher pusher = MessagingController.getInstance(getApplication()).setupPushing(account);
- if (pusher != null)
- {
- pushing = true;
- Log.i(Email.LOG_TAG, "Starting configured pusher for account " + account.getDescription());
- pusher.start();
- }
+ pushing |= MessagingController.getInstance(getApplication()).setupPushing(account);
}
if (pushing)
{