[DO NOT MERGE] Prevent RemoteViews crashing SystemUi am: 2feec60bc3
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21985880 Change-Id: I479a21502ba0488f607da6a8212fc04a48b6f211 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -31,6 +31,7 @@ import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
@@ -311,19 +312,26 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
} catch (final RuntimeException e) {
|
||||
Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e);
|
||||
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;
|
||||
handleViewError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* heights should correspond to the full area the AppWidgetHostView is given. Padding added by
|
||||
@@ -953,4 +961,15 @@ public class AppWidgetHostView extends FrameLayout implements AppWidgetHost.AppW
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.util.ContrastColorUtil;
|
||||
import com.android.internal.widget.CachingIconView;
|
||||
import com.android.internal.widget.CallLayout;
|
||||
@@ -1702,7 +1703,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
MetricsLogger metricsLogger,
|
||||
SmartReplyConstants smartReplyConstants,
|
||||
SmartReplyController smartReplyController,
|
||||
FeatureFlags featureFlags) {
|
||||
FeatureFlags featureFlags,
|
||||
IStatusBarService statusBarService) {
|
||||
mEntry = entry;
|
||||
mAppName = appName;
|
||||
if (mMenuRow == null) {
|
||||
@@ -1731,7 +1733,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
mPeopleNotificationIdentifier,
|
||||
rivSubcomponentFactory,
|
||||
smartReplyConstants,
|
||||
smartReplyController);
|
||||
smartReplyController,
|
||||
statusBarService);
|
||||
}
|
||||
mOnUserInteractionCallback = onUserInteractionCallback;
|
||||
mBubblesManagerOptional = bubblesManagerOptional;
|
||||
|
||||
@@ -29,6 +29,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
@@ -100,6 +101,7 @@ public class ExpandableNotificationRowController implements NotifViewController
|
||||
private final SmartReplyConstants mSmartReplyConstants;
|
||||
private final SmartReplyController mSmartReplyController;
|
||||
private final ExpandableNotificationRowDragController mDragController;
|
||||
private final IStatusBarService mStatusBarService;
|
||||
private final ExpandableNotificationRow.ExpandableNotificationRowLogger mLoggerCallback =
|
||||
new ExpandableNotificationRow.ExpandableNotificationRowLogger() {
|
||||
@Override
|
||||
@@ -157,7 +159,8 @@ public class ExpandableNotificationRowController implements NotifViewController
|
||||
FeatureFlags featureFlags,
|
||||
PeopleNotificationIdentifier peopleNotificationIdentifier,
|
||||
Optional<BubblesManager> bubblesManagerOptional,
|
||||
ExpandableNotificationRowDragController dragController) {
|
||||
ExpandableNotificationRowDragController dragController,
|
||||
IStatusBarService statusBarService) {
|
||||
mView = view;
|
||||
mListContainer = listContainer;
|
||||
mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory;
|
||||
@@ -189,6 +192,7 @@ public class ExpandableNotificationRowController implements NotifViewController
|
||||
mLogBufferLogger = logBufferLogger;
|
||||
mSmartReplyConstants = smartReplyConstants;
|
||||
mSmartReplyController = smartReplyController;
|
||||
mStatusBarService = statusBarService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,7 +224,8 @@ public class ExpandableNotificationRowController implements NotifViewController
|
||||
mMetricsLogger,
|
||||
mSmartReplyConstants,
|
||||
mSmartReplyController,
|
||||
mFeatureFlags
|
||||
mFeatureFlags,
|
||||
mStatusBarService
|
||||
);
|
||||
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
|
||||
if (mAllowLongPress) {
|
||||
|
||||
@@ -21,10 +21,13 @@ import android.annotation.Nullable;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.IndentingPrintWriter;
|
||||
@@ -39,6 +42,7 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.statusbar.RemoteInputController;
|
||||
@@ -129,6 +133,7 @@ public class NotificationContentView extends FrameLayout implements Notification
|
||||
private Runnable mExpandedVisibleListener;
|
||||
private PeopleNotificationIdentifier mPeopleIdentifier;
|
||||
private RemoteInputViewSubcomponent.Factory mRemoteInputSubcomponentFactory;
|
||||
private IStatusBarService mStatusBarService;
|
||||
|
||||
/**
|
||||
* List of listeners for when content views become inactive (i.e. not the showing view).
|
||||
@@ -196,11 +201,13 @@ public class NotificationContentView extends FrameLayout implements Notification
|
||||
PeopleNotificationIdentifier peopleNotificationIdentifier,
|
||||
RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
|
||||
SmartReplyConstants smartReplyConstants,
|
||||
SmartReplyController smartReplyController) {
|
||||
SmartReplyController smartReplyController,
|
||||
IStatusBarService statusBarService) {
|
||||
mPeopleIdentifier = peopleNotificationIdentifier;
|
||||
mRemoteInputSubcomponentFactory = rivSubcomponentFactory;
|
||||
mSmartReplyConstants = smartReplyConstants;
|
||||
mSmartReplyController = smartReplyController;
|
||||
mStatusBarService = statusBarService;
|
||||
}
|
||||
|
||||
public void reinflate() {
|
||||
@@ -2176,4 +2183,36 @@ public class NotificationContentView extends FrameLayout implements Notification
|
||||
protected void setHeadsUpWrapper(NotificationViewWrapper headsUpWrapper) {
|
||||
mHeadsUpWrapper = headsUpWrapper;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.logging.MetricsLogger
|
||||
import com.android.internal.statusbar.IStatusBarService
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.classifier.FalsingCollector
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
@@ -93,6 +94,7 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() {
|
||||
private val peopleNotificationIdentifier: PeopleNotificationIdentifier = mock()
|
||||
private val bubblesManager: BubblesManager = mock()
|
||||
private val dragController: ExpandableNotificationRowDragController = mock()
|
||||
private val statusBarService: IStatusBarService = mock()
|
||||
private lateinit var controller: ExpandableNotificationRowController
|
||||
|
||||
@Before
|
||||
@@ -129,7 +131,8 @@ class ExpandableNotificationRowControllerTest : SysuiTestCase() {
|
||||
featureFlags,
|
||||
peopleNotificationIdentifier,
|
||||
Optional.of(bubblesManager),
|
||||
dragController
|
||||
dragController,
|
||||
statusBarService
|
||||
)
|
||||
whenever(view.childrenContainer).thenReturn(childrenContainer)
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ class NotificationContentViewTest : SysuiTestCase() {
|
||||
doReturn(10).whenever(spyRow).intrinsicHeight
|
||||
|
||||
with(view) {
|
||||
initialize(mPeopleNotificationIdentifier, mock(), mock(), mock())
|
||||
initialize(mPeopleNotificationIdentifier, mock(), mock(), mock(), mock())
|
||||
setContainingNotification(spyRow)
|
||||
setHeights(/* smallHeight= */ 10, /* headsUpMaxHeight= */ 20, /* maxHeight= */ 30)
|
||||
contractedChild = createViewWithHeight(10)
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.view.LayoutInflater;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.systemui.TestableDependency;
|
||||
import com.android.systemui.classifier.FalsingCollectorFake;
|
||||
import com.android.systemui.classifier.FalsingManagerFake;
|
||||
@@ -548,7 +549,8 @@ public class NotificationTestHelper {
|
||||
mock(MetricsLogger.class),
|
||||
mock(SmartReplyConstants.class),
|
||||
mock(SmartReplyController.class),
|
||||
mFeatureFlags);
|
||||
mFeatureFlags,
|
||||
mock(IStatusBarService.class));
|
||||
|
||||
row.setAboveShelfChangedListener(aboveShelf -> { });
|
||||
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
|
||||
|
||||
Reference in New Issue
Block a user