Merge "Use Drawables for senders image. Less animation jank, less GC jank, less memory." into jb-ub-mail-ur11
diff --git a/res/raw/template_conversation_upper.html b/res/raw/template_conversation_upper.html
index 5ba3a84..fb69324 100644
--- a/res/raw/template_conversation_upper.html
+++ b/res/raw/template_conversation_upper.html
@@ -55,6 +55,7 @@
-webkit-transform: translate3d(0, 0, 0);
}
}
+ %s
</style>
</head>
<body style="margin: 0 %spx;">
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 955febf..40a965e 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -32,7 +32,7 @@
<string-array name="compose_modes">
<item msgid="8631190144210933782">"जवाब दें"</item>
<item msgid="4085029907540221568">"सभी को जवाब दें"</item>
- <item msgid="857480048798815437">"अग्रेषित करें"</item>
+ <item msgid="857480048798815437">"इसको भेजें"</item>
</string-array>
<string name="reply_attribution" msgid="717207316577386788">"<xliff:g id="DATE">%s</xliff:g> को, <xliff:g id="PERSON">%s</xliff:g> ने लिखा:"</string>
<string name="forward_attribution" msgid="1498936339458535158">"---------- अग्रेषित संदेश ----------<br>प्रेषक: <xliff:g id="FROM">%1$s</xliff:g><br>दिनांक: <xliff:g id="DATE">%2$s</xliff:g><br>विषय: <xliff:g id="SUBJECT">%3$s</xliff:g><br>प्रति: <xliff:g id="TO">%4$s</xliff:g><br>"</string>
@@ -69,7 +69,7 @@
<string name="reply" msgid="2032052598496088561">"प्रत्युत्तर दें"</string>
<string name="reply_all" msgid="7257248094625487557">"सब को जवाब दें"</string>
<string name="resume_draft" msgid="6450150180834092146">"संपादित करें"</string>
- <string name="forward" msgid="6822914459902983767">"अग्रेषित करें"</string>
+ <string name="forward" msgid="6822914459902983767">"इसको भेजें"</string>
<string name="menu_compose" msgid="6274193058224230645">"लिखें"</string>
<string name="menu_change_folders" msgid="1542713666608888717">"फ़ोल्डर बदलें"</string>
<string name="menu_move_to" msgid="9138296669516358542">"इसमें ले जाएं"</string>
@@ -106,7 +106,7 @@
<string name="download_again" msgid="7418568915429156518">"पुनः डाउनलोड करें"</string>
<string name="more_info_attachment" msgid="717244337981816703">"जानकारी"</string>
<string name="attachment_type_blocked" msgid="7878184764428642891">"दुर्भाग्यवश, आप इस प्रकार के अनुलग्नक को सहेज या खोल नहीं सकते."</string>
- <string name="no_application_found" msgid="1945184804521392093">"कोई भी एप्लिकेशन इस अनुलग्नक को देखने के लिए नहीं खोल सकता."</string>
+ <string name="no_application_found" msgid="1945184804521392093">"कोई भी एप्स इस अनुलग्नक को देखने के लिए नहीं खोल सकता."</string>
<string name="fetching_attachment" msgid="2599763030649526179">"अनुलग्नक फ़ेच कर रहा है"</string>
<string name="please_wait" msgid="8797634225088247121">"कृपया प्रतीक्षा करें…"</string>
<string name="saved" msgid="6660844285730790469">"सहेजा गया, <xliff:g id="SIZE">%s</xliff:g>"</string>
@@ -393,7 +393,7 @@
<string name="account_settings_param" msgid="5277032997773498476">"खाता सेटिंग"</string>
<string name="unsent_messages_in_outbox" msgid="8754987959475577698">"<xliff:g id="OUTBOX">%2$s</xliff:g> में <xliff:g id="NUMBER">%1$s</xliff:g> अप्रेषित"</string>
<string name="turn_auto_sync_on_dialog_title" msgid="8981949974921704813">"स्वत:-समन्वयन चालू करें?"</string>
- <string name="turn_auto_sync_on_dialog_body" msgid="5070811094706347971">"आपके द्वारा न केवल Gmail में, बल्कि सभी एप्लिकेशन और खातों में किए जाने वाले बदलाव, वेब, आपके अन्य उपकरणों, और आपके <xliff:g id="PHONE_OR_TABLET">%1$s</xliff:g> के बीच समन्वयित किए जाएंगे."</string>
+ <string name="turn_auto_sync_on_dialog_body" msgid="5070811094706347971">"आपके द्वारा न केवल Gmail में, बल्कि सभी एप्स और खातों में किए जाने वाले बदलाव, वेब, आपके अन्य उपकरणों, और आपके <xliff:g id="PHONE_OR_TABLET">%1$s</xliff:g> के बीच समन्वयित किए जाएंगे."</string>
<string name="phone" msgid="5171715391553213328">"फ़ोन"</string>
<string name="tablet" msgid="7956969657216748522">"टेबलेट"</string>
<string name="turn_auto_sync_on_dialog_confirm_btn" msgid="1445158420197688714">"चालू करें"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d4106d6..5453934 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -935,4 +935,8 @@
LIMIT=30] -->
<string name="turn_auto_sync_on_dialog_confirm_btn">Turn on</string>
+ <!-- Button in conversation list to show more folders [CHAR LIMIT=50] -->
+ <string name="show_n_more_folders">Show <xliff:g id="number">%1$s</xliff:g> more folders</string>
+ <!-- Button in conversation list to hide folders [CHAR LIMIT=50] -->
+ <string name="hide_folders">Hide folders</string>
</resources>
diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java
index 6df2d18..7a3ca0f 100644
--- a/src/com/android/mail/browse/ConversationCursor.java
+++ b/src/com/android/mail/browse/ConversationCursor.java
@@ -165,6 +165,8 @@
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
+ private final boolean mCachingEnabled;
+
private void setCursor(UnderlyingCursorWrapper cursor) {
// If we have an existing underlying cursor, make sure it's closed
if (mUnderlyingCursor != null) {
@@ -193,6 +195,9 @@
mName = name;
qProjection = UIProvider.CONVERSATION_PROJECTION;
mCursorObserver = new CursorObserver(new Handler(Looper.getMainLooper()));
+
+ // Disable caching on low memory devices
+ mCachingEnabled = !Utils.isLowRamDevice(activity);
}
/**
@@ -357,7 +362,7 @@
* notes on thread safety.
*/
private int mCachePos;
- private boolean mCachingEnabled = true;
+ private boolean mCachingEnabled;
private final NewCursorUpdateObserver mCursorUpdateObserver;
private boolean mUpdateObserverRegistered = false;
@@ -370,9 +375,11 @@
private boolean mCursorUpdated = false;
- public UnderlyingCursorWrapper(Cursor result) {
+ public UnderlyingCursorWrapper(Cursor result, boolean cachingEnabled) {
super(result);
+ mCachingEnabled = cachingEnabled;
+
// Register the content observer immediately, as we want to make sure that we don't miss
// any updates
mCursorUpdateObserver =
@@ -639,7 +646,8 @@
uri, time, result.getCount());
}
System.gc();
- return new UnderlyingCursorWrapper(result);
+
+ return new UnderlyingCursorWrapper(result, mCachingEnabled);
}
static boolean offUiThread() {
diff --git a/src/com/android/mail/preferences/MailPrefs.java b/src/com/android/mail/preferences/MailPrefs.java
index c6146c8..3791055 100644
--- a/src/com/android/mail/preferences/MailPrefs.java
+++ b/src/com/android/mail/preferences/MailPrefs.java
@@ -23,6 +23,7 @@
import com.android.mail.providers.Account;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogUtils;
+import com.android.mail.utils.Utils;
import com.android.mail.widget.BaseWidgetProvider;
import com.google.common.collect.ImmutableSet;
@@ -396,6 +397,11 @@
}
public boolean getShowSenderImages() {
+ if (Utils.isLowRamDevice(getContext())) {
+ // Do not show sender images in conversation list on low memory devices since they are
+ // expensive to render.
+ return false;
+ }
final SharedPreferences sharedPreferences = getSharedPreferences();
return sharedPreferences.getBoolean(PreferenceKeys.SHOW_SENDER_IMAGES, true);
}
@@ -406,6 +412,9 @@
}
public boolean getShowAttachmentPreviews() {
+ if (Utils.isLowRamDevice(getContext())) {
+ return false;
+ }
final SharedPreferences sharedPreferences = getSharedPreferences();
return sharedPreferences.getBoolean(PreferenceKeys.SHOW_ATTACHMENT_PREVIEWS, true);
}
diff --git a/src/com/android/mail/ui/HtmlConversationTemplates.java b/src/com/android/mail/ui/HtmlConversationTemplates.java
index a285247..d368454 100644
--- a/src/com/android/mail/ui/HtmlConversationTemplates.java
+++ b/src/com/android/mail/ui/HtmlConversationTemplates.java
@@ -23,6 +23,7 @@
import com.android.mail.R;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
+import com.android.mail.utils.Utils;
import com.google.common.annotations.VisibleForTesting;
import java.io.IOException;
@@ -181,7 +182,9 @@
}
reset();
- append(sConversationUpper, sideMargin, conversationHeaderHeight);
+ final String border = Utils.isRunningKitkatOrLater() ?
+ "img[blocked-src] { border: 1px solid #CCCCCC; }" : "";
+ append(sConversationUpper, border, sideMargin, conversationHeaderHeight);
mInProgress = true;
}
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index f3fd875..c4927cd 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -22,6 +22,7 @@
import com.google.android.mail.common.html.parser.HtmlTreeBuilder;
import com.google.common.collect.Maps;
+import android.app.ActivityManager;
import android.app.Fragment;
import android.app.SearchManager;
import android.content.Context;
@@ -140,6 +141,26 @@
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
}
+ public static boolean isRunningKitkatOrLater() {
+ // TODO - change to SDK_INT check when API is finalized
+ return Build.VERSION.CODENAME.startsWith("K");
+ }
+
+ /**
+ * @return Whether we are running on a low memory device. This is used to disable certain
+ * memory intensive features in the app.
+ */
+ public static boolean isLowRamDevice(Context context) {
+ // TODO: use SDK_INT to check if device is KitKat or greater.
+ if (Build.VERSION.CODENAME.startsWith("K")) {
+ final ActivityManager am = (ActivityManager) context.getSystemService(
+ Context.ACTIVITY_SERVICE);
+ return am.isLowRamDevice();
+ } else {
+ return false;
+ }
+ }
+
/**
* Sets WebView in a restricted mode suitable for email use.
*
diff --git a/src/com/android/mail/widget/BaseWidgetProvider.java b/src/com/android/mail/widget/BaseWidgetProvider.java
index 8d0be11..98a5ad6 100644
--- a/src/com/android/mail/widget/BaseWidgetProvider.java
+++ b/src/com/android/mail/widget/BaseWidgetProvider.java
@@ -52,7 +52,6 @@
public static final String EXTRA_FOLDER_URI = "folder-uri";
public static final String EXTRA_FOLDER_CONVERSATION_LIST_URI = "folder-conversation-list-uri";
public static final String EXTRA_FOLDER_DISPLAY_NAME = "folder-display-name";
- public static final String EXTRA_UNREAD = "unread";
public static final String EXTRA_UPDATE_ALL_WIDGETS = "update-all-widgets";
public static final String WIDGET_ACCOUNT_PREFIX = "widget-account-";
@@ -139,8 +138,8 @@
} else if (Utils.ACTION_NOTIFY_DATASET_CHANGED.equals(action)) {
// Receive notification for a certain account.
final Bundle extras = intent.getExtras();
- final Uri accountUri = (Uri)extras.getParcelable(Utils.EXTRA_ACCOUNT_URI);
- final Uri folderUri = (Uri)extras.getParcelable(Utils.EXTRA_FOLDER_URI);
+ final Uri accountUri = extras.getParcelable(Utils.EXTRA_ACCOUNT_URI);
+ final Uri folderUri = extras.getParcelable(Utils.EXTRA_FOLDER_URI);
final boolean updateAllWidgets = extras.getBoolean(EXTRA_UPDATE_ALL_WIDGETS, false);
if (accountUri == null && Utils.isEmpty(folderUri) && !updateAllWidgets) {
@@ -383,12 +382,12 @@
WidgetService.class);
}
- private final void migrateAllLegacyWidgetInformation(Context context) {
+ private void migrateAllLegacyWidgetInformation(Context context) {
final int[] currentWidgetIds = getCurrentWidgetIds(context);
migrateLegacyWidgets(context, currentWidgetIds);
}
- private final void migrateLegacyWidgets(Context context, int[] widgetIds) {
+ private void migrateLegacyWidgets(Context context, int[] widgetIds) {
for (int widgetId : widgetIds) {
// We only want to bother to attempt to upgrade a widget if we don't already
// have information about.
@@ -398,7 +397,7 @@
}
}
- private final void validateAllWidgetInformation(Context context) {
+ private void validateAllWidgetInformation(Context context) {
final int[] widgetIds = getCurrentWidgetIds(context);
for (int widgetId : widgetIds) {
final String accountFolder = MailPrefs.get(context).getWidgetConfiguration(widgetId);
diff --git a/src/com/android/mail/widget/WidgetService.java b/src/com/android/mail/widget/WidgetService.java
index daf57ce..7ad6095 100644
--- a/src/com/android/mail/widget/WidgetService.java
+++ b/src/com/android/mail/widget/WidgetService.java
@@ -60,7 +60,7 @@
/**
* Lock to avoid race condition between widgets.
*/
- private static Object sWidgetLock = new Object();
+ private static final Object sWidgetLock = new Object();
private static final String LOG_TAG = LogTag.getLogTag();
@@ -202,6 +202,7 @@
private static final int FOLDER_LOADER_ID = 0;
private static final int CONVERSATION_CURSOR_LOADER_ID = 1;
+ private static final int ACCOUNT_LOADER_ID = 2;
private final Context mContext;
private final int mAppWidgetId;
@@ -214,6 +215,7 @@
private CursorLoader mConversationCursorLoader;
private Cursor mConversationCursor;
private CursorLoader mFolderLoader;
+ private CursorLoader mAccountLoader;
private FolderUpdateHandler mFolderUpdateHandler;
private int mFolderCount;
private boolean mShouldShowViewMore;
@@ -232,8 +234,8 @@
mFolderType = intent.getIntExtra(WidgetProvider.EXTRA_FOLDER_TYPE, FolderType.DEFAULT);
mFolderDisplayName = intent.getStringExtra(WidgetProvider.EXTRA_FOLDER_DISPLAY_NAME);
- Uri folderUri = intent.getParcelableExtra(WidgetProvider.EXTRA_FOLDER_URI);
- Uri folderConversationListUri =
+ final Uri folderUri = intent.getParcelableExtra(WidgetProvider.EXTRA_FOLDER_URI);
+ final Uri folderConversationListUri =
intent.getParcelableExtra(WidgetProvider.EXTRA_FOLDER_CONVERSATION_LIST_URI);
if (folderUri != null && folderConversationListUri != null) {
mFolderUri = folderUri;
@@ -241,6 +243,7 @@
} else {
// This is a old intent created in version UR8 (or earlier).
String folderString = intent.getStringExtra(Utils.EXTRA_FOLDER);
+ //noinspection deprecation
Folder folder = Folder.fromString(folderString);
if (folder != null) {
mFolderUri = folder.folderUri.fullUri;
@@ -304,6 +307,10 @@
res.getInteger(R.integer.widget_folder_refresh_delay_ms));
mFolderUpdateHandler.scheduleTask();
+ mAccountLoader = new CursorLoader(mContext, mAccount.uri,
+ UIProvider.ACCOUNTS_PROJECTION_NO_CAPABILITIES, null, null, null);
+ mAccountLoader.registerListener(ACCOUNT_LOADER_ID, this);
+ mAccountLoader.startLoading();
}
@Override
@@ -325,6 +332,12 @@
mFolderLoader.unregisterListener(this);
mFolderLoader = null;
}
+
+ if (mAccountLoader != null) {
+ mAccountLoader.reset();
+ mAccountLoader.unregisterListener(this);
+ mAccountLoader = null;
+ }
}
@Override
@@ -360,7 +373,7 @@
* Returns the number of conversations that should be shown in the widget. This method
* doesn't update the boolean that indicates that the "show more" item should be included
* in the list.
- * @return
+ * @return count
*/
private int getConversationCount() {
synchronized (sWidgetLock) {
@@ -519,6 +532,11 @@
final RemoteViews remoteViews =
new RemoteViews(mContext.getPackageName(), R.layout.widget);
+ if (!mService.isWidgetConfigured(mContext, mAppWidgetId, mAccount)) {
+ BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolderType,
+ mFolderUri, mFolderConversationListUri, mFolderDisplayName);
+ }
+
if (loader == mFolderLoader) {
if (!isDataValid(data)) {
return;
@@ -586,6 +604,9 @@
mContext.getString(R.string.no_conversations));
appWidgetManager.partiallyUpdateAppWidget(mAppWidgetId, remoteViews);
}
+ } else if (loader == mAccountLoader) {
+ BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolderType,
+ mFolderUri, mFolderConversationListUri, mFolderDisplayName);
}
}