Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4ee810d authored by Adam Cohen's avatar Adam Cohen Committed by Android (Google) Code Review
Browse files

Merge "Catching RemoteViews#apply() layout inflation exceptions in RemoteViewsAdapter"

parents fbaa1ea1 b7ffea69
Loading
Loading
Loading
Loading
+65 −27
Original line number Diff line number Diff line
@@ -53,6 +53,10 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
    // This ensures that we don't stay continually bound to the service and that it can be destroyed
    // if we need the memory elsewhere in the system.
    private static final int sUnbindServiceDelay = 5000;

    // Default height for the default loading view, in case we cannot get inflate the first view
    private static final int sDefaultLoadingViewHeight = 50;

    // Type defs for controlling different messages across the main and worker message queues
    private static final int sDefaultMessageType = 0;
    private static final int sUnbindServiceMessageType = 1;
@@ -386,21 +390,39 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback

            // Create a new loading view
            synchronized (mCache) {
                boolean customLoadingViewAvailable = false;

                if (mUserLoadingView != null) {
                    // A user-specified loading view
                    // Try to inflate user-specified loading view
                    try {
                        View loadingView = mUserLoadingView.apply(parent.getContext(), parent);
                    loadingView.setTagInternal(com.android.internal.R.id.rowTypeId, new Integer(0));
                        loadingView.setTagInternal(com.android.internal.R.id.rowTypeId,
                                new Integer(0));
                        layout.addView(loadingView);
                } else {
                        customLoadingViewAvailable = true;
                    } catch (Exception e) {
                        Log.w(TAG, "Error inflating custom loading view, using default loading" +
                                "view instead", e);
                    }
                }
                if (!customLoadingViewAvailable) {
                    // A default loading view
                    // Use the size of the first row as a guide for the size of the loading view
                    if (mFirstViewHeight < 0) {
                        try {
                            View firstView = mFirstView.apply(parent.getContext(), parent);
                            firstView.measure(
                                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                            mFirstViewHeight = firstView.getMeasuredHeight();
                            mFirstView = null;
                        } catch (Exception e) {
                            float density = mContext.getResources().getDisplayMetrics().density;
                            mFirstViewHeight = (int)
                                    Math.round(sDefaultLoadingViewHeight * density);
                            mFirstView = null;
                            Log.w(TAG, "Error inflating first RemoteViews" + e);
                        }
                    }

                    // Compose the loading view text
@@ -937,6 +959,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
                indexMetaData.isRequested = true;
                int typeId = indexMetaData.typeId;

                try {
                    // Reuse the convert view where possible
                    if (layout != null) {
                        if (convertViewTypeId == typeId) {
@@ -950,11 +973,26 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback

                    // Otherwise, create a new view to be returned
                    View newView = rv.apply(context, parent);
                newView.setTagInternal(com.android.internal.R.id.rowTypeId, new Integer(typeId));
                    newView.setTagInternal(com.android.internal.R.id.rowTypeId,
                            new Integer(typeId));
                    layout.addView(newView);
                if (hasNewItems) loadNextIndexInBackground();

                    return layout;

                } catch (Exception e){
                    // We have to make sure that we successfully inflated the RemoteViews, if not
                    // we return the loading view instead.
                    Log.w(TAG, "Error inflating RemoteViews at position: " + position + ", using" +
                            "loading view instead" + e);

                    RemoteViewsFrameLayout loadingView = null;
                    final RemoteViewsMetaData metaData = mCache.getMetaData();
                    synchronized (metaData) {
                        loadingView = metaData.createLoadingView(position, convertView, parent);
                    }
                    return loadingView;
                } finally {
                    if (hasNewItems) loadNextIndexInBackground();
                }
            } else {
                // If the cache does not have the RemoteViews at this position, then create a
                // loading view and queue the actual position to be loaded in the background