Merge "This CL makes the widget launch correctly"
diff --git a/proguard.flags b/proguard.flags
index 38fa05a..61b14fe 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -27,3 +27,7 @@
 -keepclasseswithmembers class com.android.mail.UnifiedEmail {
   public <methods>;
 }
+
+-keepclasseswithmembers class com.android.mail.ui.AnimatingItemView {
+  *** setAnimatedHeight(...);
+}
diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java
index 4bd76b0..f106c97 100644
--- a/src/com/android/mail/browse/ConversationCursor.java
+++ b/src/com/android/mail/browse/ConversationCursor.java
@@ -35,6 +35,7 @@
 
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.UIProvider;
+import com.android.mail.providers.UIProvider.ConversationOperations;
 import com.google.common.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
@@ -916,17 +917,28 @@
                     return ContentProviderOperation.newInsert(uri)
                             .withValues(mValues).build();
                 case ARCHIVE:
-                    // TODO: (mindyp) build out archive correctly.
                     sProvider.deleteLocal(mUri);
-                    return ContentProviderOperation.newDelete(uri).build();
+
+                    // Create an update operation that represents archive
+                    return ContentProviderOperation.newUpdate(uri).withValue(
+                            ConversationOperations.OPERATION_KEY, ConversationOperations.ARCHIVE)
+                            .build();
                 case MUTE:
-                    // TODO: (mindyp) build out mute correctly.
-                    sProvider.deleteLocal(mUri);
-                    return ContentProviderOperation.newDelete(uri).build();
+                    if (mLocalDeleteOnUpdate) {
+                        sProvider.deleteLocal(mUri);
+                    }
+
+                    // Create an update operation that represents mute
+                    return ContentProviderOperation.newUpdate(uri).withValue(
+                            ConversationOperations.OPERATION_KEY, ConversationOperations.MUTE)
+                            .build();
                 case REPORT_SPAM:
-                    // TODO: (mindyp) build out report spam correctly.
                     sProvider.deleteLocal(mUri);
-                    return ContentProviderOperation.newDelete(uri).build();
+
+                    // Create an update operation that represents report spam
+                    return ContentProviderOperation.newUpdate(uri).withValue(
+                            ConversationOperations.OPERATION_KEY,
+                            ConversationOperations.REPORT_SPAM).build();
                 default:
                     throw new UnsupportedOperationException(
                             "No such ConversationOperation type: " + mType);
@@ -1059,4 +1071,9 @@
     public boolean requery() {
         return true;
     }
+
+    @Override
+    protected void finalize() {
+        close();
+    }
 }
diff --git a/src/com/android/mail/browse/SelectedConversationsActionMenu.java b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
index 6bf21e5..62102de 100644
--- a/src/com/android/mail/browse/SelectedConversationsActionMenu.java
+++ b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
@@ -22,6 +22,7 @@
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.Folder;
 import com.android.mail.providers.UIProvider;
+import com.android.mail.providers.UIProvider.FolderCapabilities;
 import com.android.mail.providers.UIProvider.ConversationColumns;
 import com.android.mail.ui.AnimatedAdapter;
 import com.android.mail.ui.ActionCompleteListener;
@@ -257,19 +258,21 @@
                 break;
             }
         }
-        MenuItem star = menu.findItem(R.id.star);
+        final MenuItem star = menu.findItem(R.id.star);
         star.setVisible(showStar);
-        MenuItem unstar = menu.findItem(R.id.remove_star);
+        final MenuItem unstar = menu.findItem(R.id.remove_star);
         unstar.setVisible(!showStar);
-        MenuItem read = menu.findItem(R.id.read);
+        final MenuItem read = menu.findItem(R.id.read);
         read.setVisible(!showMarkUnread);
-        MenuItem unread = menu.findItem(R.id.unread);
+        final MenuItem unread = menu.findItem(R.id.unread);
         unread.setVisible(showMarkUnread);
-        MenuItem archive = menu.findItem(R.id.archive);
-        archive.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.ARCHIVE));
-        MenuItem spam = menu.findItem(R.id.report_spam);
-        spam.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_SPAM));
-        MenuItem mute = menu.findItem(R.id.mute);
+        final MenuItem archive = menu.findItem(R.id.archive);
+        archive.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.ARCHIVE) &&
+                mFolder.supportsCapability(FolderCapabilities.ARCHIVE));
+        final MenuItem spam = menu.findItem(R.id.report_spam);
+        spam.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.REPORT_SPAM) &&
+                mFolder.supportsCapability(FolderCapabilities.ARCHIVE));
+        final MenuItem mute = menu.findItem(R.id.mute);
         mute.setVisible(mAccount.supportsCapability(UIProvider.AccountCapabilities.MUTE));
         return true;
     }
@@ -412,6 +415,12 @@
                     Conversation.delete(mContext, conversations);
                     break;
                 case R.id.mute:
+                    if (mFolder.supportsCapability(FolderCapabilities.DESTRUCTIVE_MUTE)) {
+                        // Make sure to set the localDeleteOnUpdate flag for these conversatons.
+                        for (Conversation conversation: conversations) {
+                            conversation.localDeleteOnUpdate = true;
+                        }
+                    }
                     Conversation.mute(mContext, conversations);
                     break;
                 case R.id.report_spam:
diff --git a/src/com/android/mail/providers/Folder.java b/src/com/android/mail/providers/Folder.java
index eeba954..83fcb7f 100644
--- a/src/com/android/mail/providers/Folder.java
+++ b/src/com/android/mail/providers/Folder.java
@@ -316,4 +316,8 @@
         }
         return result.toString();
     }
+
+    public boolean supportsCapability(int capability) {
+        return (capabilities & capability) != 0;
+    }
 }
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index 7133fe5..18c5044 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -17,12 +17,16 @@
 
 package com.android.mail.providers;
 
+import android.content.ContentProvider;
+import android.content.ContentValues;
 import android.content.Context;
 import android.provider.BaseColumns;
 import android.text.TextUtils;
+import android.net.Uri;
 
 import com.android.common.contacts.DataUsageStatUpdater;
 
+import java.lang.String;
 import java.util.ArrayList;
 
 
@@ -306,6 +310,23 @@
         public static final int PARENT = 0x0002;
         public static final int CAN_HOLD_MAIL = 0x0004;
         public static final int CAN_ACCEPT_MOVED_MESSAGES = 0x0008;
+        /**
+         * For accounts that support archive, this will indicate that this folder supports
+         * the archive functionality.
+         */
+        public static final int ARCHIVE = 0x0010;
+
+        /**
+         * For accounts that support report spam, this will indicate that this folder supports
+         * the report spam functionality.
+         */
+        public static final int REPORT_SPAM = 0x0020;
+
+        /**
+         * For accounts that support mute, this will indicate if a mute is performed from within
+         * this folder, the action is destructive.
+         */
+        public static final int DESTRUCTIVE_MUTE = 0x0040;
     }
 
     public static final class FolderColumns {
@@ -496,19 +517,46 @@
          */
         public static final String FOLDER_LIST = "folderList";
 
-        public ConversationColumns() {
+        private ConversationColumns() {
         }
     }
 
     /**
-     * Returns a uri that, when queried, will return a cursor with a list of information for the
-     * list of configured accounts.
-     * @return
+     * List of operations that can can be performed on a conversation. These operations are applied
+     * with {@link ContentProvider#update(Uri, ContentValues, String, String[])}
+     * where the conversation uri is specified, and the ContentValues specifies the operation to
+     * be performed.
+     * <p/>
+     * The operation to be performed is specified in the ContentValues by
+     * the {@link ConversationOperations#OPERATION_KEY}
+     * <p/>
+     * Note not all UI providers will support these operations.  {@link AccountCapabilities} can
+     * be used to determine which operations are supported.
      */
-    // TODO: create a static registry for the starting point for the UI provider.
-//    public static Uri getAccountsUri() {
-//        return Uri.parse(BASE_URI_STRING + "/");
-//    }
+    public static final class ConversationOperations {
+        /**
+         * ContentValues key used to specify the operation to be performed
+         */
+        public static final String OPERATION_KEY = "operation";
+
+        /**
+         * Archive operation
+         */
+        public static final String ARCHIVE = "archive";
+
+        /**
+         * Mute operation
+         */
+        public static final String MUTE = "mute";
+
+        /**
+         * Report spam operation
+         */
+        public static final String REPORT_SPAM = "report_spam";
+
+        private ConversationOperations() {
+        }
+    }
 
     public static final class DraftType {
         public static final int NOT_A_DRAFT = 0;
diff --git a/src/com/android/mail/ui/MailActivity.java b/src/com/android/mail/ui/MailActivity.java
index d5904a6..724c681 100644
--- a/src/com/android/mail/ui/MailActivity.java
+++ b/src/com/android/mail/ui/MailActivity.java
@@ -20,6 +20,7 @@
 import android.app.Dialog;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.StrictMode;
 import android.view.ActionMode;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -40,6 +41,8 @@
     // TODO(viki) This class lacks: What's New dialog
     // TODO(viki) This class lacks: Sync Window Upgrade dialog
 
+    private static final boolean STRICT_MODE = true;
+
     /**
      * The activity controller to which we delegate most Activity lifecycle events.
      */
@@ -112,6 +115,21 @@
 
     @Override
     public void onCreate(Bundle savedState) {
+        if (STRICT_MODE) {
+            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+                    .detectDiskReads()
+                    .detectDiskWrites()
+                    .detectNetwork()   // or .detectAll() for all detectable problems
+                    .penaltyLog()
+                    .penaltyFlashScreen()
+                    .build());
+            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+                    .detectLeakedSqlLiteObjects()
+                    .detectLeakedClosableObjects()
+                    .penaltyLog()
+//                    .penaltyDeath()
+                    .build());
+        }
         super.onCreate(savedState);
 
         mViewMode = new ViewMode(this);