diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/service/wallpaper/WallpaperService.java | 50 | ||||
| -rw-r--r-- | core/java/android/view/IWindowSession.aidl | 26 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 8 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 54 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 115 |
5 files changed, 160 insertions, 93 deletions
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index d645e3f746d7..60dbf84d555c 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -105,7 +105,7 @@ public abstract class WallpaperService extends Service { static final String TAG = "WallpaperService"; static final boolean DEBUG = false; - + private static final int DO_ATTACH = 10; private static final int DO_DETACH = 20; private static final int DO_SET_DESIRED_SIZE = 30; @@ -126,7 +126,7 @@ public abstract class WallpaperService extends Service { private final ArrayList<Engine> mActiveEngines = new ArrayList<Engine>(); - + static final class WallpaperCommand { String action; int x; @@ -145,7 +145,7 @@ public abstract class WallpaperService extends Service { */ public class Engine { IWallpaperEngineWrapper mIWallpaperEngine; - + // Copies from mIWallpaperEngine. HandlerCaller mCaller; IWallpaperConnection mConnection; @@ -155,7 +155,7 @@ public abstract class WallpaperService extends Service { boolean mVisible; boolean mReportedVisible; boolean mDestroyed; - + // Current window state. boolean mCreated; boolean mSurfaceCreated; @@ -258,7 +258,7 @@ public abstract class WallpaperService extends Service { } super.setFixedSize(width, height); } - + public void setKeepScreenOn(boolean screenOn) { throw new UnsupportedOperationException( "Wallpapers do not support keep screen on"); @@ -403,14 +403,14 @@ public abstract class WallpaperService extends Service { mClockFunction = clockFunction; mHandler = handler; } - + /** * Provides access to the surface in which this wallpaper is drawn. */ public SurfaceHolder getSurfaceHolder() { return mSurfaceHolder; } - + /** * Convenience for {@link WallpaperManager#getDesiredMinimumWidth() * WallpaperManager.getDesiredMinimumWidth()}, returning the width @@ -419,7 +419,7 @@ public abstract class WallpaperService extends Service { public int getDesiredMinimumWidth() { return mIWallpaperEngine.mReqWidth; } - + /** * Convenience for {@link WallpaperManager#getDesiredMinimumHeight() * WallpaperManager.getDesiredMinimumHeight()}, returning the height @@ -437,7 +437,7 @@ public abstract class WallpaperService extends Service { public boolean isVisible() { return mReportedVisible; } - + /** * Returns true if this engine is running in preview mode -- that is, * it is being shown to the user before they select it as the actual @@ -456,7 +456,7 @@ public abstract class WallpaperService extends Service { public boolean isInAmbientMode() { return mIsInAmbientMode; } - + /** * Control whether this wallpaper will receive raw touch events * from the window manager as the user interacts with the window @@ -557,7 +557,7 @@ public abstract class WallpaperService extends Service { * {@link WallpaperManager#sendWallpaperCommand}. * The default implementation does nothing, and always returns null * as the result. - * + * * @param action The name of the command to perform. This tells you * what to do and how to interpret the rest of the arguments. * @param x Generic integer parameter. @@ -794,7 +794,7 @@ public abstract class WallpaperService extends Service { } mLayout.format = mFormat; - + mCurWindowFlags = mWindowFlags; mLayout.flags = mWindowFlags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS @@ -1020,7 +1020,7 @@ public abstract class WallpaperService extends Service { mIsCreating = false; mSurfaceCreated = true; if (redrawNeeded) { - mSession.finishDrawing(mWindow); + mSession.finishDrawing(mWindow, null /* postDrawTransaction */); } mIWallpaperEngine.reportShown(); } @@ -1045,7 +1045,7 @@ public abstract class WallpaperService extends Service { mSurfaceHolder.setSizeFromLayout(); mInitializing = true; mSession = WindowManagerGlobal.getWindowSession(); - + mWindow.setSession(mSession); mLayout.packageName = getPackageName(); @@ -1149,7 +1149,7 @@ public abstract class WallpaperService extends Service { } } } - + void doOffsetsChanged(boolean always) { if (mDestroyed) { return; @@ -1187,7 +1187,7 @@ public abstract class WallpaperService extends Service { mOffsetsChanged = true; } } - + if (sync) { try { if (DEBUG) Log.v(TAG, "Reporting offsets change complete"); @@ -1196,7 +1196,7 @@ public abstract class WallpaperService extends Service { } } } - + void doCommand(WallpaperCommand cmd) { Bundle result; if (!mDestroyed) { @@ -1213,7 +1213,7 @@ public abstract class WallpaperService extends Service { } } } - + void reportSurfaceDestroyed() { if (mSurfaceCreated) { mSurfaceCreated = false; @@ -1229,12 +1229,12 @@ public abstract class WallpaperService extends Service { onSurfaceDestroyed(mSurfaceHolder); } } - + void detach() { if (mDestroyed) { return; } - + mDestroyed = true; if (mIWallpaperEngine.mDisplayManager != null) { @@ -1246,9 +1246,9 @@ public abstract class WallpaperService extends Service { if (DEBUG) Log.v(TAG, "onVisibilityChanged(false): " + this); onVisibilityChanged(false); } - + reportSurfaceDestroyed(); - + if (DEBUG) Log.v(TAG, "onDestroy(): " + this); onDestroy(); @@ -1256,18 +1256,18 @@ public abstract class WallpaperService extends Service { try { if (DEBUG) Log.v(TAG, "Removing window and destroying surface " + mSurfaceHolder.getSurface() + " of: " + this); - + if (mInputEventReceiver != null) { mInputEventReceiver.dispose(); mInputEventReceiver = null; } - + mSession.remove(mWindow); } catch (RemoteException e) { } mSurfaceHolder.mSurface.release(); mCreated = false; - + // Dispose the input channel after removing the window so the Window Manager // doesn't interpret the input channel being closed as an abnormal termination. if (mInputChannel != null) { diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index caab00c3863e..37b6f1317fbf 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -2,15 +2,15 @@ ** ** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -31,6 +31,7 @@ import android.view.WindowManager; import android.view.InsetsState; import android.view.Surface; import android.view.SurfaceControl; +import android.view.Transaction; import java.util.List; @@ -57,7 +58,7 @@ interface IWindowSession { * position should be ignored) and surface of the window. The surface * will be invalid if the window is currently hidden, else you can use it * to draw the window's contents. - * + * * @param window The window being modified. * @param seq Ordering sequence number. * @param attrs If non-null, new attributes to apply to the window. @@ -147,8 +148,15 @@ interface IWindowSession { */ 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 - void finishDrawing(IWindow window); + void finishDrawing(IWindow window, in Transaction postDrawTransaction); @UnsupportedAppUsage void setInTouchMode(boolean showFocus); diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index bb169e01bbac..c1633ae507ad 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -2693,6 +2693,14 @@ public final class SurfaceControl implements Parcelable { 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 public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) { if (mNativeObject == 0) { diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 353544779086..4891b43c829e 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -98,7 +98,8 @@ import java.util.concurrent.locks.ReentrantLock; * artifacts may occur on previous versions of the platform when its window is * 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 boolean DEBUG = false; @@ -120,7 +121,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb boolean mDrawFinished = false; final Rect mScreenRect = new Rect(); - SurfaceSession mSurfaceSession; + final SurfaceSession mSurfaceSession = new SurfaceSession(); SurfaceControl mSurfaceControl; // In the case of format changes we switch out the surface in-place @@ -266,11 +267,22 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb 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 protected void onAttachedToWindow() { super.onAttachedToWindow(); getViewRootImpl().addWindowStoppedCallback(this); + getViewRootImpl().addSurfaceChangedCallback(this); mWindowStopped = false; mViewVisibility = getVisibility() == VISIBLE; @@ -356,6 +368,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb // the SurfaceHolder forward, most live wallpapers do it. if (viewRoot != null) { viewRoot.removeWindowStoppedCallback(this); + viewRoot.removeSurfaceChangedCallback(this); } mAttachedToWindow = false; @@ -637,21 +650,34 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); if (creating) { - viewRoot.createBoundsSurface(mSubLayer); - mSurfaceSession = new SurfaceSession(); mDeferredDestroySurfaceControl = mSurfaceControl; 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(); - - mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) - .setName(name) - .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0) - .setBufferSize(mSurfaceWidth, mSurfaceHeight) - .setFormat(mFormat) - .setParent(viewRoot.getSurfaceControl()) - .setFlags(mSurfaceFlags) - .build(); + mSurfaceControl = + new SurfaceControl.Builder(mSurfaceSession) + .setName(name) + .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0) + .setBufferSize(mSurfaceWidth, mSurfaceHeight) + .setFormat(mFormat) + .setParent(viewRoot.getBoundsLayer()) + .setFlags(mSurfaceFlags) + .build(); mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession) .setName("Background for -" + name) .setOpaque(true) @@ -674,7 +700,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb SurfaceControl.openTransaction(); try { - mSurfaceControl.setLayer(mSubLayer); + mSurfaceControl.setRelativeLayer(viewRoot.getSurfaceControl(), mSubLayer); if (mViewVisibility) { mSurfaceControl.show(); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 30bb2bbd3385..16de906b1085 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -68,6 +68,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; @@ -476,17 +477,19 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage public final Surface mSurface = new Surface(); 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 - * are set to the parent's bounds adjusted for surface insets. This surface is created when - * {@link ViewRootImpl#createBoundsSurface(int)} is called. - * By parenting to this bounds surface, child surfaces can ensure they do not draw into the - * surface inset regions set by the parent window. + * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to + * the surface insets. This surface is created only if a client requests it via {@link + * #getBoundsLayer()}. By parenting to this bounds surface, child surfaces can ensure they do + * not draw into the surface inset regions set by the parent window. */ - public final Surface mBoundsSurface = new Surface(); - private SurfaceSession mSurfaceSession; - private SurfaceControl mBoundsSurfaceControl; + private SurfaceControl mBoundsLayer; + private final Transaction mTransaction = new Transaction(); @UnsupportedAppUsage @@ -1576,65 +1579,76 @@ public final class ViewRootImpl implements ViewParent, } } - /** - * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and - * crop bounds set to the parent's bounds adjusted for surface insets. - * - * @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. + /** Register callback to be notified when the ViewRootImpl surface changes. */ + interface SurfaceChangedCallback { + void surfaceChangedCallback(SurfaceControl.Transaction transaction); + } + + private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>(); + void addSurfaceChangedCallback(SurfaceChangedCallback c) { + mSurfaceChangedCallbacks.add(c); + } + + 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); } + } - mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession) + /** + * 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()) .setParent(mSurfaceControl) .build(); - setBoundsSurfaceCrop(); - mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer) - .show(mBoundsSurfaceControl) - .apply(); - mBoundsSurface.copyFrom(mBoundsSurfaceControl); + setBoundsLayerCrop(mTransaction); + mTransaction.show(mBoundsLayer).apply(); + } + return mBoundsLayer; } - private void setBoundsSurfaceCrop() { + private void setBoundsLayerCrop(Transaction t) { // mWinFrame is already adjusted for surface insets. So offset it and use it as // the cropping bounds. mTempBoundsRect.set(mWinFrame); mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left, 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 - * changed or the surface has resized, update the bounds surface. + * Called after window layout to update the bounds surface. If the surface insets have changed + * or the surface has resized, update the bounds surface. */ - private void updateBoundsSurface() { - if (mBoundsSurfaceControl != null && mSurface.isValid()) { - setBoundsSurfaceCrop(); - mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl, + private void updateBoundsLayer() { + if (mBoundsLayer != null) { + setBoundsLayerCrop(mTransaction); + mTransaction.deferTransactionUntilSurface(mBoundsLayer, mSurface, mSurface.getNextFrameNumber()) .apply(); } } private void destroySurface() { + if (mBoundsLayer != null) { + mBoundsLayer.release(); + mBoundsLayer = null; + } mSurface.release(); mSurfaceControl.release(); - - mSurfaceSession = null; - - if (mBoundsSurfaceControl != null) { - mBoundsSurfaceControl.remove(); - mBoundsSurface.release(); - mBoundsSurfaceControl = null; - } } /** @@ -2598,7 +2612,7 @@ public final class ViewRootImpl implements ViewParent, } if (surfaceSizeChanged) { - updateBoundsSurface(); + updateBoundsLayer(); } final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); @@ -3438,7 +3452,9 @@ public final class ViewRootImpl implements ViewParent, private void reportDrawFinished() { try { mDrawsNeededToReport = 0; - mWindowSession.finishDrawing(mWindow); + if (mSurfaceControl.isValid()) { + mWindowSession.finishDrawing(mWindow, mChangeSurfaceTransaction); + } } catch (RemoteException e) { // Have fun! } @@ -7089,6 +7105,9 @@ public final class ViewRootImpl implements ViewParent, frameNumber = mSurface.getNextFrameNumber(); } + mPreviousSurfaceControlHandle = mSurfaceControl.isValid() + ? mSurfaceControl.getHandle() : null; + int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, @@ -7102,6 +7121,11 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); } + if (mPreviousSurfaceControlHandle != null && mSurfaceControl.isValid() + && mPreviousSurfaceControlHandle != mSurfaceControl.getHandle()) { + notifySurfaceChanged(mChangeSurfaceTransaction); + } + mPendingAlwaysConsumeSystemBars = (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0; @@ -7326,7 +7350,8 @@ public final class ViewRootImpl implements ViewParent, try { if ((relayoutWindow(mWindowAttributes, viewVisibility, false) & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { - mWindowSession.finishDrawing(mWindow); + mWindowSession.finishDrawing( + mWindow, null /* postDrawTransaction */); } } catch (RemoteException e) { } |
