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