Fix remote views cache to avoid lockscreen widget crosstalk
Bug: 7660973
RemoteViewsAdapter will now store the userId as part of the cache key
when caching remote views to optimize for orientation changes.
Change-Id: I7c4e52b3995d4f56ebfa35aa9516327e182ad892
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index c122bb2..499f6ad 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -21,6 +21,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
+
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
@@ -33,7 +34,6 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
-import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
@@ -90,13 +90,15 @@
private Handler mMainQueue;
// We cache the FixedSizeRemoteViewsCaches across orientation. These are the related data
- // structures;
- private static final HashMap<Pair<Intent.FilterComparison, Integer>, FixedSizeRemoteViewsCache>
- sCachedRemoteViewsCaches = new HashMap<Pair<Intent.FilterComparison, Integer>,
+ // structures;
+ private static final HashMap<RemoteViewsCacheKey,
+ FixedSizeRemoteViewsCache> sCachedRemoteViewsCaches
+ = new HashMap<RemoteViewsCacheKey,
FixedSizeRemoteViewsCache>();
- private static final HashMap<Pair<Intent.FilterComparison, Integer>, Runnable>
- sRemoteViewsCacheRemoveRunnables = new HashMap<Pair<Intent.FilterComparison, Integer>,
- Runnable>();
+ private static final HashMap<RemoteViewsCacheKey, Runnable>
+ sRemoteViewsCacheRemoveRunnables
+ = new HashMap<RemoteViewsCacheKey, Runnable>();
+
private static HandlerThread sCacheRemovalThread;
private static Handler sCacheRemovalQueue;
@@ -771,6 +773,33 @@
}
}
+ static class RemoteViewsCacheKey {
+ final Intent.FilterComparison filter;
+ final int widgetId;
+ final int userId;
+
+ RemoteViewsCacheKey(Intent.FilterComparison filter, int widgetId, int userId) {
+ this.filter = filter;
+ this.widgetId = widgetId;
+ this.userId = userId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RemoteViewsCacheKey)) {
+ return false;
+ }
+ RemoteViewsCacheKey other = (RemoteViewsCacheKey) o;
+ return other.filter.equals(filter) && other.widgetId == widgetId
+ && other.userId == userId;
+ }
+
+ @Override
+ public int hashCode() {
+ return (filter == null ? 0 : filter.hashCode()) ^ (widgetId << 2) ^ (userId << 10);
+ }
+ }
+
public RemoteViewsAdapter(Context context, Intent intent, RemoteAdapterConnectionCallback callback) {
mContext = context;
mIntent = intent;
@@ -786,7 +815,6 @@
} else {
mUserId = UserHandle.myUserId();
}
-
// Strip the previously injected app widget id from service intent
if (intent.hasExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID)) {
intent.removeExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID);
@@ -808,8 +836,8 @@
mCallback = new WeakReference<RemoteAdapterConnectionCallback>(callback);
mServiceConnection = new RemoteViewsAdapterServiceConnection(this);
- Pair<Intent.FilterComparison, Integer> key = new Pair<Intent.FilterComparison, Integer>
- (new Intent.FilterComparison(mIntent), mAppWidgetId);
+ RemoteViewsCacheKey key = new RemoteViewsCacheKey(new Intent.FilterComparison(mIntent),
+ mAppWidgetId, mUserId);
synchronized(sCachedRemoteViewsCaches) {
if (sCachedRemoteViewsCaches.containsKey(key)) {
@@ -850,8 +878,8 @@
}
public void saveRemoteViewsCache() {
- final Pair<Intent.FilterComparison, Integer> key = new Pair<Intent.FilterComparison,
- Integer> (new Intent.FilterComparison(mIntent), mAppWidgetId);
+ final RemoteViewsCacheKey key = new RemoteViewsCacheKey(
+ new Intent.FilterComparison(mIntent), mAppWidgetId, mUserId);
synchronized(sCachedRemoteViewsCaches) {
// If we already have a remove runnable posted for this key, remove it.