Merge "Catching TransactionTooLargeException when binding widget." into ub-launcher3-master

This commit is contained in:
Sunny Goyal 2016-11-15 19:07:31 +00:00 committed by Android (Google) Code Review
commit f8d5370a9f
5 changed files with 58 additions and 26 deletions

View File

@ -19,6 +19,7 @@
android:layout_height="match_parent"
android:gravity="center"
android:elevation="2dp"
android:theme="@style/WidgetContainerTheme"
android:background="@drawable/quantum_panel_dark"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:textColor="@color/widgets_view_item_text_color"

View File

@ -20,10 +20,8 @@ import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.os.DeadObjectException;
import android.os.TransactionTooLargeException;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import java.util.ArrayList;
@ -36,6 +34,7 @@ import java.util.ArrayList;
public class LauncherAppWidgetHost extends AppWidgetHost {
private final ArrayList<Runnable> mProviderChangeListeners = new ArrayList<Runnable>();
private final SparseArray<LauncherAppWidgetHostView> mViews = new SparseArray<>();
private Launcher mLauncher;
@ -45,9 +44,11 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
}
@Override
protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
protected LauncherAppWidgetHostView onCreateView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
return new LauncherAppWidgetHostView(context);
LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
mViews.put(appWidgetId, view);
return view;
}
@Override
@ -55,15 +56,13 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
try {
super.startListening();
} catch (Exception e) {
if (e.getCause() instanceof TransactionTooLargeException ||
e.getCause() instanceof DeadObjectException) {
// We're willing to let this slide. The exception is being caused by the list of
// RemoteViews which is being passed back. The startListening relationship will
// have been established by this point, and we will end up populating the
// widgets upon bind anyway. See issue 14255011 for more context.
} else {
if (!Utilities.isBinderSizeError(e)) {
throw new RuntimeException(e);
}
// We're willing to let this slide. The exception is being caused by the list of
// RemoteViews which is being passed back. The startListening relationship will
// have been established by this point, and we will end up populating the
// widgets upon bind anyway. See issue 14255011 for more context.
}
}
@ -98,7 +97,24 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
lahv.updateLastInflationOrientation();
return lahv;
} else {
return super.createView(context, appWidgetId, appWidget);
try {
return super.createView(context, appWidgetId, appWidget);
} catch (Exception e) {
if (!Utilities.isBinderSizeError(e)) {
throw new RuntimeException(e);
}
// If the exception was thrown while fetching the remote views, let the view stay.
// This will ensure that if the widget posts a valid update later, the view
// will update.
LauncherAppWidgetHostView view = mViews.get(appWidgetId);
if (view == null) {
view = onCreateView(mLauncher, appWidgetId, appWidget);
}
view.setAppWidget(appWidgetId, appWidget);
view.switchToErrorView();
return view;
}
}
}
@ -114,4 +130,16 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
// launcher spans accordingly.
info.initSpans();
}
@Override
public void deleteAppWidgetId(int appWidgetId) {
super.deleteAppWidgetId(appWidgetId);
mViews.remove(appWidgetId);
}
@Override
protected void clearViews() {
super.clearViews();
mViews.clear();
}
}

View File

@ -77,7 +77,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
mContext = context;
mLongPressHelper = new CheckLongPressHelper(this);
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mInflater = LayoutInflater.from(context);
setAccessibilityDelegate(Launcher.getLauncher(context).getAccessibilityDelegate());
setBackgroundResource(R.drawable.widget_internal_focus_bg);
@ -316,6 +316,11 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
setSelected(childIsFocused);
}
public void switchToErrorView() {
// Update the widget with 0 Layout id, to reset the view to error view.
updateAppWidget(new RemoteViews(getAppWidgetInfo().provider.getPackageName(), 0));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
try {
@ -324,8 +329,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
post(new Runnable() {
@Override
public void run() {
// Update the widget with 0 Layout id, to reset the view to error view.
updateAppWidget(new RemoteViews(getAppWidgetInfo().provider.getPackageName(), 0));
switchToErrorView();
}
});
}

View File

@ -38,7 +38,9 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.PowerManager;
import android.os.TransactionTooLargeException;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
@ -648,4 +650,9 @@ public final class Utilities {
accessibilityManager.sendAccessibilityEvent(event);
}
}
public static boolean isBinderSizeError(Exception e) {
return e.getCause() instanceof TransactionTooLargeException
|| e.getCause() instanceof DeadObjectException;
}
}

View File

@ -6,17 +6,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.DeadObjectException;
import android.os.TransactionTooLargeException;
import android.util.Log;
import com.android.launcher3.AppFilter;
import com.android.launcher3.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.config.ProviderConfig;
@ -24,10 +21,7 @@ import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.Preconditions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
/**
* Widgets data model that is used by the adapters of the widget views and controllers.
@ -80,9 +74,7 @@ public class WidgetsModel {
}
setWidgetsAndShortcuts(widgetsAndShortcuts);
} catch (Exception e) {
if (!ProviderConfig.IS_DOGFOOD_BUILD &&
(e.getCause() instanceof TransactionTooLargeException ||
e.getCause() instanceof DeadObjectException)) {
if (!ProviderConfig.IS_DOGFOOD_BUILD && Utilities.isBinderSizeError(e)) {
// the returned value may be incomplete and will not be refreshed until the next
// time Launcher starts.
// TODO: after figuring out a repro step, introduce a dirty bit to check when