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