Loading core/java/android/service/wallpaper/WallpaperService.java +25 −25 Original line number Original line Diff line number Diff line Loading @@ -1020,7 +1020,7 @@ public abstract class WallpaperService extends Service { mIsCreating = false; mIsCreating = false; mSurfaceCreated = true; mSurfaceCreated = true; if (redrawNeeded) { if (redrawNeeded) { mSession.finishDrawing(mWindow); mSession.finishDrawing(mWindow, null /* postDrawTransaction */); } } mIWallpaperEngine.reportShown(); mIWallpaperEngine.reportShown(); } } Loading core/java/android/view/IWindowSession.aidl +17 −9 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.view.WindowManager; import android.view.InsetsState; import android.view.InsetsState; import android.view.Surface; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl; import android.view.Transaction; import java.util.List; import java.util.List; Loading Loading @@ -147,8 +148,15 @@ interface IWindowSession { */ */ void getDisplayFrame(IWindow window, out Rect outDisplayFrame); void getDisplayFrame(IWindow window, out Rect outDisplayFrame); /** * Called when the client has finished drawing the surface, if needed. * * @param postDrawTransaction transaction filled by the client that can be * used to synchronize any post draw transactions with the server. Transaction * is null if there is no sync required. */ @UnsupportedAppUsage @UnsupportedAppUsage void finishDrawing(IWindow window); void finishDrawing(IWindow window, in Transaction postDrawTransaction); @UnsupportedAppUsage @UnsupportedAppUsage void setInTouchMode(boolean showFocus); void setInTouchMode(boolean showFocus); Loading core/java/android/view/SurfaceControl.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -2693,6 +2693,14 @@ public final class SurfaceControl implements Parcelable { return this; return this; } } /** * Writes the transaction to parcel, clearing the transaction as if it had been applied so * it can be used to store future transactions. It's the responsibility of the parcel * reader to apply the original transaction. * * @param dest parcel to write the transaction to * @param flags */ @Override @Override public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) { public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) { if (mNativeObject == 0) { if (mNativeObject == 0) { Loading core/java/android/view/SurfaceView.java +40 −14 Original line number Original line Diff line number Diff line Loading @@ -98,7 +98,8 @@ import java.util.concurrent.locks.ReentrantLock; * artifacts may occur on previous versions of the platform when its window is * artifacts may occur on previous versions of the platform when its window is * positioned asynchronously.</p> * positioned asynchronously.</p> */ */ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback { public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback, ViewRootImpl.SurfaceChangedCallback { private static final String TAG = "SurfaceView"; private static final String TAG = "SurfaceView"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; Loading @@ -120,7 +121,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb boolean mDrawFinished = false; boolean mDrawFinished = false; final Rect mScreenRect = new Rect(); final Rect mScreenRect = new Rect(); SurfaceSession mSurfaceSession; final SurfaceSession mSurfaceSession = new SurfaceSession(); SurfaceControl mSurfaceControl; SurfaceControl mSurfaceControl; // In the case of format changes we switch out the surface in-place // In the case of format changes we switch out the surface in-place Loading Loading @@ -266,11 +267,22 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateSurface(); updateSurface(); } } /** @hide */ @Override public void surfaceChangedCallback(SurfaceControl.Transaction transaction) { if (getViewRootImpl() != null && mBackgroundControl != null && mSurfaceControl != null) { SurfaceControl sc = getViewRootImpl().getSurfaceControl(); transaction.setRelativeLayer(mBackgroundControl, sc, Integer.MIN_VALUE); transaction.setRelativeLayer(mSurfaceControl, sc, mSubLayer); } } @Override @Override protected void onAttachedToWindow() { protected void onAttachedToWindow() { super.onAttachedToWindow(); super.onAttachedToWindow(); getViewRootImpl().addWindowStoppedCallback(this); getViewRootImpl().addWindowStoppedCallback(this); getViewRootImpl().addSurfaceChangedCallback(this); mWindowStopped = false; mWindowStopped = false; mViewVisibility = getVisibility() == VISIBLE; mViewVisibility = getVisibility() == VISIBLE; Loading Loading @@ -356,6 +368,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb // the SurfaceHolder forward, most live wallpapers do it. // the SurfaceHolder forward, most live wallpapers do it. if (viewRoot != null) { if (viewRoot != null) { viewRoot.removeWindowStoppedCallback(this); viewRoot.removeWindowStoppedCallback(this); viewRoot.removeSurfaceChangedCallback(this); } } mAttachedToWindow = false; mAttachedToWindow = false; Loading Loading @@ -637,19 +650,32 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); if (creating) { if (creating) { viewRoot.createBoundsSurface(mSubLayer); mSurfaceSession = new SurfaceSession(); mDeferredDestroySurfaceControl = mSurfaceControl; mDeferredDestroySurfaceControl = mSurfaceControl; updateOpaqueFlag(); updateOpaqueFlag(); // SurfaceView hierarchy // ViewRootImpl surface // - bounds layer (crops all child surfaces to parent surface insets) // - SurfaceView surface (drawn relative to ViewRootImpl surface) // - Background color layer (drawn behind all SurfaceView surfaces) // // The bounds layer is used to crop the surface view so it does not draw into // the parent surface inset region. Since there can be multiple surface views // below or above the parent surface, one option is to create multiple bounds // layer for each z order. The other option, the one implement is to create // a single bounds layer and set z order for each child surface relative to the // parent surface. // When creating the surface view, we parent it to the bounds layer and then // set the relative z order. When the parent surface changes, we have to // make sure to update the relative z via ViewRootImpl.SurfaceChangedCallback. final String name = "SurfaceView - " + viewRoot.getTitle().toString(); final String name = "SurfaceView - " + viewRoot.getTitle().toString(); mSurfaceControl = mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) new SurfaceControl.Builder(mSurfaceSession) .setName(name) .setName(name) .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0) .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0) .setBufferSize(mSurfaceWidth, mSurfaceHeight) .setBufferSize(mSurfaceWidth, mSurfaceHeight) .setFormat(mFormat) .setFormat(mFormat) .setParent(viewRoot.getSurfaceControl()) .setParent(viewRoot.getBoundsLayer()) .setFlags(mSurfaceFlags) .setFlags(mSurfaceFlags) .build(); .build(); mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession) mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession) Loading @@ -674,7 +700,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb SurfaceControl.openTransaction(); SurfaceControl.openTransaction(); try { try { mSurfaceControl.setLayer(mSubLayer); mSurfaceControl.setRelativeLayer(viewRoot.getSurfaceControl(), mSubLayer); if (mViewVisibility) { if (mViewVisibility) { mSurfaceControl.show(); mSurfaceControl.show(); Loading core/java/android/view/ViewRootImpl.java +70 −45 Original line number Original line Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Bundle; import android.os.Debug; import android.os.Debug; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; Loading Loading @@ -476,17 +477,19 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage @UnsupportedAppUsage public final Surface mSurface = new Surface(); public final Surface mSurface = new Surface(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); private IBinder mPreviousSurfaceControlHandle = null; private final Transaction mChangeSurfaceTransaction = new Transaction(); private final SurfaceSession mSurfaceSession = new SurfaceSession(); /** /** * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to * are set to the parent's bounds adjusted for surface insets. This surface is created when * the surface insets. This surface is created only if a client requests it via {@link * {@link ViewRootImpl#createBoundsSurface(int)} is called. * #getBoundsLayer()}. By parenting to this bounds surface, child surfaces can ensure they do * By parenting to this bounds surface, child surfaces can ensure they do not draw into the * not draw into the surface inset regions set by the parent window. * surface inset regions set by the parent window. */ */ public final Surface mBoundsSurface = new Surface(); private SurfaceControl mBoundsLayer; private SurfaceSession mSurfaceSession; private SurfaceControl mBoundsSurfaceControl; private final Transaction mTransaction = new Transaction(); private final Transaction mTransaction = new Transaction(); @UnsupportedAppUsage @UnsupportedAppUsage Loading Loading @@ -1576,65 +1579,76 @@ public final class ViewRootImpl implements ViewParent, } } } } /** /** Register callback to be notified when the ViewRootImpl surface changes. */ * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and interface SurfaceChangedCallback { * crop bounds set to the parent's bounds adjusted for surface insets. void surfaceChangedCallback(SurfaceControl.Transaction transaction); * * @param zOrderLayer Z order relative to the parent surface. */ public void createBoundsSurface(int zOrderLayer) { if (mSurfaceSession == null) { mSurfaceSession = new SurfaceSession(); } } if (mBoundsSurfaceControl != null && mBoundsSurface.isValid()) { return; // surface control for bounds surface already exists. private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>(); void addSurfaceChangedCallback(SurfaceChangedCallback c) { mSurfaceChangedCallbacks.add(c); } } mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) void removeSurfaceChangedCallback(SurfaceChangedCallback c) { mSurfaceChangedCallbacks.remove(c); } private void notifySurfaceChanged(SurfaceControl.Transaction transaction) { for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) { mSurfaceChangedCallbacks.get(i).surfaceChangedCallback(transaction); } } /** * Returns a child layer with the same bounds as its parent {@code mSurface} and cropped to the * surface insets. If the layer does not exist, it is created. * * <p>Parenting to this layer will ensure that its children are cropped by the view's surface * insets. */ public SurfaceControl getBoundsLayer() { if (mBoundsLayer == null) { mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession) .setContainerLayer() .setName("Bounds for - " + getTitle().toString()) .setName("Bounds for - " + getTitle().toString()) .setParent(mSurfaceControl) .setParent(mSurfaceControl) .build(); .build(); setBoundsSurfaceCrop(); setBoundsLayerCrop(mTransaction); mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer) mTransaction.show(mBoundsLayer).apply(); .show(mBoundsSurfaceControl) } .apply(); return mBoundsLayer; mBoundsSurface.copyFrom(mBoundsSurfaceControl); } } private void setBoundsSurfaceCrop() { private void setBoundsLayerCrop(Transaction t) { // mWinFrame is already adjusted for surface insets. So offset it and use it as // mWinFrame is already adjusted for surface insets. So offset it and use it as // the cropping bounds. // the cropping bounds. mTempBoundsRect.set(mWinFrame); mTempBoundsRect.set(mWinFrame); mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left, mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left, mWindowAttributes.surfaceInsets.top); mWindowAttributes.surfaceInsets.top); mTransaction.setWindowCrop(mBoundsSurfaceControl, mTempBoundsRect); t.setWindowCrop(mBoundsLayer, mTempBoundsRect); } } /** /** * Called after window layout to update the bounds surface. If the surface insets have * Called after window layout to update the bounds surface. If the surface insets have changed * changed or the surface has resized, update the bounds surface. * or the surface has resized, update the bounds surface. */ */ private void updateBoundsSurface() { private void updateBoundsLayer() { if (mBoundsSurfaceControl != null && mSurface.isValid()) { if (mBoundsLayer != null) { setBoundsSurfaceCrop(); setBoundsLayerCrop(mTransaction); mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl, mTransaction.deferTransactionUntilSurface(mBoundsLayer, mSurface, mSurface.getNextFrameNumber()) mSurface, mSurface.getNextFrameNumber()) .apply(); .apply(); } } } } private void destroySurface() { private void destroySurface() { if (mBoundsLayer != null) { mBoundsLayer.release(); mBoundsLayer = null; } mSurface.release(); mSurface.release(); mSurfaceControl.release(); mSurfaceControl.release(); mSurfaceSession = null; if (mBoundsSurfaceControl != null) { mBoundsSurfaceControl.remove(); mBoundsSurface.release(); mBoundsSurfaceControl = null; } } } /** /** Loading Loading @@ -2598,7 +2612,7 @@ public final class ViewRootImpl implements ViewParent, } } if (surfaceSizeChanged) { if (surfaceSizeChanged) { updateBoundsSurface(); updateBoundsLayer(); } } final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); Loading Loading @@ -3438,7 +3452,9 @@ public final class ViewRootImpl implements ViewParent, private void reportDrawFinished() { private void reportDrawFinished() { try { try { mDrawsNeededToReport = 0; mDrawsNeededToReport = 0; mWindowSession.finishDrawing(mWindow); if (mSurfaceControl.isValid()) { mWindowSession.finishDrawing(mWindow, mChangeSurfaceTransaction); } } catch (RemoteException e) { } catch (RemoteException e) { // Have fun! // Have fun! } } Loading Loading @@ -7089,6 +7105,9 @@ public final class ViewRootImpl implements ViewParent, frameNumber = mSurface.getNextFrameNumber(); frameNumber = mSurface.getNextFrameNumber(); } } mPreviousSurfaceControlHandle = mSurfaceControl.isValid() ? mSurfaceControl.getHandle() : null; int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params, int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, Loading @@ -7102,6 +7121,11 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); destroySurface(); } } if (mPreviousSurfaceControlHandle != null && mSurfaceControl.isValid() && mPreviousSurfaceControlHandle != mSurfaceControl.getHandle()) { notifySurfaceChanged(mChangeSurfaceTransaction); } mPendingAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0; (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0; Loading Loading @@ -7326,7 +7350,8 @@ public final class ViewRootImpl implements ViewParent, try { try { if ((relayoutWindow(mWindowAttributes, viewVisibility, false) if ((relayoutWindow(mWindowAttributes, viewVisibility, false) & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mWindowSession.finishDrawing(mWindow); mWindowSession.finishDrawing( mWindow, null /* postDrawTransaction */); } } } catch (RemoteException e) { } catch (RemoteException e) { } } Loading Loading
core/java/android/service/wallpaper/WallpaperService.java +25 −25 Original line number Original line Diff line number Diff line Loading @@ -1020,7 +1020,7 @@ public abstract class WallpaperService extends Service { mIsCreating = false; mIsCreating = false; mSurfaceCreated = true; mSurfaceCreated = true; if (redrawNeeded) { if (redrawNeeded) { mSession.finishDrawing(mWindow); mSession.finishDrawing(mWindow, null /* postDrawTransaction */); } } mIWallpaperEngine.reportShown(); mIWallpaperEngine.reportShown(); } } Loading
core/java/android/view/IWindowSession.aidl +17 −9 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.view.WindowManager; import android.view.InsetsState; import android.view.InsetsState; import android.view.Surface; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl; import android.view.Transaction; import java.util.List; import java.util.List; Loading Loading @@ -147,8 +148,15 @@ interface IWindowSession { */ */ void getDisplayFrame(IWindow window, out Rect outDisplayFrame); void getDisplayFrame(IWindow window, out Rect outDisplayFrame); /** * Called when the client has finished drawing the surface, if needed. * * @param postDrawTransaction transaction filled by the client that can be * used to synchronize any post draw transactions with the server. Transaction * is null if there is no sync required. */ @UnsupportedAppUsage @UnsupportedAppUsage void finishDrawing(IWindow window); void finishDrawing(IWindow window, in Transaction postDrawTransaction); @UnsupportedAppUsage @UnsupportedAppUsage void setInTouchMode(boolean showFocus); void setInTouchMode(boolean showFocus); Loading
core/java/android/view/SurfaceControl.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -2693,6 +2693,14 @@ public final class SurfaceControl implements Parcelable { return this; return this; } } /** * Writes the transaction to parcel, clearing the transaction as if it had been applied so * it can be used to store future transactions. It's the responsibility of the parcel * reader to apply the original transaction. * * @param dest parcel to write the transaction to * @param flags */ @Override @Override public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) { public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) { if (mNativeObject == 0) { if (mNativeObject == 0) { Loading
core/java/android/view/SurfaceView.java +40 −14 Original line number Original line Diff line number Diff line Loading @@ -98,7 +98,8 @@ import java.util.concurrent.locks.ReentrantLock; * artifacts may occur on previous versions of the platform when its window is * artifacts may occur on previous versions of the platform when its window is * positioned asynchronously.</p> * positioned asynchronously.</p> */ */ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback { public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback, ViewRootImpl.SurfaceChangedCallback { private static final String TAG = "SurfaceView"; private static final String TAG = "SurfaceView"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; Loading @@ -120,7 +121,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb boolean mDrawFinished = false; boolean mDrawFinished = false; final Rect mScreenRect = new Rect(); final Rect mScreenRect = new Rect(); SurfaceSession mSurfaceSession; final SurfaceSession mSurfaceSession = new SurfaceSession(); SurfaceControl mSurfaceControl; SurfaceControl mSurfaceControl; // In the case of format changes we switch out the surface in-place // In the case of format changes we switch out the surface in-place Loading Loading @@ -266,11 +267,22 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateSurface(); updateSurface(); } } /** @hide */ @Override public void surfaceChangedCallback(SurfaceControl.Transaction transaction) { if (getViewRootImpl() != null && mBackgroundControl != null && mSurfaceControl != null) { SurfaceControl sc = getViewRootImpl().getSurfaceControl(); transaction.setRelativeLayer(mBackgroundControl, sc, Integer.MIN_VALUE); transaction.setRelativeLayer(mSurfaceControl, sc, mSubLayer); } } @Override @Override protected void onAttachedToWindow() { protected void onAttachedToWindow() { super.onAttachedToWindow(); super.onAttachedToWindow(); getViewRootImpl().addWindowStoppedCallback(this); getViewRootImpl().addWindowStoppedCallback(this); getViewRootImpl().addSurfaceChangedCallback(this); mWindowStopped = false; mWindowStopped = false; mViewVisibility = getVisibility() == VISIBLE; mViewVisibility = getVisibility() == VISIBLE; Loading Loading @@ -356,6 +368,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb // the SurfaceHolder forward, most live wallpapers do it. // the SurfaceHolder forward, most live wallpapers do it. if (viewRoot != null) { if (viewRoot != null) { viewRoot.removeWindowStoppedCallback(this); viewRoot.removeWindowStoppedCallback(this); viewRoot.removeSurfaceChangedCallback(this); } } mAttachedToWindow = false; mAttachedToWindow = false; Loading Loading @@ -637,19 +650,32 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); if (creating) { if (creating) { viewRoot.createBoundsSurface(mSubLayer); mSurfaceSession = new SurfaceSession(); mDeferredDestroySurfaceControl = mSurfaceControl; mDeferredDestroySurfaceControl = mSurfaceControl; updateOpaqueFlag(); updateOpaqueFlag(); // SurfaceView hierarchy // ViewRootImpl surface // - bounds layer (crops all child surfaces to parent surface insets) // - SurfaceView surface (drawn relative to ViewRootImpl surface) // - Background color layer (drawn behind all SurfaceView surfaces) // // The bounds layer is used to crop the surface view so it does not draw into // the parent surface inset region. Since there can be multiple surface views // below or above the parent surface, one option is to create multiple bounds // layer for each z order. The other option, the one implement is to create // a single bounds layer and set z order for each child surface relative to the // parent surface. // When creating the surface view, we parent it to the bounds layer and then // set the relative z order. When the parent surface changes, we have to // make sure to update the relative z via ViewRootImpl.SurfaceChangedCallback. final String name = "SurfaceView - " + viewRoot.getTitle().toString(); final String name = "SurfaceView - " + viewRoot.getTitle().toString(); mSurfaceControl = mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) new SurfaceControl.Builder(mSurfaceSession) .setName(name) .setName(name) .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0) .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0) .setBufferSize(mSurfaceWidth, mSurfaceHeight) .setBufferSize(mSurfaceWidth, mSurfaceHeight) .setFormat(mFormat) .setFormat(mFormat) .setParent(viewRoot.getSurfaceControl()) .setParent(viewRoot.getBoundsLayer()) .setFlags(mSurfaceFlags) .setFlags(mSurfaceFlags) .build(); .build(); mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession) mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession) Loading @@ -674,7 +700,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb SurfaceControl.openTransaction(); SurfaceControl.openTransaction(); try { try { mSurfaceControl.setLayer(mSubLayer); mSurfaceControl.setRelativeLayer(viewRoot.getSurfaceControl(), mSubLayer); if (mViewVisibility) { if (mViewVisibility) { mSurfaceControl.show(); mSurfaceControl.show(); Loading
core/java/android/view/ViewRootImpl.java +70 −45 Original line number Original line Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Bundle; import android.os.Debug; import android.os.Debug; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; Loading Loading @@ -476,17 +477,19 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage @UnsupportedAppUsage public final Surface mSurface = new Surface(); public final Surface mSurface = new Surface(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); private IBinder mPreviousSurfaceControlHandle = null; private final Transaction mChangeSurfaceTransaction = new Transaction(); private final SurfaceSession mSurfaceSession = new SurfaceSession(); /** /** * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to * are set to the parent's bounds adjusted for surface insets. This surface is created when * the surface insets. This surface is created only if a client requests it via {@link * {@link ViewRootImpl#createBoundsSurface(int)} is called. * #getBoundsLayer()}. By parenting to this bounds surface, child surfaces can ensure they do * By parenting to this bounds surface, child surfaces can ensure they do not draw into the * not draw into the surface inset regions set by the parent window. * surface inset regions set by the parent window. */ */ public final Surface mBoundsSurface = new Surface(); private SurfaceControl mBoundsLayer; private SurfaceSession mSurfaceSession; private SurfaceControl mBoundsSurfaceControl; private final Transaction mTransaction = new Transaction(); private final Transaction mTransaction = new Transaction(); @UnsupportedAppUsage @UnsupportedAppUsage Loading Loading @@ -1576,65 +1579,76 @@ public final class ViewRootImpl implements ViewParent, } } } } /** /** Register callback to be notified when the ViewRootImpl surface changes. */ * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and interface SurfaceChangedCallback { * crop bounds set to the parent's bounds adjusted for surface insets. void surfaceChangedCallback(SurfaceControl.Transaction transaction); * * @param zOrderLayer Z order relative to the parent surface. */ public void createBoundsSurface(int zOrderLayer) { if (mSurfaceSession == null) { mSurfaceSession = new SurfaceSession(); } } if (mBoundsSurfaceControl != null && mBoundsSurface.isValid()) { return; // surface control for bounds surface already exists. private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>(); void addSurfaceChangedCallback(SurfaceChangedCallback c) { mSurfaceChangedCallbacks.add(c); } } mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) void removeSurfaceChangedCallback(SurfaceChangedCallback c) { mSurfaceChangedCallbacks.remove(c); } private void notifySurfaceChanged(SurfaceControl.Transaction transaction) { for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) { mSurfaceChangedCallbacks.get(i).surfaceChangedCallback(transaction); } } /** * Returns a child layer with the same bounds as its parent {@code mSurface} and cropped to the * surface insets. If the layer does not exist, it is created. * * <p>Parenting to this layer will ensure that its children are cropped by the view's surface * insets. */ public SurfaceControl getBoundsLayer() { if (mBoundsLayer == null) { mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession) .setContainerLayer() .setName("Bounds for - " + getTitle().toString()) .setName("Bounds for - " + getTitle().toString()) .setParent(mSurfaceControl) .setParent(mSurfaceControl) .build(); .build(); setBoundsSurfaceCrop(); setBoundsLayerCrop(mTransaction); mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer) mTransaction.show(mBoundsLayer).apply(); .show(mBoundsSurfaceControl) } .apply(); return mBoundsLayer; mBoundsSurface.copyFrom(mBoundsSurfaceControl); } } private void setBoundsSurfaceCrop() { private void setBoundsLayerCrop(Transaction t) { // mWinFrame is already adjusted for surface insets. So offset it and use it as // mWinFrame is already adjusted for surface insets. So offset it and use it as // the cropping bounds. // the cropping bounds. mTempBoundsRect.set(mWinFrame); mTempBoundsRect.set(mWinFrame); mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left, mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left, mWindowAttributes.surfaceInsets.top); mWindowAttributes.surfaceInsets.top); mTransaction.setWindowCrop(mBoundsSurfaceControl, mTempBoundsRect); t.setWindowCrop(mBoundsLayer, mTempBoundsRect); } } /** /** * Called after window layout to update the bounds surface. If the surface insets have * Called after window layout to update the bounds surface. If the surface insets have changed * changed or the surface has resized, update the bounds surface. * or the surface has resized, update the bounds surface. */ */ private void updateBoundsSurface() { private void updateBoundsLayer() { if (mBoundsSurfaceControl != null && mSurface.isValid()) { if (mBoundsLayer != null) { setBoundsSurfaceCrop(); setBoundsLayerCrop(mTransaction); mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl, mTransaction.deferTransactionUntilSurface(mBoundsLayer, mSurface, mSurface.getNextFrameNumber()) mSurface, mSurface.getNextFrameNumber()) .apply(); .apply(); } } } } private void destroySurface() { private void destroySurface() { if (mBoundsLayer != null) { mBoundsLayer.release(); mBoundsLayer = null; } mSurface.release(); mSurface.release(); mSurfaceControl.release(); mSurfaceControl.release(); mSurfaceSession = null; if (mBoundsSurfaceControl != null) { mBoundsSurfaceControl.remove(); mBoundsSurface.release(); mBoundsSurfaceControl = null; } } } /** /** Loading Loading @@ -2598,7 +2612,7 @@ public final class ViewRootImpl implements ViewParent, } } if (surfaceSizeChanged) { if (surfaceSizeChanged) { updateBoundsSurface(); updateBoundsLayer(); } } final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); Loading Loading @@ -3438,7 +3452,9 @@ public final class ViewRootImpl implements ViewParent, private void reportDrawFinished() { private void reportDrawFinished() { try { try { mDrawsNeededToReport = 0; mDrawsNeededToReport = 0; mWindowSession.finishDrawing(mWindow); if (mSurfaceControl.isValid()) { mWindowSession.finishDrawing(mWindow, mChangeSurfaceTransaction); } } catch (RemoteException e) { } catch (RemoteException e) { // Have fun! // Have fun! } } Loading Loading @@ -7089,6 +7105,9 @@ public final class ViewRootImpl implements ViewParent, frameNumber = mSurface.getNextFrameNumber(); frameNumber = mSurface.getNextFrameNumber(); } } mPreviousSurfaceControlHandle = mSurfaceControl.isValid() ? mSurfaceControl.getHandle() : null; int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params, int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, Loading @@ -7102,6 +7121,11 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); destroySurface(); } } if (mPreviousSurfaceControlHandle != null && mSurfaceControl.isValid() && mPreviousSurfaceControlHandle != mSurfaceControl.getHandle()) { notifySurfaceChanged(mChangeSurfaceTransaction); } mPendingAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0; (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0; Loading Loading @@ -7326,7 +7350,8 @@ public final class ViewRootImpl implements ViewParent, try { try { if ((relayoutWindow(mWindowAttributes, viewVisibility, false) if ((relayoutWindow(mWindowAttributes, viewVisibility, false) & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mWindowSession.finishDrawing(mWindow); mWindowSession.finishDrawing( mWindow, null /* postDrawTransaction */); } } } catch (RemoteException e) { } catch (RemoteException e) { } } Loading