am 2938ac3f: Merge "Enabling RemoteViews to have a landscape and portrait layout" into jb-dev
* commit '2938ac3f9fa8d2a8031a6b4bac4d4beb97f99e06': Enabling RemoteViews to have a landscape and portrait layout
This commit is contained in:
@@ -27842,6 +27842,7 @@ package android.widget {
|
|||||||
|
|
||||||
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
|
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
|
||||||
ctor public RemoteViews(java.lang.String, int);
|
ctor public RemoteViews(java.lang.String, int);
|
||||||
|
ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
|
||||||
ctor public RemoteViews(android.os.Parcel);
|
ctor public RemoteViews(android.os.Parcel);
|
||||||
method public void addView(int, android.widget.RemoteViews);
|
method public void addView(int, android.widget.RemoteViews);
|
||||||
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
|
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentSender;
|
import android.content.IntentSender;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -87,7 +88,32 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
*/
|
*/
|
||||||
private MemoryUsageCounter mMemoryUsageCounter;
|
private MemoryUsageCounter mMemoryUsageCounter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps bitmaps to unique indicies to avoid Bitmap duplication.
|
||||||
|
*/
|
||||||
|
private BitmapCache mBitmapCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not this RemoteViews object is contained as a child of any other
|
||||||
|
* RemoteViews.
|
||||||
|
*/
|
||||||
|
private boolean mIsRoot = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constants to whether or not this RemoteViews is composed of a landscape and portrait
|
||||||
|
* RemoteViews.
|
||||||
|
*/
|
||||||
|
private static final int MODE_NORMAL = 0;
|
||||||
|
private static final int MODE_HAS_LANDSCAPE_AND_PORTRAIT = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in conjunction with the special constructor
|
||||||
|
* {@link #RemoteViews(RemoteViews, RemoteViews)} to keep track of the landscape and portrait
|
||||||
|
* RemoteViews.
|
||||||
|
*/
|
||||||
|
private RemoteViews mLandscape = null;
|
||||||
|
private RemoteViews mPortrait = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This flag indicates whether this RemoteViews object is being created from a
|
* This flag indicates whether this RemoteViews object is being created from a
|
||||||
* RemoteViewsService for use as a child of a widget collection. This flag is used
|
* RemoteViewsService for use as a child of a widget collection. This flag is used
|
||||||
@@ -163,6 +189,10 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBitmapCache(BitmapCache bitmapCache) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SetEmptyView extends Action {
|
private class SetEmptyView extends Action {
|
||||||
@@ -643,6 +673,112 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class BitmapCache {
|
||||||
|
ArrayList<Bitmap> mBitmaps;
|
||||||
|
|
||||||
|
public BitmapCache() {
|
||||||
|
mBitmaps = new ArrayList<Bitmap>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapCache(Parcel source) {
|
||||||
|
int count = source.readInt();
|
||||||
|
mBitmaps = new ArrayList<Bitmap>();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
Bitmap b = Bitmap.CREATOR.createFromParcel(source);
|
||||||
|
mBitmaps.add(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBitmapId(Bitmap b) {
|
||||||
|
if (b == null) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (mBitmaps.contains(b)) {
|
||||||
|
return mBitmaps.indexOf(b);
|
||||||
|
} else {
|
||||||
|
mBitmaps.add(b);
|
||||||
|
return (mBitmaps.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bitmap getBitmapForId(int id) {
|
||||||
|
if (id == -1 || id >= mBitmaps.size()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return mBitmaps.get(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBitmapsToParcel(Parcel dest, int flags) {
|
||||||
|
int count = mBitmaps.size();
|
||||||
|
dest.writeInt(count);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
mBitmaps.get(i).writeToParcel(dest, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 void addBitmapMemory(MemoryUsageCounter memoryCounter) {
|
||||||
|
for (int i = 0; i < mBitmaps.size(); i++) {
|
||||||
|
memoryCounter.addBitmapMemory(mBitmaps.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BitmapReflectionAction extends Action {
|
||||||
|
int bitmapId;
|
||||||
|
int viewId;
|
||||||
|
Bitmap bitmap;
|
||||||
|
String methodName;
|
||||||
|
|
||||||
|
BitmapReflectionAction(int viewId, String methodName, Bitmap bitmap) {
|
||||||
|
this.bitmap = bitmap;
|
||||||
|
this.viewId = viewId;
|
||||||
|
this.methodName = methodName;
|
||||||
|
bitmapId = mBitmapCache.getBitmapId(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitmapReflectionAction(Parcel in) {
|
||||||
|
viewId = in.readInt();
|
||||||
|
methodName = in.readString();
|
||||||
|
bitmapId = in.readInt();
|
||||||
|
bitmap = mBitmapCache.getBitmapForId(bitmapId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(TAG);
|
||||||
|
dest.writeInt(viewId);
|
||||||
|
dest.writeString(methodName);
|
||||||
|
dest.writeInt(bitmapId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(View root, ViewGroup rootParent) throws ActionException {
|
||||||
|
ReflectionAction ra = new ReflectionAction(viewId, methodName, ReflectionAction.BITMAP,
|
||||||
|
bitmap);
|
||||||
|
ra.apply(root, rootParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBitmapCache(BitmapCache bitmapCache) {
|
||||||
|
bitmapId = bitmapCache.getBitmapId(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static int TAG = 12;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for the reflection actions.
|
* Base class for the reflection actions.
|
||||||
*/
|
*/
|
||||||
@@ -894,24 +1030,7 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
case BITMAP:
|
case BITMAP:
|
||||||
if (this.value != null) {
|
if (this.value != null) {
|
||||||
final Bitmap b = (Bitmap) this.value;
|
final Bitmap b = (Bitmap) this.value;
|
||||||
final Bitmap.Config c = b.getConfig();
|
counter.addBitmapMemory(b);
|
||||||
// If we don't know, be pessimistic and assume 4
|
|
||||||
int bpp = 4;
|
|
||||||
if (c != null) {
|
|
||||||
switch (c) {
|
|
||||||
case ALPHA_8:
|
|
||||||
bpp = 1;
|
|
||||||
break;
|
|
||||||
case RGB_565:
|
|
||||||
case ARGB_4444:
|
|
||||||
bpp = 2;
|
|
||||||
break;
|
|
||||||
case ARGB_8888:
|
|
||||||
bpp = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
counter.bitmapIncrement(b.getWidth() * b.getHeight() * bpp);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -920,6 +1039,16 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void configureRemoteViewsAsChild(RemoteViews rv) {
|
||||||
|
mBitmapCache.assimilate(rv.mBitmapCache);
|
||||||
|
rv.setBitmapCache(mBitmapCache);
|
||||||
|
rv.setNotRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNotRoot() {
|
||||||
|
mIsRoot = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equivalent to calling {@link ViewGroup#addView(View)} after inflating the
|
* Equivalent to calling {@link ViewGroup#addView(View)} after inflating the
|
||||||
* given {@link RemoteViews}, or calling {@link ViewGroup#removeAllViews()}
|
* given {@link RemoteViews}, or calling {@link ViewGroup#removeAllViews()}
|
||||||
@@ -929,17 +1058,29 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
public ViewGroupAction(int viewId, RemoteViews nestedViews) {
|
public ViewGroupAction(int viewId, RemoteViews nestedViews) {
|
||||||
this.viewId = viewId;
|
this.viewId = viewId;
|
||||||
this.nestedViews = nestedViews;
|
this.nestedViews = nestedViews;
|
||||||
|
configureRemoteViewsAsChild(nestedViews);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewGroupAction(Parcel parcel) {
|
public ViewGroupAction(Parcel parcel, BitmapCache bitmapCache) {
|
||||||
viewId = parcel.readInt();
|
viewId = parcel.readInt();
|
||||||
nestedViews = parcel.readParcelable(null);
|
boolean nestedViewsNull = parcel.readInt() == 0;
|
||||||
|
if (!nestedViewsNull) {
|
||||||
|
nestedViews = new RemoteViews(parcel, bitmapCache);
|
||||||
|
} else {
|
||||||
|
nestedViews = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeInt(TAG);
|
dest.writeInt(TAG);
|
||||||
dest.writeInt(viewId);
|
dest.writeInt(viewId);
|
||||||
dest.writeParcelable(nestedViews, 0 /* no flags */);
|
if (nestedViews != null) {
|
||||||
|
dest.writeInt(1);
|
||||||
|
nestedViews.writeToParcel(dest, flags);
|
||||||
|
} else {
|
||||||
|
// signifies null
|
||||||
|
dest.writeInt(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -959,7 +1100,14 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
@Override
|
@Override
|
||||||
public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
|
public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
|
||||||
if (nestedViews != null) {
|
if (nestedViews != null) {
|
||||||
counter.bitmapIncrement(nestedViews.estimateBitmapMemoryUsage());
|
counter.increment(nestedViews.estimateMemoryUsage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBitmapCache(BitmapCache bitmapCache) {
|
||||||
|
if (nestedViews != null) {
|
||||||
|
nestedViews.setBitmapCache(bitmapCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,18 +1175,39 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
*/
|
*/
|
||||||
private class MemoryUsageCounter {
|
private class MemoryUsageCounter {
|
||||||
public void clear() {
|
public void clear() {
|
||||||
mBitmapHeapMemoryUsage = 0;
|
mMemoryUsage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bitmapIncrement(int numBytes) {
|
public void increment(int numBytes) {
|
||||||
mBitmapHeapMemoryUsage += numBytes;
|
mMemoryUsage += numBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBitmapHeapMemoryUsage() {
|
public int getMemoryUsage() {
|
||||||
return mBitmapHeapMemoryUsage;
|
return mMemoryUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mBitmapHeapMemoryUsage;
|
public void addBitmapMemory(Bitmap b) {
|
||||||
|
final Bitmap.Config c = b.getConfig();
|
||||||
|
// If we don't know, be pessimistic and assume 4
|
||||||
|
int bpp = 4;
|
||||||
|
if (c != null) {
|
||||||
|
switch (c) {
|
||||||
|
case ALPHA_8:
|
||||||
|
bpp = 1;
|
||||||
|
break;
|
||||||
|
case RGB_565:
|
||||||
|
case ARGB_4444:
|
||||||
|
bpp = 2;
|
||||||
|
break;
|
||||||
|
case ARGB_8888:
|
||||||
|
bpp = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
increment(b.getWidth() * b.getHeight() * bpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mMemoryUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1051,62 +1220,122 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
public RemoteViews(String packageName, int layoutId) {
|
public RemoteViews(String packageName, int layoutId) {
|
||||||
mPackage = packageName;
|
mPackage = packageName;
|
||||||
mLayoutId = layoutId;
|
mLayoutId = layoutId;
|
||||||
|
mBitmapCache = new BitmapCache();
|
||||||
|
|
||||||
// setup the memory usage statistics
|
// setup the memory usage statistics
|
||||||
mMemoryUsageCounter = new MemoryUsageCounter();
|
mMemoryUsageCounter = new MemoryUsageCounter();
|
||||||
recalculateMemoryUsage();
|
recalculateMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasLandscapeAndPortraitLayouts() {
|
||||||
|
return (mLandscape != null) && (mPortrait != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new RemoteViews object that will inflate as the specified
|
||||||
|
* landspace or portrait RemoteViews, depending on the current configuration.
|
||||||
|
*
|
||||||
|
* @param landscape The RemoteViews to inflate in landscape configuration
|
||||||
|
* @param portrait The RemoteViews to inflate in portrait configuration
|
||||||
|
*/
|
||||||
|
public RemoteViews(RemoteViews landscape, RemoteViews portrait) {
|
||||||
|
if (landscape == null || portrait == null) {
|
||||||
|
throw new RuntimeException("Both RemoteViews must be non-null");
|
||||||
|
}
|
||||||
|
if (landscape.getPackage().compareTo(portrait.getPackage()) != 0) {
|
||||||
|
throw new RuntimeException("Both RemoteViews must share the same package");
|
||||||
|
}
|
||||||
|
mPackage = portrait.getPackage();
|
||||||
|
mLayoutId = portrait.getLayoutId();
|
||||||
|
|
||||||
|
mLandscape = landscape;
|
||||||
|
mPortrait = portrait;
|
||||||
|
|
||||||
|
// setup the memory usage statistics
|
||||||
|
mMemoryUsageCounter = new MemoryUsageCounter();
|
||||||
|
|
||||||
|
mBitmapCache = new BitmapCache();
|
||||||
|
configureRemoteViewsAsChild(landscape);
|
||||||
|
configureRemoteViewsAsChild(portrait);
|
||||||
|
|
||||||
|
recalculateMemoryUsage();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a RemoteViews object from a parcel.
|
* Reads a RemoteViews object from a parcel.
|
||||||
*
|
*
|
||||||
* @param parcel
|
* @param parcel
|
||||||
*/
|
*/
|
||||||
public RemoteViews(Parcel parcel) {
|
public RemoteViews(Parcel parcel) {
|
||||||
mPackage = parcel.readString();
|
this(parcel, null);
|
||||||
mLayoutId = parcel.readInt();
|
}
|
||||||
mIsWidgetCollectionChild = parcel.readInt() == 1 ? true : false;
|
|
||||||
|
|
||||||
int count = parcel.readInt();
|
private RemoteViews(Parcel parcel, BitmapCache bitmapCache) {
|
||||||
if (count > 0) {
|
int mode = parcel.readInt();
|
||||||
mActions = new ArrayList<Action>(count);
|
|
||||||
for (int i=0; i<count; i++) {
|
// We only store a bitmap cache in the root of the RemoteViews.
|
||||||
int tag = parcel.readInt();
|
if (bitmapCache == null) {
|
||||||
switch (tag) {
|
mBitmapCache = new BitmapCache(parcel);
|
||||||
case SetOnClickPendingIntent.TAG:
|
} else {
|
||||||
mActions.add(new SetOnClickPendingIntent(parcel));
|
setBitmapCache(bitmapCache);
|
||||||
break;
|
setNotRoot();
|
||||||
case SetDrawableParameters.TAG:
|
}
|
||||||
mActions.add(new SetDrawableParameters(parcel));
|
|
||||||
break;
|
if (mode == MODE_NORMAL) {
|
||||||
case ReflectionAction.TAG:
|
mPackage = parcel.readString();
|
||||||
mActions.add(new ReflectionAction(parcel));
|
mLayoutId = parcel.readInt();
|
||||||
break;
|
mIsWidgetCollectionChild = parcel.readInt() == 1 ? true : false;
|
||||||
case ViewGroupAction.TAG:
|
|
||||||
mActions.add(new ViewGroupAction(parcel));
|
int count = parcel.readInt();
|
||||||
break;
|
if (count > 0) {
|
||||||
case ReflectionActionWithoutParams.TAG:
|
mActions = new ArrayList<Action>(count);
|
||||||
mActions.add(new ReflectionActionWithoutParams(parcel));
|
for (int i=0; i<count; i++) {
|
||||||
break;
|
int tag = parcel.readInt();
|
||||||
case SetEmptyView.TAG:
|
switch (tag) {
|
||||||
mActions.add(new SetEmptyView(parcel));
|
case SetOnClickPendingIntent.TAG:
|
||||||
break;
|
mActions.add(new SetOnClickPendingIntent(parcel));
|
||||||
case SetPendingIntentTemplate.TAG:
|
break;
|
||||||
mActions.add(new SetPendingIntentTemplate(parcel));
|
case SetDrawableParameters.TAG:
|
||||||
break;
|
mActions.add(new SetDrawableParameters(parcel));
|
||||||
case SetOnClickFillInIntent.TAG:
|
break;
|
||||||
mActions.add(new SetOnClickFillInIntent(parcel));
|
case ReflectionAction.TAG:
|
||||||
break;
|
mActions.add(new ReflectionAction(parcel));
|
||||||
case SetRemoteViewsAdapterIntent.TAG:
|
break;
|
||||||
mActions.add(new SetRemoteViewsAdapterIntent(parcel));
|
case ViewGroupAction.TAG:
|
||||||
break;
|
mActions.add(new ViewGroupAction(parcel, mBitmapCache));
|
||||||
case TextViewDrawableAction.TAG:
|
break;
|
||||||
mActions.add(new TextViewDrawableAction(parcel));
|
case ReflectionActionWithoutParams.TAG:
|
||||||
break;
|
mActions.add(new ReflectionActionWithoutParams(parcel));
|
||||||
default:
|
break;
|
||||||
throw new ActionException("Tag " + tag + " not found");
|
case SetEmptyView.TAG:
|
||||||
|
mActions.add(new SetEmptyView(parcel));
|
||||||
|
break;
|
||||||
|
case SetPendingIntentTemplate.TAG:
|
||||||
|
mActions.add(new SetPendingIntentTemplate(parcel));
|
||||||
|
break;
|
||||||
|
case SetOnClickFillInIntent.TAG:
|
||||||
|
mActions.add(new SetOnClickFillInIntent(parcel));
|
||||||
|
break;
|
||||||
|
case SetRemoteViewsAdapterIntent.TAG:
|
||||||
|
mActions.add(new SetRemoteViewsAdapterIntent(parcel));
|
||||||
|
break;
|
||||||
|
case TextViewDrawableAction.TAG:
|
||||||
|
mActions.add(new TextViewDrawableAction(parcel));
|
||||||
|
break;
|
||||||
|
case BitmapReflectionAction.TAG:
|
||||||
|
mActions.add(new BitmapReflectionAction(parcel));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ActionException("Tag " + tag + " not found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// MODE_HAS_LANDSCAPE_AND_PORTRAIT
|
||||||
|
mLandscape = new RemoteViews(parcel, mBitmapCache);
|
||||||
|
mPortrait = new RemoteViews(parcel, mBitmapCache);
|
||||||
|
mPackage = mPortrait.getPackage();
|
||||||
|
mLayoutId = mPortrait.getLayoutId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the memory usage statistics
|
// setup the memory usage statistics
|
||||||
@@ -1116,11 +1345,18 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RemoteViews clone() {
|
public RemoteViews clone() {
|
||||||
final RemoteViews that = new RemoteViews(mPackage, mLayoutId);
|
RemoteViews that;
|
||||||
if (mActions != null) {
|
if (!hasLandscapeAndPortraitLayouts()) {
|
||||||
that.mActions = (ArrayList<Action>)mActions.clone();
|
that = new RemoteViews(mPackage, mLayoutId);
|
||||||
}
|
|
||||||
|
|
||||||
|
if (mActions != null) {
|
||||||
|
that.mActions = (ArrayList<Action>)mActions.clone();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RemoteViews land = mLandscape.clone();
|
||||||
|
RemoteViews port = mPortrait.clone();
|
||||||
|
that = new RemoteViews(land, port);
|
||||||
|
}
|
||||||
// update the memory usage stats of the cloned RemoteViews
|
// update the memory usage stats of the cloned RemoteViews
|
||||||
that.recalculateMemoryUsage();
|
that.recalculateMemoryUsage();
|
||||||
return that;
|
return that;
|
||||||
@@ -1130,6 +1366,13 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
return mPackage;
|
return mPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reutrns the layout id of the root layout associated with this RemoteViews. In the case
|
||||||
|
* that the RemoteViews has both a landscape and portrait root, this will return the layout
|
||||||
|
* id associated with the portrait layout.
|
||||||
|
*
|
||||||
|
* @return the layout id.
|
||||||
|
*/
|
||||||
public int getLayoutId() {
|
public int getLayoutId() {
|
||||||
return mLayoutId;
|
return mLayoutId;
|
||||||
}
|
}
|
||||||
@@ -1151,20 +1394,47 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
private void recalculateMemoryUsage() {
|
private void recalculateMemoryUsage() {
|
||||||
mMemoryUsageCounter.clear();
|
mMemoryUsageCounter.clear();
|
||||||
|
|
||||||
// Accumulate the memory usage for each action
|
if (!hasLandscapeAndPortraitLayouts()) {
|
||||||
if (mActions != null) {
|
// Accumulate the memory usage for each action
|
||||||
final int count = mActions.size();
|
if (mActions != null) {
|
||||||
for (int i= 0; i < count; ++i) {
|
final int count = mActions.size();
|
||||||
mActions.get(i).updateMemoryUsageEstimate(mMemoryUsageCounter);
|
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) {
|
||||||
|
mBitmapCache = bitmapCache;
|
||||||
|
if (!hasLandscapeAndPortraitLayouts()) {
|
||||||
|
if (mActions != null) {
|
||||||
|
final int count = mActions.size();
|
||||||
|
for (int i= 0; i < count; ++i) {
|
||||||
|
mActions.get(i).setBitmapCache(bitmapCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mLandscape.setBitmapCache(bitmapCache);
|
||||||
|
mPortrait.setBitmapCache(bitmapCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an estimate of the bitmap heap memory usage for this RemoteViews.
|
* Returns an estimate of the bitmap heap memory usage for this RemoteViews.
|
||||||
*/
|
*/
|
||||||
int estimateBitmapMemoryUsage() {
|
int estimateMemoryUsage() {
|
||||||
return mMemoryUsageCounter.getBitmapHeapMemoryUsage();
|
return mMemoryUsageCounter.getMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1173,6 +1443,11 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
* @param a The action to add
|
* @param a The action to add
|
||||||
*/
|
*/
|
||||||
private void addAction(Action a) {
|
private void addAction(Action a) {
|
||||||
|
if (hasLandscapeAndPortraitLayouts()) {
|
||||||
|
throw new RuntimeException("RemoteViews specifying separate landscape and portrait" +
|
||||||
|
" layouts cannot be modified. Instead, fully configure the landscape and" +
|
||||||
|
" portrait layouts individually before constructing the combined layout.");
|
||||||
|
}
|
||||||
if (mActions == null) {
|
if (mActions == null) {
|
||||||
mActions = new ArrayList<Action>();
|
mActions = new ArrayList<Action>();
|
||||||
}
|
}
|
||||||
@@ -1644,7 +1919,7 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
* @param value The value to pass to the method.
|
* @param value The value to pass to the method.
|
||||||
*/
|
*/
|
||||||
public void setBitmap(int viewId, String methodName, Bitmap value) {
|
public void setBitmap(int viewId, String methodName, Bitmap value) {
|
||||||
addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BITMAP, value));
|
addAction(new BitmapReflectionAction(viewId, methodName, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1679,6 +1954,18 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
setCharSequence(viewId, "setContentDescription", contentDescription);
|
setCharSequence(viewId, "setContentDescription", contentDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RemoteViews getRemoteViewsToApply(Context context) {
|
||||||
|
if (hasLandscapeAndPortraitLayouts()) {
|
||||||
|
int orientation = context.getResources().getConfiguration().orientation;
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
return mLandscape;
|
||||||
|
} else {
|
||||||
|
return mPortrait;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inflates the view hierarchy represented by this object and applies
|
* Inflates the view hierarchy represented by this object and applies
|
||||||
* all of the actions.
|
* all of the actions.
|
||||||
@@ -1691,6 +1978,8 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
* @return The inflated view hierarchy
|
* @return The inflated view hierarchy
|
||||||
*/
|
*/
|
||||||
public View apply(Context context, ViewGroup parent) {
|
public View apply(Context context, ViewGroup parent) {
|
||||||
|
RemoteViews rvToApply = getRemoteViewsToApply(context);
|
||||||
|
|
||||||
View result;
|
View result;
|
||||||
|
|
||||||
Context c = prepareContext(context);
|
Context c = prepareContext(context);
|
||||||
@@ -1701,13 +1990,13 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
inflater = inflater.cloneInContext(c);
|
inflater = inflater.cloneInContext(c);
|
||||||
inflater.setFilter(this);
|
inflater.setFilter(this);
|
||||||
|
|
||||||
result = inflater.inflate(mLayoutId, parent, false);
|
result = inflater.inflate(rvToApply.getLayoutId(), parent, false);
|
||||||
|
|
||||||
performApply(result, parent);
|
rvToApply.performApply(result, parent);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies all of the actions to the provided view.
|
* Applies all of the actions to the provided view.
|
||||||
*
|
*
|
||||||
@@ -1717,8 +2006,20 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
* the {@link #apply(Context,ViewGroup)} call.
|
* the {@link #apply(Context,ViewGroup)} call.
|
||||||
*/
|
*/
|
||||||
public void reapply(Context context, View v) {
|
public void reapply(Context context, View v) {
|
||||||
|
RemoteViews rvToApply = getRemoteViewsToApply(context);
|
||||||
|
|
||||||
|
// In the case that a view has this RemoteViews applied in one orientation, is persisted
|
||||||
|
// across orientation change, and has the RemoteViews re-applied in the new orientation,
|
||||||
|
// we throw an exception, since the layouts may be completely unrelated.
|
||||||
|
if (hasLandscapeAndPortraitLayouts()) {
|
||||||
|
if (v.getId() != rvToApply.getLayoutId()) {
|
||||||
|
throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
|
||||||
|
" that does not share the same root layout id.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
prepareContext(context);
|
prepareContext(context);
|
||||||
performApply(v, (ViewGroup) v.getParent());
|
rvToApply.performApply(v, (ViewGroup) v.getParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void performApply(View v, ViewGroup parent) {
|
private void performApply(View v, ViewGroup parent) {
|
||||||
@@ -1757,25 +2058,42 @@ public class RemoteViews implements Parcelable, Filter {
|
|||||||
public boolean onLoadClass(Class clazz) {
|
public boolean onLoadClass(Class clazz) {
|
||||||
return clazz.isAnnotationPresent(RemoteView.class);
|
return clazz.isAnnotationPresent(RemoteView.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeString(mPackage);
|
if (!hasLandscapeAndPortraitLayouts()) {
|
||||||
dest.writeInt(mLayoutId);
|
dest.writeInt(MODE_NORMAL);
|
||||||
dest.writeInt(mIsWidgetCollectionChild ? 1 : 0);
|
// We only write the bitmap cache if we are the root RemoteViews, as this cache
|
||||||
int count;
|
// is shared by all children.
|
||||||
if (mActions != null) {
|
if (mIsRoot) {
|
||||||
count = mActions.size();
|
mBitmapCache.writeBitmapsToParcel(dest, flags);
|
||||||
|
}
|
||||||
|
dest.writeString(mPackage);
|
||||||
|
dest.writeInt(mLayoutId);
|
||||||
|
dest.writeInt(mIsWidgetCollectionChild ? 1 : 0);
|
||||||
|
int count;
|
||||||
|
if (mActions != null) {
|
||||||
|
count = mActions.size();
|
||||||
|
} else {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
dest.writeInt(count);
|
||||||
|
for (int i=0; i<count; i++) {
|
||||||
|
Action a = mActions.get(i);
|
||||||
|
a.writeToParcel(dest, 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
count = 0;
|
dest.writeInt(MODE_HAS_LANDSCAPE_AND_PORTRAIT);
|
||||||
}
|
// We only write the bitmap cache if we are the root RemoteViews, as this cache
|
||||||
dest.writeInt(count);
|
// is shared by all children.
|
||||||
for (int i=0; i<count; i++) {
|
if (mIsRoot) {
|
||||||
Action a = mActions.get(i);
|
mBitmapCache.writeBitmapsToParcel(dest, flags);
|
||||||
a.writeToParcel(dest, 0);
|
}
|
||||||
|
mLandscape.writeToParcel(dest, flags);
|
||||||
|
mPortrait.writeToParcel(dest, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -595,7 +595,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
|
|||||||
for (Integer i : mIndexRemoteViews.keySet()) {
|
for (Integer i : mIndexRemoteViews.keySet()) {
|
||||||
final RemoteViews v = mIndexRemoteViews.get(i);
|
final RemoteViews v = mIndexRemoteViews.get(i);
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
mem += v.estimateBitmapMemoryUsage();
|
mem += v.estimateMemoryUsage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mem;
|
return mem;
|
||||||
@@ -942,10 +942,6 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
|
|||||||
* which wouldn't otherwise be possible.
|
* which wouldn't otherwise be possible.
|
||||||
*/
|
*/
|
||||||
public void setVisibleRangeHint(int lowerBound, int upperBound) {
|
public void setVisibleRangeHint(int lowerBound, int upperBound) {
|
||||||
if (lowerBound < 0 || upperBound < 0) {
|
|
||||||
throw new RuntimeException("Attempted to set invalid range: lowerBound="+lowerBound +
|
|
||||||
"," + "upperBound="+upperBound);
|
|
||||||
}
|
|
||||||
mVisibleWindowLowerBound = lowerBound;
|
mVisibleWindowLowerBound = lowerBound;
|
||||||
mVisibleWindowUpperBound = upperBound;
|
mVisibleWindowUpperBound = upperBound;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user