diff options
Diffstat (limited to 'graphics')
31 files changed, 529 insertions, 122 deletions
diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java new file mode 100644 index 000000000000..8c6a9371d53b --- /dev/null +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 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 + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import android.view.Surface; +import android.view.SurfaceControl; + +/** + * @hide + */ +public final class BLASTBufferQueue { + // Note: This field is accessed by native code. + private long mNativeObject; // BLASTBufferQueue* + + private static native long nativeCreate(long surfaceControl, long width, long height); + private static native void nativeDestroy(long ptr); + private static native Surface nativeGetSurface(long ptr); + private static native void nativeSetNextTransaction(long ptr, long transactionPtr); + private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height); + + /** Create a new connection with the surface flinger. */ + public BLASTBufferQueue(SurfaceControl sc, int width, int height) { + mNativeObject = nativeCreate(sc.mNativeObject, width, height); + } + + public void destroy() { + nativeDestroy(mNativeObject); + } + + public Surface getSurface() { + return nativeGetSurface(mNativeObject); + } + + public void setNextTransaction(SurfaceControl.Transaction t) { + nativeSetNextTransaction(mNativeObject, t.mNativeObject); + } + + public void update(SurfaceControl sc, int width, int height) { + nativeUpdate(mNativeObject, sc.mNativeObject, width, height); + } + + @Override + protected void finalize() throws Throwable { + try { + if (mNativeObject != 0) { + nativeDestroy(mNativeObject); + } + } finally { + super.finalize(); + } + } +} + diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 44710178da5e..d900a42b1e66 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -1359,9 +1359,44 @@ public final class Bitmap implements Parcelable { * Specifies the known formats a bitmap can be compressed into */ public enum CompressFormat { - JPEG (0), - PNG (1), - WEBP (2); + /** + * Compress to the JPEG format. {@code quality} of {@code 0} means + * compress for the smallest size. {@code 100} means compress for max + * visual quality. + */ + JPEG (0), + /** + * Compress to the PNG format. PNG is lossless, so {@code quality} is + * ignored. + */ + PNG (1), + /** + * Compress to the WEBP format. {@code quality} of {@code 0} means + * compress for the smallest size. {@code 100} means compress for max + * visual quality. As of {@link android.os.Build.VERSION_CODES#Q}, a + * value of {@code 100} results in a file in the lossless WEBP format. + * Otherwise the file will be in the lossy WEBP format. + * + * @deprecated in favor of the more explicit + * {@link CompressFormat#WEBP_LOSSY} and + * {@link CompressFormat#WEBP_LOSSLESS}. + */ + @Deprecated + WEBP (2), + /** + * Compress to the WEBP lossy format. {@code quality} of {@code 0} means + * compress for the smallest size. {@code 100} means compress for max + * visual quality. + */ + WEBP_LOSSY (3), + /** + * Compress to the WEBP lossless format. {@code quality} refers to how + * much effort to put into compression. A value of {@code 0} means to + * compress quickly, resulting in a relatively large file size. + * {@code 100} means to spend more time compressing, resulting in a + * smaller file. + */ + WEBP_LOSSLESS (4); CompressFormat(int nativeInt) { this.nativeInt = nativeInt; @@ -1385,10 +1420,8 @@ public final class Bitmap implements Parcelable { * pixels). * * @param format The format of the compressed image - * @param quality Hint to the compressor, 0-100. 0 meaning compress for - * small size, 100 meaning compress for max quality. Some - * formats, like PNG which is lossless, will ignore the - * quality setting + * @param quality Hint to the compressor, 0-100. The value is interpreted + * differently depending on the {@link CompressFormat}. * @param stream The outputstream to write the compressed data. * @return true if successfully compressed to the specified stream. */ diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 5648b854db40..a815f20293c5 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -2095,9 +2095,11 @@ public class Canvas extends BaseCanvas { /** * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The - * paint's Align setting determins where along the path to start the text. + * paint's Align setting determines where along the path to start the text. * * @param text The text to be drawn + * @param index The starting index within the text to be drawn + * @param count Starting from index, the number of characters to draw * @param path The path the text should follow for its baseline * @param hOffset The distance along the path to add to the text's starting position * @param vOffset The distance above(-) or below(+) the path to position the text @@ -2110,7 +2112,7 @@ public class Canvas extends BaseCanvas { /** * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The - * paint's Align setting determins where along the path to start the text. + * paint's Align setting determines where along the path to start the text. * * @param text The text to be drawn * @param path The path the text should follow for its baseline diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index 9c4b5e8b0165..06d4fbdd85b1 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -1380,9 +1380,9 @@ public abstract class ColorSpace { */ @NonNull static ColorSpace get(@IntRange(from = MIN_ID, to = MAX_ID) int index) { - if (index < 0 || index >= Named.values().length) { + if (index < 0 || index >= sNamedColorSpaces.length) { throw new IllegalArgumentException("Invalid ID, must be in the range [0.." + - Named.values().length + ")"); + sNamedColorSpaces.length + ")"); } return sNamedColorSpaces[index]; } diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index b6b2d4e1c46a..3b864139cf71 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -28,7 +28,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.util.TimeUtils; -import android.view.FrameMetricsObserver; import android.view.IGraphicsStats; import android.view.IGraphicsStatsCallback; import android.view.NativeVectorDrawableAnimator; @@ -38,8 +37,6 @@ import android.view.SurfaceHolder; import android.view.TextureLayer; import android.view.animation.AnimationUtils; -import com.android.internal.util.VirtualRefBasePtr; - import java.io.File; import java.io.FileDescriptor; import java.lang.annotation.Retention; @@ -286,10 +283,24 @@ public class HardwareRenderer { * non-null then {@link Surface#isValid()} must be true. */ public void setSurface(@Nullable Surface surface) { + setSurface(surface, false); + } + + /** + * See {@link #setSurface(Surface)} + * + * @hide + * @param discardBuffer determines whether the surface will attempt to preserve its contents + * between frames. If set to true the renderer will attempt to preserve + * the contents of the buffer between frames if the implementation allows + * it. If set to false no attempt will be made to preserve the buffer's + * contents between frames. + */ + public void setSurface(@Nullable Surface surface, boolean discardBuffer) { if (surface != null && !surface.isValid()) { throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false."); } - nSetSurface(mNativeProxy, surface); + nSetSurface(mNativeProxy, surface, discardBuffer); } /** @@ -584,9 +595,8 @@ public class HardwareRenderer { * * @hide */ - public void addFrameMetricsObserver(FrameMetricsObserver observer) { - long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer); - observer.mNative = new VirtualRefBasePtr(nativeObserver); + public void addObserver(HardwareRendererObserver observer) { + nAddObserver(mNativeProxy, observer.getNativeInstance()); } /** @@ -594,9 +604,8 @@ public class HardwareRenderer { * * @hide */ - public void removeFrameMetricsObserver(FrameMetricsObserver observer) { - nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get()); - observer.mNative = null; + public void removeObserver(HardwareRendererObserver observer) { + nRemoveObserver(mNativeProxy, observer.getNativeInstance()); } /** @@ -1084,7 +1093,7 @@ public class HardwareRenderer { private static native void nSetName(long nativeProxy, String name); - private static native void nSetSurface(long nativeProxy, Surface window); + private static native void nSetSurface(long nativeProxy, Surface window, boolean discardBuffer); private static native boolean nPause(long nativeProxy); @@ -1156,10 +1165,9 @@ public class HardwareRenderer { private static native void nSetFrameCompleteCallback(long nativeProxy, FrameCompleteCallback callback); - private static native long nAddFrameMetricsObserver(long nativeProxy, - FrameMetricsObserver observer); + private static native void nAddObserver(long nativeProxy, long nativeObserver); - private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver); + private static native void nRemoveObserver(long nativeProxy, long nativeObserver); private static native int nCopySurfaceInto(Surface surface, int srcLeft, int srcTop, int srcRight, int srcBottom, long bitmapHandle); diff --git a/graphics/java/android/graphics/HardwareRendererObserver.java b/graphics/java/android/graphics/HardwareRendererObserver.java new file mode 100644 index 000000000000..da9d03c639f7 --- /dev/null +++ b/graphics/java/android/graphics/HardwareRendererObserver.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2019 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 + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import android.annotation.NonNull; +import android.os.Handler; + +import com.android.internal.util.VirtualRefBasePtr; + +/** + * Provides streaming access to frame stats information from HardwareRenderer to apps. + * + * @hide + */ +public class HardwareRendererObserver { + private final long[] mFrameMetrics; + private final Handler mHandler; + private final OnFrameMetricsAvailableListener mListener; + private VirtualRefBasePtr mNativePtr; + + /** + * Interface for clients that want frame timing information for each frame rendered. + * @hide + */ + public interface OnFrameMetricsAvailableListener { + /** + * Called when information is available for the previously rendered frame. + * + * Reports can be dropped if this callback takes too long to execute, as the report producer + * cannot wait for the consumer to complete. + * + * It is highly recommended that clients copy the metrics array within this method + * and defer additional computation or storage to another thread to avoid unnecessarily + * dropping reports. + * + * @param dropCountSinceLastInvocation the number of reports dropped since the last time + * this callback was invoked. + */ + void onFrameMetricsAvailable(int dropCountSinceLastInvocation); + } + + /** + * Creates a FrameMetricsObserver + * + * @param frameMetrics the available metrics. This array is reused on every call to the listener + * and thus <strong>this reference should only be used within the scope of the listener callback + * as data is not guaranteed to be valid outside the scope of that method</strong>. + * @param handler the Handler to use when invoking callbacks + */ + public HardwareRendererObserver(@NonNull OnFrameMetricsAvailableListener listener, + @NonNull long[] frameMetrics, @NonNull Handler handler) { + if (handler == null || handler.getLooper() == null) { + throw new NullPointerException("handler and its looper cannot be null"); + } + + if (handler.getLooper().getQueue() == null) { + throw new IllegalStateException("invalid looper, null message queue\n"); + } + + mFrameMetrics = frameMetrics; + mHandler = handler; + mListener = listener; + mNativePtr = new VirtualRefBasePtr(nCreateObserver()); + } + + /*package*/ long getNativeInstance() { + return mNativePtr.get(); + } + + // Called by native on the provided Handler + @SuppressWarnings("unused") + private void notifyDataAvailable() { + mHandler.post(() -> { + boolean hasMoreData = true; + while (hasMoreData) { + // a drop count of -1 is a sentinel that no more buffers are available + int dropCount = nGetNextBuffer(mNativePtr.get(), mFrameMetrics); + if (dropCount >= 0) { + mListener.onFrameMetricsAvailable(dropCount); + } else { + hasMoreData = false; + } + } + }); + } + + private native long nCreateObserver(); + private static native int nGetNextBuffer(long nativePtr, long[] data); +} diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index e7b0e2899421..bcb313e1c227 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -270,7 +270,7 @@ public final class ImageDecoder implements AutoCloseable { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { AssetFileDescriptor assetFd = null; try { - if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) { + if (mUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { assetFd = mResolver.openTypedAssetFileDescriptor(mUri, "image/*", null); } else { @@ -1677,6 +1677,9 @@ public final class ImageDecoder implements AutoCloseable { if (r == null) { return; } + if (r.width() <= 0 || r.height() <= 0) { + throw new IllegalStateException("Subset " + r + " is empty/unsorted"); + } if (r.left < 0 || r.top < 0 || r.right > width || r.bottom > height) { throw new IllegalStateException("Subset " + r + " not contained by " + "scaled image bounds: (" + width + " x " + height + ")"); diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index b7316ab03618..109d8631284d 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1114,7 +1114,7 @@ public class Paint { * Return the width for stroking. * <p /> * A value of 0 strokes in hairline mode. - * Hairlines always draws a single pixel independent of the canva's matrix. + * Hairlines always draws a single pixel independent of the canvas's matrix. * * @return the paint's stroke width, used whenever the paint's style is * Stroke or StrokeAndFill. @@ -1126,7 +1126,7 @@ public class Paint { /** * Set the width for stroking. * Pass 0 to stroke in hairline mode. - * Hairlines always draws a single pixel independent of the canva's matrix. + * Hairlines always draws a single pixel independent of the canvas's matrix. * * @param width set the paint's stroke width, used whenever the paint's * style is Stroke or StrokeAndFill. @@ -1958,8 +1958,8 @@ public class Paint { * <code> * Paint paint = new Paint(); * paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN); - * paint.measureText("abc", 0, 3); // Returns the width of "‐abc" - * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "‐abc" + * paint.measureText("abc", 0, 3); // Returns the width of "-abc" + * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "-abc" * </code> * </pre> * @@ -1985,8 +1985,8 @@ public class Paint { * <code> * Paint paint = new Paint(); * paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN); - * paint.measureText("abc", 0, 3); // Returns the width of "abc‐" - * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc‐" + * paint.measureText("abc", 0, 3); // Returns the width of "abc-" + * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc-" * </code> * </pre> * diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java index 3614f3bcb3be..9f71a0fedd05 100644 --- a/graphics/java/android/graphics/Point.java +++ b/graphics/java/android/graphics/Point.java @@ -132,7 +132,7 @@ public class Point implements Parcelable { * @param fieldId Field Id of the Rect as defined in the parent message * @hide */ - public void writeToProto(@NonNull ProtoOutputStream protoOutputStream, long fieldId) { + public void dumpDebug(@NonNull ProtoOutputStream protoOutputStream, long fieldId) { final long token = protoOutputStream.start(fieldId); protoOutputStream.write(PointProto.X, x); protoOutputStream.write(PointProto.Y, y); diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index d47f682ec2d3..9e1946c557d2 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -239,7 +239,7 @@ public final class Rect implements Parcelable { * @param fieldId Field Id of the Rect as defined in the parent message * @hide */ - public void writeToProto(@NonNull ProtoOutputStream protoOutputStream, long fieldId) { + public void dumpDebug(@NonNull ProtoOutputStream protoOutputStream, long fieldId) { final long token = protoOutputStream.start(fieldId); protoOutputStream.write(RectProto.LEFT, left); protoOutputStream.write(RectProto.TOP, top); diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java new file mode 100644 index 000000000000..5a3f2a96e31d --- /dev/null +++ b/graphics/java/android/graphics/RuntimeShader.java @@ -0,0 +1,90 @@ +/* + * Copyright 2019 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 + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +import libcore.util.NativeAllocationRegistry; + +/** + * Shader that calculates pixel output with a program (fragment shader) running on a GPU. + * @hide + */ +public class RuntimeShader extends Shader { + + private static class NoImagePreloadHolder { + public static final NativeAllocationRegistry sRegistry = + NativeAllocationRegistry.createMalloced( + RuntimeShader.class.getClassLoader(), nativeGetFinalizer()); + } + + private byte[] mUniforms; + private boolean mIsOpaque; + + /** + * Current native shader factory instance. + */ + private long mNativeInstanceRuntimeShaderFactory; + + /** + * Creates a new RuntimeShader. + * + * @param sksl The text of SKSL program to run on the GPU. + * @param uniforms Array of parameters passed by the SKSL shader. Array size depends + * on number of uniforms declared by sksl. + * @param isOpaque True if all pixels have alpha 1.0f. + */ + public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque) { + this(sksl, uniforms, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB)); + } + + private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque, + ColorSpace colorSpace) { + super(colorSpace); + mUniforms = uniforms; + mIsOpaque = isOpaque; + mNativeInstanceRuntimeShaderFactory = nativeCreateShaderFactory(sksl); + NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, + mNativeInstanceRuntimeShaderFactory); + } + + /** + * Sets new value for shader parameters. + * + * @param uniforms Array of parameters passed by the SKSL shader. Array size depends + * on number of uniforms declared by mSksl. + */ + public void updateUniforms(@Nullable byte[] uniforms) { + mUniforms = uniforms; + discardNativeInstance(); + } + + @Override + long createNativeInstance(long nativeMatrix) { + return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms, + colorSpace().getNativeInstance(), mIsOpaque); + } + + private static native long nativeCreate(long shaderFactory, long matrix, byte[] inputs, + long colorSpaceHandle, boolean isOpaque); + + private static native long nativeCreateShaderFactory(String sksl); + + private static native long nativeGetFinalizer(); +} + diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index f5fa8c546bed..e93e7dfbe22c 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -20,7 +20,7 @@ import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 08409869c626..e70529b6cd1a 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -22,7 +22,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 090d915a2f67..51b299c9ee5e 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -17,7 +17,7 @@ package android.graphics.drawable; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java index bad3791a9c24..3408b64e7536 100644 --- a/graphics/java/android/graphics/drawable/DrawableInflater.java +++ b/graphics/java/android/graphics/drawable/DrawableInflater.java @@ -16,19 +16,19 @@ package android.graphics.drawable; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - import android.annotation.DrawableRes; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.util.AttributeSet; import android.view.InflateException; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import java.io.IOException; import java.lang.reflect.Constructor; import java.util.HashMap; diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java index 64fc7042dfc7..e197e7123fed 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -18,7 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -364,6 +364,13 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb } @Override + public void jumpToCurrentState() { + if (mDrawable != null) { + mDrawable.jumpToCurrentState(); + } + } + + @Override protected boolean onLevelChange(int level) { return mDrawable != null && mDrawable.setLevel(level); } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 96ac0f9b38b5..3881955d2632 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -22,7 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Px; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -97,6 +97,14 @@ import java.lang.annotation.RetentionPolicy; * @attr ref android.R.styleable#GradientDrawablePadding_bottom */ public class GradientDrawable extends Drawable { + + /** + * Flag to determine if we should wrap negative gradient angle measurements + * for API levels that support it + * @hide + */ + public static boolean sWrapNegativeAngleMeasurements = true; + /** * Shape is a rectangle, possibly with rounded corners */ @@ -151,6 +159,9 @@ public class GradientDrawable extends Drawable { /** Radius is a fraction of the bounds size. */ private static final int RADIUS_TYPE_FRACTION_PARENT = 2; + /** Default orientation for GradientDrawable **/ + private static final Orientation DEFAULT_ORIENTATION = Orientation.TOP_BOTTOM; + /** @hide */ @IntDef({RADIUS_TYPE_PIXELS, RADIUS_TYPE_FRACTION, RADIUS_TYPE_FRACTION_PARENT}) @Retention(RetentionPolicy.SOURCE) @@ -207,7 +218,7 @@ public class GradientDrawable extends Drawable { } public GradientDrawable() { - this(new GradientState(Orientation.TOP_BOTTOM, null), null); + this(new GradientState(DEFAULT_ORIENTATION, null), null); } /** @@ -1757,33 +1768,48 @@ public class GradientDrawable extends Drawable { } int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle); - st.mAngle = ((angle % 360) + 360) % 360; // offset negative angle measures - switch (st.mAngle) { - case 0: - st.mOrientation = Orientation.LEFT_RIGHT; - break; - case 45: - st.mOrientation = Orientation.BL_TR; - break; - case 90: - st.mOrientation = Orientation.BOTTOM_TOP; - break; - case 135: - st.mOrientation = Orientation.BR_TL; - break; - case 180: - st.mOrientation = Orientation.RIGHT_LEFT; - break; - case 225: - st.mOrientation = Orientation.TR_BL; - break; - case 270: - st.mOrientation = Orientation.TOP_BOTTOM; - break; - case 315: - st.mOrientation = Orientation.TL_BR; - break; + // GradientDrawable historically has not parsed negative angle measurements and always + // stays on the default orientation for API levels older than Q. + // Only configure the orientation if the angle is greater than zero. + // Otherwise fallback on Orientation.TOP_BOTTOM + // In Android Q and later, actually wrap the negative angle measurement to the correct + // value + if (sWrapNegativeAngleMeasurements) { + st.mAngle = ((angle % 360) + 360) % 360; // offset negative angle measures + } else { + st.mAngle = angle % 360; + } + + if (st.mAngle >= 0) { + switch (st.mAngle) { + case 0: + st.mOrientation = Orientation.LEFT_RIGHT; + break; + case 45: + st.mOrientation = Orientation.BL_TR; + break; + case 90: + st.mOrientation = Orientation.BOTTOM_TOP; + break; + case 135: + st.mOrientation = Orientation.BR_TL; + break; + case 180: + st.mOrientation = Orientation.RIGHT_LEFT; + break; + case 225: + st.mOrientation = Orientation.TR_BL; + break; + case 270: + st.mOrientation = Orientation.TOP_BOTTOM; + break; + case 315: + st.mOrientation = Orientation.TL_BR; + break; + } + } else { + st.mOrientation = DEFAULT_ORIENTATION; } final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius); diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java index 3658f89abae1..cc7182c3fd1c 100644 --- a/graphics/java/android/graphics/drawable/Icon.java +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -21,7 +21,7 @@ import android.annotation.DrawableRes; import android.annotation.IdRes; import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -92,11 +92,17 @@ public final class Icon implements Parcelable { * @see #getType */ public static final int TYPE_ADAPTIVE_BITMAP = 5; + /** + * An icon that was created using {@link Icon#createWithAdaptiveBitmapContentUri}. + * @see #getType + */ + public static final int TYPE_URI_ADAPTIVE_BITMAP = 6; /** * @hide */ - @IntDef({TYPE_BITMAP, TYPE_RESOURCE, TYPE_DATA, TYPE_URI, TYPE_ADAPTIVE_BITMAP}) + @IntDef({TYPE_BITMAP, TYPE_RESOURCE, TYPE_DATA, TYPE_URI, TYPE_ADAPTIVE_BITMAP, + TYPE_URI_ADAPTIVE_BITMAP}) public @interface IconType { } @@ -113,12 +119,14 @@ public final class Icon implements Parcelable { // based on the value of mType. // TYPE_BITMAP: Bitmap + // TYPE_ADAPTIVE_BITMAP: Bitmap // TYPE_RESOURCE: Resources // TYPE_DATA: DataBytes private Object mObj1; // TYPE_RESOURCE: package name // TYPE_URI: uri string + // TYPE_URI_ADAPTIVE_BITMAP: uri string @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private String mString1; @@ -141,7 +149,8 @@ public final class Icon implements Parcelable { } /** - * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} Icon. + * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} or + * {@link #TYPE_ADAPTIVE_BITMAP} Icon. * @hide */ @UnsupportedAppUsage @@ -243,11 +252,12 @@ public final class Icon implements Parcelable { } /** - * @return The URI (as a String) for this {@link #TYPE_URI} Icon. + * @return The URI (as a String) for this {@link #TYPE_URI} or {@link #TYPE_URI_ADAPTIVE_BITMAP} + * Icon. * @hide */ public String getUriString() { - if (mType != TYPE_URI) { + if (mType != TYPE_URI && mType != TYPE_URI_ADAPTIVE_BITMAP) { throw new IllegalStateException("called getUriString() on " + this); } return mString1; @@ -256,7 +266,7 @@ public final class Icon implements Parcelable { /** * Gets the uri used to create this icon. * <p> - * Only valid for icons of type {@link #TYPE_URI}. + * Only valid for icons of type {@link #TYPE_URI} and {@link #TYPE_URI_ADAPTIVE_BITMAP}. * Note: This uri may not be available in the future, and it is * up to the caller to ensure safety if this uri is re-used and/or persisted. */ @@ -272,6 +282,7 @@ public final class Icon implements Parcelable { case TYPE_DATA: return "DATA"; case TYPE_RESOURCE: return "RESOURCE"; case TYPE_URI: return "URI"; + case TYPE_URI_ADAPTIVE_BITMAP: return "URI_MASKABLE"; default: return "UNKNOWN"; } } @@ -380,28 +391,39 @@ public final class Icon implements Parcelable { BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(), getDataLength()) ); case TYPE_URI: - final Uri uri = getUri(); - final String scheme = uri.getScheme(); - InputStream is = null; - if (ContentResolver.SCHEME_CONTENT.equals(scheme) - || ContentResolver.SCHEME_FILE.equals(scheme)) { - try { - is = context.getContentResolver().openInputStream(uri); - } catch (Exception e) { - Log.w(TAG, "Unable to load image from URI: " + uri, e); - } - } else { - try { - is = new FileInputStream(new File(mString1)); - } catch (FileNotFoundException e) { - Log.w(TAG, "Unable to load image from path: " + uri, e); - } - } + InputStream is = getUriInputStream(context); if (is != null) { return new BitmapDrawable(context.getResources(), BitmapFactory.decodeStream(is)); } break; + case TYPE_URI_ADAPTIVE_BITMAP: + is = getUriInputStream(context); + if (is != null) { + return new AdaptiveIconDrawable(null, new BitmapDrawable(context.getResources(), + BitmapFactory.decodeStream(is))); + } + break; + } + return null; + } + + private InputStream getUriInputStream(Context context) { + final Uri uri = getUri(); + final String scheme = uri.getScheme(); + if (ContentResolver.SCHEME_CONTENT.equals(scheme) + || ContentResolver.SCHEME_FILE.equals(scheme)) { + try { + return context.getContentResolver().openInputStream(uri); + } catch (Exception e) { + Log.w(TAG, "Unable to load image from URI: " + uri, e); + } + } else { + try { + return new FileInputStream(new File(mString1)); + } catch (FileNotFoundException e) { + Log.w(TAG, "Unable to load image from path: " + uri, e); + } } return null; } @@ -475,6 +497,7 @@ public final class Icon implements Parcelable { dataStream.writeInt(getResId()); break; case TYPE_URI: + case TYPE_URI_ADAPTIVE_BITMAP: dataStream.writeUTF(getUriString()); break; } @@ -513,6 +536,9 @@ public final class Icon implements Parcelable { case TYPE_URI: final String uriOrPath = inputStream.readUTF(); return createWithContentUri(uriOrPath); + case TYPE_URI_ADAPTIVE_BITMAP: + final String uri = inputStream.readUTF(); + return createWithAdaptiveBitmapContentUri(uri); } } return null; @@ -545,6 +571,7 @@ public final class Icon implements Parcelable { return getResId() == otherIcon.getResId() && Objects.equals(getResPackage(), otherIcon.getResPackage()); case TYPE_URI: + case TYPE_URI_ADAPTIVE_BITMAP: return Objects.equals(getUriString(), otherIcon.getUriString()); } return false; @@ -665,12 +692,40 @@ public final class Icon implements Parcelable { if (uri == null) { throw new IllegalArgumentException("Uri must not be null."); } - final Icon rep = new Icon(TYPE_URI); - rep.mString1 = uri.toString(); + return createWithContentUri(uri.toString()); + } + + /** + * Create an Icon pointing to an image file specified by URI. Image file should follow the icon + * design guideline defined by {@link AdaptiveIconDrawable}. + * + * @param uri A uri referring to local content:// or file:// image data. + */ + @NonNull + public static Icon createWithAdaptiveBitmapContentUri(@NonNull String uri) { + if (uri == null) { + throw new IllegalArgumentException("Uri must not be null."); + } + final Icon rep = new Icon(TYPE_URI_ADAPTIVE_BITMAP); + rep.mString1 = uri; return rep; } /** + * Create an Icon pointing to an image file specified by URI. Image file should follow the icon + * design guideline defined by {@link AdaptiveIconDrawable}. + * + * @param uri A uri referring to local content:// or file:// image data. + */ + @NonNull + public static Icon createWithAdaptiveBitmapContentUri(@NonNull Uri uri) { + if (uri == null) { + throw new IllegalArgumentException("Uri must not be null."); + } + return createWithAdaptiveBitmapContentUri(uri.toString()); + } + + /** * Store a color to use whenever this Icon is drawn. * * @param tint a color, as in {@link Drawable#setTint(int)} @@ -758,6 +813,7 @@ public final class Icon implements Parcelable { } break; case TYPE_URI: + case TYPE_URI_ADAPTIVE_BITMAP: sb.append(" uri=").append(getUriString()); break; } @@ -809,6 +865,7 @@ public final class Icon implements Parcelable { mObj1 = a; break; case TYPE_URI: + case TYPE_URI_ADAPTIVE_BITMAP: final String uri = in.readString(); mString1 = uri; break; @@ -840,6 +897,7 @@ public final class Icon implements Parcelable { dest.writeBlob(getDataBytes(), getDataOffset(), getDataLength()); break; case TYPE_URI: + case TYPE_URI_ADAPTIVE_BITMAP: dest.writeString(getUriString()); break; } diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java index bc8a4cbd7e9d..005a4d175fd5 100644 --- a/graphics/java/android/graphics/drawable/InsetDrawable.java +++ b/graphics/java/android/graphics/drawable/InsetDrawable.java @@ -18,7 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 760d554888ee..fb4146f04bc9 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -18,7 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index 8561d95ddd88..99d27ba4c469 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -18,7 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 1540cc22e295..e5e4d4527fca 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -18,7 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java index db5f082bd853..43766b636adb 100644 --- a/graphics/java/android/graphics/drawable/RotateDrawable.java +++ b/graphics/java/android/graphics/drawable/RotateDrawable.java @@ -16,22 +16,22 @@ package android.graphics.drawable; -import com.android.internal.R; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; -import android.graphics.Canvas; -import android.graphics.Rect; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; -import android.content.res.TypedArray; import android.content.res.Resources.Theme; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.util.AttributeSet; import android.util.MathUtils; import android.util.TypedValue; -import android.util.AttributeSet; + +import com.android.internal.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java index 91ed061e511d..af7eed4b3897 100644 --- a/graphics/java/android/graphics/drawable/ScaleDrawable.java +++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java @@ -16,14 +16,9 @@ package android.graphics.drawable; -import com.android.internal.R; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; @@ -34,6 +29,11 @@ import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; +import com.android.internal.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import java.io.IOException; /** diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java index f67188c22609..2920acbe514c 100644 --- a/graphics/java/android/graphics/drawable/StateListDrawable.java +++ b/graphics/java/android/graphics/drawable/StateListDrawable.java @@ -18,7 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.Resources.Theme; import android.content.res.TypedArray; diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java index 276f3662189b..401e05ffc139 100644 --- a/graphics/java/android/graphics/drawable/TransitionDrawable.java +++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java @@ -16,7 +16,7 @@ package android.graphics.drawable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.Resources; import android.graphics.Canvas; diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index aa19b2a0e94c..e6fa866df3ab 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -16,7 +16,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.ComplexColor; diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java index 552088f7c478..ba96a06cc852 100644 --- a/graphics/java/android/graphics/fonts/Font.java +++ b/graphics/java/android/graphics/fonts/Font.java @@ -519,12 +519,13 @@ public final class Font { } Font f = (Font) o; return mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex - && Arrays.equals(f.mAxes, mAxes) && f.mBuffer.equals(mBuffer); + && Arrays.equals(f.mAxes, mAxes) && f.mBuffer.equals(mBuffer) + && Objects.equals(f.mLocaleList, mLocaleList); } @Override public int hashCode() { - return Objects.hash(mFontStyle, mTtcIndex, Arrays.hashCode(mAxes), mBuffer); + return Objects.hash(mFontStyle, mTtcIndex, Arrays.hashCode(mAxes), mBuffer, mLocaleList); } @Override diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java index bcee559d8291..4e6580ea5f53 100644 --- a/graphics/java/android/graphics/fonts/FontVariationAxis.java +++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java @@ -18,7 +18,7 @@ package android.graphics.fonts; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.text.TextUtils; diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index bd1a49205fd5..54710e58687c 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -19,7 +19,7 @@ package android.graphics.pdf; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Matrix; @@ -29,7 +29,9 @@ import android.os.ParcelFileDescriptor; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; + import com.android.internal.util.Preconditions; + import dalvik.system.CloseGuard; import libcore.io.IoUtils; diff --git a/graphics/java/android/graphics/pdf/TEST_MAPPING b/graphics/java/android/graphics/pdf/TEST_MAPPING new file mode 100644 index 000000000000..d763598f5ba0 --- /dev/null +++ b/graphics/java/android/graphics/pdf/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "CtsPdfTestCases" + } + ] +} |