@Override @Implementation public boolean equals(Object object) { if (!(object instanceof AccessibilityEvent)) { return false; } final AccessibilityEvent event = (AccessibilityEvent) object; final ShadowAccessibilityEvent otherShadow = (ShadowAccessibilityEvent) ShadowExtractor.extract(event); boolean areEqual = (eventType == otherShadow.eventType); areEqual &= (enabled == otherShadow.enabled); areEqual &= TextUtils.equals(contentDescription, otherShadow.contentDescription); areEqual &= TextUtils.equals(packageName, otherShadow.packageName); areEqual &= TextUtils.equals(className, otherShadow.className); boolean parcelableDataEqual = false; if (getParcelableData() == null && otherShadow.getParcelableData() == null) { parcelableDataEqual = true; } else if (getParcelableData().equals(otherShadow.getParcelableData())) { parcelableDataEqual = true; } areEqual &= parcelableDataEqual; return areEqual; }
@Implementation public static AccessibilityEvent obtain(AccessibilityEvent event) { ShadowAccessibilityEvent shadowEvent = ((ShadowAccessibilityEvent) ShadowExtractor.extract(event)); AccessibilityEvent obtainedInstance = shadowEvent.getClone(); sAllocationCount++; StrictEqualityEventWrapper wrapper = new StrictEqualityEventWrapper(obtainedInstance); obtainedInstances.put(wrapper, Thread.currentThread().getStackTrace()); orderedInstances.put(sAllocationCount, wrapper); return obtainedInstance; }
@Implementation public static AccessibilityEvent obtain(int eventType) { // We explicitly avoid allocating the AccessibilityEvent from the actual pool by using // the private constructor. Not doing so affects test suites which use both shadow and // non-shadow objects. final AccessibilityEvent obtainedInstance = ReflectionHelpers.callConstructor(AccessibilityEvent.class); final ShadowAccessibilityEvent shadowObtained = ((ShadowAccessibilityEvent) ShadowExtractor.extract(obtainedInstance)); sAllocationCount++; StrictEqualityEventWrapper wrapper = new StrictEqualityEventWrapper(obtainedInstance); obtainedInstances.put(wrapper, Thread.currentThread().getStackTrace()); orderedInstances.put(sAllocationCount, wrapper); shadowObtained.eventType = eventType; return obtainedInstance; }
/** * Check for leaked objects that were {@code obtain}ed but never {@code recycle}d. * * @param printUnrecycledEventsToSystemErr - if true, stack traces of calls to {@code obtain} that * lack matching calls to {@code recycle} are dumped to System.err. * @return {@code true} if there are unrecycled events */ public static boolean areThereUnrecycledEvents(boolean printUnrecycledEventsToSystemErr) { if (printUnrecycledEventsToSystemErr) { for (final StrictEqualityEventWrapper wrapper : obtainedInstances.keySet()) { final ShadowAccessibilityEvent shadow = ((ShadowAccessibilityEvent) ShadowExtractor.extract(wrapper.mEvent)); System.err.println( String.format( "Leaked AccessibilityEvent. Stack trace of allocation:", shadow.getContentDescription())); for (final StackTraceElement stackTraceElement : obtainedInstances.get(wrapper)) { System.err.println(stackTraceElement.toString()); } } } return (obtainedInstances.size() != 0); }
/** @return A shallow copy. */ private AccessibilityEvent getClone() { // We explicitly avoid allocating the AccessibilityEvent from the actual pool by using // the private constructor. Not doing so affects test suites which use both shadow and // non-shadow objects. final AccessibilityEvent newEvent = ReflectionHelpers.callConstructor(AccessibilityEvent.class); final ShadowAccessibilityEvent newShadow = (ShadowAccessibilityEvent) ShadowExtractor.extract(newEvent); newShadow.eventType = eventType; newShadow.contentDescription = contentDescription; newShadow.packageName = packageName; newShadow.className = className; newShadow.enabled = enabled; newShadow.setParcelableData(getParcelableData()); return newEvent; }