summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Robert Carr <racarr@google.com> 2016-10-05 15:33:16 -0700
committer Robert Carr <racarr@google.com> 2016-10-19 14:56:47 -0700
commit6cfc4e31b7bde552f8e57e97e0cbeb88ccffab3b (patch)
treea7ddacff227a8bfa68ea0ec469dffe3f02a19aac
parentec36a7a9448cb5b3f674809820e666bb49005bb3 (diff)
Prevent crash from early Toast surface destruction.
To understand this change it's first helpful to review Toasts. The ViewRoot is constructed on the client side, but it's added, to a window token controlled by the NotificationManagerService. When we call NotificationManagerService#cancelToast, the system will remove this window token. With the window token removed, the WindowManager needs to destroy the surface to prevent orphaned windows. If we destroy the Surface before removing the toast on the client side however, we've never asked the ViewRoot to stop rendering and we could have a crash. To solve this we just have to ensure we call removeView before cancelToast. Test: cts-tradefed run singleCommand cts -d -o --module CtsWidgetTestCases --test android.widget.cts.ToastTest Bug: 31547288 Change-Id: I96672b0ac07ff18e9f51348f2ed42913c5a5226f
-rw-r--r--core/java/android/widget/Toast.java67
1 files changed, 43 insertions, 24 deletions
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 4efcb097e8d1..789e60b62799 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -100,13 +100,13 @@ public class Toast {
*/
public Toast(Context context) {
mContext = context;
- mTN = new TN();
+ mTN = new TN(context.getPackageName());
mTN.mY = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.toast_y_offset);
mTN.mGravity = context.getResources().getInteger(
com.android.internal.R.integer.config_toastDefaultGravity);
}
-
+
/**
* Show the view for the specified duration.
*/
@@ -133,15 +133,9 @@ public class Toast {
* after the appropriate duration.
*/
public void cancel() {
- mTN.hide();
-
- try {
- getService().cancelToast(mContext.getPackageName(), mTN);
- } catch (RemoteException e) {
- // Empty
- }
+ mTN.cancel();
}
-
+
/**
* Set the view to show.
* @see #getView
@@ -328,21 +322,37 @@ public class Toast {
}
private static class TN extends ITransientNotification.Stub {
- final Runnable mHide = new Runnable() {
- @Override
- public void run() {
- handleHide();
- // Don't do this in handleHide() because it is also invoked by handleShow()
- mNextView = null;
- }
- };
-
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
+
+ private static final int SHOW = 0;
+ private static final int HIDE = 1;
+ private static final int CANCEL = 2;
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- IBinder token = (IBinder) msg.obj;
- handleShow(token);
+ switch (msg.what) {
+ case SHOW: {
+ IBinder token = (IBinder) msg.obj;
+ handleShow(token);
+ break;
+ }
+ case HIDE: {
+ handleHide();
+ // Don't do this in handleHide() because it is also invoked by handleShow()
+ mNextView = null;
+ break;
+ }
+ case CANCEL: {
+ handleHide();
+ // Don't do this in handleHide() because it is also invoked by handleShow()
+ mNextView = null;
+ try {
+ getService().cancelToast(mPackageName, TN.this);
+ } catch (RemoteException e) {
+ }
+ break;
+ }
+ }
}
};
@@ -358,10 +368,12 @@ public class Toast {
WindowManager mWM;
+ String mPackageName;
+
static final long SHORT_DURATION_TIMEOUT = 4000;
static final long LONG_DURATION_TIMEOUT = 7000;
- TN() {
+ TN(String packageName) {
// XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
final WindowManager.LayoutParams params = mParams;
@@ -374,6 +386,8 @@ public class Toast {
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+
+ mPackageName = packageName;
}
/**
@@ -382,7 +396,7 @@ public class Toast {
@Override
public void show(IBinder windowToken) {
if (localLOGV) Log.v(TAG, "SHOW: " + this);
- mHandler.obtainMessage(0, windowToken).sendToTarget();
+ mHandler.obtainMessage(SHOW, windowToken).sendToTarget();
}
/**
@@ -391,7 +405,12 @@ public class Toast {
@Override
public void hide() {
if (localLOGV) Log.v(TAG, "HIDE: " + this);
- mHandler.post(mHide);
+ mHandler.obtainMessage(HIDE).sendToTarget();
+ }
+
+ public void cancel() {
+ if (localLOGV) Log.v(TAG, "CANCEL: " + this);
+ mHandler.obtainMessage(CANCEL).sendToTarget();
}
public void handleShow(IBinder windowToken) {