diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 2b1558937d217..4d308d90ce2dc 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -258,6 +258,14 @@ interface IWallpaperManager { */ boolean lockScreenWallpaperExists(); + /** + * Return true if there is a static wallpaper on the specified screen. With which=FLAG_LOCK, + * always return false if the lock screen doesn't run its own wallpaper engine. + * + * @hide + */ + boolean isStaticWallpaper(int which); + /** * Temporary method for project b/197814683. * Return true if the lockscreen wallpaper always uses a WallpaperService, not a static image. diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 70c42d8f3b8a9..c0106ab0bc11a 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -658,15 +658,8 @@ public class WallpaperManager { return currentWallpaper; } } - if (returnDefault) { - Bitmap defaultWallpaper = mDefaultWallpaper; - if (defaultWallpaper == null || defaultWallpaper.isRecycled()) { - defaultWallpaper = getDefaultWallpaper(context, which); - synchronized (this) { - mDefaultWallpaper = defaultWallpaper; - } - } - return defaultWallpaper; + if (returnDefault || (which == FLAG_LOCK && isStaticWallpaper(FLAG_LOCK))) { + return getDefaultWallpaper(context, which); } return null; } @@ -705,7 +698,7 @@ public class WallpaperManager { } // If user wallpaper is unavailable, may be the default one instead. if ((dimensions == null || dimensions.width() == 0 || dimensions.height() == 0) - && returnDefault) { + && (returnDefault || (which == FLAG_LOCK && isStaticWallpaper(FLAG_LOCK)))) { InputStream is = openDefaultWallpaper(context, which); if (is != null) { try { @@ -769,18 +762,39 @@ public class WallpaperManager { } private Bitmap getDefaultWallpaper(Context context, @SetWallpaperFlags int which) { - InputStream is = openDefaultWallpaper(context, which); - if (is != null) { - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - return BitmapFactory.decodeStream(is, null, options); - } catch (OutOfMemoryError e) { + Bitmap defaultWallpaper = mDefaultWallpaper; + if (defaultWallpaper == null || defaultWallpaper.isRecycled()) { + defaultWallpaper = null; + try (InputStream is = openDefaultWallpaper(context, which)) { + if (is != null) { + BitmapFactory.Options options = new BitmapFactory.Options(); + defaultWallpaper = BitmapFactory.decodeStream(is, null, options); + } + } catch (OutOfMemoryError | IOException e) { Log.w(TAG, "Can't decode stream", e); - } finally { - IoUtils.closeQuietly(is); } } - return null; + synchronized (this) { + mDefaultWallpaper = defaultWallpaper; + } + return defaultWallpaper; + } + + /** + * Return true if there is a static wallpaper on the specified screen. + * With {@code which=}{@link #FLAG_LOCK}, always return false if the lockscreen doesn't run + * its own wallpaper engine. + */ + private boolean isStaticWallpaper(@SetWallpaperFlags int which) { + if (mService == null) { + Log.w(TAG, "WallpaperService not running"); + throw new RuntimeException(new DeadSystemException()); + } + try { + return mService.isStaticWallpaper(which); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } } @@ -882,21 +896,14 @@ public class WallpaperManager { *
  • Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions.
  • * - *
    * - * Retrieve the current system wallpaper; if - * no wallpaper is set, the system built-in static wallpaper is returned. - * This is returned as an - * abstract Drawable that you can install in a View to display whatever - * wallpaper the user has currently set. *

    - * This method can return null if there is no system wallpaper available, if - * wallpapers are not supported in the current user, or if the calling app is not - * permitted to access the system wallpaper. + * Equivalent to {@link #getDrawable(int)} with {@code which=}{@link #FLAG_SYSTEM}. + *

    * - * @return Returns a Drawable object that will draw the system wallpaper, - * or {@code null} if no system wallpaper exists or if the calling application - * is not able to access the wallpaper. + * @return A Drawable object for the requested wallpaper. + * + * @see #getDrawable(int) * * @throws SecurityException as described in the note */ @@ -919,23 +926,29 @@ public class WallpaperManager { *
  • Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions.
  • * - *
    * - * Retrieve the requested wallpaper; if - * no wallpaper is set, the requested built-in static wallpaper is returned. - * This is returned as an - * abstract Drawable that you can install in a View to display whatever - * wallpaper the user has currently set. *

    - * This method can return null if the requested wallpaper is not available, if - * wallpapers are not supported in the current user, or if the calling app is not - * permitted to access the requested wallpaper. + * Retrieve the requested wallpaper for the specified wallpaper type if the wallpaper is not + * a live wallpaper. This method should not be used to display the user wallpaper on an app: + * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WALLPAPER} should be used instead. + *

    + *

    + * When called with {@code which=}{@link #FLAG_SYSTEM}, + * if there is a live wallpaper on home screen, the built-in default wallpaper is returned. + *

    + *

    + * When called with {@code which=}{@link #FLAG_LOCK}, if there is a live wallpaper + * on lock screen, or if the lock screen and home screen share the same wallpaper engine, + * {@code null} is returned. + *

    + *

    + * {@link #getWallpaperInfo(int)} can be used to determine whether there is a live wallpaper + * on a specified screen type. + *

    * - * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws + * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws * IllegalArgumentException if an invalid wallpaper is requested. - * @return Returns a Drawable object that will draw the requested wallpaper, - * or {@code null} if the requested wallpaper does not exist or if the calling application - * is not able to access the wallpaper. + * @return A Drawable object for the requested wallpaper. * * @throws SecurityException as described in the note */ @@ -943,7 +956,8 @@ public class WallpaperManager { @RequiresPermission(anyOf = {MANAGE_EXTERNAL_STORAGE, READ_WALLPAPER_INTERNAL}) public Drawable getDrawable(@SetWallpaperFlags int which) { final ColorManagementProxy cmProxy = getColorManagementProxy(); - Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, which, cmProxy); + boolean returnDefault = which != FLAG_LOCK; + Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, returnDefault, which, cmProxy); if (bm != null) { Drawable dr = new BitmapDrawable(mContext.getResources(), bm); dr.setDither(false); @@ -1175,15 +1189,14 @@ public class WallpaperManager { *
  • Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions.
  • * - *
    * - * Retrieve the current system wallpaper; if there is no wallpaper set, - * a null pointer is returned. This is returned as an - * abstract Drawable that you can install in a View to display whatever - * wallpaper the user has currently set. + *

    + * Equivalent to {@link #getDrawable()}. + *

    * - * @return Returns a Drawable object that will draw the wallpaper or a - * null pointer if wallpaper is unset. + * @return A Drawable object for the requested wallpaper. + * + * @see #getDrawable() * * @throws SecurityException as described in the note */ @@ -1206,31 +1219,23 @@ public class WallpaperManager { *
  • Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions.
  • * - *
    * - * Retrieve the requested wallpaper; if there is no wallpaper set, - * a null pointer is returned. This is returned as an - * abstract Drawable that you can install in a View to display whatever - * wallpaper the user has currently set. + *

    + * Equivalent to {@link #getDrawable(int)}. + *

    * - * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws + * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws * IllegalArgumentException if an invalid wallpaper is requested. - * @return Returns a Drawable object that will draw the wallpaper or a null pointer if - * wallpaper is unset. + * @return A Drawable object for the requested wallpaper. + * + * @see #getDrawable(int) * * @throws SecurityException as described in the note */ @Nullable @RequiresPermission(anyOf = {MANAGE_EXTERNAL_STORAGE, READ_WALLPAPER_INTERNAL}) public Drawable peekDrawable(@SetWallpaperFlags int which) { - final ColorManagementProxy cmProxy = getColorManagementProxy(); - Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, which, cmProxy); - if (bm != null) { - Drawable dr = new BitmapDrawable(mContext.getResources(), bm); - dr.setDither(false); - return dr; - } - return null; + return getDrawable(which); } /** @@ -1246,19 +1251,14 @@ public class WallpaperManager { *
  • Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions.
  • * - *
    * - * Like {@link #getDrawable()}, but the returned Drawable has a number - * of limitations to reduce its overhead as much as possible. It will - * never scale the wallpaper (only centering it if the requested bounds - * do match the bitmap bounds, which should not be typical), doesn't - * allow setting an alpha, color filter, or other attributes, etc. The - * bounds of the returned drawable will be initialized to the same bounds - * as the wallpaper, so normally you will not need to touch it. The - * drawable also assumes that it will be used in a context running in - * the same density as the screen (not in density compatibility mode). + *

    + * Equivalent to {@link #getFastDrawable(int)} with {@code which=}{@link #FLAG_SYSTEM}. + *

    * - * @return Returns a Drawable object that will draw the wallpaper. + * @return A Drawable object for the requested wallpaper. + * + * @see #getFastDrawable(int) * * @throws SecurityException as described in the note */ @@ -1295,7 +1295,8 @@ public class WallpaperManager { * * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws * IllegalArgumentException if an invalid wallpaper is requested. - * @return Returns a Drawable object that will draw the wallpaper. + * @return An optimized Drawable object for the requested wallpaper, or {@code null} + * in some cases as specified in {@link #getDrawable(int)}. * * @throws SecurityException as described in the note */ @@ -1303,7 +1304,8 @@ public class WallpaperManager { @RequiresPermission(anyOf = {MANAGE_EXTERNAL_STORAGE, READ_WALLPAPER_INTERNAL}) public Drawable getFastDrawable(@SetWallpaperFlags int which) { final ColorManagementProxy cmProxy = getColorManagementProxy(); - Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, which, cmProxy); + boolean returnDefault = which != FLAG_LOCK; + Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, returnDefault, which, cmProxy); if (bm != null) { return new FastBitmapDrawable(bm); } @@ -1323,13 +1325,14 @@ public class WallpaperManager { *
  • Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions.
  • * - *
    * - * Like {@link #getFastDrawable()}, but if there is no wallpaper set, - * a null pointer is returned. + *

    + * Equivalent to {@link #getFastDrawable()}. + *

    * - * @return Returns an optimized Drawable object that will draw the - * wallpaper or a null pointer if these is none. + * @return An optimized Drawable object for the requested wallpaper. + * + * @see #getFastDrawable() * * @throws SecurityException as described in the note */ @@ -1352,31 +1355,29 @@ public class WallpaperManager { *
  • Apps with {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE} * can still access the real wallpaper on all versions.
  • * - *
    * - * Like {@link #getFastDrawable()}, but if there is no wallpaper set, - * a null pointer is returned. + *

    + * Equivalent to {@link #getFastDrawable(int)}. + *

    * * @param which The {@code FLAG_*} identifier of a valid wallpaper type. Throws * IllegalArgumentException if an invalid wallpaper is requested. - * @return Returns an optimized Drawable object that will draw the - * wallpaper or a null pointer if these is none. + * @return An optimized Drawable object for the requested wallpaper. * * @throws SecurityException as described in the note */ @Nullable @RequiresPermission(anyOf = {MANAGE_EXTERNAL_STORAGE, READ_WALLPAPER_INTERNAL}) public Drawable peekFastDrawable(@SetWallpaperFlags int which) { - final ColorManagementProxy cmProxy = getColorManagementProxy(); - Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, which, cmProxy); - if (bm != null) { - return new FastBitmapDrawable(bm); - } - return null; + return getFastDrawable(which); } /** - * Whether the wallpaper supports Wide Color Gamut or not. + * Whether the wallpaper supports Wide Color Gamut or not. This is only meant to be used by + * ImageWallpaper, and will always return false if the wallpaper for the specified screen + * is not an ImageWallpaper. This will also return false when called with {@link #FLAG_LOCK} if + * the lock and home screen share the same wallpaper engine. + * * @param which The wallpaper whose image file is to be retrieved. Must be a single * defined kind of wallpaper, either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}. * @return true when supported. @@ -1422,7 +1423,7 @@ public class WallpaperManager { } /** - * Like {@link #getDrawable()} but returns a Bitmap. + * Like {@link #getDrawable(int)} but returns a Bitmap. * * @param hardware Asks for a hardware backed bitmap. * @param which Specifies home or lock screen @@ -1445,7 +1446,7 @@ public class WallpaperManager { } /** - * Like {@link #getDrawable()} but returns a Bitmap for the provided user. + * Like {@link #getDrawable(int)} but returns a Bitmap for the provided user. * * @param which Specifies home or lock screen * @hide @@ -1453,12 +1454,29 @@ public class WallpaperManager { @TestApi @Nullable public Bitmap getBitmapAsUser(int userId, boolean hardware, @SetWallpaperFlags int which) { + boolean returnDefault = which != FLAG_LOCK; + return getBitmapAsUser(userId, hardware, which, returnDefault); + } + + /** + * Overload of {@link #getBitmapAsUser(int, boolean, int)} with a returnDefault argument. + * + * @param returnDefault If true, return the default static wallpaper if no custom static + * wallpaper is set on the specified screen. + * If false, return {@code null} in that case. + * @hide + */ + @Nullable + public Bitmap getBitmapAsUser(int userId, boolean hardware, + @SetWallpaperFlags int which, boolean returnDefault) { final ColorManagementProxy cmProxy = getColorManagementProxy(); - return sGlobals.peekWallpaperBitmap(mContext, true, which, userId, hardware, cmProxy); + return sGlobals.peekWallpaperBitmap(mContext, returnDefault, + which, userId, hardware, cmProxy); } /** * Peek the dimensions of system wallpaper of the user without decoding it. + * Equivalent to {@link #peekBitmapDimensions(int)} with {@code which=}{@link #FLAG_SYSTEM}. * * @return the dimensions of system wallpaper * @hide @@ -1472,16 +1490,45 @@ public class WallpaperManager { /** * Peek the dimensions of given wallpaper of the user without decoding it. * - * @param which Wallpaper type. Must be either {@link #FLAG_SYSTEM} or - * {@link #FLAG_LOCK}. - * @return the dimensions of system wallpaper + *

    + * When called with {@code which=}{@link #FLAG_SYSTEM}, if there is a live wallpaper on + * home screen, the built-in default wallpaper dimensions are returned. + *

    + *

    + * When called with {@code which=}{@link #FLAG_LOCK}, if there is a live wallpaper + * on lock screen, or if the lock screen and home screen share the same wallpaper engine, + * {@code null} is returned. + *

    + *

    + * {@link #getWallpaperInfo(int)} can be used to determine whether there is a live wallpaper + * on a specified screen type. + *

    + * + * @param which Wallpaper type. Must be either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}. + * @return the dimensions of specified wallpaper * @hide */ @TestApi @Nullable public Rect peekBitmapDimensions(@SetWallpaperFlags int which) { + boolean returnDefault = which != FLAG_LOCK; + return peekBitmapDimensions(which, returnDefault); + } + + /** + * Overload of {@link #peekBitmapDimensions(int)} with a returnDefault argument. + * + * @param which Wallpaper type. Must be either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}. + * @param returnDefault If true, always return the default static wallpaper dimensions + * if no custom static wallpaper is set on the specified screen. + * If false, always return {@code null} in that case. + * @return the dimensions of specified wallpaper + * @hide + */ + @Nullable + public Rect peekBitmapDimensions(@SetWallpaperFlags int which, boolean returnDefault) { checkExactlyOneWallpaperFlagSet(which); - return sGlobals.peekWallpaperDimensions(mContext, true /* returnDefault */, which, + return sGlobals.peekWallpaperDimensions(mContext, returnDefault, which, mContext.getUserId()); } diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java index cd1ad1ba788f1..316b54eb0c80a 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java @@ -173,7 +173,7 @@ public class ImageWallpaper extends WallpaperService { .isLockscreenLiveWallpaperEnabled(); mSurfaceHolder = surfaceHolder; Rect dimensions = mIsLockscreenLiveWallpaperEnabled - ? mWallpaperManager.peekBitmapDimensions(getSourceFlag()) + ? mWallpaperManager.peekBitmapDimensions(getSourceFlag(), true) : mWallpaperManager.peekBitmapDimensions(); int width = Math.max(MIN_SURFACE_WIDTH, dimensions.width()); int height = Math.max(MIN_SURFACE_HEIGHT, dimensions.height()); @@ -325,7 +325,7 @@ public class ImageWallpaper extends WallpaperService { try { bitmap = mIsLockscreenLiveWallpaperEnabled ? mWallpaperManager.getBitmapAsUser( - mUserTracker.getUserId(), false, getSourceFlag()) + mUserTracker.getUserId(), false, getSourceFlag(), true) : mWallpaperManager.getBitmapAsUser(mUserTracker.getUserId(), false); if (bitmap != null && bitmap.getByteCount() > RecordingCanvas.MAX_BITMAP_SIZE) { @@ -347,7 +347,7 @@ public class ImageWallpaper extends WallpaperService { try { bitmap = mIsLockscreenLiveWallpaperEnabled ? mWallpaperManager.getBitmapAsUser( - mUserTracker.getUserId(), false, getSourceFlag()) + mUserTracker.getUserId(), false, getSourceFlag(), true) : mWallpaperManager.getBitmapAsUser(mUserTracker.getUserId(), false); } catch (RuntimeException | OutOfMemoryError e) { Log.w(TAG, "Unable to load default wallpaper!", e); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 6f640700949e3..84d3a216ac91c 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -2788,6 +2788,20 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + /** + * Returns true if there is a static wallpaper on the specified screen. With which=FLAG_LOCK, + * always return false if the lockscreen doesn't run its own wallpaper engine. + */ + @Override + public boolean isStaticWallpaper(int which) { + synchronized (mLock) { + WallpaperData wallpaperData = (which == FLAG_LOCK ? mLockWallpaperMap : mWallpaperMap) + .get(mCurrentUserId); + if (wallpaperData == null) return false; + return mImageWallpaper.equals(wallpaperData.wallpaperComponent); + } + } + /** * Sets wallpaper dim amount for the calling UID. This applies to all destinations (home, lock) * with an active wallpaper engine.