1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.M; 4 import static org.robolectric.util.reflector.Reflector.reflector; 5 6 import android.annotation.Nullable; 7 import android.content.Context; 8 import android.graphics.Bitmap; 9 import android.graphics.drawable.Drawable; 10 import android.graphics.drawable.Icon; 11 import android.graphics.drawable.Icon.OnDrawableLoadedListener; 12 import android.net.Uri; 13 import android.os.Handler; 14 import android.os.Message; 15 import java.util.concurrent.Executor; 16 import org.robolectric.annotation.HiddenApi; 17 import org.robolectric.annotation.Implementation; 18 import org.robolectric.annotation.Implements; 19 import org.robolectric.annotation.RealObject; 20 import org.robolectric.util.reflector.Direct; 21 import org.robolectric.util.reflector.ForType; 22 23 @SuppressWarnings({"UnusedDeclaration"}) 24 @Implements(value = Icon.class, minSdk = M) 25 public class ShadowIcon { 26 27 @Nullable private static Executor executorOverride; 28 29 /** Set the executor where async drawable loading will run. */ overrideExecutor(Executor executor)30 public static void overrideExecutor(Executor executor) { 31 executorOverride = executor; 32 } 33 34 @RealObject private Icon realIcon; 35 36 @HiddenApi 37 @Implementation getType()38 public int getType() { 39 return reflector(IconReflector.class, realIcon).getType(); 40 } 41 42 @HiddenApi 43 @Implementation getResId()44 public int getResId() { 45 return reflector(IconReflector.class, realIcon).getResId(); 46 } 47 48 @HiddenApi 49 @Implementation getBitmap()50 public Bitmap getBitmap() { 51 return reflector(IconReflector.class, realIcon).getBitmap(); 52 } 53 54 @HiddenApi 55 @Implementation getUri()56 public Uri getUri() { 57 return reflector(IconReflector.class, realIcon).getUri(); 58 } 59 60 @HiddenApi 61 @Implementation getDataLength()62 public int getDataLength() { 63 return reflector(IconReflector.class, realIcon).getDataLength(); 64 } 65 66 @HiddenApi 67 @Implementation getDataOffset()68 public int getDataOffset() { 69 return reflector(IconReflector.class, realIcon).getDataOffset(); 70 } 71 72 @HiddenApi 73 @Implementation getDataBytes()74 public byte[] getDataBytes() { 75 return reflector(IconReflector.class, realIcon).getDataBytes(); 76 } 77 78 @Implementation loadDrawableAsync(Context context, Message andThen)79 protected void loadDrawableAsync(Context context, Message andThen) { 80 if (executorOverride != null) { 81 executorOverride.execute( 82 () -> { 83 andThen.obj = realIcon.loadDrawable(context); 84 andThen.sendToTarget(); 85 }); 86 } else { 87 reflector(IconReflector.class, realIcon).loadDrawableAsync(context, andThen); 88 } 89 } 90 91 @Implementation loadDrawableAsync( Context context, final OnDrawableLoadedListener listener, Handler handler)92 protected void loadDrawableAsync( 93 Context context, final OnDrawableLoadedListener listener, Handler handler) { 94 if (executorOverride != null) { 95 executorOverride.execute( 96 () -> { 97 Drawable result = realIcon.loadDrawable(context); 98 handler.post(() -> listener.onDrawableLoaded(result)); 99 }); 100 } else { 101 reflector(IconReflector.class, realIcon).loadDrawableAsync(context, listener, handler); 102 } 103 } 104 105 @ForType(Icon.class) 106 interface IconReflector { 107 108 @Direct getType()109 int getType(); 110 111 @Direct getResId()112 int getResId(); 113 114 @Direct getBitmap()115 Bitmap getBitmap(); 116 117 @Direct getUri()118 Uri getUri(); 119 120 @Direct getDataLength()121 int getDataLength(); 122 123 @Direct getDataOffset()124 int getDataOffset(); 125 126 @Direct getDataBytes()127 byte[] getDataBytes(); 128 129 @Direct loadDrawableAsync(Context context, Message andThen)130 void loadDrawableAsync(Context context, Message andThen); 131 132 @Direct loadDrawableAsync( Context context, final OnDrawableLoadedListener listener, Handler handler)133 void loadDrawableAsync( 134 Context context, final OnDrawableLoadedListener listener, Handler handler); 135 } 136 } 137