Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dde61229 authored by Chris Poultney's avatar Chris Poultney Committed by Android (Google) Code Review
Browse files

Merge "Add APIs for setting static wallpaers using WallpaperDescription" into main

parents 9005c46c 16d4a302
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -541,7 +541,9 @@ package android.app {
    method @Nullable public android.graphics.Rect peekBitmapDimensions();
    method @Nullable public android.graphics.Rect peekBitmapDimensions();
    method @Nullable public android.graphics.Rect peekBitmapDimensions(int);
    method @Nullable public android.graphics.Rect peekBitmapDimensions(int);
    method @FlaggedApi("com.android.window.flags.multi_crop") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setBitmapWithCrops(@Nullable android.graphics.Bitmap, @NonNull java.util.Map<android.graphics.Point,android.graphics.Rect>, boolean, int) throws java.io.IOException;
    method @FlaggedApi("com.android.window.flags.multi_crop") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setBitmapWithCrops(@Nullable android.graphics.Bitmap, @NonNull java.util.Map<android.graphics.Point,android.graphics.Rect>, boolean, int) throws java.io.IOException;
    method @FlaggedApi("android.app.live_wallpaper_content_handling") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setBitmapWithDescription(@Nullable android.graphics.Bitmap, @NonNull android.app.wallpaper.WallpaperDescription, boolean, int) throws java.io.IOException;
    method @FlaggedApi("com.android.window.flags.multi_crop") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setStreamWithCrops(@NonNull java.io.InputStream, @NonNull java.util.Map<android.graphics.Point,android.graphics.Rect>, boolean, int) throws java.io.IOException;
    method @FlaggedApi("com.android.window.flags.multi_crop") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setStreamWithCrops(@NonNull java.io.InputStream, @NonNull java.util.Map<android.graphics.Point,android.graphics.Rect>, boolean, int) throws java.io.IOException;
    method @FlaggedApi("android.app.live_wallpaper_content_handling") @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setStreamWithDescription(@NonNull java.io.InputStream, @NonNull android.app.wallpaper.WallpaperDescription, boolean, int) throws java.io.IOException;
    method public void setWallpaperZoomOut(@NonNull android.os.IBinder, float);
    method public void setWallpaperZoomOut(@NonNull android.os.IBinder, float);
    method public boolean shouldEnableWideColorGamut();
    method public boolean shouldEnableWideColorGamut();
    method public boolean wallpaperSupportsWcg(int);
    method public boolean wallpaperSupportsWcg(int);
@@ -907,6 +909,15 @@ package android.app.usage {


}
}


package android.app.wallpaper {

  public static final class WallpaperDescription.Builder {
    method @NonNull public android.app.wallpaper.WallpaperDescription.Builder setCropHints(@NonNull java.util.Map<android.graphics.Point,android.graphics.Rect>);
    method @NonNull public android.app.wallpaper.WallpaperDescription.Builder setCropHints(@NonNull android.util.SparseArray<android.graphics.Rect>);
  }

}

package android.appwidget {
package android.appwidget {


  public class AppWidgetManager {
  public class AppWidgetManager {
+42 −0
Original line number Original line Diff line number Diff line
@@ -2491,6 +2491,27 @@ public class WallpaperManager {
        return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
        return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
    }
    }


    /**
     * Version of setBitmap that allows specification of wallpaper metadata including how the
     * wallpaper will be positioned for different display sizes.
     *
     * @param fullImage   A bitmap that will supply the wallpaper imagery.
     * @param description Wallpaper metadata including desired cropping
     * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper
     *                    image for restore to a future device; {@code false} otherwise.
     * @param which       Flags indicating which wallpaper(s) to configure with the new imagery.
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @TestApi
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    public int setBitmapWithDescription(@Nullable Bitmap fullImage,
            @NonNull WallpaperDescription description, boolean allowBackup,
            @SetWallpaperFlags int which) throws IOException {
        return setBitmapWithCrops(fullImage, description.getCropHints(), allowBackup, which,
                mContext.getUserId());
    }

    private final void validateRect(Rect rect) {
    private final void validateRect(Rect rect) {
        if (rect != null && rect.isEmpty()) {
        if (rect != null && rect.isEmpty()) {
            throw new IllegalArgumentException("visibleCrop rectangle must be valid and non-empty");
            throw new IllegalArgumentException("visibleCrop rectangle must be valid and non-empty");
@@ -2699,6 +2720,27 @@ public class WallpaperManager {
        return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
        return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
    }
    }


    /**
     * Version of setStream that allows specification of wallpaper metadata including how the
     * wallpaper will be positioned for different display sizes.
     *
     * @param bitmapData  A stream containing the raw data to install as a wallpaper. This
     *                    data can be in any format handled by {@link BitmapRegionDecoder}.
     * @param description Wallpaper metadata including desired cropping
     * @param allowBackup {@code true} if the OS is permitted to back up this wallpaper
     *                    image for restore to a future device; {@code false} otherwise.
     * @param which       Flags indicating which wallpaper(s) to configure with the new imagery.
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @TestApi
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
    public int setStreamWithDescription(@NonNull InputStream bitmapData,
            @NonNull WallpaperDescription description, boolean allowBackup,
            @SetWallpaperFlags int which) throws IOException {
        return setStreamWithCrops(bitmapData, description.getCropHints(), allowBackup, which);
    }

    /**
    /**
     * Return whether any users are currently set to use the wallpaper
     * Return whether any users are currently set to use the wallpaper
     * with the given resource ID.  That is, their wallpaper has been
     * with the given resource ID.  That is, their wallpaper has been
+146 −6
Original line number Original line Diff line number Diff line
@@ -19,8 +19,14 @@ package android.app.wallpaper;
import static android.app.Flags.FLAG_LIVE_WALLPAPER_CONTENT_HANDLING;
import static android.app.Flags.FLAG_LIVE_WALLPAPER_CONTENT_HANDLING;


import android.annotation.FlaggedApi;
import android.annotation.FlaggedApi;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.WallpaperInfo;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
import android.app.WallpaperManager.ScreenOrientation;
import android.content.ComponentName;
import android.content.ComponentName;
import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
@@ -29,6 +35,8 @@ import android.text.Html;
import android.text.Spanned;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.SpannedString;
import android.util.Log;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
@@ -43,6 +51,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;


/**
/**
@@ -71,12 +80,15 @@ public final class WallpaperDescription implements Parcelable {
    @Nullable private final Uri mContextUri;
    @Nullable private final Uri mContextUri;
    @Nullable private final CharSequence mContextDescription;
    @Nullable private final CharSequence mContextDescription;
    @NonNull private final PersistableBundle mContent;
    @NonNull private final PersistableBundle mContent;
    @NonNull private final SparseArray<Rect> mCropHints;
    private final float mSampleSize;


    private WallpaperDescription(@Nullable ComponentName component,
    private WallpaperDescription(@Nullable ComponentName component,
            @Nullable String id, @Nullable Uri thumbnail, @Nullable CharSequence title,
            @Nullable String id, @Nullable Uri thumbnail, @Nullable CharSequence title,
            @Nullable List<CharSequence> description, @Nullable Uri contextUri,
            @Nullable List<CharSequence> description, @Nullable Uri contextUri,
            @Nullable CharSequence contextDescription,
            @Nullable CharSequence contextDescription,
            @Nullable PersistableBundle content) {
            @Nullable PersistableBundle content, @NonNull SparseArray<Rect> cropHints,
            float sampleSize) {
        this.mComponent = component;
        this.mComponent = component;
        this.mId = id;
        this.mId = id;
        this.mThumbnail = thumbnail;
        this.mThumbnail = thumbnail;
@@ -85,6 +97,8 @@ public final class WallpaperDescription implements Parcelable {
        this.mContextUri = contextUri;
        this.mContextUri = contextUri;
        this.mContextDescription = contextDescription;
        this.mContextDescription = contextDescription;
        this.mContent = (content != null) ? content : new PersistableBundle();
        this.mContent = (content != null) ? content : new PersistableBundle();
        this.mCropHints = cropHints;
        this.mSampleSize = sampleSize;
    }
    }


    /** @return the component for this wallpaper, or {@code null} for a static wallpaper */
    /** @return the component for this wallpaper, or {@code null} for a static wallpaper */
@@ -134,6 +148,24 @@ public final class WallpaperDescription implements Parcelable {
        return mContent;
        return mContent;
    }
    }


    /**
     * @return the cropping for the current image as described in
     * {@link Builder#setCropHints(SparseArray)}
     * @hide
     */
    @NonNull
    public SparseArray<Rect> getCropHints() {
        return mCropHints;
    }

    /**
     * @return the subsamling size as described in {@link Builder#setSampleSize(float)}.
     * @hide
     */
    public float getSampleSize() {
        return mSampleSize;
    }

    ////// Comparison overrides
    ////// Comparison overrides


    @Override
    @Override
@@ -163,9 +195,23 @@ public final class WallpaperDescription implements Parcelable {
        if (mContextDescription != null) {
        if (mContextDescription != null) {
            out.attribute(null, "contextdescription", toHtml(mContextDescription));
            out.attribute(null, "contextdescription", toHtml(mContextDescription));
        }
        }

        for (Pair<Integer, String> pair : screenDimensionPairs()) {
            @ScreenOrientation int orientation = pair.first;
            String attrName = pair.second;
            Rect cropHint = mCropHints.get(orientation);
            if (cropHint == null) continue;
            out.attributeInt(null, "cropLeft" + attrName, cropHint.left);
            out.attributeInt(null, "cropTop" + attrName, cropHint.top);
            out.attributeInt(null, "cropRight" + attrName, cropHint.right);
            out.attributeInt(null, "cropBottom" + attrName, cropHint.bottom);
        }
        out.attributeFloat(null, "sampleSize", mSampleSize);

        out.startTag(null, XML_TAG_DESCRIPTION);
        out.startTag(null, XML_TAG_DESCRIPTION);
        for (CharSequence s : mDescription) out.attribute(null, "descriptionline", toHtml(s));
        for (CharSequence s : mDescription) out.attribute(null, "descriptionline", toHtml(s));
        out.endTag(null, XML_TAG_DESCRIPTION);
        out.endTag(null, XML_TAG_DESCRIPTION);

        try {
        try {
            out.startTag(null, XML_TAG_CONTENT);
            out.startTag(null, XML_TAG_CONTENT);
            mContent.saveToXml(out);
            mContent.saveToXml(out);
@@ -194,6 +240,19 @@ public final class WallpaperDescription implements Parcelable {
        CharSequence contextDescription = fromHtml(
        CharSequence contextDescription = fromHtml(
                in.getAttributeValue(null, "contextdescription"));
                in.getAttributeValue(null, "contextdescription"));


        SparseArray<Rect> cropHints = new SparseArray<>();
        screenDimensionPairs().forEach(pair -> {
            @ScreenOrientation int orientation = pair.first;
            String attrName = pair.second;
            Rect crop = new Rect(
                    in.getAttributeInt(null, "cropLeft" + attrName, 0),
                    in.getAttributeInt(null, "cropTop" + attrName, 0),
                    in.getAttributeInt(null, "cropRight" + attrName, 0),
                    in.getAttributeInt(null, "cropBottom" + attrName, 0));
            if (!crop.isEmpty()) cropHints.put(orientation, crop);
        });
        float sampleSize = in.getAttributeFloat(null, "sampleSize", 1f);

        List<CharSequence> description = new ArrayList<>();
        List<CharSequence> description = new ArrayList<>();
        PersistableBundle content = null;
        PersistableBundle content = null;
        int type;
        int type;
@@ -213,7 +272,7 @@ public final class WallpaperDescription implements Parcelable {
        }
        }


        return new WallpaperDescription(componentName, id, thumbnail, title, description,
        return new WallpaperDescription(componentName, id, thumbnail, title, description,
                contextUri, contextDescription, content);
                contextUri, contextDescription, content, cropHints, sampleSize);
    }
    }


    private static String toHtml(@NonNull CharSequence c) {
    private static String toHtml(@NonNull CharSequence c) {
@@ -253,6 +312,13 @@ public final class WallpaperDescription implements Parcelable {
        mContextUri = Uri.CREATOR.createFromParcel(in);
        mContextUri = Uri.CREATOR.createFromParcel(in);
        mContextDescription = in.readCharSequence();
        mContextDescription = in.readCharSequence();
        mContent = PersistableBundle.CREATOR.createFromParcel(in);
        mContent = PersistableBundle.CREATOR.createFromParcel(in);
        mCropHints = new SparseArray<>();
        screenDimensionPairs().forEach(pair -> {
            int orientation = pair.first;
            Rect crop = in.readTypedObject(Rect.CREATOR);
            if (crop != null) mCropHints.put(orientation, crop);
        });
        mSampleSize = in.readFloat();
    }
    }


    @NonNull
    @NonNull
@@ -283,6 +349,11 @@ public final class WallpaperDescription implements Parcelable {
        Uri.writeToParcel(dest, mContextUri);
        Uri.writeToParcel(dest, mContextUri);
        dest.writeCharSequence(mContextDescription);
        dest.writeCharSequence(mContextDescription);
        dest.writePersistableBundle(mContent);
        dest.writePersistableBundle(mContent);
        screenDimensionPairs().forEach(pair -> {
            int orientation = pair.first;
            dest.writeTypedObject(mCropHints.get(orientation), flags);
        });
        dest.writeFloat(mSampleSize);
    }
    }


    ////// Builder
    ////// Builder
@@ -293,9 +364,17 @@ public final class WallpaperDescription implements Parcelable {
     */
     */
    @NonNull
    @NonNull
    public Builder toBuilder() {
    public Builder toBuilder() {
        return new Builder().setComponent(mComponent).setId(mId).setThumbnail(mThumbnail).setTitle(
        return new Builder()
                mTitle).setDescription(mDescription).setContextUri(
                .setComponent(mComponent)
                mContextUri).setContextDescription(mContextDescription).setContent(mContent);
                .setId(mId)
                .setThumbnail(mThumbnail)
                .setTitle(mTitle)
                .setDescription(mDescription)
                .setContextUri(mContextUri)
                .setContextDescription(mContextDescription)
                .setContent(mContent)
                .setCropHints(mCropHints)
                .setSampleSize(mSampleSize);
    }
    }


    /** Builder for the immutable {@link WallpaperDescription} class */
    /** Builder for the immutable {@link WallpaperDescription} class */
@@ -308,6 +387,9 @@ public final class WallpaperDescription implements Parcelable {
        @Nullable private Uri mContextUri;
        @Nullable private Uri mContextUri;
        @Nullable private CharSequence mContextDescription;
        @Nullable private CharSequence mContextDescription;
        @NonNull private PersistableBundle mContent = new PersistableBundle();
        @NonNull private PersistableBundle mContent = new PersistableBundle();
        @NonNull
        private SparseArray<Rect> mCropHints = new SparseArray<>();
        private float mSampleSize = 1f;


        /** Creates a new, empty {@link Builder}. */
        /** Creates a new, empty {@link Builder}. */
        public Builder() {}
        public Builder() {}
@@ -416,11 +498,69 @@ public final class WallpaperDescription implements Parcelable {
            return this;
            return this;
        }
        }


        /**
         * Defines which part of the source wallpaper image is in the stored crop file.
         *
         * @param cropHints map from screen dimensions to a sub-region of the image to display
         *                  for those dimensions. The {@code Rect} sub-region may have a larger
         *                  width/height ratio than the screen dimensions to apply a horizontal
         *                  parallax effect. If the map is empty or some entries are missing, the
         *                  system will apply a default strategy to position the wallpaper for
         *                  any unspecified screen dimensions.
         * @hide
         */
        @NonNull
        @TestApi
        @SuppressLint("MissingGetterMatchingBuilder")
        public Builder setCropHints(@NonNull Map<Point, Rect> cropHints) {
            mCropHints = new SparseArray<>();
            cropHints.forEach(
                    (point, rect) -> mCropHints.put(WallpaperManager.getOrientation(point), rect));
            return this;
        }

        /**
         * Defines which part of the source wallpaper image is in the stored crop file.
         *
         * @param cropHints map from {@link ScreenOrientation} to a sub-region of the image to
         *                  display for that screen orientation.
         * @hide
         */
        @NonNull
        @TestApi
        @SuppressLint("MissingGetterMatchingBuilder")
        public Builder setCropHints(@NonNull SparseArray<Rect> cropHints) {
            mCropHints = cropHints;
            return this;
        }

        /**
         * How much the crop is sub-sampled. A value > 1 means that the image quality was reduced.
         * This is the ratio between the cropHint height and the actual stored crop file height.
         * height.
         *
         * @param sampleSize Sub-sampling value
         * @hide
         */
        @NonNull
        public Builder setSampleSize(float sampleSize) {
            mSampleSize = sampleSize;
            return this;
        }

        /** Creates and returns the {@link WallpaperDescription} represented by this builder. */
        /** Creates and returns the {@link WallpaperDescription} represented by this builder. */
        @NonNull
        @NonNull
        public WallpaperDescription build() {
        public WallpaperDescription build() {
            return new WallpaperDescription(mComponent, mId, mThumbnail, mTitle, mDescription,
            return new WallpaperDescription(mComponent, mId, mThumbnail, mTitle, mDescription,
                    mContextUri, mContextDescription, mContent);
                    mContextUri, mContextDescription, mContent, mCropHints, mSampleSize);
        }
        }
    }
    }

    private static List<Pair<Integer, String>> screenDimensionPairs() {
        return List.of(
                new Pair<>(WallpaperManager.ORIENTATION_PORTRAIT, "Portrait"),
                new Pair<>(WallpaperManager.ORIENTATION_LANDSCAPE, "Landscape"),
                new Pair<>(WallpaperManager.ORIENTATION_SQUARE_PORTRAIT, "SquarePortrait"),
                new Pair<>(WallpaperManager.ORIENTATION_SQUARE_LANDSCAPE, "SquareLandscape"));
    }
}
}
+148 −32

File changed.

Preview size limit exceeded, changes collapsed.