Merge "Turn on ActionBar on the 1-pane message list"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f8cfcd1..c9f6ebb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -181,8 +181,8 @@
used when only one account is set up.
"num_new_message" will be replaced with the number of new messages. [CHAR LIMIT=none] -->
<plurals name="notification_num_new_messages_single_account">
- <item quantity="one"><xliff:g id="num_new_message">%1$d</xliff:g></item> new
- <item quantity="other"><xliff:g id="num_new_message">%1$d</xliff:g></item> new
+ <item quantity="one"><xliff:g id="num_new_message">%1$d</xliff:g> new</item>
+ <item quantity="other"><xliff:g id="num_new_message">%1$d</xliff:g> new</item>
</plurals>
<!-- "new message" notification body for the number of new messages,
@@ -378,11 +378,15 @@
messages moved to <xliff:g id="mailbox_name" example="Inbox" >%2$s</xliff:g></item>
</plurals>
<!-- Notification ticker when a forwarded attachment couldn't be sent [CHAR LIMIT=none] -->
- <string name="forward_download_failed_ticker">"An attachment couldn't be forwarded"</string>
+ <string name="forward_download_failed_ticker">Could not forward one or more attachments</string>
<!-- Notification text when a forwarded attachment couldn't be sent -->
- <string name="forward_download_failed_notification">"The attachment "<xliff:g id="filename">%s
- </xliff:g>" couldn't be sent with your outgoing mail because it couldn't be downloaded."
- </string>
+ <string name="forward_download_failed_notification">Could not forward <xliff:g id="filename">
+ %s</xliff:g></string>
+ <!-- Notification ticker when email account authentication fails [CHAR LIMIT=20] -->
+ <string name="login_failed_ticker"><xliff:g id="account_name">%s
+ </xliff:g> sign-in failed</string>
+ <!-- Notification text when email account authentication fails [CHAR LIMIT=75]-->
+ <string name="login_failed_notification">Touch to change account settings</string>
<!-- Size unit for bytes for attachments [CHAR LIMIT=10] -->
<plurals name="message_view_attachment_bytes">
@@ -646,6 +650,11 @@
being supported -->
<string name="account_setup_failed_security_policies_unsupported">
This server requires security features your phone does not support.</string>
+ <!-- Warning given to users when they request disabling device administration (i.e. that their
+ administered accounts will be deleted) [CHAR LIMIT=none] -->
+ <string name="disable_admin_warning">WARNING: Deactivating the Email application\'s authority
+ to administer your device will delete all Email accounts that require it, along with their
+ email, contacts, calendar events, and other data.</string>
<!-- Notification ticker when device security required -->
<string name="security_notification_ticker_fmt">
diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java
index a541ab0..cd24535 100644
--- a/src/com/android/exchange/EasSyncService.java
+++ b/src/com/android/exchange/EasSyncService.java
@@ -2363,10 +2363,14 @@
status = EmailServiceStatus.SUCCESS;
}
- try {
- ExchangeService.callback().syncMailboxStatus(mMailboxId, status, 0);
- } catch (RemoteException e1) {
- // Don't care if this fails
+ // Send a callback if this run was initiated by a service call
+ if (mSyncReason == ExchangeService.SYNC_SERVICE_START_SYNC ||
+ mSyncReason == ExchangeService.SYNC_SERVICE_PART_REQUEST) {
+ try {
+ ExchangeService.callback().syncMailboxStatus(mMailboxId, status, 0);
+ } catch (RemoteException e1) {
+ // Don't care if this fails
+ }
}
// Make sure ExchangeService knows about this
diff --git a/src/com/android/exchange/ExchangeService.java b/src/com/android/exchange/ExchangeService.java
index 7b87b75..ff0cd35 100644
--- a/src/com/android/exchange/ExchangeService.java
+++ b/src/com/android/exchange/ExchangeService.java
@@ -19,6 +19,7 @@
import com.android.email.AccountBackupRestore;
import com.android.email.Email;
+import com.android.email.NotificationController;
import com.android.email.Utility;
import com.android.email.mail.transport.SSLUtils;
import com.android.email.provider.EmailContent;
@@ -260,15 +261,23 @@
(INSTANCE == null) ? null: INSTANCE.mCallbackList;
if (callbackList != null) {
// Call everyone on our callback list
- // Exceptions can be safely ignored
int count = callbackList.beginBroadcast();
- for (int i = 0; i < count; i++) {
- try {
- wrapper.call(callbackList.getBroadcastItem(i));
- } catch (RemoteException e) {
+ try {
+ for (int i = 0; i < count; i++) {
+ try {
+ wrapper.call(callbackList.getBroadcastItem(i));
+ } catch (RemoteException e) {
+ // Safe to ignore
+ } catch (RuntimeException e) {
+ // We don't want an exception in one call to prevent other calls, so
+ // we'll just log this and continue
+ Log.e(TAG, "Caught RuntimeException in broadcast", e);
+ }
}
+ } finally {
+ // No matter what, we need to finish the broadcast
+ callbackList.finishBroadcast();
}
- callbackList.finishBroadcast();
}
}
@@ -975,14 +984,17 @@
* is null, mailboxes from all accounts with the specified hold will be released
* @param reason the reason for the SyncError (AbstractSyncService.EXIT_XXX)
* @param account an Account whose mailboxes should be released (or all if null)
+ * @return whether or not any mailboxes were released
*/
- /*package*/ void releaseSyncHolds(Context context, int reason, Account account) {
- releaseSyncHoldsImpl(context, reason, account);
+ /*package*/ boolean releaseSyncHolds(Context context, int reason, Account account) {
+ boolean holdWasReleased = releaseSyncHoldsImpl(context, reason, account);
kick("security release");
+ return holdWasReleased;
}
- private void releaseSyncHoldsImpl(Context context, int reason, Account account) {
+ private boolean releaseSyncHoldsImpl(Context context, int reason, Account account) {
synchronized(sSyncLock) {
+ boolean holdWasReleased = false;
ArrayList<Long> releaseList = new ArrayList<Long>();
for (long mailboxId: mSyncErrorMap.keySet()) {
if (account != null) {
@@ -1000,7 +1012,9 @@
}
for (long mailboxId: releaseList) {
mSyncErrorMap.remove(mailboxId);
+ holdWasReleased = true;
}
+ return holdWasReleased;
}
}
@@ -2376,6 +2390,20 @@
SyncError syncError = errorMap.get(mailboxId);
exchangeService.releaseMailbox(mailboxId);
int exitStatus = svc.mExitStatus;
+ Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
+ if (m == null) return;
+
+ if (exitStatus != AbstractSyncService.EXIT_LOGIN_FAILURE) {
+ long accountId = m.mAccountKey;
+ Account account = Account.restoreAccountWithId(exchangeService, accountId);
+ if (account == null) return;
+ if (exchangeService.releaseSyncHolds(exchangeService,
+ AbstractSyncService.EXIT_LOGIN_FAILURE, account)) {
+ NotificationController.getInstance(exchangeService)
+ .cancelLoginFailedNotification(accountId);
+ }
+ }
+
switch (exitStatus) {
case AbstractSyncService.EXIT_DONE:
if (svc.hasPendingRequests()) {
@@ -2389,8 +2417,6 @@
break;
// I/O errors get retried at increasing intervals
case AbstractSyncService.EXIT_IO_ERROR:
- Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
- if (m == null) return;
if (syncError != null) {
syncError.escalate();
log(m.mDisplayName + " held for " + syncError.holdDelay + "ms");
@@ -2400,8 +2426,11 @@
}
break;
// These errors are not retried automatically
- case AbstractSyncService.EXIT_SECURITY_FAILURE:
case AbstractSyncService.EXIT_LOGIN_FAILURE:
+ NotificationController.getInstance(exchangeService)
+ .showLoginFailedNotification(m.mAccountKey);
+ // Fall through
+ case AbstractSyncService.EXIT_SECURITY_FAILURE:
case AbstractSyncService.EXIT_EXCEPTION:
errorMap.put(mailboxId, exchangeService.new SyncError(exitStatus, true));
break;
diff --git a/src/com/android/exchange/provider/ExchangeDirectoryProvider.java b/src/com/android/exchange/provider/ExchangeDirectoryProvider.java
index 11b7230..b267da9 100644
--- a/src/com/android/exchange/provider/ExchangeDirectoryProvider.java
+++ b/src/com/android/exchange/provider/ExchangeDirectoryProvider.java
@@ -228,7 +228,7 @@
} else if (column.equals(Directory.EXPORT_SUPPORT)) {
row[i] = Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY;
} else if (column.equals(Directory.SHORTCUT_SUPPORT)) {
- row[i] = Directory.SHORTCUT_SUPPORT_FULL;
+ row[i] = Directory.SHORTCUT_SUPPORT_NONE;
}
}
cursor.addRow(row);
diff --git a/tests/src/com/android/exchange/ExchangeServiceAccountTests.java b/tests/src/com/android/exchange/ExchangeServiceAccountTests.java
index 425e9c4..9b92726 100644
--- a/tests/src/com/android/exchange/ExchangeServiceAccountTests.java
+++ b/tests/src/com/android/exchange/ExchangeServiceAccountTests.java
@@ -73,7 +73,8 @@
// We should have 4
assertEquals(4, errorMap.keySet().size());
// Release the holds on acct2 (there are two of them)
- exchangeService.releaseSyncHolds(context, AbstractSyncService.EXIT_SECURITY_FAILURE, acct2);
+ assertTrue(exchangeService.releaseSyncHolds(context,
+ AbstractSyncService.EXIT_SECURITY_FAILURE, acct2));
// There should be two left
assertEquals(2, errorMap.keySet().size());
// And these are the two...
@@ -86,19 +87,22 @@
// We should have 4 again
assertEquals(4, errorMap.keySet().size());
// Release all of the security holds
- exchangeService.releaseSyncHolds(context, AbstractSyncService.EXIT_SECURITY_FAILURE, null);
+ assertTrue(exchangeService.releaseSyncHolds(context,
+ AbstractSyncService.EXIT_SECURITY_FAILURE, null));
// There should be one left
assertEquals(1, errorMap.keySet().size());
// And this is the one
assertNotNull(errorMap.get(box2.mId));
// Release the i/o holds on account 2 (there aren't any)
- exchangeService.releaseSyncHolds(context, AbstractSyncService.EXIT_IO_ERROR, acct2);
+ assertFalse(exchangeService.releaseSyncHolds(context,
+ AbstractSyncService.EXIT_IO_ERROR, acct2));
// There should still be one left
assertEquals(1, errorMap.keySet().size());
// Release the i/o holds on account 1 (there's one)
- exchangeService.releaseSyncHolds(context, AbstractSyncService.EXIT_IO_ERROR, acct1);
+ assertTrue(exchangeService.releaseSyncHolds(context,
+ AbstractSyncService.EXIT_IO_ERROR, acct1));
// There should still be one left
assertEquals(0, errorMap.keySet().size());
}