1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.M;
4 import static android.os.Build.VERSION_CODES.N;
5 import static android.os.Build.VERSION_CODES.N_MR1;
6 import static android.os.Build.VERSION_CODES.O;
7 import static android.os.Build.VERSION_CODES.P;
8 import static android.os.Build.VERSION_CODES.Q;
9 import static android.os.Build.VERSION_CODES.R;
10 import static android.os.Build.VERSION_CODES.S;
11 import static org.robolectric.util.reflector.Reflector.reflector;
12 
13 import android.graphics.Bitmap;
14 import android.graphics.ColorSpace;
15 import android.graphics.ColorSpace.Rgb.TransferParameters;
16 import android.graphics.Matrix;
17 import android.hardware.HardwareBuffer;
18 import android.os.Parcel;
19 import android.os.Parcelable;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.nio.Buffer;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Map;
27 import org.robolectric.RuntimeEnvironment;
28 import org.robolectric.annotation.ClassName;
29 import org.robolectric.annotation.Implementation;
30 import org.robolectric.annotation.Implements;
31 import org.robolectric.annotation.Resetter;
32 import org.robolectric.nativeruntime.BitmapNatives;
33 import org.robolectric.nativeruntime.ColorSpaceRgbNatives;
34 import org.robolectric.nativeruntime.DefaultNativeRuntimeLoader;
35 import org.robolectric.nativeruntime.NativeAllocationRegistryNatives;
36 import org.robolectric.util.reflector.Accessor;
37 import org.robolectric.util.reflector.ForType;
38 import org.robolectric.util.reflector.Static;
39 import org.robolectric.versioning.AndroidVersions.U;
40 import org.robolectric.versioning.AndroidVersions.V;
41 
42 /** Shadow for {@link Bitmap} that is backed by native code */
43 @Implements(
44     value = Bitmap.class,
45     minSdk = O,
46     isInAndroidSdk = false,
47     callNativeMethodsByDefault = true)
48 public class ShadowNativeBitmap extends ShadowBitmap {
49   private int createdFromResId;
50 
51   private static final List<Long> colorSpaceAllocationsP =
52       Collections.synchronizedList(new ArrayList<>());
53 
54   /** Called by {@link ShadowNativeBitmapFactory}. */
setCreatedFromResId(int createdFromResId)55   void setCreatedFromResId(int createdFromResId) {
56     this.createdFromResId = createdFromResId;
57   }
58 
59   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeCreate( int[] colors, int offset, int stride, int width, int height, int nativeConfig, boolean mutable, long nativeColorSpace)60   protected static Bitmap nativeCreate(
61       int[] colors,
62       int offset,
63       int stride,
64       int width,
65       int height,
66       int nativeConfig,
67       boolean mutable,
68       long nativeColorSpace) {
69     DefaultNativeRuntimeLoader.injectAndLoad();
70     return BitmapNatives.nativeCreate(
71         colors, offset, stride, width, height, nativeConfig, mutable, nativeColorSpace);
72   }
73 
74   @Implementation(minSdk = O, maxSdk = P)
nativeCreate( int[] colors, int offset, int stride, int width, int height, int nativeConfig, boolean mutable, float[] xyzD50, ColorSpace.Rgb.TransferParameters p)75   protected static Bitmap nativeCreate(
76       int[] colors,
77       int offset,
78       int stride,
79       int width,
80       int height,
81       int nativeConfig,
82       boolean mutable,
83       float[] xyzD50,
84       ColorSpace.Rgb.TransferParameters p) {
85     DefaultNativeRuntimeLoader.injectAndLoad();
86     long colorSpacePtr = 0;
87     if (xyzD50 != null && p != null) {
88       colorSpacePtr =
89           ColorSpaceRgbNatives.nativeCreate(
90               (float) p.a,
91               (float) p.b,
92               (float) p.c,
93               (float) p.d,
94               (float) p.e,
95               (float) p.f,
96               (float) p.g,
97               xyzD50);
98       colorSpaceAllocationsP.add(colorSpacePtr);
99     }
100     return nativeCreate(
101         colors, offset, stride, width, height, nativeConfig, mutable, colorSpacePtr);
102   }
103 
104   @Implementation(maxSdk = U.SDK_INT)
nativeCopy(long nativeSrcBitmap, int nativeConfig, boolean isMutable)105   protected static Bitmap nativeCopy(long nativeSrcBitmap, int nativeConfig, boolean isMutable) {
106     return BitmapNatives.nativeCopy(nativeSrcBitmap, nativeConfig, isMutable);
107   }
108 
109   @Implementation(minSdk = M, maxSdk = U.SDK_INT)
nativeCopyAshmem(long nativeSrcBitmap)110   protected static Bitmap nativeCopyAshmem(long nativeSrcBitmap) {
111     return BitmapNatives.nativeCopyAshmem(nativeSrcBitmap);
112   }
113 
114   @Implementation(minSdk = N, maxSdk = U.SDK_INT)
nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig)115   protected static Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig) {
116     return BitmapNatives.nativeCopyAshmemConfig(nativeSrcBitmap, nativeConfig);
117   }
118 
119   @Implementation(minSdk = N, maxSdk = U.SDK_INT)
nativeGetNativeFinalizer()120   protected static long nativeGetNativeFinalizer() {
121     return BitmapNatives.nativeGetNativeFinalizer();
122   }
123 
124   @Implementation(maxSdk = P, methodName = "nativeRecycle")
nativeRecyclePreQ(long nativeBitmap)125   protected static boolean nativeRecyclePreQ(long nativeBitmap) {
126     BitmapNatives.nativeRecycle(nativeBitmap);
127     return true;
128   }
129 
130   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeRecycle(long nativeBitmap)131   protected static void nativeRecycle(long nativeBitmap) {
132     BitmapNatives.nativeRecycle(nativeBitmap);
133   }
134 
135   @Implementation(minSdk = O, maxSdk = U.SDK_INT)
nativeReconfigure( long nativeBitmap, int width, int height, int config, boolean isPremultiplied)136   protected static void nativeReconfigure(
137       long nativeBitmap, int width, int height, int config, boolean isPremultiplied) {
138     BitmapNatives.nativeReconfigure(nativeBitmap, width, height, config, isPremultiplied);
139   }
140 
141   @Implementation(maxSdk = U.SDK_INT)
nativeCompress( long nativeBitmap, int format, int quality, OutputStream stream, byte[] tempStorage)142   protected static boolean nativeCompress(
143       long nativeBitmap, int format, int quality, OutputStream stream, byte[] tempStorage) {
144     return BitmapNatives.nativeCompress(nativeBitmap, format, quality, stream, tempStorage);
145   }
146 
147   @Implementation(maxSdk = U.SDK_INT)
nativeErase(long nativeBitmap, int color)148   protected static void nativeErase(long nativeBitmap, int color) {
149     BitmapNatives.nativeErase(nativeBitmap, color);
150   }
151 
152   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeErase(long nativeBitmap, long colorSpacePtr, long color)153   protected static void nativeErase(long nativeBitmap, long colorSpacePtr, long color) {
154     BitmapNatives.nativeErase(nativeBitmap, colorSpacePtr, color);
155   }
156 
157   @Implementation(maxSdk = U.SDK_INT)
nativeRowBytes(long nativeBitmap)158   protected static int nativeRowBytes(long nativeBitmap) {
159     return BitmapNatives.nativeRowBytes(nativeBitmap);
160   }
161 
162   @Implementation(maxSdk = U.SDK_INT)
nativeConfig(long nativeBitmap)163   protected static int nativeConfig(long nativeBitmap) {
164     return BitmapNatives.nativeConfig(nativeBitmap);
165   }
166 
167   @Implementation(maxSdk = U.SDK_INT)
nativeGetPixel(long nativeBitmap, int x, int y)168   protected static int nativeGetPixel(long nativeBitmap, int x, int y) {
169     return BitmapNatives.nativeGetPixel(nativeBitmap, x, y);
170   }
171 
172   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeGetColor(long nativeBitmap, int x, int y)173   protected static long nativeGetColor(long nativeBitmap, int x, int y) {
174     return BitmapNatives.nativeGetColor(nativeBitmap, x, y);
175   }
176 
177   @Implementation(maxSdk = U.SDK_INT)
nativeGetPixels( long nativeBitmap, int[] pixels, int offset, int stride, int x, int y, int width, int height)178   protected static void nativeGetPixels(
179       long nativeBitmap,
180       int[] pixels,
181       int offset,
182       int stride,
183       int x,
184       int y,
185       int width,
186       int height) {
187     BitmapNatives.nativeGetPixels(nativeBitmap, pixels, offset, stride, x, y, width, height);
188   }
189 
190   @Implementation(maxSdk = U.SDK_INT)
nativeSetPixel(long nativeBitmap, int x, int y, int color)191   protected static void nativeSetPixel(long nativeBitmap, int x, int y, int color) {
192     BitmapNatives.nativeSetPixel(nativeBitmap, x, y, color);
193   }
194 
195   @Implementation(maxSdk = U.SDK_INT)
nativeSetPixels( long nativeBitmap, int[] colors, int offset, int stride, int x, int y, int width, int height)196   protected static void nativeSetPixels(
197       long nativeBitmap,
198       int[] colors,
199       int offset,
200       int stride,
201       int x,
202       int y,
203       int width,
204       int height) {
205     BitmapNatives.nativeSetPixels(nativeBitmap, colors, offset, stride, x, y, width, height);
206   }
207 
208   @Implementation(maxSdk = U.SDK_INT)
nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst)209   protected static void nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst) {
210     BitmapNatives.nativeCopyPixelsToBuffer(nativeBitmap, dst);
211   }
212 
213   @Implementation(maxSdk = U.SDK_INT)
nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src)214   protected static void nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src) {
215     BitmapNatives.nativeCopyPixelsFromBuffer(nativeBitmap, src);
216   }
217 
218   @Implementation(maxSdk = U.SDK_INT)
nativeGenerationId(long nativeBitmap)219   protected static int nativeGenerationId(long nativeBitmap) {
220     return BitmapNatives.nativeGenerationId(nativeBitmap);
221   }
222 
223   // returns a new bitmap built from the native bitmap's alpha, and the paint
224   @Implementation(maxSdk = U.SDK_INT)
nativeExtractAlpha(long nativeBitmap, long nativePaint, int[] offsetXY)225   protected static Bitmap nativeExtractAlpha(long nativeBitmap, long nativePaint, int[] offsetXY) {
226     return BitmapNatives.nativeExtractAlpha(nativeBitmap, nativePaint, offsetXY);
227   }
228 
229   @Implementation(maxSdk = U.SDK_INT)
nativeHasAlpha(long nativeBitmap)230   protected static boolean nativeHasAlpha(long nativeBitmap) {
231     return BitmapNatives.nativeHasAlpha(nativeBitmap);
232   }
233 
234   @Implementation(maxSdk = U.SDK_INT)
nativeIsPremultiplied(long nativeBitmap)235   protected static boolean nativeIsPremultiplied(long nativeBitmap) {
236     return BitmapNatives.nativeIsPremultiplied(nativeBitmap);
237   }
238 
239   @Implementation(maxSdk = U.SDK_INT)
nativeSetPremultiplied(long nativeBitmap, boolean isPremul)240   protected static void nativeSetPremultiplied(long nativeBitmap, boolean isPremul) {
241     BitmapNatives.nativeSetPremultiplied(nativeBitmap, isPremul);
242   }
243 
244   @Implementation(maxSdk = U.SDK_INT)
nativeSetHasAlpha( long nativeBitmap, boolean hasAlpha, boolean requestPremul)245   protected static void nativeSetHasAlpha(
246       long nativeBitmap, boolean hasAlpha, boolean requestPremul) {
247     BitmapNatives.nativeSetHasAlpha(nativeBitmap, hasAlpha, requestPremul);
248   }
249 
250   @Implementation(maxSdk = U.SDK_INT)
nativeHasMipMap(long nativeBitmap)251   protected static boolean nativeHasMipMap(long nativeBitmap) {
252     return BitmapNatives.nativeHasMipMap(nativeBitmap);
253   }
254 
255   @Implementation(maxSdk = U.SDK_INT)
nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap)256   protected static void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap) {
257     BitmapNatives.nativeSetHasMipMap(nativeBitmap, hasMipMap);
258   }
259 
260   @Implementation(maxSdk = U.SDK_INT)
nativeSameAs(long nativeBitmap0, long nativeBitmap1)261   protected static boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1) {
262     return BitmapNatives.nativeSameAs(nativeBitmap0, nativeBitmap1);
263   }
264 
265   @Implementation(minSdk = N_MR1, maxSdk = U.SDK_INT)
nativePrepareToDraw(long nativeBitmap)266   protected static void nativePrepareToDraw(long nativeBitmap) {
267     BitmapNatives.nativePrepareToDraw(nativeBitmap);
268   }
269 
270   @Implementation(minSdk = O, maxSdk = U.SDK_INT)
nativeGetAllocationByteCount(long nativeBitmap)271   protected static int nativeGetAllocationByteCount(long nativeBitmap) {
272     return BitmapNatives.nativeGetAllocationByteCount(nativeBitmap);
273   }
274 
275   @Implementation(minSdk = O, maxSdk = U.SDK_INT)
nativeCopyPreserveInternalConfig(long nativeBitmap)276   protected static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) {
277     return BitmapNatives.nativeCopyPreserveInternalConfig(nativeBitmap);
278   }
279 
280   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeWrapHardwareBufferBitmap( HardwareBuffer buffer, long nativeColorSpace)281   protected static Bitmap nativeWrapHardwareBufferBitmap(
282       HardwareBuffer buffer, long nativeColorSpace) {
283     return BitmapNatives.nativeWrapHardwareBufferBitmap(buffer, nativeColorSpace);
284   }
285 
286   @Implementation(minSdk = R, maxSdk = U.SDK_INT)
nativeGetHardwareBuffer(long nativeBitmap)287   protected static HardwareBuffer nativeGetHardwareBuffer(long nativeBitmap) {
288     return BitmapNatives.nativeGetHardwareBuffer(nativeBitmap);
289   }
290 
291   @Implementation(minSdk = O, maxSdk = P)
nativeGetColorSpace(long nativePtr, float[] xyz, float[] params)292   protected static boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params) {
293     ColorSpace colorSpace = nativeComputeColorSpace(nativePtr);
294     if (colorSpace == null) {
295       return false;
296     }
297     // In Android P, 'nativeGetColorSpace' is responsible for filling out the 'xyz' and 'params'
298     // float arrays. However, in Q and above, 'nativeGetColorSpace' was removed, and
299     // 'nativeComputeColorSpace' returns the ColorSpace object itself. This means for P, we need to
300     // do the reverse operations and generate the float arrays given the detected color space.
301     if (colorSpace instanceof ColorSpace.Rgb) {
302       TransferParameters transferParameters = ((ColorSpace.Rgb) colorSpace).getTransferParameters();
303       params[0] = (float) transferParameters.a;
304       params[1] = (float) transferParameters.b;
305       params[2] = (float) transferParameters.c;
306       params[3] = (float) transferParameters.d;
307       params[4] = (float) transferParameters.e;
308       params[5] = (float) transferParameters.f;
309       params[6] = (float) transferParameters.g;
310       ColorSpace.Rgb rgb =
311           (ColorSpace.Rgb)
312               ColorSpace.adapt(
313                   colorSpace, reflector(ColorSpaceReflector.class).getIlluminantD50XYZ());
314       rgb.getTransform(xyz);
315     }
316     return true;
317   }
318 
319   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeComputeColorSpace(long nativePtr)320   protected static ColorSpace nativeComputeColorSpace(long nativePtr) {
321     return BitmapNatives.nativeComputeColorSpace(nativePtr);
322   }
323 
324   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeSetColorSpace(long nativePtr, long nativeColorSpace)325   protected static void nativeSetColorSpace(long nativePtr, long nativeColorSpace) {
326     BitmapNatives.nativeSetColorSpace(nativePtr, nativeColorSpace);
327   }
328 
329   @Implementation(minSdk = O, maxSdk = U.SDK_INT)
nativeIsSRGB(long nativePtr)330   protected static boolean nativeIsSRGB(long nativePtr) {
331     return BitmapNatives.nativeIsSRGB(nativePtr);
332   }
333 
334   @Implementation(minSdk = P, maxSdk = U.SDK_INT)
nativeIsSRGBLinear(long nativePtr)335   protected static boolean nativeIsSRGBLinear(long nativePtr) {
336     return BitmapNatives.nativeIsSRGBLinear(nativePtr);
337   }
338 
339   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeSetImmutable(long nativePtr)340   protected static void nativeSetImmutable(long nativePtr) {
341     BitmapNatives.nativeSetImmutable(nativePtr);
342   }
343 
344   @Implementation(minSdk = Q, maxSdk = U.SDK_INT)
nativeIsImmutable(long nativePtr)345   protected static boolean nativeIsImmutable(long nativePtr) {
346     return BitmapNatives.nativeIsImmutable(nativePtr);
347   }
348 
349   @Implementation(minSdk = S, maxSdk = U.SDK_INT)
nativeIsBackedByAshmem(long nativePtr)350   protected static boolean nativeIsBackedByAshmem(long nativePtr) {
351     return BitmapNatives.nativeIsBackedByAshmem(nativePtr);
352   }
353 
354   /**
355    * This is called by {@link Bitmap#getGainmap} to check if a Gainmap exists for the Bitmap. This
356    * method must be present in Android U and below to avoid an UnsatisfiedLinkError.
357    */
358   @Implementation(minSdk = U.SDK_INT)
nativeExtractGainmap( long nativePtr)359   protected static @ClassName("android.graphics.Gainmap") Object nativeExtractGainmap(
360       long nativePtr) {
361     // No-op implementation
362     return null;
363   }
364 
365   @ForType(ColorSpace.class)
366   interface ColorSpaceReflector {
367     @Accessor("ILLUMINANT_D50_XYZ")
368     @Static
getIlluminantD50XYZ()369     float[] getIlluminantD50XYZ();
370 
371     @Accessor("sNamedColorSpaces")
getNamedColorSpaces()372     ColorSpace[] getNamedColorSpaces();
373 
374     @Accessor("sNamedColorSpaceMap")
getNamedColorSpaceMap()375     Map<Integer, ColorSpace> getNamedColorSpaceMap();
376   }
377 
378   @Implementation
writeToParcel(Parcel p, int flags)379   protected void writeToParcel(Parcel p, int flags) {
380     // Modeled after
381     // https://cs.android.com/android/platform/superproject/+/android-12.0.0_r1:frameworks/base/libs/hwui/jni/Bitmap.cpp;l=872.
382     reflector(BitmapReflector.class, realBitmap).checkRecycled("Can't parcel a recycled bitmap");
383     int width = realBitmap.getWidth();
384     int height = realBitmap.getHeight();
385     p.writeInt(width);
386     p.writeInt(height);
387     p.writeInt(realBitmap.getDensity());
388     p.writeBoolean(realBitmap.isMutable());
389     p.writeSerializable(realBitmap.getConfig());
390     ColorSpace colorSpace = realBitmap.getColorSpace();
391     boolean hasColorSpace = colorSpace != null;
392     p.writeBoolean(hasColorSpace);
393     if (hasColorSpace) {
394       p.writeString(colorSpace.getName());
395     }
396     p.writeBoolean(realBitmap.hasAlpha());
397     int[] pixels = new int[width * height];
398     realBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
399     p.writeIntArray(pixels);
400 
401     if (RuntimeEnvironment.getApiLevel() >= U.SDK_INT) {
402       Object gainmap = reflector(BitmapReflector.class, realBitmap).getGainmap();
403       if (gainmap != null) {
404         p.writeBoolean(true);
405         p.writeTypedObject((Parcelable) gainmap, flags);
406       } else {
407         p.writeBoolean(false);
408       }
409     }
410   }
411 
412   @Implementation
nativeCreateFromParcel(Parcel p)413   protected static Bitmap nativeCreateFromParcel(Parcel p) {
414     int parceledWidth = p.readInt();
415     int parceledHeight = p.readInt();
416     int density = p.readInt();
417     boolean mutable = p.readBoolean();
418     Bitmap.Config parceledConfig = (Bitmap.Config) p.readSerializable();
419     ColorSpace colorSpace = null;
420     boolean hasColorSpace = p.readBoolean();
421     if (hasColorSpace) {
422       String colorSpaceName = p.readString();
423       ColorSpace[] namedColorSpaces;
424       if (RuntimeEnvironment.getApiLevel() >= V.SDK_INT) {
425         // Starting Android V, we need to access the color space map to get all supported color
426         // spaces.
427         Map<Integer, ColorSpace> namedColorSpaceMap =
428             reflector(ColorSpaceReflector.class).getNamedColorSpaceMap();
429         namedColorSpaces =
430             namedColorSpaceMap.values().toArray(new ColorSpace[namedColorSpaceMap.size()]);
431       } else {
432         // Before V, we directly access the color space array.
433         namedColorSpaces = reflector(ColorSpaceReflector.class).getNamedColorSpaces();
434       }
435 
436       for (ColorSpace named : namedColorSpaces) {
437         if (named.getName().equals(colorSpaceName)) {
438           colorSpace = named;
439           break;
440         }
441       }
442     }
443     boolean hasAlpha = p.readBoolean();
444     int[] parceledColors = new int[parceledHeight * parceledWidth];
445     p.readIntArray(parceledColors);
446     Bitmap bitmap;
447     if (colorSpace != null) {
448       bitmap =
449           Bitmap.createBitmap(parceledWidth, parceledHeight, parceledConfig, hasAlpha, colorSpace);
450     } else {
451       bitmap = Bitmap.createBitmap(parceledWidth, parceledHeight, parceledConfig, hasAlpha);
452     }
453     bitmap.setPixels(parceledColors, 0, parceledWidth, 0, 0, parceledWidth, parceledHeight);
454     bitmap.setDensity(density);
455     if (!mutable) {
456       bitmap = bitmap.copy(parceledConfig, false);
457     }
458     return bitmap;
459   }
460 
461   @Implementation(minSdk = O, maxSdk = P)
nativeCopyColorSpace(long srcBitmap, long dstBitmap)462   protected static void nativeCopyColorSpace(long srcBitmap, long dstBitmap) {
463     BitmapNatives.nativeCopyColorSpaceP(srcBitmap, dstBitmap);
464   }
465 
466   @Override
getCreatedFromBitmap()467   public Bitmap getCreatedFromBitmap() {
468     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
469   }
470 
471   /**
472    * Resource ID from which this Bitmap was created.
473    *
474    * @return Resource ID from which this Bitmap was created, or {@code 0} if this Bitmap was not
475    *     created from a resource.
476    */
477   @Override
getCreatedFromResId()478   public int getCreatedFromResId() {
479     return createdFromResId;
480   }
481 
482   @Override
getCreatedFromPath()483   public String getCreatedFromPath() {
484     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
485   }
486 
487   @Override
getCreatedFromStream()488   public InputStream getCreatedFromStream() {
489     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
490   }
491 
492   @Override
getCreatedFromBytes()493   public byte[] getCreatedFromBytes() {
494     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
495   }
496 
497   @Override
getCreatedFromX()498   public int getCreatedFromX() {
499     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
500   }
501 
502   @Override
getCreatedFromY()503   public int getCreatedFromY() {
504     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
505   }
506 
507   @Override
getCreatedFromWidth()508   public int getCreatedFromWidth() {
509     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
510   }
511 
512   @Override
getCreatedFromHeight()513   public int getCreatedFromHeight() {
514     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
515   }
516 
517   @Override
getCreatedFromColors()518   public int[] getCreatedFromColors() {
519     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
520   }
521 
522   @Override
getCreatedFromMatrix()523   public Matrix getCreatedFromMatrix() {
524     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
525   }
526 
527   @Override
getCreatedFromFilter()528   public boolean getCreatedFromFilter() {
529     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
530   }
531 
532   @Override
setMutable(boolean mutable)533   public void setMutable(boolean mutable) {
534     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
535   }
536 
537   @Override
appendDescription(String s)538   public void appendDescription(String s) {
539     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
540   }
541 
542   @Override
getDescription()543   public String getDescription() {
544     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
545   }
546 
547   @Override
setDescription(String s)548   public void setDescription(String s) {
549     throw new UnsupportedOperationException("Legacy ShadowBitmap APIs are not supported");
550   }
551 
552   @Resetter
reset()553   public static void reset() {
554     synchronized (colorSpaceAllocationsP) {
555       for (Long ptr : colorSpaceAllocationsP) {
556         NativeAllocationRegistryNatives.applyFreeFunction(
557             ColorSpaceRgbNatives.nativeGetNativeFinalizer(), ptr);
558       }
559       colorSpaceAllocationsP.clear();
560     }
561   }
562 }
563