am 2daf9dc9: Merge "Prevent crash in AppWidgetHost that can be triggered by an AppWidget" into jb-dev

* commit '2daf9dc9eb462b8e16e8871a6f4573cded1e3fa6':
  Prevent crash in AppWidgetHost that can be triggered by an AppWidget
This commit is contained in:
Adam Cohen
2012-07-24 22:13:52 -07:00
committed by Android Git Automerger

View File

@@ -246,7 +246,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
* A FrameLayout which contains a loading view, and manages the re/applying of RemoteViews when * A FrameLayout which contains a loading view, and manages the re/applying of RemoteViews when
* they are loaded. * they are loaded.
*/ */
private class RemoteViewsFrameLayout extends FrameLayout { private static class RemoteViewsFrameLayout extends FrameLayout {
public RemoteViewsFrameLayout(Context context) { public RemoteViewsFrameLayout(Context context) {
super(context); super(context);
} }
@@ -301,7 +301,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
* Notifies each of the RemoteViewsFrameLayouts associated with a particular position that * Notifies each of the RemoteViewsFrameLayouts associated with a particular position that
* the associated RemoteViews has loaded. * the associated RemoteViews has loaded.
*/ */
public void notifyOnRemoteViewsLoaded(int position, RemoteViews view, int typeId) { public void notifyOnRemoteViewsLoaded(int position, RemoteViews view) {
if (view == null) return; if (view == null) return;
final Integer pos = position; final Integer pos = position;
@@ -331,7 +331,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
/** /**
* The meta-data associated with the cache in it's current state. * The meta-data associated with the cache in it's current state.
*/ */
private class RemoteViewsMetaData { private static class RemoteViewsMetaData {
int count; int count;
int viewTypeCount; int viewTypeCount;
boolean hasStableIds; boolean hasStableIds;
@@ -390,14 +390,23 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
} }
} }
public boolean isViewTypeInRange(int typeId) {
int mappedType = getMappedViewType(typeId);
if (mappedType >= viewTypeCount) {
return false;
} else {
return true;
}
}
private RemoteViewsFrameLayout createLoadingView(int position, View convertView, private RemoteViewsFrameLayout createLoadingView(int position, View convertView,
ViewGroup parent) { ViewGroup parent, Object lock, LayoutInflater layoutInflater) {
// Create and return a new FrameLayout, and setup the references for this position // Create and return a new FrameLayout, and setup the references for this position
final Context context = parent.getContext(); final Context context = parent.getContext();
RemoteViewsFrameLayout layout = new RemoteViewsFrameLayout(context); RemoteViewsFrameLayout layout = new RemoteViewsFrameLayout(context);
// Create a new loading view // Create a new loading view
synchronized (mCache) { synchronized (lock) {
boolean customLoadingViewAvailable = false; boolean customLoadingViewAvailable = false;
if (mUserLoadingView != null) { if (mUserLoadingView != null) {
@@ -425,7 +434,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
mFirstViewHeight = firstView.getMeasuredHeight(); mFirstViewHeight = firstView.getMeasuredHeight();
mFirstView = null; mFirstView = null;
} catch (Exception e) { } catch (Exception e) {
float density = mContext.getResources().getDisplayMetrics().density; float density = context.getResources().getDisplayMetrics().density;
mFirstViewHeight = (int) mFirstViewHeight = (int)
Math.round(sDefaultLoadingViewHeight * density); Math.round(sDefaultLoadingViewHeight * density);
mFirstView = null; mFirstView = null;
@@ -434,7 +443,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
} }
// Compose the loading view text // Compose the loading view text
TextView loadingTextView = (TextView) mLayoutInflater.inflate( TextView loadingTextView = (TextView) layoutInflater.inflate(
com.android.internal.R.layout.remote_views_adapter_default_loading_view, com.android.internal.R.layout.remote_views_adapter_default_loading_view,
layout, false); layout, false);
loadingTextView.setHeight(mFirstViewHeight); loadingTextView.setHeight(mFirstViewHeight);
@@ -451,7 +460,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
/** /**
* The meta-data associated with a single item in the cache. * The meta-data associated with a single item in the cache.
*/ */
private class RemoteViewsIndexMetaData { private static class RemoteViewsIndexMetaData {
int typeId; int typeId;
long itemId; long itemId;
boolean isRequested; boolean isRequested;
@@ -462,10 +471,11 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
public void set(RemoteViews v, long id, boolean requested) { public void set(RemoteViews v, long id, boolean requested) {
itemId = id; itemId = id;
if (v != null) if (v != null) {
typeId = v.getLayoutId(); typeId = v.getLayoutId();
else } else {
typeId = 0; typeId = 0;
}
isRequested = requested; isRequested = requested;
} }
} }
@@ -473,7 +483,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
/** /**
* *
*/ */
private class FixedSizeRemoteViewsCache { private static class FixedSizeRemoteViewsCache {
private static final String TAG = "FixedSizeRemoteViewsCache"; private static final String TAG = "FixedSizeRemoteViewsCache";
// The meta data related to all the RemoteViews, ie. count, is stable, etc. // The meta data related to all the RemoteViews, ie. count, is stable, etc.
@@ -861,21 +871,36 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
"returned from RemoteViewsFactory."); "returned from RemoteViewsFactory.");
return; return;
} }
synchronized (mCache) {
// Cache the RemoteViews we loaded
mCache.insert(position, remoteViews, itemId, isRequested);
// Notify all the views that we have previously returned for this index that int layoutId = remoteViews.getLayoutId();
// there is new data for it. RemoteViewsMetaData metaData = mCache.getMetaData();
final RemoteViews rv = remoteViews; boolean viewTypeInRange;
final int typeId = mCache.getMetaDataAt(position).typeId; synchronized (metaData) {
if (notifyWhenLoaded) { viewTypeInRange = metaData.isViewTypeInRange(layoutId);
mMainQueue.post(new Runnable() { }
@Override synchronized (mCache) {
public void run() { if (viewTypeInRange) {
mRequestedViews.notifyOnRemoteViewsLoaded(position, rv, typeId); // Cache the RemoteViews we loaded
} mCache.insert(position, remoteViews, itemId, isRequested);
});
// Notify all the views that we have previously returned for this index that
// there is new data for it.
final RemoteViews rv = remoteViews;
if (notifyWhenLoaded) {
mMainQueue.post(new Runnable() {
@Override
public void run() {
mRequestedViews.notifyOnRemoteViewsLoaded(position, rv);
}
});
}
} else {
// We need to log an error here, as the the view type count specified by the
// factory is less than the number of view types returned. We don't return this
// view to the AdapterView, as this will cause an exception in the hosting process,
// which contains the associated AdapterView.
Log.e(TAG, "Error: widget's RemoteViewsFactory returns more view types than " +
" indicated by getViewTypeCount() ");
} }
} }
} }
@@ -1010,7 +1035,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
RemoteViewsFrameLayout loadingView = null; RemoteViewsFrameLayout loadingView = null;
final RemoteViewsMetaData metaData = mCache.getMetaData(); final RemoteViewsMetaData metaData = mCache.getMetaData();
synchronized (metaData) { synchronized (metaData) {
loadingView = metaData.createLoadingView(position, convertView, parent); loadingView = metaData.createLoadingView(position, convertView, parent,
mCache, mLayoutInflater);
} }
return loadingView; return loadingView;
} finally { } finally {
@@ -1022,7 +1048,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
RemoteViewsFrameLayout loadingView = null; RemoteViewsFrameLayout loadingView = null;
final RemoteViewsMetaData metaData = mCache.getMetaData(); final RemoteViewsMetaData metaData = mCache.getMetaData();
synchronized (metaData) { synchronized (metaData) {
loadingView = metaData.createLoadingView(position, convertView, parent); loadingView = metaData.createLoadingView(position, convertView, parent,
mCache, mLayoutInflater);
} }
mRequestedViews.add(position, loadingView); mRequestedViews.add(position, loadingView);