Merge "Add WindowManager side timeout for toasts." into nyc-dev
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index a3a40eb..89e146b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1726,6 +1726,16 @@
*/
public CharSequence accessibilityTitle;
+ /**
+ * Sets a timeout in milliseconds before which the window will be removed
+ * by the window manager. Useful for transient notifications like toasts
+ * so we don't have to rely on client cooperation to ensure the window
+ * is removed. Must be specified at window creation time.
+ *
+ * @hide
+ */
+ public long removeTimeoutMilliseconds = -1;
+
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
@@ -1846,6 +1856,7 @@
out.writeInt(needsMenuKey);
out.writeInt(accessibilityIdOfAnchor);
TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags);
+ out.writeLong(removeTimeoutMilliseconds);
}
public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1899,6 +1910,7 @@
needsMenuKey = in.readInt();
accessibilityIdOfAnchor = in.readInt();
accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ removeTimeoutMilliseconds = in.readLong();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -2119,6 +2131,9 @@
changes |= ACCESSIBILITY_TITLE_CHANGED;
}
+ // This can't change, it's only set at window creation time.
+ removeTimeoutMilliseconds = o.removeTimeoutMilliseconds;
+
return changes;
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 207f675..7762675 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -163,6 +163,7 @@
*/
public void setDuration(@Duration int duration) {
mDuration = duration;
+ mTN.mDuration = duration;
}
/**
@@ -342,7 +343,7 @@
};
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
- final Handler mHandler = new Handler();
+ final Handler mHandler = new Handler();
int mGravity;
int mX, mY;
@@ -352,9 +353,13 @@
View mView;
View mNextView;
+ int mDuration;
WindowManager mWM;
+ static final long SHORT_DURATION_TIMEOUT = 5000;
+ static final long LONG_DURATION_TIMEOUT = 1000;
+
TN() {
// XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
@@ -417,6 +422,8 @@
mParams.verticalMargin = mVerticalMargin;
mParams.horizontalMargin = mHorizontalMargin;
mParams.packageName = packageName;
+ mParams.removeTimeoutMilliseconds = mDuration ==
+ Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
if (mView.getParent() != null) {
if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0a0f0f0..57dc97a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2107,6 +2107,11 @@
if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
reportNewConfig = true;
}
+ if (attrs.removeTimeoutMilliseconds > 0) {
+ mH.sendMessageDelayed(
+ mH.obtainMessage(H.WINDOW_REMOVE_TIMEOUT, win),
+ attrs.removeTimeoutMilliseconds);
+ }
}
if (reportNewConfig) {
@@ -7788,8 +7793,8 @@
public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
-
public static final int UPDATE_ANIMATION_SCALE = 51;
+ public static final int WINDOW_REMOVE_TIMEOUT = 52;
/**
* Used to denote that an integer field in a message will not be used.
@@ -8402,6 +8407,18 @@
mAmInternal.notifyStartingWindowDrawn();
}
break;
+ case WINDOW_REMOVE_TIMEOUT: {
+ final WindowState window = (WindowState) msg.obj;
+ synchronized(mWindowMap) {
+ // It's counterintuitive that we check that "mWindowRemovalAllowed"
+ // is false. But in fact if it's true, it means a remove has already
+ // been requested and we better just not do anything.
+ if (!window.mRemoved && !window.mWindowRemovalAllowed) {
+ removeWindowLocked(window);
+ }
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: exit");