Merge "Add enter-animation-done callback for system windows" into lmp-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
159da3dba8
@ -85,4 +85,9 @@ oneway interface IWindow {
|
||||
* is done.
|
||||
*/
|
||||
void doneAnimating();
|
||||
|
||||
/**
|
||||
* Called for non-application windows when the enter animation has completed.
|
||||
*/
|
||||
void dispatchWindowShown();
|
||||
}
|
||||
|
@ -3089,6 +3089,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private final static int MSG_INVALIDATE_WORLD = 23;
|
||||
private final static int MSG_WINDOW_MOVED = 24;
|
||||
private final static int MSG_SYNTHESIZE_INPUT_EVENT = 25;
|
||||
private final static int MSG_DISPATCH_WINDOW_SHOWN = 26;
|
||||
|
||||
final class ViewRootHandler extends Handler {
|
||||
@Override
|
||||
@ -3138,6 +3139,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
return "MSG_WINDOW_MOVED";
|
||||
case MSG_SYNTHESIZE_INPUT_EVENT:
|
||||
return "MSG_SYNTHESIZE_INPUT_EVENT";
|
||||
case MSG_DISPATCH_WINDOW_SHOWN:
|
||||
return "MSG_DISPATCH_WINDOW_SHOWN";
|
||||
}
|
||||
return super.getMessageName(message);
|
||||
}
|
||||
@ -3366,6 +3369,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
invalidateWorld(mView);
|
||||
}
|
||||
} break;
|
||||
case MSG_DISPATCH_WINDOW_SHOWN: {
|
||||
handleDispatchWindowShown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5212,6 +5218,10 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
public void handleDispatchWindowShown() {
|
||||
mAttachInfo.mTreeObserver.dispatchOnWindowShown();
|
||||
}
|
||||
|
||||
public void getLastTouchPoint(Point outLocation) {
|
||||
outLocation.x = (int) mLastTouchPoint.x;
|
||||
outLocation.y = (int) mLastTouchPoint.y;
|
||||
@ -6072,6 +6082,10 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void dispatchWindowShown() {
|
||||
mHandler.sendEmptyMessage(MSG_DISPATCH_WINDOW_SHOWN);
|
||||
}
|
||||
|
||||
public void dispatchCloseSystemDialogs(String reason) {
|
||||
Message msg = Message.obtain();
|
||||
msg.what = MSG_CLOSE_SYSTEM_DIALOGS;
|
||||
@ -6582,6 +6596,14 @@ public final class ViewRootImpl implements ViewParent,
|
||||
viewAncestor.dispatchDoneAnimating();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchWindowShown() {
|
||||
final ViewRootImpl viewAncestor = mViewAncestor.get();
|
||||
if (viewAncestor != null) {
|
||||
viewAncestor.dispatchWindowShown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
|
||||
|
@ -44,10 +44,15 @@ public final class ViewTreeObserver {
|
||||
private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
|
||||
private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
|
||||
private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
|
||||
private CopyOnWriteArray<OnWindowShownListener> mOnWindowShownListeners;
|
||||
|
||||
// These listeners cannot be mutated during dispatch
|
||||
private ArrayList<OnDrawListener> mOnDrawListeners;
|
||||
|
||||
/** Remains false until #dispatchOnWindowShown() is called. If a listener registers after
|
||||
* that the listener will be immediately called. */
|
||||
private boolean mWindowShown;
|
||||
|
||||
private boolean mAlive = true;
|
||||
|
||||
/**
|
||||
@ -173,6 +178,19 @@ public final class ViewTreeObserver {
|
||||
public void onScrollChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback noting when a system window has been displayed.
|
||||
* This is only used for non-Activity windows. Activity windows can use
|
||||
* Activity.onEnterAnimationComplete() to get the same signal.
|
||||
* @hide
|
||||
*/
|
||||
public interface OnWindowShownListener {
|
||||
/**
|
||||
* Callback method to be invoked when a non-activity window is fully shown.
|
||||
*/
|
||||
void onWindowShown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters used with OnComputeInternalInsetsListener.
|
||||
*
|
||||
@ -375,6 +393,14 @@ public final class ViewTreeObserver {
|
||||
}
|
||||
}
|
||||
|
||||
if (observer.mOnWindowShownListeners != null) {
|
||||
if (mOnWindowShownListeners != null) {
|
||||
mOnWindowShownListeners.addAll(observer.mOnWindowShownListeners);
|
||||
} else {
|
||||
mOnWindowShownListeners = observer.mOnWindowShownListeners;
|
||||
}
|
||||
}
|
||||
|
||||
observer.kill();
|
||||
}
|
||||
|
||||
@ -567,6 +593,45 @@ public final class ViewTreeObserver {
|
||||
mOnPreDrawListeners.remove(victim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when the view tree window has been shown
|
||||
*
|
||||
* @param listener The callback to add
|
||||
*
|
||||
* @throws IllegalStateException If {@link #isAlive()} returns false
|
||||
* @hide
|
||||
*/
|
||||
public void addOnWindowShownListener(OnWindowShownListener listener) {
|
||||
checkIsAlive();
|
||||
|
||||
if (mOnWindowShownListeners == null) {
|
||||
mOnWindowShownListeners = new CopyOnWriteArray<OnWindowShownListener>();
|
||||
}
|
||||
|
||||
mOnWindowShownListeners.add(listener);
|
||||
if (mWindowShown) {
|
||||
listener.onWindowShown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a previously installed window shown callback
|
||||
*
|
||||
* @param victim The callback to remove
|
||||
*
|
||||
* @throws IllegalStateException If {@link #isAlive()} returns false
|
||||
*
|
||||
* @see #addOnWindowShownListener(OnWindowShownListener)
|
||||
* @hide
|
||||
*/
|
||||
public void removeOnWindowShownListener(OnWindowShownListener victim) {
|
||||
checkIsAlive();
|
||||
if (mOnWindowShownListeners == null) {
|
||||
return;
|
||||
}
|
||||
mOnWindowShownListeners.remove(victim);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Register a callback to be invoked when the view tree is about to be drawn.</p>
|
||||
* <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
|
||||
@ -853,6 +918,27 @@ public final class ViewTreeObserver {
|
||||
return cancelDraw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies registered listeners that the window is now shown
|
||||
* @hide
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final void dispatchOnWindowShown() {
|
||||
mWindowShown = true;
|
||||
final CopyOnWriteArray<OnWindowShownListener> listeners = mOnWindowShownListeners;
|
||||
if (listeners != null && listeners.size() > 0) {
|
||||
CopyOnWriteArray.Access<OnWindowShownListener> access = listeners.start();
|
||||
try {
|
||||
int count = access.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
access.get(i).onWindowShown();
|
||||
}
|
||||
} finally {
|
||||
listeners.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies registered listeners that the drawing pass is about to start.
|
||||
*/
|
||||
|
@ -102,4 +102,8 @@ public class BaseIWindow extends IWindow.Stub {
|
||||
@Override
|
||||
public void doneAnimating() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchWindowShown() {
|
||||
}
|
||||
}
|
||||
|
@ -17,17 +17,11 @@
|
||||
package com.android.server.am;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Service;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Slog;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -39,11 +33,10 @@ import com.android.internal.R;
|
||||
* in the background rather than just freeze the screen and not know if the user-switch affordance
|
||||
* was being handled.
|
||||
*/
|
||||
final class UserSwitchingDialog extends AlertDialog {
|
||||
final class UserSwitchingDialog extends AlertDialog
|
||||
implements ViewTreeObserver.OnWindowShownListener {
|
||||
private static final String TAG = "ActivityManagerUserSwitchingDialog";
|
||||
|
||||
private static final int MSG_START_USER = 1;
|
||||
|
||||
private final ActivityManagerService mService;
|
||||
private final int mUserId;
|
||||
|
||||
@ -74,19 +67,21 @@ final class UserSwitchingDialog extends AlertDialog {
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
// Slog.v(TAG, "show called");
|
||||
super.show();
|
||||
// TODO: Instead of just an arbitrary delay, wait for a signal that the window was fully
|
||||
// displayed by the window manager
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER), 250);
|
||||
final View decorView = getWindow().getDecorView();
|
||||
if (decorView != null) {
|
||||
decorView.getViewTreeObserver().addOnWindowShownListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_START_USER:
|
||||
mService.startUserInForeground(mUserId, UserSwitchingDialog.this);
|
||||
break;
|
||||
}
|
||||
@Override
|
||||
public void onWindowShown() {
|
||||
// Slog.v(TAG, "onWindowShown called");
|
||||
mService.startUserInForeground(mUserId, this);
|
||||
final View decorView = getWindow().getDecorView();
|
||||
if (decorView != null) {
|
||||
decorView.getViewTreeObserver().removeOnWindowShownListener(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -2487,7 +2487,9 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
win.mWinAnimator.mEnterAnimationPending = true;
|
||||
final WindowStateAnimator winAnimator = win.mWinAnimator;
|
||||
winAnimator.mEnterAnimationPending = true;
|
||||
winAnimator.mEnteringAnimation = true;
|
||||
|
||||
if (displayContent.isDefaultDisplay) {
|
||||
mPolicy.getContentInsetHintLw(attrs, outContentInsets);
|
||||
@ -3099,6 +3101,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (oldVisibility == View.GONE) {
|
||||
winAnimator.mEnterAnimationPending = true;
|
||||
}
|
||||
winAnimator.mEnteringAnimation = true;
|
||||
if (toBeDisplayed) {
|
||||
if (win.isDrawnLw() && okToDisplay()) {
|
||||
winAnimator.applyEnterAnimationLocked();
|
||||
@ -3167,6 +3170,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
} else {
|
||||
winAnimator.mEnterAnimationPending = false;
|
||||
winAnimator.mEnteringAnimation = false;
|
||||
if (winAnimator.mSurfaceControl != null) {
|
||||
if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
|
||||
+ ": mExiting=" + win.mExiting);
|
||||
|
@ -40,6 +40,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.os.Debug;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
import android.view.Display;
|
||||
@ -141,6 +142,11 @@ class WindowStateAnimator {
|
||||
// an enter animation.
|
||||
boolean mEnterAnimationPending;
|
||||
|
||||
/** Used to indicate that this window is undergoing an enter animation. Used for system
|
||||
* windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the
|
||||
* window is first added or shown, cleared when the callback has been made. */
|
||||
boolean mEnteringAnimation;
|
||||
|
||||
boolean keyguardGoingAwayAnimation;
|
||||
|
||||
/** This is set when there is no Surface */
|
||||
@ -428,6 +434,14 @@ class WindowStateAnimator {
|
||||
mWin.mChildWindows.get(i).mWinAnimator.finishExit();
|
||||
}
|
||||
|
||||
if (mEnteringAnimation && mWin.mAppToken == null) {
|
||||
try {
|
||||
mEnteringAnimation = false;
|
||||
mWin.mClient.dispatchWindowShown();
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!mWin.mExiting) {
|
||||
return;
|
||||
}
|
||||
|
@ -94,6 +94,10 @@ public final class BridgeWindow implements IWindow {
|
||||
public void doneAnimating() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchWindowShown() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder asBinder() {
|
||||
// pass for now.
|
||||
|
Reference in New Issue
Block a user