[automerge] [DO NOT MERGE] Prevent RemoteViews crashing SystemUi 2p: c3db1e4451

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22096945

Bug: 268193777
Change-Id: I6a87ed9842b7c5fc14a6277a803d76270315b560
Merged-In: Ib3bda769c499b4069b49c566b1b227f98f707a8a
This commit is contained in:
Valentin Iftime
2023-03-15 14:33:31 +00:00
committed by Presubmit Automerger Backend
6 changed files with 83 additions and 15 deletions

View File

@@ -30,6 +30,7 @@ import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps; import android.content.pm.LauncherApps;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
@@ -310,19 +311,26 @@ public class AppWidgetHostView extends FrameLayout {
super.onLayout(changed, left, top, right, bottom); super.onLayout(changed, left, top, right, bottom);
} catch (final RuntimeException e) { } catch (final RuntimeException e) {
Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e); Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e);
removeViewInLayout(mView); handleViewError();
View child = getErrorView();
prepareView(child);
addViewInLayout(child, 0, child.getLayoutParams());
measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
mView = child;
mViewMode = VIEW_MODE_ERROR;
} }
} }
/**
* Remove bad view and replace with error message view
*/
private void handleViewError() {
removeViewInLayout(mView);
View child = getErrorView();
prepareView(child);
addViewInLayout(child, 0, child.getLayoutParams());
measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
mView = child;
mViewMode = VIEW_MODE_ERROR;
}
/** /**
* Provide guidance about the size of this widget to the AppWidgetManager. The widths and * Provide guidance about the size of this widget to the AppWidgetManager. The widths and
* heights should correspond to the full area the AppWidgetHostView is given. Padding added by * heights should correspond to the full area the AppWidgetHostView is given. Padding added by
@@ -932,4 +940,15 @@ public class AppWidgetHostView extends FrameLayout {
reapplyLastRemoteViews(); reapplyLastRemoteViews();
} }
} }
@Override
protected void dispatchDraw(@NonNull Canvas canvas) {
try {
super.dispatchDraw(canvas);
} catch (Exception e) {
// Catch draw exceptions that may be caused by RemoteViews
Log.e(TAG, "Drawing view failed: " + e);
post(this::handleViewError);
}
}
} }

View File

@@ -69,6 +69,7 @@ import android.widget.ImageView;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ContrastColorUtil; import com.android.internal.util.ContrastColorUtil;
import com.android.internal.widget.CachingIconView; import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.CallLayout; import com.android.internal.widget.CallLayout;
@@ -1554,7 +1555,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
PeopleNotificationIdentifier peopleNotificationIdentifier, PeopleNotificationIdentifier peopleNotificationIdentifier,
OnUserInteractionCallback onUserInteractionCallback, OnUserInteractionCallback onUserInteractionCallback,
Optional<BubblesManager> bubblesManagerOptional, Optional<BubblesManager> bubblesManagerOptional,
NotificationGutsManager gutsManager) { NotificationGutsManager gutsManager,
IStatusBarService statusBarService) {
mEntry = entry; mEntry = entry;
mAppName = appName; mAppName = appName;
if (mMenuRow == null) { if (mMenuRow == null) {

View File

@@ -25,6 +25,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -84,6 +85,7 @@ public class ExpandableNotificationRowController implements NodeController {
private final boolean mAllowLongPress; private final boolean mAllowLongPress;
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
private final Optional<BubblesManager> mBubblesManagerOptional; private final Optional<BubblesManager> mBubblesManagerOptional;
private final IStatusBarService mStatusBarService;
@Inject @Inject
public ExpandableNotificationRowController( public ExpandableNotificationRowController(
@@ -109,7 +111,8 @@ public class ExpandableNotificationRowController implements NodeController {
FalsingManager falsingManager, FalsingManager falsingManager,
FalsingCollector falsingCollector, FalsingCollector falsingCollector,
PeopleNotificationIdentifier peopleNotificationIdentifier, PeopleNotificationIdentifier peopleNotificationIdentifier,
Optional<BubblesManager> bubblesManagerOptional) { Optional<BubblesManager> bubblesManagerOptional,
IStatusBarService statusBarService) {
mView = view; mView = view;
mListContainer = listContainer; mListContainer = listContainer;
mActivatableNotificationViewController = activatableNotificationViewController; mActivatableNotificationViewController = activatableNotificationViewController;
@@ -134,6 +137,7 @@ public class ExpandableNotificationRowController implements NodeController {
mFalsingCollector = falsingCollector; mFalsingCollector = falsingCollector;
mPeopleNotificationIdentifier = peopleNotificationIdentifier; mPeopleNotificationIdentifier = peopleNotificationIdentifier;
mBubblesManagerOptional = bubblesManagerOptional; mBubblesManagerOptional = bubblesManagerOptional;
mStatusBarService = statusBarService;
} }
/** /**
@@ -160,7 +164,8 @@ public class ExpandableNotificationRowController implements NodeController {
mPeopleNotificationIdentifier, mPeopleNotificationIdentifier,
mOnUserInteractionCallback, mOnUserInteractionCallback,
mBubblesManagerOptional, mBubblesManagerOptional,
mNotificationGutsManager mNotificationGutsManager,
mStatusBarService
); );
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
if (mAllowLongPress) { if (mAllowLongPress) {

View File

@@ -21,10 +21,13 @@ import android.annotation.Nullable;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.RemoteException;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
@@ -40,6 +43,7 @@ import android.widget.LinearLayout;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency; import com.android.systemui.Dependency;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.RemoteInputController;
@@ -125,6 +129,8 @@ public class NotificationContentView extends FrameLayout {
private RemoteInputController mRemoteInputController; private RemoteInputController mRemoteInputController;
private Runnable mExpandedVisibleListener; private Runnable mExpandedVisibleListener;
private PeopleNotificationIdentifier mPeopleIdentifier; private PeopleNotificationIdentifier mPeopleIdentifier;
private IStatusBarService mStatusBarService;
/** /**
* List of listeners for when content views become inactive (i.e. not the showing view). * List of listeners for when content views become inactive (i.e. not the showing view).
*/ */
@@ -178,6 +184,7 @@ public class NotificationContentView extends FrameLayout {
mHybridGroupManager = new HybridGroupManager(getContext()); mHybridGroupManager = new HybridGroupManager(getContext());
mSmartReplyConstants = Dependency.get(SmartReplyConstants.class); mSmartReplyConstants = Dependency.get(SmartReplyConstants.class);
mSmartReplyController = Dependency.get(SmartReplyController.class); mSmartReplyController = Dependency.get(SmartReplyController.class);
mStatusBarService = Dependency.get(IStatusBarService.class);
initView(); initView();
} }
@@ -1978,4 +1985,36 @@ public class NotificationContentView extends FrameLayout {
} }
return Notification.COLOR_INVALID; return Notification.COLOR_INVALID;
} }
@Override
protected void dispatchDraw(Canvas canvas) {
try {
super.dispatchDraw(canvas);
} catch (Exception e) {
// Catch draw exceptions that may be caused by RemoteViews
Log.e(TAG, "Drawing view failed: " + e);
cancelNotification(e);
}
}
private void cancelNotification(Exception exception) {
try {
setVisibility(GONE);
final StatusBarNotification sbn = mNotificationEntry.getSbn();
if (mStatusBarService != null) {
// report notification inflation errors back up
// to notification delegates
mStatusBarService.onNotificationError(
sbn.getPackageName(),
sbn.getTag(),
sbn.getId(),
sbn.getUid(),
sbn.getInitialPid(),
exception.getMessage(),
sbn.getUser().getIdentifier());
}
} catch (RemoteException ex) {
Log.e(TAG, "cancelNotification failed: " + ex);
}
}
} }

View File

@@ -265,7 +265,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
new FalsingManagerFake(), new FalsingManagerFake(),
new FalsingCollectorFake(), new FalsingCollectorFake(),
mPeopleNotificationIdentifier, mPeopleNotificationIdentifier,
Optional.of(mock(BubblesManager.class)) Optional.of(mock(BubblesManager.class)),
mock(IStatusBarService.class)
)); ));
when(mNotificationRowComponentBuilder.activatableNotificationView(any())) when(mNotificationRowComponentBuilder.activatableNotificationView(any()))

View File

@@ -43,6 +43,7 @@ import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.TestableDependency; import com.android.systemui.TestableDependency;
import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.classifier.FalsingManagerFake;
@@ -472,7 +473,8 @@ public class NotificationTestHelper {
mPeopleNotificationIdentifier, mPeopleNotificationIdentifier,
mock(OnUserInteractionCallback.class), mock(OnUserInteractionCallback.class),
Optional.of(mock(BubblesManager.class)), Optional.of(mock(BubblesManager.class)),
mock(NotificationGutsManager.class)); mock(NotificationGutsManager.class),
mock(IStatusBarService.class));
row.setAboveShelfChangedListener(aboveShelf -> { }); row.setAboveShelfChangedListener(aboveShelf -> { });
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags); mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);