• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import android.os.Build;
4 import android.os.Build.VERSION_CODES;
5 import android.util.EventLog;
6 import java.util.ArrayList;
7 import java.util.Collection;
8 import java.util.List;
9 import org.robolectric.RuntimeEnvironment;
10 import org.robolectric.annotation.Implementation;
11 import org.robolectric.annotation.Implements;
12 import org.robolectric.annotation.Resetter;
13 import org.robolectric.shadow.api.Shadow;
14 
15 @Implements(EventLog.class)
16 public class ShadowEventLog {
17 
18   /**
19    * Constant written to the log if the parameter is null.
20    *
21    * <p>This matches how the real android code handles nulls.
22    */
23   static final String NULL_PLACE_HOLDER = "NULL";
24 
25   @Implements(EventLog.Event.class)
26   public static class ShadowEvent {
27 
28     private Object data;
29     private int tag;
30     private int processId;
31     private int threadId;
32     private long timeNanos;
33 
34     @Implementation
getData()35     protected Object getData() {
36       return data;
37     }
38 
39     @Implementation
getTag()40     protected int getTag() {
41       return tag;
42     }
43 
44     @Implementation
getProcessId()45     protected int getProcessId() {
46       return processId;
47     }
48 
49     @Implementation
getThreadId()50     protected int getThreadId() {
51       return threadId;
52     }
53 
54     @Implementation
getTimeNanos()55     protected long getTimeNanos() {
56       return timeNanos;
57     }
58   }
59 
60   private static final List<EventLog.Event> events = new ArrayList<>();
61 
62   /** Class to build {@link EventLog.Event} */
63   public static class EventBuilder {
64 
65     private final Object data;
66     private final int tag;
67     private int processId = ShadowProcess.myPid();
68     private int threadId = ShadowProcess.myTid();
69     private long timeNanos = System.nanoTime();
70 
EventBuilder(int tag, Object data)71     public EventBuilder(int tag, Object data) {
72       this.tag = tag;
73       this.data = data;
74     }
75 
setProcessId(int processId)76     public EventBuilder setProcessId(int processId) {
77       this.processId = processId;
78       return this;
79     }
80 
setThreadId(int threadId)81     public EventBuilder setThreadId(int threadId) {
82       this.threadId = threadId;
83       return this;
84     }
85 
setTimeNanos(long timeNanos)86     public EventBuilder setTimeNanos(long timeNanos) {
87       this.timeNanos = timeNanos;
88       return this;
89     }
90 
build()91     public EventLog.Event build() {
92       EventLog.Event event;
93       if (RuntimeEnvironment.getApiLevel() >= Build.VERSION_CODES.N) {
94         // Prefer a real factory method over reflection for construction.
95         event = EventLog.Event.fromBytes(new byte[0]);
96       } else {
97         event = Shadow.newInstanceOf(EventLog.Event.class);
98       }
99       ShadowEvent shadowEvent = Shadow.extract(event);
100       shadowEvent.data = data;
101       shadowEvent.tag = tag;
102       shadowEvent.processId = processId;
103       shadowEvent.threadId = threadId;
104       shadowEvent.timeNanos = timeNanos;
105       return event;
106     }
107   }
108 
109   /** Add event to {@link EventLog}. */
addEvent(EventLog.Event event)110   public static void addEvent(EventLog.Event event) {
111     events.add(event);
112   }
113 
114   @Resetter
clearAll()115   public static void clearAll() {
116     events.clear();
117   }
118 
119   /** Writes an event log message, returning an approximation of the bytes written. */
120   @Implementation
writeEvent(int tag, String str)121   protected static int writeEvent(int tag, String str) {
122     if (str == null) {
123       str = NULL_PLACE_HOLDER;
124     }
125     addEvent(new EventBuilder(tag, str).build());
126     return Integer.BYTES + str.length();
127   }
128 
129   /** Writes an event log message, returning an approximation of the bytes written. */
130   @Implementation
writeEvent(int tag, Object... list)131   protected static int writeEvent(int tag, Object... list) {
132     if (list == null) {
133       // This matches how the real android code handles nulls
134       return writeEvent(tag, (String) null);
135     }
136     addEvent(new EventBuilder(tag, list).build());
137     return Integer.BYTES + list.length * Integer.BYTES;
138   }
139 
140   /** Writes an event log message, returning an approximation of the bytes written. */
141   @Implementation
writeEvent(int tag, int value)142   protected static int writeEvent(int tag, int value) {
143     addEvent(new EventBuilder(tag, value).build());
144     return Integer.BYTES + Integer.BYTES;
145   }
146 
147   /** Writes an event log message, returning an approximation of the bytes written. */
148   @Implementation(minSdk = VERSION_CODES.M)
writeEvent(int tag, float value)149   protected static int writeEvent(int tag, float value) {
150     addEvent(new EventBuilder(tag, value).build());
151     return Integer.BYTES + Float.BYTES;
152   }
153 
154   /** Writes an event log message, returning an approximation of the bytes written. */
155   @Implementation
writeEvent(int tag, long value)156   protected static int writeEvent(int tag, long value) {
157     addEvent(new EventBuilder(tag, value).build());
158     return Integer.BYTES + Long.BYTES;
159   }
160 
161   @Implementation
readEvents(int[] tags, Collection<EventLog.Event> output)162   protected static void readEvents(int[] tags, Collection<EventLog.Event> output) {
163     for (EventLog.Event event : events) {
164       for (int tag : tags) {
165         if (tag == event.getTag()) {
166           output.add(event);
167           break;
168         }
169       }
170     }
171   }
172 }
173