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:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user