Show the list of conversations for the folder selected in the widget.

Going to take a cleanup pass after this is in and move things off the UI
thread, see if I can pass parcelable objects via remote views (seems
like I can't), or see if I can get away with just having a folderuri.

Change-Id: I28aaee942cef963a88043bb355ad1a21fdfc5f21
diff --git a/src/com/android/mail/persistence/Persistence.java b/src/com/android/mail/persistence/Persistence.java
new file mode 100644
index 0000000..3e24ddd
--- /dev/null
+++ b/src/com/android/mail/persistence/Persistence.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mail.persistence;
+
+import com.android.mail.utils.LogUtils;
+import com.google.common.annotations.VisibleForTesting;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+import java.util.Set;
+
+/**
+ * This class is used to read and write Mail data to the persistent store. Note that each
+ * key is suffixed with the account name, which is why I need to do some manual work in
+ * order to get/set these values.
+ */
+public class Persistence {
+    public static final String TAG = new LogUtils().getLogTag();
+
+    private static Persistence mInstance = null;
+
+    private static SharedPreferences sSharedPrefs;
+
+    private Persistence() {
+        //  Singleton only, use getInstance()
+    }
+
+    // The name of our shared preferences store
+    public static final String SHARED_PREFERENCES_NAME = "UnifiedEmail";
+
+    public static Persistence getInstance() {
+        if (mInstance == null) {
+            mInstance = new Persistence();
+        }
+
+        return mInstance;
+    }
+
+    public static SharedPreferences getPreferences(Context context) {
+        if (sSharedPrefs == null) {
+            sSharedPrefs = context.getSharedPreferences(
+                    SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+        }
+        return sSharedPrefs;
+    }
+
+    private String makeKey(String account, String key) {
+        return account != null ? account + "-" + key : key;
+    }
+
+    public void setString(Context context, String account, String key, String value) {
+        Editor editor = getPreferences(context).edit();
+        editor.putString(makeKey(account, key), value);
+        editor.apply();
+    }
+
+    public void setStringSet(Context context, String account, String key, Set<String> values) {
+        Editor editor = getPreferences(context).edit();
+        editor.putStringSet(makeKey(account, key) , values);
+        editor.apply();
+    }
+
+    public Set<String> getStringSet(Context context, String account, String key, Set<String> def) {
+        return getPreferences(context).getStringSet(makeKey(account, key), def);
+    }
+
+    public void setBoolean(Context context, String account, String key, Boolean value) {
+        Editor editor = getPreferences(context).edit();
+        editor.putBoolean(makeKey(account, key), value);
+        editor.apply();
+    }
+
+    @VisibleForTesting
+    public void remove(Context context, String account, String key) {
+        remove(context, makeKey(account, key));
+    }
+
+    private void remove(Context context, String key) {
+        Editor editor = getPreferences(context).edit();
+        editor.remove(key);
+        editor.apply();
+    }
+}
diff --git a/src/com/android/mail/providers/Account.java b/src/com/android/mail/providers/Account.java
index 3287632..8a8f11a 100644
--- a/src/com/android/mail/providers/Account.java
+++ b/src/com/android/mail/providers/Account.java
@@ -30,7 +30,7 @@
     /**
      * The uri to directly access the information for this account.
      */
-    public final String accountUri;
+    public final String uri;
 
     /**
      * The possible capabilities that this account supports.
@@ -96,7 +96,7 @@
     public Account(Parcel in) {
         super(in);
         providerVersion = in.readInt();
-        accountUri = in.readString();
+        uri = in.readString();
         capabilities = in.readInt();
         folderListUri = in.readString();
         searchUri = in.readString();
@@ -114,7 +114,7 @@
         accountFromAddressesUri = cursor.getString(UIProvider.ACCOUNT_FROM_ADDRESSES_URI_COLUMN);
         capabilities = cursor.getInt(UIProvider.ACCOUNT_CAPABILITIES_COLUMN);
         providerVersion = cursor.getInt(UIProvider.ACCOUNT_PROVIDER_VERISON_COLUMN);
-        accountUri = cursor.getString(UIProvider.ACCOUNT_URI_COLUMN);
+        uri = cursor.getString(UIProvider.ACCOUNT_URI_COLUMN);
         folderListUri = cursor.getString(UIProvider.ACCOUNT_FOLDER_LIST_URI_COLUMN);
         searchUri = cursor.getString(UIProvider.ACCOUNT_SEARCH_URI_COLUMN);
         saveDraftUri = cursor.getString(UIProvider.ACCOUNT_SAVE_DRAFT_URI_COLUMN);
@@ -133,7 +133,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         super.writeToParcel(dest, flags);
         dest.writeInt(providerVersion);
-        dest.writeString(accountUri);
+        dest.writeString(uri);
         dest.writeInt(capabilities);
         dest.writeString(folderListUri);
         dest.writeString(searchUri);
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index 168d6cd..2fe83e0 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -38,7 +38,6 @@
 import android.webkit.WebView;
 
 import com.android.mail.R;
-import com.android.mail.browse.ConversationCursor;
 import com.android.mail.providers.Account;
 import com.android.mail.providers.Folder;
 import com.android.mail.providers.UIProvider;
diff --git a/src/com/android/mail/widget/BaseWidgetProvider.java b/src/com/android/mail/widget/BaseWidgetProvider.java
index 167f80b..c011709 100644
--- a/src/com/android/mail/widget/BaseWidgetProvider.java
+++ b/src/com/android/mail/widget/BaseWidgetProvider.java
@@ -17,6 +17,7 @@
 package com.android.mail.widget;
 
 import com.android.mail.R;
+import com.android.mail.persistence.Persistence;
 import com.android.mail.providers.Account;
 import com.android.mail.providers.AccountCacheProvider;
 import com.android.mail.providers.Folder;
@@ -33,6 +34,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences.Editor;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Parcel;
@@ -51,7 +53,7 @@
     private static final String ACCOUNT_FOLDER_PREFERENCE_SEPARATOR = " ";
 
     private static String createWidgetPreferenceValue(Account account, Folder folder) {
-        return account.name + ACCOUNT_FOLDER_PREFERENCE_SEPARATOR + folder.name;
+        return account.uri + ACCOUNT_FOLDER_PREFERENCE_SEPARATOR + folder.uri;
 
     }
 
@@ -60,13 +62,10 @@
      */
     static void saveWidgetInformation(Context context, int appWidgetId, Account account,
             Folder folder) {
-        // TODO: (mindyp) save widget information.
-        /*
-         * Editor editor = Persistence.getPreferences(context).edit();
-         * editor.putString(WidgetProvider.WIDGET_ACCOUNT_PREFIX + appWidgetId,
-         * BaseWidgetProvider.createWidgetPreferenceValue(account, folder));
-         * editor.apply();
-         */
+        Editor editor = Persistence.getPreferences(context).edit();
+        editor.putString(WidgetProvider.WIDGET_ACCOUNT_PREFIX + appWidgetId,
+                BaseWidgetProvider.createWidgetPreferenceValue(account, folder));
+        editor.apply();
     }
 
     /**
@@ -75,14 +74,14 @@
     @Override
     public void onDeleted(Context context, int[] appWidgetIds) {
         super.onDeleted(context, appWidgetIds);
-
         // TODO: (mindyp) save widget information.
-        /*
-         * Editor editor = Persistence.getPreferences(context).edit(); for (int
-         * i = 0; i < appWidgetIds.length; ++i) { // Remove the account in the
-         * preference editor.remove(WIDGET_ACCOUNT_PREFIX + appWidgetIds[i]); }
-         * editor.apply();
-         */
+        Editor editor = Persistence.getPreferences(context).edit();
+        for (int i = 0; i < appWidgetIds.length; ++i) {
+            // Remove the account in the preference
+            editor.remove(WIDGET_ACCOUNT_PREFIX + appWidgetIds[i]);
+        }
+        editor.apply();
+
     }
 
     /**
@@ -113,17 +112,17 @@
             for (int id : getCurrentWidgetIds(context)) {
                 // Retrieve the persisted information for this widget from
                 // preferences.
-                // TODO: (mindyp) get widget preferences.
-                /*
-                 * final String accountFolder =
-                 * Persistence.getPreferences(context)
-                 * .getString(WIDGET_ACCOUNT_PREFIX + id, null); // If the
-                 * account matched, update the widget. if (accountFolder !=
-                 * null) { final String[] parsedInfo = TextUtils.split(
-                 * accountFolder, ACCOUNT_FOLDER_PREFERENCE_SEPARATOR); if
-                 * (accountToBeUpdated.equals(parsedInfo[0])) {
-                 * widgetsToUpdate.add(id); } }
-                 */
+                final String accountFolder = Persistence.getPreferences(context).getString(
+                        WIDGET_ACCOUNT_PREFIX + id, null);
+                // If the account matched, update the widget.
+                if (accountFolder != null) {
+                    final String[] parsedInfo = TextUtils.split(accountFolder,
+                            ACCOUNT_FOLDER_PREFERENCE_SEPARATOR);
+                    if (accountToBeUpdated.equals(parsedInfo[0])) {
+                        widgetsToUpdate.add(id);
+                    }
+                }
+
             }
             if (widgetsToUpdate.size() > 0) {
                 final int[] widgets = Ints.toArray(widgetsToUpdate);
@@ -140,36 +139,51 @@
     public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
         super.onUpdate(context, appWidgetManager, appWidgetIds);
         // Update each of the widgets with a remote adapter
+        ContentResolver resolver = context.getContentResolver();
         for (int i = 0; i < appWidgetIds.length; ++i) {
             // Get the account for this widget from preference
-            // TODO: (mindyp) get widget preferences.
-            /*
-             * String accountFolder =
-             * Persistence.getPreferences(context).getString(
-             * WIDGET_ACCOUNT_PREFIX + appWidgetIds[i], null);
-             */
-            String accountFolder = null;
-            String account = null;
-            String folder = null;
+            String accountFolder = Persistence.getPreferences(context).getString(
+                    WIDGET_ACCOUNT_PREFIX + appWidgetIds[i], null);
+            String accountUri = null;
+            String folderUri = null;
             if (!TextUtils.isEmpty(accountFolder)) {
                 final String[] parsedInfo = TextUtils.split(accountFolder,
                         ACCOUNT_FOLDER_PREFERENCE_SEPARATOR);
                 if (parsedInfo.length == 2) {
-                    account = parsedInfo[0];
-                    folder = parsedInfo[1];
+                    accountUri = parsedInfo[0];
+                    folderUri = parsedInfo[1];
                 } else {
                     // TODO: (mindyp) how can we lookup the associated account?
                     // AccountCacheProvider?
-                    account = accountFolder;
-                    folder = "inbox"; // account.getAccountInbox(context,
+                    accountUri = accountFolder;
+                    folderUri = null; // account.getAccountInbox(context,
                                       // account);
                 }
             }
             // account will be null the first time a widget is created. This is
             // OK, as isAccountValid will return false, allowing the widget to
-            // be configured
-            updateWidget(context, appWidgetIds[i], new Account(Parcel.obtain()),
-                    new Folder(Parcel.obtain()));
+            // be configured.
+
+            // Lookup the account by URI.
+            Account account = null;
+            if (!TextUtils.isEmpty(accountUri)) {
+                Cursor accountCursor = resolver.query(Uri.parse(accountUri),
+                        UIProvider.ACCOUNTS_PROJECTION, null, null, null);
+                if (accountCursor != null) {
+                    accountCursor.moveToFirst();
+                    account = new Account(accountCursor);
+                }
+            }
+            Folder folder = null;
+            if (!TextUtils.isEmpty(folderUri)) {
+                Cursor folderCursor = resolver.query(Uri.parse(folderUri),
+                        UIProvider.FOLDERS_PROJECTION, null, null, null);
+                if (folderCursor != null) {
+                    folderCursor.moveToFirst();
+                    folder = new Folder(folderCursor);
+                }
+            }
+            updateWidget(context, appWidgetIds[i], account, folder);
         }
     }
 
@@ -179,10 +193,10 @@
                     AccountCacheProvider.getAccountsUri(), UIProvider.ACCOUNTS_PROJECTION, null,
                     null, null);
             if (accountCursor.moveToFirst()) {
-                Account newAccount = new Account(accountCursor);
                 do {
+                    String newAccount = accountCursor.getString(UIProvider.ACCOUNT_URI_COLUMN);
                     if (account != null && newAccount != null
-                            && TextUtils.equals(account.name, newAccount.name))
+                            && TextUtils.equals(account.uri, newAccount))
                         return true;
                 } while (accountCursor.moveToNext());
             }
@@ -191,20 +205,14 @@
     }
 
     /**
-     * Returns if a widget is configured with the given account.
+     * Returns true if this widget id has been configured and saved.
      */
     public static boolean isWidgetConfigured(Context context, int appWidgetId, Account account,
             Folder folder) {
         if (isAccountValid(context, account)) {
             // TODO: (mindyp) get widget preferences.
-            /*
-             * final String accountFolder =
-             * Persistence.getPreferences(context).getString(
-             * WIDGET_ACCOUNT_PREFIX + appWidgetId, null);
-             */
-            // Return true if this widget id has been configured and saved.
-            final String accountFolder = null;
-            return accountFolder != null;
+            return Persistence.getPreferences(context).getString(
+                    WIDGET_ACCOUNT_PREFIX + appWidgetId, null) != null;
         }
         return false;
     }
@@ -214,7 +222,6 @@
      */
     public static void updateWidget(Context context, int appWidgetId, Account account, Folder folder) {
         RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
-        PendingIntent clickIntent;
         final boolean isAccountValid = isAccountValid(context, account);
 
         if (!isAccountValid) {
@@ -231,7 +238,7 @@
             configureIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
             configureIntent.setData(Uri.parse(configureIntent.toUri(Intent.URI_INTENT_SCHEME)));
             configureIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
-            clickIntent = PendingIntent.getActivity(context, 0, configureIntent,
+            PendingIntent clickIntent = PendingIntent.getActivity(context, 0, configureIntent,
                     PendingIntent.FLAG_UPDATE_CURRENT);
             remoteViews.setOnClickPendingIntent(R.id.widget_configuration, clickIntent);
         } else {
@@ -243,18 +250,8 @@
     }
 
     private static boolean isFolderSynchronized(Context context, Account account, Folder folder) {
-        // Determine if the folder has been configured to be synced
-        final ContentResolver resolver = context.getContentResolver();
-
-        // TODO: (mindyp) Get the current sync window for the specified account
-        final Cursor settings = account.getSettings();
-        final Set<String> synchronizedFoldersSet = Sets.newHashSet();
-
-        // TODO: Add all of the synchronized folders to the set
-        // synchronizedFoldersSet.addAll(settings.getFoldersIncluded());
-        // synchronizedFoldersSet.addAll(settings.getFoldersPartial());
-
-        return synchronizedFoldersSet.contains(folder);
+        // TODO: (mindyp) check the folder settings to see if it is syncing.
+        return true;
     }
 
     /**
@@ -291,11 +288,10 @@
         // Launch an intent to avoid ANRs
         final Intent intent = new Intent(context, WidgetService.class);
         intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
-        intent.putExtra(EXTRA_ACCOUNT, account);
-        intent.putExtra(EXTRA_FOLDER, folder);
+        intent.putExtra(EXTRA_ACCOUNT, account.uri);
+        intent.putExtra(EXTRA_FOLDER, folder.uri);
         intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
         remoteViews.setRemoteAdapter(R.id.conversation_list, intent);
-
         // Open mail app when click on header
         final Intent mailIntent = Utils.createViewConversationIntent(context, account, folder,
                 UIProvider.INVALID_CONVERSATION_ID);
@@ -310,7 +306,6 @@
         clickIntent = PendingIntent.getActivity(context, 0, composeIntent,
                 PendingIntent.FLAG_UPDATE_CURRENT);
         remoteViews.setOnClickPendingIntent(R.id.widget_compose, clickIntent);
-
         // On click intent for Conversation
         final Intent conversationIntent = new Intent();
         conversationIntent.setAction(Intent.ACTION_VIEW);
diff --git a/src/com/android/mail/widget/WidgetService.java b/src/com/android/mail/widget/WidgetService.java
index ac462ec..220f6e1 100644
--- a/src/com/android/mail/widget/WidgetService.java
+++ b/src/com/android/mail/widget/WidgetService.java
@@ -16,7 +16,6 @@
 package com.android.mail.widget;
 
 import com.android.mail.R;
-import com.android.mail.browse.ConversationCursor;
 import com.android.mail.providers.Account;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.Folder;
@@ -42,8 +41,6 @@
 import android.widget.RemoteViews;
 import android.widget.RemoteViewsService;
 
-import java.util.Map;
-
 public class WidgetService extends RemoteViewsService {
     /**
      * Lock to avoid race condition between widgets.
@@ -76,14 +73,24 @@
         private boolean mShouldShowViewMore;
         private boolean mFolderInformationShown = false;
         private ContentResolver mResolver;
+        private String mFolderUri;
 
         public MailFactory(Context context, Intent intent) {
             mContext = context;
             mAppWidgetId = intent.getIntExtra(
                     AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
-            mAccount = intent.getParcelableExtra(WidgetProvider.EXTRA_ACCOUNT);
-            final Folder folder = intent.getParcelableExtra(WidgetProvider.EXTRA_FOLDER);
-            mFolder = folder != null ? folder : mAccount.getAccountInbox();
+            String accountUri = intent.getStringExtra(WidgetProvider.EXTRA_ACCOUNT);
+            Cursor cursor = context.getContentResolver().query(Uri.parse(accountUri),
+                    UIProvider.ACCOUNTS_PROJECTION, null, null, null);
+            cursor.moveToFirst();
+            mAccount = new Account(cursor);
+            cursor.close();
+            mFolderUri = intent.getStringExtra(WidgetProvider.EXTRA_FOLDER);
+            Cursor folderCursor = context.getContentResolver().query(Uri.parse(mFolderUri),
+                    UIProvider.FOLDERS_PROJECTION, null, null, null);
+            folderCursor.moveToFirst();
+            mFolder = new Folder(folderCursor);
+            folderCursor.close();
             mWidgetConversationViewBuilder = new WidgetConversationViewBuilder(mContext, mAccount);
             mResolver = context.getContentResolver();
         }
@@ -102,7 +109,7 @@
             mConversationCursor = mResolver.query(Uri.parse(mFolder.conversationListUri),
                     UIProvider.CONVERSATION_PROJECTION, null, null, null);
 
-            mFolderLoader = new CursorLoader(mContext, Uri.parse(mFolder.uri),
+            mFolderLoader = new CursorLoader(mContext, Uri.parse(mFolderUri),
                     UIProvider.FOLDERS_PROJECTION, null, null, null);
             mFolderLoader.registerListener(0, this);
             mFolderUpdateHandler = new FolderUpdateHandler(mContext.getResources().getInteger(
@@ -186,8 +193,8 @@
                 // Split the senders and status from the instructions.
                 SpannableStringBuilder senderBuilder = new SpannableStringBuilder();
                 SpannableStringBuilder statusBuilder = new SpannableStringBuilder();
-                Utils.getStyledSenderSnippet(mContext, conversation.senders, senderBuilder,
-                        statusBuilder, MAX_SENDERS_LENGTH, false, false, false);
+                senderBuilder.append(conversation.senders);
+                // TODO: (mindyp) create stylized sender text.
 
                 // Get styled date.
                 CharSequence date = DateUtils.getRelativeTimeSpanString(
diff --git a/tests/src/com/android/mail/providers/AccountTests.java b/tests/src/com/android/mail/providers/AccountTests.java
index b346cd5..6beb009 100644
--- a/tests/src/com/android/mail/providers/AccountTests.java
+++ b/tests/src/com/android/mail/providers/AccountTests.java
@@ -45,7 +45,7 @@
         assertEquals(outAccount.accountFromAddressesUri, account.accountFromAddressesUri);
         assertEquals(outAccount.capabilities, account.capabilities);
         assertEquals(outAccount.providerVersion, account.providerVersion);
-        assertEquals(outAccount.accountUri, account.accountUri);
+        assertEquals(outAccount.uri, account.uri);
         assertEquals(outAccount.folderListUri, account.folderListUri);
         assertEquals(outAccount.searchUri, account.searchUri);
         assertEquals(outAccount.saveDraftUri, account.saveDraftUri);