Merge "Merge "Update UnlockMethodCache when keyguard visibility changes" into oc-mr1-dev am: cbda08c5ec am: 9223437066"
diff --git a/api/current.txt b/api/current.txt
index c7816eb..9c39295 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -51075,10 +51075,11 @@
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
ctor public RemoteViews(java.lang.String, int);
ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
+ ctor public RemoteViews(android.widget.RemoteViews);
ctor public RemoteViews(android.os.Parcel);
method public void addView(int, android.widget.RemoteViews);
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
- method public android.widget.RemoteViews clone();
+ method public deprecated android.widget.RemoteViews clone();
method public int describeContents();
method public int getLayoutId();
method public java.lang.String getPackage();
diff --git a/api/system-current.txt b/api/system-current.txt
index 7e25988..4a76bfb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -55053,10 +55053,11 @@
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
ctor public RemoteViews(java.lang.String, int);
ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
+ ctor public RemoteViews(android.widget.RemoteViews);
ctor public RemoteViews(android.os.Parcel);
method public void addView(int, android.widget.RemoteViews);
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
- method public android.widget.RemoteViews clone();
+ method public deprecated android.widget.RemoteViews clone();
method public int describeContents();
method public int getLayoutId();
method public java.lang.String getPackage();
diff --git a/api/test-current.txt b/api/test-current.txt
index edce863..9f52666 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -51578,10 +51578,11 @@
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
ctor public RemoteViews(java.lang.String, int);
ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
+ ctor public RemoteViews(android.widget.RemoteViews);
ctor public RemoteViews(android.os.Parcel);
method public void addView(int, android.widget.RemoteViews);
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
- method public android.widget.RemoteViews clone();
+ method public deprecated android.widget.RemoteViews clone();
method public int describeContents();
method public int getLayoutId();
method public java.lang.String getPackage();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 46742b8..bc85fad 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -144,11 +144,6 @@
private ArrayList<Action> mActions;
/**
- * A class to keep track of memory usage by this RemoteViews
- */
- private MemoryUsageCounter mMemoryUsageCounter;
-
- /**
* Maps bitmaps to unique indicies to avoid Bitmap duplication.
*/
private BitmapCache mBitmapCache;
@@ -294,7 +289,6 @@
public String asyncMethodName;
}
-
/**
* This annotation indicates that a subclass of View is allowed to be used
* with the {@link RemoteViews} mechanism.
@@ -386,14 +380,6 @@
return 0;
}
- /**
- * Overridden by each class to report on it's own memory usage
- */
- public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
- // We currently only calculate Bitmap memory usage, so by default,
- // don't do anything here
- }
-
public void setBitmapCache(BitmapCache bitmapCache) {
// Do nothing
}
@@ -466,7 +452,7 @@
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
// reference the bitmap cache. We don't want to modify the object as it may need to
// be merged and applied multiple times.
- RemoteViews copy = newRv.clone();
+ RemoteViews copy = new RemoteViews(newRv);
HashMap<String, Action> map = new HashMap<String, Action>();
if (mActions == null) {
@@ -500,7 +486,6 @@
// Because pruning can remove the need for bitmaps, we reconstruct the bitmap cache
mBitmapCache = new BitmapCache();
setBitmapCache(mBitmapCache);
- recalculateMemoryUsage();
}
private static class RemoteViewsContextWrapper extends ContextWrapper {
@@ -1162,15 +1147,17 @@
}
private static class BitmapCache {
+
ArrayList<Bitmap> mBitmaps;
+ int mBitmapMemory = -1;
public BitmapCache() {
- mBitmaps = new ArrayList<Bitmap>();
+ mBitmaps = new ArrayList<>();
}
public BitmapCache(Parcel source) {
int count = source.readInt();
- mBitmaps = new ArrayList<Bitmap>();
+ mBitmaps = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
Bitmap b = Bitmap.CREATOR.createFromParcel(source);
mBitmaps.add(b);
@@ -1185,6 +1172,7 @@
return mBitmaps.indexOf(b);
} else {
mBitmaps.add(b);
+ mBitmapMemory = -1;
return (mBitmaps.size() - 1);
}
}
@@ -1206,28 +1194,15 @@
}
}
- public void assimilate(BitmapCache bitmapCache) {
- ArrayList<Bitmap> bitmapsToBeAdded = bitmapCache.mBitmaps;
- int count = bitmapsToBeAdded.size();
- for (int i = 0; i < count; i++) {
- Bitmap b = bitmapsToBeAdded.get(i);
- if (!mBitmaps.contains(b)) {
- mBitmaps.add(b);
+ public int getBitmapMemory() {
+ if (mBitmapMemory < 0) {
+ mBitmapMemory = 0;
+ int count = mBitmaps.size();
+ for (int i = 0; i < count; i++) {
+ mBitmapMemory += mBitmaps.get(i).getAllocationByteCount();
}
}
- }
-
- public void addBitmapMemory(MemoryUsageCounter memoryCounter) {
- for (int i = 0; i < mBitmaps.size(); i++) {
- memoryCounter.addBitmapMemory(mBitmaps.get(i));
- }
- }
-
- @Override
- protected BitmapCache clone() {
- BitmapCache bitmapCache = new BitmapCache();
- bitmapCache.mBitmaps.addAll(mBitmaps);
- return bitmapCache;
+ return mBitmapMemory;
}
}
@@ -1429,37 +1404,17 @@
case CHAR_SEQUENCE:
TextUtils.writeToParcel((CharSequence)this.value, out, flags);
break;
- case URI:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((Uri)this.value).writeToParcel(out, flags);
- }
- break;
- case BITMAP:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((Bitmap)this.value).writeToParcel(out, flags);
- }
- break;
case BUNDLE:
out.writeBundle((Bundle) this.value);
break;
+ case URI:
+ case BITMAP:
case INTENT:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((Intent)this.value).writeToParcel(out, flags);
- }
- break;
case COLOR_STATE_LIST:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((ColorStateList)this.value).writeToParcel(out, flags);
- }
- break;
case ICON:
out.writeInt(this.value != null ? 1 : 0);
if (this.value != null) {
- ((Icon)this.value).writeToParcel(out, flags);
+ ((Parcelable) this.value).writeToParcel(out, flags);
}
break;
default:
@@ -1595,7 +1550,6 @@
}
private void configureRemoteViewsAsChild(RemoteViews rv) {
- mBitmapCache.assimilate(rv.mBitmapCache);
rv.setBitmapCache(mBitmapCache);
rv.setNotRoot();
}
@@ -1693,11 +1647,6 @@
}
@Override
- public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
- counter.increment(mNestedViews.estimateMemoryUsage());
- }
-
- @Override
public void setBitmapCache(BitmapCache bitmapCache) {
mNestedViews.setBitmapCache(bitmapCache);
}
@@ -2302,30 +2251,6 @@
}
/**
- * Simple class used to keep track of memory usage in a RemoteViews.
- *
- */
- private class MemoryUsageCounter {
- public void clear() {
- mMemoryUsage = 0;
- }
-
- public void increment(int numBytes) {
- mMemoryUsage += numBytes;
- }
-
- public int getMemoryUsage() {
- return mMemoryUsage;
- }
-
- public void addBitmapMemory(Bitmap b) {
- increment(b.getAllocationByteCount());
- }
-
- int mMemoryUsage;
- }
-
- /**
* Create a new RemoteViews object that will display the views contained
* in the specified layout file.
*
@@ -2363,9 +2288,6 @@
mApplication = application;
mLayoutId = layoutId;
mBitmapCache = new BitmapCache();
- // setup the memory usage statistics
- mMemoryUsageCounter = new MemoryUsageCounter();
- recalculateMemoryUsage();
}
private boolean hasLandscapeAndPortraitLayouts() {
@@ -2393,14 +2315,49 @@
mLandscape = landscape;
mPortrait = portrait;
- // setup the memory usage statistics
- mMemoryUsageCounter = new MemoryUsageCounter();
-
mBitmapCache = new BitmapCache();
configureRemoteViewsAsChild(landscape);
configureRemoteViewsAsChild(portrait);
+ }
- recalculateMemoryUsage();
+ /**
+ * Creates a copy of another RemoteViews.
+ */
+ public RemoteViews(RemoteViews src) {
+ mBitmapCache = src.mBitmapCache;
+ mApplication = src.mApplication;
+ mIsRoot = src.mIsRoot;
+ mLayoutId = src.mLayoutId;
+ mIsWidgetCollectionChild = src.mIsWidgetCollectionChild;
+ mReapplyDisallowed = src.mReapplyDisallowed;
+
+ if (src.hasLandscapeAndPortraitLayouts()) {
+ mLandscape = new RemoteViews(src.mLandscape);
+ mPortrait = new RemoteViews(src.mPortrait);
+
+ }
+
+ if (src.mActions != null) {
+ mActions = new ArrayList<>();
+
+ Parcel p = Parcel.obtain();
+ int count = src.mActions.size();
+ for (int i = 0; i < count; i++) {
+ p.setDataPosition(0);
+ Action a = src.mActions.get(i);
+ a.writeToParcel(
+ p, a.hasSameAppInfo(mApplication) ? PARCELABLE_ELIDE_DUPLICATES : 0);
+ p.setDataPosition(0);
+ // Since src is already in memory, we do not care about stack overflow as it has
+ // already been read once.
+ mActions.add(getActionFromParcel(p, 0));
+ }
+ p.recycle();
+ }
+
+ // Now that everything is initialized and duplicated, setting a new BitmapCache will
+ // re-initialize the cache.
+ setBitmapCache(new BitmapCache());
}
/**
@@ -2437,71 +2394,9 @@
int count = parcel.readInt();
if (count > 0) {
- mActions = new ArrayList<Action>(count);
- for (int i=0; i<count; i++) {
- int tag = parcel.readInt();
- switch (tag) {
- case SET_ON_CLICK_PENDING_INTENT_TAG:
- mActions.add(new SetOnClickPendingIntent(parcel));
- break;
- case SET_DRAWABLE_PARAMETERS_TAG:
- mActions.add(new SetDrawableParameters(parcel));
- break;
- case REFLECTION_ACTION_TAG:
- mActions.add(new ReflectionAction(parcel));
- break;
- case VIEW_GROUP_ACTION_ADD_TAG:
- mActions.add(new ViewGroupActionAdd(parcel, mBitmapCache, mApplication,
- depth));
- break;
- case VIEW_GROUP_ACTION_REMOVE_TAG:
- mActions.add(new ViewGroupActionRemove(parcel));
- break;
- case SET_REFLECTION_ACTION_WITHOUT_PARAMS_TAG:
- mActions.add(new ReflectionActionWithoutParams(parcel));
- break;
- case SET_EMPTY_VIEW_ACTION_TAG:
- mActions.add(new SetEmptyView(parcel));
- break;
- case SET_PENDING_INTENT_TEMPLATE_TAG:
- mActions.add(new SetPendingIntentTemplate(parcel));
- break;
- case SET_ON_CLICK_FILL_IN_INTENT_TAG:
- mActions.add(new SetOnClickFillInIntent(parcel));
- break;
- case SET_REMOTE_VIEW_ADAPTER_INTENT_TAG:
- mActions.add(new SetRemoteViewsAdapterIntent(parcel));
- break;
- case TEXT_VIEW_DRAWABLE_ACTION_TAG:
- mActions.add(new TextViewDrawableAction(parcel));
- break;
- case TEXT_VIEW_SIZE_ACTION_TAG:
- mActions.add(new TextViewSizeAction(parcel));
- break;
- case VIEW_PADDING_ACTION_TAG:
- mActions.add(new ViewPaddingAction(parcel));
- break;
- case BITMAP_REFLECTION_ACTION_TAG:
- mActions.add(new BitmapReflectionAction(parcel));
- break;
- case SET_REMOTE_VIEW_ADAPTER_LIST_TAG:
- mActions.add(new SetRemoteViewsAdapterList(parcel));
- break;
- case TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG:
- mActions.add(new TextViewDrawableColorFilterAction(parcel));
- break;
- case SET_REMOTE_INPUTS_ACTION_TAG:
- mActions.add(new SetRemoteInputsAction(parcel));
- break;
- case LAYOUT_PARAM_ACTION_TAG:
- mActions.add(new LayoutParamAction(parcel));
- break;
- case OVERRIDE_TEXT_COLORS_TAG:
- mActions.add(new OverrideTextColorsAction(parcel));
- break;
- default:
- throw new ActionException("Tag " + tag + " not found");
- }
+ mActions = new ArrayList<>(count);
+ for (int i = 0; i < count; i++) {
+ mActions.add(getActionFromParcel(parcel, depth));
}
}
} else {
@@ -2512,40 +2407,69 @@
mLayoutId = mPortrait.getLayoutId();
}
mReapplyDisallowed = parcel.readInt() == 0;
-
- // setup the memory usage statistics
- mMemoryUsageCounter = new MemoryUsageCounter();
- recalculateMemoryUsage();
}
+ private Action getActionFromParcel(Parcel parcel, int depth) {
+ int tag = parcel.readInt();
+ switch (tag) {
+ case SET_ON_CLICK_PENDING_INTENT_TAG:
+ return new SetOnClickPendingIntent(parcel);
+ case SET_DRAWABLE_PARAMETERS_TAG:
+ return new SetDrawableParameters(parcel);
+ case REFLECTION_ACTION_TAG:
+ return new ReflectionAction(parcel);
+ case VIEW_GROUP_ACTION_ADD_TAG:
+ return new ViewGroupActionAdd(parcel, mBitmapCache, mApplication, depth);
+ case VIEW_GROUP_ACTION_REMOVE_TAG:
+ return new ViewGroupActionRemove(parcel);
+ case SET_REFLECTION_ACTION_WITHOUT_PARAMS_TAG:
+ return new ReflectionActionWithoutParams(parcel);
+ case SET_EMPTY_VIEW_ACTION_TAG:
+ return new SetEmptyView(parcel);
+ case SET_PENDING_INTENT_TEMPLATE_TAG:
+ return new SetPendingIntentTemplate(parcel);
+ case SET_ON_CLICK_FILL_IN_INTENT_TAG:
+ return new SetOnClickFillInIntent(parcel);
+ case SET_REMOTE_VIEW_ADAPTER_INTENT_TAG:
+ return new SetRemoteViewsAdapterIntent(parcel);
+ case TEXT_VIEW_DRAWABLE_ACTION_TAG:
+ return new TextViewDrawableAction(parcel);
+ case TEXT_VIEW_SIZE_ACTION_TAG:
+ return new TextViewSizeAction(parcel);
+ case VIEW_PADDING_ACTION_TAG:
+ return new ViewPaddingAction(parcel);
+ case BITMAP_REFLECTION_ACTION_TAG:
+ return new BitmapReflectionAction(parcel);
+ case SET_REMOTE_VIEW_ADAPTER_LIST_TAG:
+ return new SetRemoteViewsAdapterList(parcel);
+ case TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG:
+ return new TextViewDrawableColorFilterAction(parcel);
+ case SET_REMOTE_INPUTS_ACTION_TAG:
+ return new SetRemoteInputsAction(parcel);
+ case LAYOUT_PARAM_ACTION_TAG:
+ return new LayoutParamAction(parcel);
+ case OVERRIDE_TEXT_COLORS_TAG:
+ return new OverrideTextColorsAction(parcel);
+ default:
+ throw new ActionException("Tag " + tag + " not found");
+ }
+ };
+
/**
* Returns a deep copy of the RemoteViews object. The RemoteView may not be
* attached to another RemoteView -- it must be the root of a hierarchy.
*
+ * @deprecated use {@link #RemoteViews(RemoteViews)} instead.
* @throws IllegalStateException if this is not the root of a RemoteView
* hierarchy
*/
@Override
+ @Deprecated
public RemoteViews clone() {
- synchronized (this) {
- Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. "
- + "May only clone the root of a RemoteView hierarchy.");
+ Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. "
+ + "May only clone the root of a RemoteView hierarchy.");
- Parcel p = Parcel.obtain();
-
- // Do not parcel the Bitmap cache - doing so creates an expensive copy of all bitmaps.
- // Instead pretend we're not owning the cache while parceling.
- mIsRoot = false;
- writeToParcel(p, PARCELABLE_ELIDE_DUPLICATES);
- p.setDataPosition(0);
- mIsRoot = true;
-
- RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication, 0);
- rv.mIsRoot = true;
-
- p.recycle();
- return rv;
- }
+ return new RemoteViews(this);
}
public String getPackage() {
@@ -2575,30 +2499,6 @@
}
/**
- * Updates the memory usage statistics.
- */
- private void recalculateMemoryUsage() {
- mMemoryUsageCounter.clear();
-
- if (!hasLandscapeAndPortraitLayouts()) {
- // Accumulate the memory usage for each action
- if (mActions != null) {
- final int count = mActions.size();
- for (int i= 0; i < count; ++i) {
- mActions.get(i).updateMemoryUsageEstimate(mMemoryUsageCounter);
- }
- }
- if (mIsRoot) {
- mBitmapCache.addBitmapMemory(mMemoryUsageCounter);
- }
- } else {
- mMemoryUsageCounter.increment(mLandscape.estimateMemoryUsage());
- mMemoryUsageCounter.increment(mPortrait.estimateMemoryUsage());
- mBitmapCache.addBitmapMemory(mMemoryUsageCounter);
- }
- }
-
- /**
* Recursively sets BitmapCache in the hierarchy and update the bitmap ids.
*/
private void setBitmapCache(BitmapCache bitmapCache) {
@@ -2621,7 +2521,7 @@
*/
/** @hide */
public int estimateMemoryUsage() {
- return mMemoryUsageCounter.getMemoryUsage();
+ return mBitmapCache.getBitmapMemory();
}
/**
@@ -2636,12 +2536,9 @@
" portrait layouts individually before constructing the combined layout.");
}
if (mActions == null) {
- mActions = new ArrayList<Action>();
+ mActions = new ArrayList<>();
}
mActions.add(a);
-
- // update the memory usage stats
- a.updateMemoryUsageEstimate(mMemoryUsageCounter);
}
/**
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index bf994a9..d26437e 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -16,6 +16,10 @@
package android.widget;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
@@ -36,10 +40,6 @@
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
@@ -336,7 +336,9 @@
parent.addView(R.id.layout, views);
views = parent;
}
+ // Both clone and parcel/unparcel work,
views.clone();
+ parcelAndRecreate(views);
views = new RemoteViews(mPackage, R.layout.remote_views_test);
for (int i = 0; i < 11; i++) {
@@ -344,8 +346,10 @@
parent.addView(R.id.layout, views);
views = parent;
}
- exception.expect(IllegalArgumentException.class);
+ // Clone works but parcel/unparcel fails
views.clone();
+ exception.expect(IllegalArgumentException.class);
+ parcelAndRecreate(views);
}
@Test
@@ -355,15 +359,27 @@
views = new RemoteViews(views,
new RemoteViews(mPackage, R.layout.remote_views_test));
}
+ // Both clone and parcel/unparcel work,
views.clone();
+ parcelAndRecreate(views);
views = new RemoteViews(mPackage, R.layout.remote_views_test);
for (int i = 0; i < 11; i++) {
- RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test);
- parent.addView(R.id.layout, views);
- views = parent;
+ views = new RemoteViews(views,
+ new RemoteViews(mPackage, R.layout.remote_views_test));
}
- exception.expect(IllegalArgumentException.class);
+ // Clone works but parcel/unparcel fails
views.clone();
+ exception.expect(IllegalArgumentException.class);
+ parcelAndRecreate(views);
+ }
+
+ private void parcelAndRecreate(RemoteViews views) {
+ Parcel p = Parcel.obtain();
+ views.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ RemoteViews.CREATOR.createFromParcel(p);
+ p.recycle();
}
}