summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java50
-rw-r--r--core/java/android/view/IWindowSession.aidl26
-rw-r--r--core/java/android/view/SurfaceControl.java8
-rw-r--r--core/java/android/view/SurfaceView.java54
-rw-r--r--core/java/android/view/ViewRootImpl.java115
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) {
}