[DO NOT MERGE] Prevent RemoteViews crashing SystemUi am: cfc0b34432
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22101922 Change-Id: I62e92592c74fbcd08b022e1d332ec96a79b1b7e1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -28,6 +28,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.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -250,19 +251,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
|
||||||
@@ -725,4 +733,15 @@ public class AppWidgetHostView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
post(this::handleViewError);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,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.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
@@ -1612,7 +1613,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
OnAppOpsClickListener onAppOpsClickListener,
|
OnAppOpsClickListener onAppOpsClickListener,
|
||||||
FalsingManager falsingManager,
|
FalsingManager falsingManager,
|
||||||
StatusBarStateController statusBarStateController,
|
StatusBarStateController statusBarStateController,
|
||||||
PeopleNotificationIdentifier peopleNotificationIdentifier) {
|
PeopleNotificationIdentifier peopleNotificationIdentifier,
|
||||||
|
IStatusBarService statusBarService) {
|
||||||
mAppName = appName;
|
mAppName = appName;
|
||||||
if (mMenuRow == null) {
|
if (mMenuRow == null) {
|
||||||
mMenuRow = new NotificationMenuRow(mContext, peopleNotificationIdentifier);
|
mMenuRow = new NotificationMenuRow(mContext, peopleNotificationIdentifier);
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENAB
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import com.android.internal.statusbar.IStatusBarService;
|
||||||
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;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
@@ -69,6 +71,7 @@ public class ExpandableNotificationRowController {
|
|||||||
private final FalsingManager mFalsingManager;
|
private final FalsingManager mFalsingManager;
|
||||||
private final boolean mAllowLongPress;
|
private final boolean mAllowLongPress;
|
||||||
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
||||||
|
private final IStatusBarService mStatusBarService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ExpandableNotificationRowController(ExpandableNotificationRow view,
|
public ExpandableNotificationRowController(ExpandableNotificationRow view,
|
||||||
@@ -84,7 +87,8 @@ public class ExpandableNotificationRowController {
|
|||||||
NotificationGutsManager notificationGutsManager,
|
NotificationGutsManager notificationGutsManager,
|
||||||
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
|
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
|
||||||
@DismissRunnable Runnable onDismissRunnable, FalsingManager falsingManager,
|
@DismissRunnable Runnable onDismissRunnable, FalsingManager falsingManager,
|
||||||
PeopleNotificationIdentifier peopleNotificationIdentifier) {
|
PeopleNotificationIdentifier peopleNotificationIdentifier,
|
||||||
|
IStatusBarService statusBarService) {
|
||||||
mView = view;
|
mView = view;
|
||||||
mActivatableNotificationViewController = activatableNotificationViewController;
|
mActivatableNotificationViewController = activatableNotificationViewController;
|
||||||
mMediaManager = mediaManager;
|
mMediaManager = mediaManager;
|
||||||
@@ -105,6 +109,7 @@ public class ExpandableNotificationRowController {
|
|||||||
mAllowLongPress = allowLongPress;
|
mAllowLongPress = allowLongPress;
|
||||||
mFalsingManager = falsingManager;
|
mFalsingManager = falsingManager;
|
||||||
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
|
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
|
||||||
|
mStatusBarService = statusBarService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,7 +130,8 @@ public class ExpandableNotificationRowController {
|
|||||||
mOnAppOpsClickListener,
|
mOnAppOpsClickListener,
|
||||||
mFalsingManager,
|
mFalsingManager,
|
||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
mPeopleNotificationIdentifier
|
mPeopleNotificationIdentifier,
|
||||||
|
mStatusBarService
|
||||||
);
|
);
|
||||||
mView.setOnDismissRunnable(mOnDismissRunnable);
|
mView.setOnDismissRunnable(mOnDismissRunnable);
|
||||||
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
|
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ 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.service.notification.StatusBarNotification;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
@@ -45,6 +47,7 @@ import android.widget.LinearLayout;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.ContrastColorUtil;
|
import com.android.internal.util.ContrastColorUtil;
|
||||||
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.statusbar.MediaTransferManager;
|
import com.android.systemui.statusbar.MediaTransferManager;
|
||||||
import com.android.systemui.statusbar.RemoteInputController;
|
import com.android.systemui.statusbar.RemoteInputController;
|
||||||
@@ -126,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).
|
||||||
*/
|
*/
|
||||||
@@ -182,6 +187,7 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
mMediaTransferManager = new MediaTransferManager(getContext());
|
mMediaTransferManager = new MediaTransferManager(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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1965,4 +1971,35 @@ 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);
|
||||||
|
if (mStatusBarService != null) {
|
||||||
|
// report notification inflation errors back up
|
||||||
|
// to notification delegates
|
||||||
|
mStatusBarService.onNotificationError(
|
||||||
|
mStatusBarNotification.getPackageName(),
|
||||||
|
mStatusBarNotification.getTag(),
|
||||||
|
mStatusBarNotification.getId(),
|
||||||
|
mStatusBarNotification.getUid(),
|
||||||
|
mStatusBarNotification.getInitialPid(),
|
||||||
|
exception.getMessage(),
|
||||||
|
mStatusBarNotification.getUser().getIdentifier());
|
||||||
|
}
|
||||||
|
} catch (RemoteException ex) {
|
||||||
|
Log.e(TAG, "cancelNotification failed: " + ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import android.testing.TestableLooper;
|
|||||||
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
|
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.internal.statusbar.IStatusBarService;
|
||||||
import com.android.internal.util.NotificationMessagingUtil;
|
import com.android.internal.util.NotificationMessagingUtil;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
@@ -252,7 +253,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
|
|||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
mFalsingManager,
|
mFalsingManager,
|
||||||
mPeopleNotificationIdentifier
|
mPeopleNotificationIdentifier,
|
||||||
|
mock(IStatusBarService.class)
|
||||||
));
|
));
|
||||||
|
|
||||||
when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
|
when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
|
||||||
|
|||||||
@@ -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.bubbles.BubbleController;
|
import com.android.systemui.bubbles.BubbleController;
|
||||||
import com.android.systemui.bubbles.BubblesTestActivity;
|
import com.android.systemui.bubbles.BubblesTestActivity;
|
||||||
@@ -424,7 +425,9 @@ public class NotificationTestHelper {
|
|||||||
mock(ExpandableNotificationRow.OnAppOpsClickListener.class),
|
mock(ExpandableNotificationRow.OnAppOpsClickListener.class),
|
||||||
mock(FalsingManager.class),
|
mock(FalsingManager.class),
|
||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
mPeopleNotificationIdentifier);
|
mPeopleNotificationIdentifier,
|
||||||
|
mock(IStatusBarService.class));
|
||||||
|
|
||||||
row.setAboveShelfChangedListener(aboveShelf -> { });
|
row.setAboveShelfChangedListener(aboveShelf -> { });
|
||||||
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
|
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
|
||||||
inflateAndWait(entry);
|
inflateAndWait(entry);
|
||||||
|
|||||||
Reference in New Issue
Block a user