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

Commit 47083cab authored by Chris Poultney's avatar Chris Poultney
Browse files

Add new content handling methods and implementation

Bug: 347235611
Test: manual testing with flag enabled and disabled
Test: CTS tests to be added with b/373596341
Flag: android.app.live_wallpaper_content_handling
API-Coverage-Bug: 373596341
Change-Id: I6f79b5ed85be8ba0bc52021e8ddac274d47d4273
parent c82eab1c
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -9677,9 +9677,11 @@ package android.app.wallpaper {
    method @Nullable public String getId();
    method @Nullable public android.net.Uri getThumbnail();
    method @Nullable public CharSequence getTitle();
    method @NonNull public static android.app.wallpaper.WallpaperDescription readFromStream(@NonNull java.io.InputStream) throws java.io.IOException;
    method @NonNull public android.app.wallpaper.WallpaperDescription.Builder toBuilder();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @Nullable public static final android.os.Parcelable.Creator<android.app.wallpaper.WallpaperDescription> CREATOR;
    method public void writeToStream(@NonNull java.io.OutputStream) throws java.io.IOException;
    field @NonNull public static final android.os.Parcelable.Creator<android.app.wallpaper.WallpaperDescription> CREATOR;
  }
  public static final class WallpaperDescription.Builder {
@@ -42085,6 +42087,7 @@ package android.service.wallpaper {
    ctor public WallpaperService();
    method public final android.os.IBinder onBind(android.content.Intent);
    method @MainThread public abstract android.service.wallpaper.WallpaperService.Engine onCreateEngine();
    method @FlaggedApi("android.app.live_wallpaper_content_handling") @MainThread @Nullable public android.service.wallpaper.WallpaperService.Engine onCreateEngine(@NonNull android.app.wallpaper.WallpaperDescription);
    field public static final String SERVICE_INTERFACE = "android.service.wallpaper.WallpaperService";
    field public static final String SERVICE_META_DATA = "android.service.wallpaper";
  }
@@ -42100,6 +42103,7 @@ package android.service.wallpaper {
    method public boolean isPreview();
    method public boolean isVisible();
    method public void notifyColorsChanged();
    method @FlaggedApi("android.app.live_wallpaper_content_handling") @Nullable public android.app.wallpaper.WallpaperDescription onApplyWallpaper(int);
    method @MainThread public void onApplyWindowInsets(android.view.WindowInsets);
    method @MainThread public android.os.Bundle onCommand(String, int, int, int, android.os.Bundle, boolean);
    method @MainThread @Nullable public android.app.WallpaperColors onComputeColors();
+2 −0
Original line number Diff line number Diff line
@@ -1264,8 +1264,10 @@ package android.app {
  public class WallpaperManager {
    method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void clearWallpaper(int, int);
    method @FloatRange(from=0.0f, to=1.0f) @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT) public float getWallpaperDimAmount();
    method @FlaggedApi("android.app.live_wallpaper_content_handling") @Nullable @RequiresPermission(android.Manifest.permission.READ_WALLPAPER_INTERNAL) public android.app.wallpaper.WallpaperInstance getWallpaperInstance(int);
    method public void setDisplayOffset(android.os.IBinder, int, int);
    method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT) public boolean setWallpaperComponent(android.content.ComponentName);
    method @FlaggedApi("android.app.live_wallpaper_content_handling") @RequiresPermission(allOf={android.Manifest.permission.SET_WALLPAPER_COMPONENT, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public boolean setWallpaperComponentWithDescription(@NonNull android.app.wallpaper.WallpaperDescription, int);
    method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT) public boolean setWallpaperComponentWithFlags(@NonNull android.content.ComponentName, int);
    method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT) public void setWallpaperDimAmount(@FloatRange(from=0.0f, to=1.0f) float);
  }
+11 −2
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.os.ParcelFileDescriptor;
import android.app.IWallpaperManagerCallback;
import android.app.ILocalWallpaperColorConsumer;
import android.app.WallpaperInfo;
import android.app.wallpaper.WallpaperDescription;
import android.app.wallpaper.WallpaperInstance;
import android.content.ComponentName;
import android.app.WallpaperColors;

@@ -61,8 +63,8 @@ interface IWallpaperManager {
    /**
     * Set the live wallpaper.
     */
    void setWallpaperComponentChecked(in ComponentName name, in String callingPackage, int which,
            int userId);
    void setWallpaperComponentChecked(in WallpaperDescription description, in String callingPackage,
            int which, int userId);

    /**
     * Set the live wallpaper. This only affects the system wallpaper.
@@ -129,6 +131,13 @@ interface IWallpaperManager {
     */
    WallpaperInfo getWallpaperInfoWithFlags(int which, int userId);

   /**
    * Return the instance information about the wallpaper described by `which`, or null if lock
    * screen is requested and it is the same as home.
    */
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.READ_WALLPAPER_INTERNAL)")
    WallpaperInstance getWallpaperInstance(int which, int userId);

    /**
     * Return a file descriptor for the file that contains metadata about the given user's
     * wallpaper.
+85 −2
Original line number Diff line number Diff line
@@ -21,10 +21,12 @@ import static android.Manifest.permission.READ_WALLPAPER_INTERNAL;
import static android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static android.app.Flags.FLAG_LIVE_WALLPAPER_CONTENT_HANDLING;

import static com.android.window.flags.Flags.FLAG_MULTI_CROP;
import static com.android.window.flags.Flags.multiCrop;

import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
@@ -39,6 +41,8 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UiContext;
import android.app.compat.CompatChanges;
import android.app.wallpaper.WallpaperDescription;
import android.app.wallpaper.WallpaperInstance;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
@@ -2022,6 +2026,34 @@ public class WallpaperManager {
        }
    }

    /**
     * Returns the description of the designated wallpaper. Returns null if the lock screen
     * wallpaper is requested lock screen wallpaper is not set.

     * @param which Specifies wallpaper to request (home or lock).
     * @throws IllegalArgumentException if {@code which} is not exactly one of
     * {{@link #FLAG_SYSTEM},{@link #FLAG_LOCK}}.
     *
     * @hide
     */
    @Nullable
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @RequiresPermission(READ_WALLPAPER_INTERNAL)
    @SystemApi
    public WallpaperInstance getWallpaperInstance(@SetWallpaperFlags int which) {
        checkExactlyOneWallpaperFlagSet(which);
        try {
            if (sGlobals.mService == null) {
                Log.w(TAG, "WallpaperService not running");
                throw new RuntimeException(new DeadSystemException());
            } else {
                return sGlobals.mService.getWallpaperInstance(which, mContext.getUserId());
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get an open, readable file descriptor for the file that contains metadata about the
     * context user's wallpaper.
@@ -2955,15 +2987,66 @@ public class WallpaperManager {
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
    @RequiresPermission(allOf = {android.Manifest.permission.SET_WALLPAPER_COMPONENT,
            Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)
    public boolean setWallpaperComponentWithFlags(@NonNull ComponentName name,
            @SetWallpaperFlags int which, int userId) {
        WallpaperDescription description = new WallpaperDescription.Builder().setComponent(
                name).build();
        return setWallpaperComponentWithDescription(description, which, userId);
    }

    /**
     * Set the implementation of {@link android.service.wallpaper.WallpaperService} used to render
     * wallpaper, along with associated metadata.
     *
     * <p>This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
     * permission. The caller must hold the INTERACT_ACROSS_USERS_FULL permission to change
     * another user's wallpaper.
     * </p>
     *
     * @param description wallpaper component and metadata to set
     * @param which Specifies wallpaper destination (home and/or lock).
     * @return true on success, otherwise false
     *
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @SystemApi
    @RequiresPermission(allOf = {android.Manifest.permission.SET_WALLPAPER_COMPONENT,
            Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)
    public boolean setWallpaperComponentWithDescription(@NonNull WallpaperDescription description,
            @SetWallpaperFlags int which) {
        return setWallpaperComponentWithDescription(description, which, mContext.getUserId());
    }

    /**
     * Set the implementation of {@link android.service.wallpaper.WallpaperService} used to render
     * wallpaper, along with associated metadata.
     *
     * <p>This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
     * permission. The caller must hold the INTERACT_ACROSS_USERS_FULL permission to change
     * another user's wallpaper.
     * </p>
     *
     * @param description wallpaper component and metadata to set
     * @param which Specifies wallpaper destination (home and/or lock).
     * @param userId User for whom the component should be set.
     * @return true on success, otherwise false
     *
     * @hide
     */
    @FlaggedApi(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
    @RequiresPermission(allOf = {android.Manifest.permission.SET_WALLPAPER_COMPONENT,
            Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)
    public boolean setWallpaperComponentWithDescription(@NonNull WallpaperDescription description,
            @SetWallpaperFlags int which, int userId) {
        if (sGlobals.mService == null) {
            Log.w(TAG, "WallpaperManagerService not running");
            throw new RuntimeException(new DeadSystemException());
        }
        try {
            sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName(),
            sGlobals.mService.setWallpaperComponentChecked(description, mContext.getOpPackageName(),
                    which, userId);
            return true;
        } catch (RemoteException e) {
+46 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.app.wallpaper;

import static android.app.Flags.FLAG_LIVE_WALLPAPER_CONTENT_HANDLING;

import static java.nio.charset.StandardCharsets.UTF_8;

import android.annotation.FlaggedApi;
import android.app.WallpaperInfo;
import android.content.ComponentName;
@@ -29,6 +31,7 @@ import android.text.Html;
import android.text.Spanned;
import android.text.SpannedString;
import android.util.Log;
import android.util.Xml;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -40,6 +43,8 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -149,6 +154,46 @@ public final class WallpaperDescription implements Parcelable {
        return Objects.hash(mComponent, mId);
    }

    ////// Stream read/write

    /**
     * Writes the content of the {@link WallpaperDescription} to a {@link OutputStream}.
     *
     * <p>The content can be read by {@link #readFromStream}. This method is intended for use by
     * trusted apps only, and the format is not guaranteed to be stable.</p>
     */
    public void writeToStream(@NonNull OutputStream outputStream) throws IOException {
        TypedXmlSerializer serializer = Xml.newFastSerializer();
        serializer.setOutput(outputStream, UTF_8.name());
        serializer.startTag(null, "description");
        try {
            saveToXml(serializer);
        } catch (XmlPullParserException e) {
            throw new IOException(e);
        }
        serializer.endTag(null, "description");
        serializer.flush();
    }

    /**
     * Reads a {@link PersistableBundle} from an {@link InputStream}.
     *
     * <p>The stream must be generated by {@link #writeToStream}. This method is intended for use by
     * trusted apps only, and the format is not guaranteed to be stable.</p>
     */
    @NonNull
    public static WallpaperDescription readFromStream(@NonNull InputStream inputStream)
            throws IOException {
        try {
            TypedXmlPullParser parser = Xml.newFastPullParser();
            parser.setInput(inputStream, UTF_8.name());
            parser.next();
            return WallpaperDescription.restoreFromXml(parser);
        } catch (XmlPullParserException e) {
            throw new IOException(e);
        }
    }

    ////// XML storage

    /** @hide */
@@ -255,7 +300,7 @@ public final class WallpaperDescription implements Parcelable {
        mContent = PersistableBundle.CREATOR.createFromParcel(in);
    }

    @Nullable
    @NonNull
    public static final Creator<WallpaperDescription> CREATOR = new Creator<>() {
        @Override
        public WallpaperDescription createFromParcel(Parcel source) {
Loading