• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static org.robolectric.util.reflector.Reflector.reflector;
4 
5 import android.os.Handler;
6 import android.os.Message;
7 import org.robolectric.annotation.Implements;
8 import org.robolectric.annotation.LooperMode;
9 import org.robolectric.annotation.Resetter;
10 import org.robolectric.util.reflector.Accessor;
11 import org.robolectric.util.reflector.Direct;
12 import org.robolectric.util.reflector.ForType;
13 import org.robolectric.util.reflector.Static;
14 
15 /**
16  * The shadow API for {@link android.os.Message}.
17  *
18  * <p>Different shadow implementations will be used depending on the current {@link LooperMode}. See
19  * {@link ShadowLegacyMessage} and {@link ShadowPausedMessage} for details.
20  */
21 @Implements(value = Message.class, shadowPicker = ShadowMessage.Picker.class)
22 public abstract class ShadowMessage {
23 
24   /** The shadow Picker for this class */
25   public static class Picker extends LooperShadowPicker<ShadowMessage> {
26 
Picker()27     public Picker() {
28       super(ShadowLegacyMessage.class, ShadowPausedMessage.class);
29     }
30   }
31 
32   /** Exposes the package-private {@link Message#recycleUnchecked()} */
recycleUnchecked()33   public abstract void recycleUnchecked();
34 
35   /**
36    * Stores the {@link Runnable} instance that has been scheduled to invoke this message. This is
37    * called when the message is enqueued by {@link ShadowLegacyMessageQueue#enqueueMessage} and is
38    * used when the message is recycled to ensure that the correct {@link Runnable} instance is
39    * removed from the associated scheduler.
40    *
41    * @param r the {@link Runnable} instance that is scheduled to trigger this message.
42    *     <p>#if ($api >= 21) * @see #recycleUnchecked() #else * @see #recycle() #end
43    *     <p>Only supported in {@link LooperMode.Mode.LEGACY}.
44    */
setScheduledRunnable(Runnable r)45   public abstract void setScheduledRunnable(Runnable r);
46 
47   /**
48    * Convenience method to provide getter access to the private field {@code Message.next}.
49    *
50    * <p>Only supported in {@link LooperMode.Mode.LEGACY}
51    *
52    * @return The next message in the current message chain.
53    * @see #setNext(Message)
54    */
getNext()55   public abstract Message getNext();
56 
57   /**
58    * Convenience method to provide setter access to the private field {@code Message.next}.
59    *
60    * <p>Only supported in {@link LooperMode.Mode.LEGACY}
61    *
62    * @param next the new next message for the current message.
63    * @see #getNext()
64    */
setNext(Message next)65   public abstract void setNext(Message next);
66 
67   /**
68    * Resets the static state of the {@link Message} class by
69    * emptying the message pool.
70    */
71   @Resetter
reset()72   public static void reset() {
73     Object lock = reflector(MessageReflector.class).getPoolSync();
74     synchronized (lock) {
75       reflector(MessageReflector.class).setPoolSize(0);
76       reflector(MessageReflector.class).setPool(null);
77     }
78   }
79 
80   /** Accessor interface for {@link Message}'s internals. */
81   @ForType(Message.class)
82   interface MessageReflector {
83 
84     @Direct
recycle()85     void recycle();
86 
87     @Direct
recycleUnchecked()88     void recycleUnchecked();
89 
90     @Static
91     @Accessor("sPool")
setPool(Message o)92     void setPool(Message o);
93 
94     @Static
95     @Accessor("sPoolSize")
setPoolSize(int size)96     void setPoolSize(int size);
97 
98     @Static
99     @Accessor("sPoolSync")
getPoolSync()100     Object getPoolSync();
101 
102     @Accessor("when")
getWhen()103     long getWhen();
104 
105     @Accessor("next")
getNext()106     Message getNext();
107 
108     @Accessor("next")
setNext(Message next)109     void setNext(Message next);
110 
111     @Accessor("target")
getTarget()112     Handler getTarget();
113   }
114 }
115