diff options
| -rw-r--r-- | core/java/android/view/IWindowSession.aidl | 17 | ||||
| -rw-r--r-- | core/java/android/view/Surface.java | 14 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 11 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 14 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 14 | ||||
| -rw-r--r-- | core/jni/android_view_Surface.cpp | 5 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 19 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/Session.java | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 53 |
9 files changed, 151 insertions, 2 deletions
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 017364a5a0b1..427284be100e 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -96,6 +96,23 @@ interface IWindowSession { out Rect outOutsets, out Configuration outConfig, out Surface outSurface); /** + * Position a window relative to it's parent (attached) window without triggering + * a full relayout. This action may be deferred until a given frame number + * for the parent window appears. This allows for synchronizing movement of a child + * to repainting the contents of the parent. + * + * @param window The window being modified. Must be attached to a parent window + * or this call will fail. + * @param x The new x position + * @param y The new y position + * @param deferTransactionUntilFrame Frame number from our parent (attached) to + * defer this action until. + * @param outFrame Rect in which is placed the new position/size on screen. + */ + void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame, + out Rect outFrame); + + /** * If a call to relayout() asked to have the surface destroy deferred, * it must call this once it is okay to destroy that surface. */ diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 6de4d3e4e4c3..394660fb538b 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -56,6 +56,8 @@ public class Surface implements Parcelable { private static native int nativeGetWidth(long nativeObject); private static native int nativeGetHeight(long nativeObject); + private static native long nativeGetNextFrameNumber(long nativeObject); + public static final Parcelable.Creator<Surface> CREATOR = new Parcelable.Creator<Surface>() { @Override @@ -220,6 +222,18 @@ public class Surface implements Parcelable { } /** + * Returns the next frame number which will be dequeued for rendering. + * Intended for use with SurfaceFlinger's deferred transactions API. + * + * @hide + */ + public long getNextFrameNumber() { + synchronized (mLock) { + return nativeGetNextFrameNumber(mNativeObject); + } + } + + /** * Returns true if the consumer of this Surface is running behind the producer. * * @return True if the consumer is more than one buffer ahead of the producer. diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index bcf9b2c7fe7c..b58c68f782ee 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -81,6 +81,9 @@ public class SurfaceControl { private static native boolean nativeSetActiveConfig(IBinder displayToken, int id); private static native void nativeSetDisplayPowerMode( IBinder displayToken, int mode); + private static native void nativeDeferTransactionUntil(long nativeObject, + IBinder handle, long frame); + private static native IBinder nativeGetHandle(long nativeObject); private final CloseGuard mCloseGuard = CloseGuard.get(); @@ -358,6 +361,14 @@ public class SurfaceControl { nativeCloseTransaction(); } + public void deferTransactionUntil(IBinder handle, long frame) { + nativeDeferTransactionUntil(mNativeObject, handle, frame); + } + + public IBinder getHandle() { + return nativeGetHandle(mNativeObject); + } + /** flag the transaction as an animation */ public static void setAnimationTransaction() { nativeSetAnimationTransaction(); diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index db68c29d025f..dddea210ed83 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -448,11 +448,10 @@ public class SurfaceView extends View { final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight; final boolean visibleChanged = mVisible != mRequestedVisible; final boolean layoutSizeChanged = getWidth() != mLayout.width || getHeight() != mLayout.height; + final boolean positionChanged = mLeft != mLocation[0] || mTop != mLocation[1]; if (force || creating || formatChanged || sizeChanged || visibleChanged - || mLeft != mLocation[0] || mTop != mLocation[1] || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded || layoutSizeChanged) { - if (DEBUG) Log.i(TAG, "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged + " visible=" + visibleChanged @@ -616,11 +615,22 @@ public class SurfaceView extends View { mSession.performDeferredDestroy(mWindow); } } catch (RemoteException ex) { + Log.e(TAG, "Exception from relayout", ex); } if (DEBUG) Log.v( TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y + " w=" + mLayout.width + " h=" + mLayout.height + ", frame=" + mSurfaceFrame); + } else if (positionChanged) { // Only the position has changed + mLeft = mLocation[0]; + mTop = mLocation[1]; + try { + mSession.repositionChild(mWindow, mLeft, mTop, + viewRoot != null ? viewRoot.getNextFrameNumber() : -1, + mWinFrame); + } catch (RemoteException ex) { + Log.e(TAG, "Exception from relayout", ex); + } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 14e7d6c4e81e..e6a845c2c6b1 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -6555,6 +6555,20 @@ public final class ViewRootImpl implements ViewParent, } } + long getNextFrameNumber() { + long frameNumber = -1; + if (mSurfaceHolder != null) { + mSurfaceHolder.mSurfaceLock.lock(); + } + if (mSurface.isValid()) { + frameNumber = mSurface.getNextFrameNumber(); + } + if (mSurfaceHolder != null) { + mSurfaceHolder.mSurfaceLock.unlock(); + } + return frameNumber; + } + class TakenSurfaceHolder extends BaseSurfaceHolder { @Override public boolean onAllowLockCanvas() { diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 24055e76234e..b4e52f4281ad 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -461,6 +461,10 @@ static jint nativeGetHeight(JNIEnv* env, jclass clazz, jlong nativeObject) { anw->query(anw, NATIVE_WINDOW_HEIGHT, &value); return value; } +static jlong nativeGetNextFrameNumber(JNIEnv *env, jclass clazz, jlong nativeObject) { + Surface* surface = reinterpret_cast<Surface*>(nativeObject); + return surface->getNextFrameNumber(); +} namespace uirenderer { @@ -537,6 +541,7 @@ static const JNINativeMethod gSurfaceMethods[] = { (void*)nativeWriteToParcel }, {"nativeGetWidth", "(J)I", (void*)nativeGetWidth }, {"nativeGetHeight", "(J)I", (void*)nativeGetHeight }, + {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber }, // HWUI context {"nHwuiCreate", "(JJ)J", (void*) hwui::create }, diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 65ebb6633a8f..43a6b78ffdde 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -570,6 +570,21 @@ static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject return JNI_TRUE; } + +static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeObject, + jobject handleObject, jlong frameNumber) { + auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + sp<IBinder> handle = ibinderForJavaObject(env, handleObject); + + ctrl->deferTransactionUntil(handle, frameNumber); +} + +static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) { + auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + + return javaObjectForIBinder(env, ctrl->getHandle()); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod sSurfaceControlMethods[] = { @@ -637,6 +652,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeGetAnimationFrameStats }, {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V", (void*)nativeSetDisplayPowerMode }, + {"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V", + (void*)nativeDeferTransactionUntil }, + {"nativeGetHandle", "(J)Landroid/os/IBinder;", + (void*)nativeGetHandle } }; int register_android_view_SurfaceControl(JNIEnv* env) diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 1f62bc15024e..c47c377f4cb8 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -187,6 +187,12 @@ final class Session extends IWindowSession.Stub mService.removeWindow(this, window); } + @Override + public void repositionChild(IWindow window, int x, int y, long deferTransactionUntilFrame, + Rect outFrame) { + mService.repositionChild(this, window, x, y, deferTransactionUntilFrame, outFrame); + } + public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0170bb965540..72d5f5973e3d 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2460,6 +2460,59 @@ public class WindowManagerService extends IWindowManager.Stub } } + private void repositionChildInner(Session session, IWindow client, + int x, int y, long deferTransactionUntilFrame, Rect outFrame) { + synchronized(mWindowMap) { + WindowState win = windowForClientLocked(session, client, false); + if (win == null) { + return; + } + if (win.mAttachedWindow == null) { + throw new IllegalArgumentException( + "repositionChild called but window is not" + + "attached to a parent win=" + win); + } + + win.mFrame.left = x; + win.mFrame.top = y; + + win.mWinAnimator.computeShownFrameLocked(); + + if (SHOW_TRANSACTIONS) { + Slog.i(TAG, ">>> OPEN TRANSACTION repositionChild"); + } + + SurfaceControl.openTransaction(); + + if (deferTransactionUntilFrame > 0) { + win.mWinAnimator.mSurfaceControl.deferTransactionUntil( + win.mAttachedWindow.mWinAnimator.mSurfaceControl.getHandle(), + deferTransactionUntilFrame); + } + win.mWinAnimator.setSurfaceBoundariesLocked(false); + + SurfaceControl.closeTransaction(); + if (SHOW_TRANSACTIONS) { + Slog.i(TAG, "<<< CLOSE TRANSACTION repositionChild"); + } + + outFrame = win.mCompatFrame; + } + } + + public void repositionChild(Session session, IWindow client, + int x, int y, long deferTransactionUntilFrame, Rect outFrame) { + Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild"); + long origId = Binder.clearCallingIdentity(); + + try { + repositionChildInner(session, client, x, y, deferTransactionUntilFrame, outFrame); + } finally { + Binder.restoreCallingIdentity(origId); + Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); + } + } + public int relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, |