diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/IWallpaperManager.aidl | 6 | ||||
-rw-r--r-- | core/java/android/app/WallpaperManager.java | 43 | ||||
-rw-r--r-- | core/java/android/service/wallpaper/IWallpaperEngine.aidl | 2 | ||||
-rw-r--r-- | core/java/android/service/wallpaper/IWallpaperService.aidl | 3 | ||||
-rw-r--r-- | core/java/android/service/wallpaper/WallpaperService.java | 172 | ||||
-rw-r--r-- | core/java/android/view/IWindowSession.aidl | 5 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 2 | ||||
-rw-r--r-- | core/java/android/view/WindowInsets.java | 54 |
8 files changed, 257 insertions, 30 deletions
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 181eb63..3b5900b 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -16,6 +16,7 @@ package android.app; +import android.graphics.Rect; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.app.IWallpaperManagerCallback; @@ -73,6 +74,11 @@ interface IWallpaperManager { int getHeightHint(); /** + * Sets extra padding that we would like the wallpaper to have outside of the display. + */ + void setDisplayPadding(in Rect padding); + + /** * Returns the name of the wallpaper. Private API. */ String getName(); diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 48ff5b6..8bfe6d3 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -16,6 +16,7 @@ package android.app; +import android.annotation.SystemApi; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -951,6 +952,48 @@ public class WallpaperManager { } /** + * Specify extra padding that the wallpaper should have outside of the display. + * That is, the given padding supplies additional pixels the wallpaper should extend + * outside of the display itself. + * @param padding The number of pixels the wallpaper should extend beyond the display, + * on its left, top, right, and bottom sides. + * @hide + */ + @SystemApi + public void setDisplayPadding(Rect padding) { + try { + if (sGlobals.mService == null) { + Log.w(TAG, "WallpaperService not running"); + } else { + sGlobals.mService.setDisplayPadding(padding); + } + } catch (RemoteException e) { + // Ignore + } + } + + /** + * Apply a raw offset to the wallpaper window. Should only be used in + * combination with {@link #setDisplayPadding(android.graphics.Rect)} when you + * have ensured that the wallpaper will extend outside of the display area so that + * it can be moved without leaving part of the display uncovered. + * @param x The offset, in pixels, to apply to the left edge. + * @param y The offset, in pixels, to apply to the top edge. + * @hide + */ + @SystemApi + public void setDisplayOffset(IBinder windowToken, int x, int y) { + try { + //Log.v(TAG, "Sending new wallpaper display offsets from app..."); + WindowManagerGlobal.getWindowSession().setWallpaperDisplayOffset( + windowToken, x, y); + //Log.v(TAG, "...app returning after sending display offset!"); + } catch (RemoteException e) { + // Ignore. + } + } + + /** * Set the position of the current wallpaper within any larger space, when * that wallpaper is visible behind the given window. The X and Y offsets * are floating point numbers ranging from 0 to 1, representing where the diff --git a/core/java/android/service/wallpaper/IWallpaperEngine.aidl b/core/java/android/service/wallpaper/IWallpaperEngine.aidl index faccde2..de527e9 100644 --- a/core/java/android/service/wallpaper/IWallpaperEngine.aidl +++ b/core/java/android/service/wallpaper/IWallpaperEngine.aidl @@ -16,6 +16,7 @@ package android.service.wallpaper; +import android.graphics.Rect; import android.view.MotionEvent; import android.os.Bundle; @@ -24,6 +25,7 @@ import android.os.Bundle; */ oneway interface IWallpaperEngine { void setDesiredSize(int width, int height); + void setDisplayPadding(in Rect padding); void setVisibility(boolean visible); void dispatchPointer(in MotionEvent event); void dispatchWallpaperCommand(String action, int x, int y, diff --git a/core/java/android/service/wallpaper/IWallpaperService.aidl b/core/java/android/service/wallpaper/IWallpaperService.aidl index bc7a1d7..5fd0157 100644 --- a/core/java/android/service/wallpaper/IWallpaperService.aidl +++ b/core/java/android/service/wallpaper/IWallpaperService.aidl @@ -16,6 +16,7 @@ package android.service.wallpaper; +import android.graphics.Rect; import android.service.wallpaper.IWallpaperConnection; /** @@ -24,5 +25,5 @@ import android.service.wallpaper.IWallpaperConnection; oneway interface IWallpaperService { void attach(IWallpaperConnection connection, IBinder windowToken, int windowType, boolean isPreview, - int reqWidth, int reqHeight); + int reqWidth, int reqHeight, in Rect padding); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index f3c26c8..26e9a30 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -16,6 +16,14 @@ package android.service.wallpaper; +import android.content.res.TypedArray; +import android.os.Build; +import android.os.SystemProperties; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.ViewRootImpl; +import android.view.WindowInsets; +import com.android.internal.R; import com.android.internal.os.HandlerCaller; import com.android.internal.view.BaseIWindow; import com.android.internal.view.BaseSurfaceHolder; @@ -56,6 +64,8 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; + /** * A wallpaper service is responsible for showing a live wallpaper behind * applications that would like to sit on top of it. This service object @@ -90,7 +100,8 @@ public abstract class WallpaperService extends Service { private static final int DO_ATTACH = 10; private static final int DO_DETACH = 20; private static final int DO_SET_DESIRED_SIZE = 30; - + private static final int DO_SET_DISPLAY_PADDING = 40; + private static final int MSG_UPDATE_SURFACE = 10000; private static final int MSG_VISIBILITY_CHANGED = 10010; private static final int MSG_WALLPAPER_OFFSETS = 10020; @@ -150,13 +161,23 @@ public abstract class WallpaperService extends Service { WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS; int mCurWindowFlags = mWindowFlags; int mCurWindowPrivateFlags = mWindowPrivateFlags; + TypedValue mOutsetBottom; final Rect mVisibleInsets = new Rect(); final Rect mWinFrame = new Rect(); final Rect mOverscanInsets = new Rect(); final Rect mContentInsets = new Rect(); final Rect mStableInsets = new Rect(); + final Rect mDispatchedOverscanInsets = new Rect(); + final Rect mDispatchedContentInsets = new Rect(); + final Rect mDispatchedStableInsets = new Rect(); + final Rect mFinalSystemInsets = new Rect(); + final Rect mFinalStableInsets = new Rect(); final Configuration mConfiguration = new Configuration(); - + + private boolean mIsEmulator; + private boolean mIsCircularEmulator; + private boolean mWindowIsRound; + final WindowManager.LayoutParams mLayout = new WindowManager.LayoutParams(); IWindowSession mSession; @@ -406,7 +427,7 @@ public abstract class WallpaperService extends Service { */ public void onCreate(SurfaceHolder surfaceHolder) { } - + /** * Called right before the engine is going away. After this the * surface will be destroyed and this Engine object is no longer @@ -414,7 +435,7 @@ public abstract class WallpaperService extends Service { */ public void onDestroy() { } - + /** * Called to inform you of the wallpaper becoming visible or * hidden. <em>It is very important that a wallpaper only use @@ -422,7 +443,17 @@ public abstract class WallpaperService extends Service { */ public void onVisibilityChanged(boolean visible) { } - + + /** + * Called with the current insets that are in effect for the wallpaper. + * This gives you the part of the overall wallpaper surface that will + * generally be visible to the user (ignoring position offsets applied to it). + * + * @param insets Insets to apply. + */ + public void onApplyWindowInsets(WindowInsets insets) { + } + /** * Called as the user performs touch-screen interaction with the * window that is currently showing this wallpaper. Note that the @@ -432,7 +463,7 @@ public abstract class WallpaperService extends Service { */ public void onTouchEvent(MotionEvent event) { } - + /** * Called to inform you of the wallpaper's offsets changing * within its contain, corresponding to the container's @@ -443,7 +474,7 @@ public abstract class WallpaperService extends Service { float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { } - + /** * Process a command that was sent to the wallpaper with * {@link WallpaperManager#sendWallpaperCommand}. @@ -465,14 +496,14 @@ public abstract class WallpaperService extends Service { Bundle extras, boolean resultRequested) { return null; } - + /** * Called when an application has changed the desired virtual size of * the wallpaper. */ public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) { } - + /** * Convenience for {@link SurfaceHolder.Callback#surfaceChanged * SurfaceHolder.Callback.surfaceChanged()}. @@ -561,16 +592,20 @@ public abstract class WallpaperService extends Service { if (mDestroyed) { Log.w(TAG, "Ignoring updateSurface: destroyed"); } - + + boolean fixedSize = false; int myWidth = mSurfaceHolder.getRequestedWidth(); if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT; + else fixedSize = true; int myHeight = mSurfaceHolder.getRequestedHeight(); if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT; - + else fixedSize = true; + final boolean creating = !mCreated; final boolean surfaceCreating = !mSurfaceCreated; final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat(); boolean sizeChanged = mWidth != myWidth || mHeight != myHeight; + boolean insetsChanged = !mCreated; final boolean typeChanged = mType != mSurfaceHolder.getRequestedType(); final boolean flagsChanged = mCurWindowFlags != mWindowFlags || mCurWindowPrivateFlags != mWindowPrivateFlags; @@ -607,6 +642,32 @@ public abstract class WallpaperService extends Service { mLayout.token = mWindowToken; if (!mCreated) { + // Retrieve watch round and outset info + final WindowManager windowService = (WindowManager)getSystemService( + Context.WINDOW_SERVICE); + TypedArray windowStyle = obtainStyledAttributes( + com.android.internal.R.styleable.Window); + final Display display = windowService.getDefaultDisplay(); + final boolean shouldUseBottomOutset = + display.getDisplayId() == Display.DEFAULT_DISPLAY; + if (shouldUseBottomOutset && windowStyle.hasValue( + R.styleable.Window_windowOutsetBottom)) { + if (mOutsetBottom == null) mOutsetBottom = new TypedValue(); + windowStyle.getValue(R.styleable.Window_windowOutsetBottom, + mOutsetBottom); + } else { + mOutsetBottom = null; + } + mWindowIsRound = getResources().getBoolean( + com.android.internal.R.bool.config_windowIsRound); + windowStyle.recycle(); + + // detect emulator + mIsEmulator = Build.HARDWARE.contains("goldfish"); + mIsCircularEmulator = SystemProperties.getBoolean( + ViewRootImpl.PROPERTY_EMULATOR_CIRCULAR, false); + + // Add window mLayout.type = mIWallpaperEngine.mWindowType; mLayout.gravity = Gravity.START|Gravity.TOP; mLayout.setTitle(WallpaperService.this.getClass().getName()); @@ -627,6 +688,11 @@ public abstract class WallpaperService extends Service { mSurfaceHolder.mSurfaceLock.lock(); mDrawingAllowed = true; + if (!fixedSize) { + mLayout.surfaceInsets.set(mIWallpaperEngine.mDisplayPadding); + } else { + mLayout.surfaceInsets.set(0, 0, 0, 0); + } final int relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, @@ -636,16 +702,39 @@ public abstract class WallpaperService extends Service { + ", frame=" + mWinFrame); int w = mWinFrame.width(); + int h = mWinFrame.height(); + + if (!fixedSize) { + final Rect padding = mIWallpaperEngine.mDisplayPadding; + w += padding.left + padding.right; + h += padding.top + padding.bottom; + mOverscanInsets.left += padding.left; + mOverscanInsets.top += padding.top; + mOverscanInsets.right += padding.right; + mOverscanInsets.bottom += padding.bottom; + mContentInsets.left += padding.left; + mContentInsets.top += padding.top; + mContentInsets.right += padding.right; + mContentInsets.bottom += padding.bottom; + mStableInsets.left += padding.left; + mStableInsets.top += padding.top; + mStableInsets.right += padding.right; + mStableInsets.bottom += padding.bottom; + } + if (mCurWidth != w) { sizeChanged = true; mCurWidth = w; } - int h = mWinFrame.height(); if (mCurHeight != h) { sizeChanged = true; mCurHeight = h; } + insetsChanged |= !mDispatchedOverscanInsets.equals(mOverscanInsets); + insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets); + insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets); + mSurfaceHolder.setSurfaceFrameSize(w, h); mSurfaceHolder.mSurfaceLock.unlock(); @@ -702,6 +791,25 @@ public abstract class WallpaperService extends Service { } } + if (insetsChanged) { + mDispatchedOverscanInsets.set(mOverscanInsets); + mDispatchedContentInsets.set(mContentInsets); + mDispatchedStableInsets.set(mStableInsets); + final boolean isRound = (mIsEmulator && mIsCircularEmulator) + || mWindowIsRound; + mFinalSystemInsets.set(mDispatchedOverscanInsets); + mFinalStableInsets.set(mDispatchedStableInsets); + if (mOutsetBottom != null) { + final DisplayMetrics metrics = getResources().getDisplayMetrics(); + mFinalSystemInsets.bottom = + ( (int) mOutsetBottom.getDimension(metrics) ) + + mIWallpaperEngine.mDisplayPadding.bottom; + } + WindowInsets insets = new WindowInsets(mFinalSystemInsets, + null, mFinalStableInsets, isRound); + onApplyWindowInsets(insets); + } + if (redrawNeeded) { onSurfaceRedrawNeeded(mSurfaceHolder); SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks(); @@ -781,7 +889,7 @@ public abstract class WallpaperService extends Service { mReportedVisible = false; updateSurface(false, false, false); } - + void doDesiredSizeChanged(int desiredWidth, int desiredHeight) { if (!mDestroyed) { if (DEBUG) Log.v(TAG, "onDesiredSizeChanged(" @@ -792,14 +900,24 @@ public abstract class WallpaperService extends Service { doOffsetsChanged(true); } } - + + void doDisplayPaddingChanged(Rect padding) { + if (!mDestroyed) { + if (DEBUG) Log.v(TAG, "onDisplayPaddingChanged(" + padding + "): " + this); + if (!mIWallpaperEngine.mDisplayPadding.equals(padding)) { + mIWallpaperEngine.mDisplayPadding.set(padding); + updateSurface(true, false, false); + } + } + } + void doVisibilityChanged(boolean visible) { if (!mDestroyed) { mVisible = visible; reportVisibility(); } } - + void reportVisibility() { if (!mDestroyed) { boolean visible = mVisible && mScreenOn; @@ -956,12 +1074,13 @@ public abstract class WallpaperService extends Service { boolean mShownReported; int mReqWidth; int mReqHeight; - + final Rect mDisplayPadding = new Rect(); + Engine mEngine; - + IWallpaperEngineWrapper(WallpaperService context, IWallpaperConnection conn, IBinder windowToken, - int windowType, boolean isPreview, int reqWidth, int reqHeight) { + int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding) { mCaller = new HandlerCaller(context, context.getMainLooper(), this, true); mConnection = conn; mWindowToken = windowToken; @@ -969,16 +1088,22 @@ public abstract class WallpaperService extends Service { mIsPreview = isPreview; mReqWidth = reqWidth; mReqHeight = reqHeight; + mDisplayPadding.set(padding); Message msg = mCaller.obtainMessage(DO_ATTACH); mCaller.sendMessage(msg); } - + public void setDesiredSize(int width, int height) { Message msg = mCaller.obtainMessageII(DO_SET_DESIRED_SIZE, width, height); mCaller.sendMessage(msg); } - + + public void setDisplayPadding(Rect padding) { + Message msg = mCaller.obtainMessageO(DO_SET_DISPLAY_PADDING, padding); + mCaller.sendMessage(msg); + } + public void setVisibility(boolean visible) { Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED, visible ? 1 : 0); @@ -1041,6 +1166,9 @@ public abstract class WallpaperService extends Service { mEngine.doDesiredSizeChanged(message.arg1, message.arg2); return; } + case DO_SET_DISPLAY_PADDING: { + mEngine.doDisplayPaddingChanged((Rect) message.obj); + } case MSG_UPDATE_SURFACE: mEngine.updateSurface(true, false, false); break; @@ -1102,9 +1230,9 @@ public abstract class WallpaperService extends Service { @Override public void attach(IWallpaperConnection conn, IBinder windowToken, - int windowType, boolean isPreview, int reqWidth, int reqHeight) { + int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding) { new IWallpaperEngineWrapper(mTarget, conn, windowToken, - windowType, isPreview, reqWidth, reqHeight); + windowType, isPreview, reqWidth, reqHeight, padding); } } diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 0f3f182..037ed28 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -177,6 +177,11 @@ interface IWindowSession { void wallpaperOffsetsComplete(IBinder window); + /** + * Apply a raw offset to the wallpaper service when shown behind this window. + */ + void setWallpaperDisplayOffset(IBinder windowToken, int x, int y); + Bundle sendWallpaperCommand(IBinder window, String action, int x, int y, int z, in Bundle extras, boolean sync); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 80b9ade..43ab4ef 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -121,7 +121,7 @@ public final class ViewRootImpl implements ViewParent, private static final String PROPERTY_MEDIA_DISABLED = "config.disable_media"; // property used by emulator to determine display shape - private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; + public static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; /** * Maximum time we allow the user to roll the trackball enough to generate diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 571a8f0..24c3c1a 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -378,35 +378,75 @@ public final class WindowInsets { } /** - * @hide + * Returns the top stable inset in pixels. + * + * <p>The stable inset represents the area of a full-screen window that <b>may</b> be + * partially or fully obscured by the system UI elements. This value does not change + * based on the visibility state of those elements; for example, if the status bar is + * normally shown, but temporarily hidden, the stable inset will still provide the inset + * associated with the status bar being shown.</p> + * + * @return The top stable inset */ public int getStableInsetTop() { return mStableInsets.top; } /** - * @hide + * Returns the left stable inset in pixels. + * + * <p>The stable inset represents the area of a full-screen window that <b>may</b> be + * partially or fully obscured by the system UI elements. This value does not change + * based on the visibility state of those elements; for example, if the status bar is + * normally shown, but temporarily hidden, the stable inset will still provide the inset + * associated with the status bar being shown.</p> + * + * @return The left stable inset */ public int getStableInsetLeft() { return mStableInsets.left; } /** - * @hide + * Returns the right stable inset in pixels. + * + * <p>The stable inset represents the area of a full-screen window that <b>may</b> be + * partially or fully obscured by the system UI elements. This value does not change + * based on the visibility state of those elements; for example, if the status bar is + * normally shown, but temporarily hidden, the stable inset will still provide the inset + * associated with the status bar being shown.</p> + * + * @return The right stable inset */ public int getStableInsetRight() { return mStableInsets.right; } /** - * @hide + * Returns the bottom stable inset in pixels. + * + * <p>The stable inset represents the area of a full-screen window that <b>may</b> be + * partially or fully obscured by the system UI elements. This value does not change + * based on the visibility state of those elements; for example, if the status bar is + * normally shown, but temporarily hidden, the stable inset will still provide the inset + * associated with the status bar being shown.</p> + * + * @return The bottom stable inset */ public int getStableInsetBottom() { return mStableInsets.bottom; } /** - * @hide + * Returns true if this WindowInsets has nonzero stable insets. + * + * <p>The stable inset represents the area of a full-screen window that <b>may</b> be + * partially or fully obscured by the system UI elements. This value does not change + * based on the visibility state of those elements; for example, if the status bar is + * normally shown, but temporarily hidden, the stable inset will still provide the inset + * associated with the status bar being shown.</p> + * + * @return true if any of the stable inset values are nonzero */ public boolean hasStableInsets() { return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0 @@ -414,7 +454,9 @@ public final class WindowInsets { } /** - * @hide + * Returns a copy of this WindowInsets with the stable insets fully consumed. + * + * @return A modified copy of this WindowInsets */ public WindowInsets consumeStableInsets() { final WindowInsets result = new WindowInsets(this); |