ViewDebug.java revision a1f3e4aef19882b4b81075d9205bd363efe1e66d
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 20c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.util.DisplayMetrics; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 22105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.Context; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 24c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.graphics.Canvas; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Environment; 26c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.os.Debug; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedWriter; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileWriter; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.DataOutputStream; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStreamWriter; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedOutputStream; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.LinkedList; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.CountDownLatch; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.TimeUnit; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.annotation.Target; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.annotation.ElementType; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.annotation.Retention; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.annotation.RetentionPolicy; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Field; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Method; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.InvocationTargetException; 50c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport java.lang.reflect.AccessibleObject; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Various debugging/tracing tools related to {@link View} and the view hierarchy. 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ViewDebug { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5713922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * Log tag used to log errors related to the consistency of the view hierarchy. 5813922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * 5913922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * @hide 6013922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy */ 6113922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy public static final String CONSISTENCY_LOG_TAG = "ViewConsistency"; 6213922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 6313922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy /** 6413922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * Flag indicating the consistency check should check layout-related properties. 6513922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * 6613922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * @hide 6713922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy */ 6813922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy public static final int CONSISTENCY_LAYOUT = 0x1; 6913922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 7013922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy /** 7113922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * Flag indicating the consistency check should check drawing-related properties. 7213922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * 7313922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * @hide 7413922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy */ 7513922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy public static final int CONSISTENCY_DRAWING = 0x2; 7613922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 7713922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy /** 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables or disables view hierarchy tracing. Any invoker of 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #trace(View, android.view.ViewDebug.HierarchyTraceType)} should first 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * check that this value is set to true as not to affect performance. 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final boolean TRACE_HIERARCHY = false; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables or disables view recycler tracing. Any invoker of 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #trace(View, android.view.ViewDebug.RecyclerTraceType, int[])} should first 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * check that this value is set to true as not to affect performance. 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final boolean TRACE_RECYCLER = false; 90a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The system property of dynamic switch for capturing view information 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when it is set, we dump interested fields and methods for the view on focus 94a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview"; 96a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The system property of dynamic switch for capturing event information 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when it is set, we log key events, touch/motion and trackball events 100a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent"; 102c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10413922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * Profiles drawing times in the events log. 10513922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * 10613922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * @hide 10713922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy */ 10813922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy @Debug.DebugProperty 10913922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy public static boolean profileDrawing = false; 11013922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 11113922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy /** 11213922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * Profiles layout times in the events log. 11313922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * 11413922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * @hide 11513922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy */ 11613922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy @Debug.DebugProperty 11713922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy public static boolean profileLayout = false; 11813922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 11913922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy /** 12013922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * Profiles real fps (times between draws) and displays the result. 12113922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * 12213922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * @hide 12313922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy */ 12413922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy @Debug.DebugProperty 12513922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy public static boolean showFps = false; 12613922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 12713922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy /** 12813922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * <p>Enables or disables views consistency check. Even when this property is enabled, 12913922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * view consistency checks happen only if {@link android.util.Config#DEBUG} is set 13013922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * to true. The value of this property can be configured externally in one of the 13113922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * following files:</p> 13213922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * <ul> 13313922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * <li>/system/debug.prop</li> 13413922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * <li>/debug.prop</li> 13513922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * <li>/data/debug.prop</li> 13613922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * </ul> 13713922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy * @hide 13813922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy */ 13913922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy @Debug.DebugProperty 14013922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy public static boolean consistencyCheckEnabled = false; 14113922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 14213922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy static { 14313922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy Debug.setFieldsOn(ViewDebug.class, true); 14413922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy } 14513922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy 14613922e03037d71a538f24ddf61c0b61bb4eb5af0Romain Guy /** 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This annotation can be used to mark fields and methods to be dumped by 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the view server. Only non-void methods with no arguments can be annotated 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by this annotation. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.FIELD, ElementType.METHOD }) 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface ExportedProperty { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When resolveId is true, and if the annotated field/method return value 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is an int, the value is converted to an Android's resource name. 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the property's value must be transformed into an Android 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * resource name, false otherwise 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean resolveId() default false; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A mapping can be defined to map int values to specific strings. For 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance, View.getVisibility() returns 0, 4 or 8. However, these values 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * actually mean VISIBLE, INVISIBLE and GONE. A mapping can be used to see 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * these human readable values: 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.ExportedProperty(mapping = { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 0, to = "VISIBLE"), 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 4, to = "INVISIBLE"), 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 8, to = "GONE") 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }) 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public int getVisibility() { ... 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An array of int to String mappings 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.ViewDebug.IntToString 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntToString[] mapping() default { }; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 185c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * A mapping can be defined to map array indices to specific strings. 186c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * A mapping can be used to see human readable values for the indices 187c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * of an array: 188c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 189c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <pre> 190809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.ExportedProperty(indexMapping = { 191c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 0, to = "INVALID"), 192c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 1, to = "FIRST"), 193c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 2, to = "SECOND") 194c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * }) 195c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * private int[] mElements; 196c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <pre> 197c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 198c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @return An array of int to String mappings 199c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 200c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @see android.view.ViewDebug.IntToString 201c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @see #mapping() 202c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project */ 203c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project IntToString[] indexMapping() default { }; 204c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 205c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project /** 206809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * A flags mapping can be defined to map flags encoded in an integer to 207809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * specific strings. A mapping can be used to see human readable values 208809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * for the flags of an integer: 209809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 210809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <pre> 211809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.ExportedProperty(flagMapping = { 212809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = ENABLED, name = "ENABLED"), 213809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = DISABLED, name = "DISABLED"), 214809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * }) 215809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * private int mFlags; 216809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <pre> 217809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 218809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * A specified String is output when the following is true: 219a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * 220809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An array of int to String mappings 221809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 222809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy FlagToString[] flagMapping() default { }; 223809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 224809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When deep export is turned on, this property is not dumped. Instead, the 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * properties contained in this property are dumped. Each child property 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is prefixed with the name of this property. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the properties of this property should be dumped 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 231a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * @see #prefix() 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean deepExport() default false; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The prefix to use on child properties when deep export is enabled 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a prefix as a String 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #deepExport() 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String prefix() default ""; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines a mapping from an int value to a String. Such a mapping can be used 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in a @ExportedProperty to provide more meaningful values to the end user. 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.ViewDebug.ExportedProperty 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.TYPE }) 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface IntToString { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The original int value to map to a String. 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An arbitrary int value. 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int from(); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The String to use in place of the original int value. 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An arbitrary non-null String. 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String to(); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 268809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 269809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 270809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * Defines a mapping from an flag to a String. Such a mapping can be used 271809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * in a @ExportedProperty to provide more meaningful values to the end user. 272809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 273809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @see android.view.ViewDebug.ExportedProperty 274809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 275809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy @Target({ ElementType.TYPE }) 276809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy @Retention(RetentionPolicy.RUNTIME) 277809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy public @interface FlagToString { 278809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 279809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The mask to apply to the original value. 280809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 281809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary int value. 282809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 283809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int mask(); 284809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 285809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 286809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The value to compare to the result of: 287809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <code>original value & {@link #mask()}</code>. 288809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 289809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary value. 290809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 291809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int equals(); 292809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 293809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 294809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The String to use in place of the original int value. 295809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 296809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary non-null String. 297809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 298809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy String name(); 299809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 300809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 301809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * Indicates whether to output the flag when the test is true, 302809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * or false. Defaults to true. 303809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 304809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy boolean outputIf() default true; 305809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 306809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This annotation can be used to mark fields and methods to be dumped when 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the view is captured. Methods with this annotation must have no arguments 310f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler * and must return a valid type of data. 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.FIELD, ElementType.METHOD }) 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface CapturedViewProperty { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 316a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * When retrieveReturn is true, we need to retrieve second level methods 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod() 318a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * we will set retrieveReturn = true on the annotation of 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * myView.getFirstLevelMethod() 320a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * @return true if we need the second level methods 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 322a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy boolean retrieveReturn() default false; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 324a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Maximum delay in ms after which we stop trying to capture a View's drawing 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int CAPTURE_TIMEOUT = 4000; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE"; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_DUMP = "DUMP"; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; 335c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static final String REMOTE_PROFILE = "PROFILE"; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Field[]> sFieldsForClasses; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Method[]> sMethodsForClasses; 339c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static HashMap<AccessibleObject, ExportedProperty> sAnnotations; 340c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines the type of hierarhcy trace to output to the hierarchy traces file. 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum HierarchyTraceType { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE, 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE_CHILD, 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE_CHILD_IN_PARENT, 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project REQUEST_LAYOUT, 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ON_LAYOUT, 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ON_MEASURE, 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DRAW, 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BUILD_CACHE 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static BufferedWriter sHierarchyTraces; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static ViewRoot sHierarhcyRoot; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String sHierarchyTracePrefix; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines the type of recycler trace to output to the recycler traces file. 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum RecyclerTraceType { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NEW_VIEW, 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BIND_VIEW, 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RECYCLE_FROM_ACTIVE_HEAP, 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RECYCLE_FROM_SCRAP_HEAP, 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MOVE_TO_ACTIVE_HEAP, 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MOVE_TO_SCRAP_HEAP, 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MOVE_FROM_ACTIVE_TO_SCRAP_HEAP 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class RecyclerTrace { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int view; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public RecyclerTraceType type; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int position; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int indexOnScreen; 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static View sRecyclerOwnerView; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static List<View> sRecyclerViews; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static List<RecyclerTrace> sRecyclerTraces; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String sRecyclerTracePrefix; 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of instanciated Views. 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The number of Views instanciated in the current process. 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getViewInstanceCount() { 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return View.sInstanceCount; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of instanciated ViewRoots. 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The number of ViewRoots instanciated in the current process. 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getViewRootInstanceCount() { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ViewRoot.getInstanceCount(); 404a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Outputs a trace to the currently opened recycler traces. The trace records the type of 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * recycler action performed on the supplied view as well as a number of parameters. 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view the view to trace 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param type the type of the trace 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parameters parameters depending on the type of the trace 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void trace(View view, RecyclerTraceType type, int... parameters) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sRecyclerOwnerView == null || sRecyclerViews == null) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!sRecyclerViews.contains(view)) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerViews.add(view); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int index = sRecyclerViews.indexOf(view); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RecyclerTrace trace = new RecyclerTrace(); 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trace.view = index; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trace.type = type; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trace.position = parameters[0]; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project trace.indexOnScreen = parameters[1]; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerTraces.add(trace); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Starts tracing the view recycler of the specified view. The trace is identified by a prefix, 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * used to build the traces files names: <code>/EXTERNAL/view-recycler/PREFIX.traces</code> and 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>/EXTERNAL/view-recycler/PREFIX.recycler</code>. 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Only one view recycler can be traced at the same time. After calling this method, any 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * other invocation will result in a <code>IllegalStateException</code> unless 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #stopRecyclerTracing()} is invoked before. 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Traces files are created only after {@link #stopRecyclerTracing()} is invoked. 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method will return immediately if TRACE_RECYCLER is false. 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param prefix the traces files name prefix 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view the view whose recycler must be traced 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #stopRecyclerTracing() 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #trace(View, android.view.ViewDebug.RecyclerTraceType, int[]) 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void startRecyclerTracing(String prefix, View view) { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection PointlessBooleanExpression,ConstantConditions 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TRACE_RECYCLER) { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sRecyclerOwnerView != null) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("You must call stopRecyclerTracing() before running" + 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " a new trace!"); 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerTracePrefix = prefix; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerOwnerView = view; 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerViews = new ArrayList<View>(); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerTraces = new LinkedList<RecyclerTrace>(); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Stops the current view recycer tracing. 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calling this method creates the file <code>/EXTERNAL/view-recycler/PREFIX.traces</code> 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * containing all the traces (or method calls) relative to the specified view's recycler. 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calling this method creates the file <code>/EXTERNAL/view-recycler/PREFIX.recycler</code> 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * containing all of the views used by the recycler of the view supplied to 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #startRecyclerTracing(String, View)}. 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method will return immediately if TRACE_RECYCLER is false. 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #startRecyclerTracing(String, View) 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #trace(View, android.view.ViewDebug.RecyclerTraceType, int[]) 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stopRecyclerTracing() { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection PointlessBooleanExpression,ConstantConditions 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TRACE_RECYCLER) { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sRecyclerOwnerView == null || sRecyclerViews == null) { 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("You must call startRecyclerTracing() before" + 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " stopRecyclerTracing()!"); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/"); 497c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project //noinspection ResultOfMethodCallIgnored 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recyclerDump.mkdirs(); 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".recycler"); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final BufferedWriter out = new BufferedWriter(new FileWriter(recyclerDump), 8 * 1024); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (View view : sRecyclerViews) { 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String name = view.getClass().getName(); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(name); 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e("View", "Could not dump recycler content"); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/"); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".traces"); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final FileOutputStream file = new FileOutputStream(recyclerDump); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final DataOutputStream out = new DataOutputStream(file); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (RecyclerTrace trace : sRecyclerTraces) { 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeInt(trace.view); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeInt(trace.type.ordinal()); 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeInt(trace.position); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeInt(trace.indexOnScreen); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.flush(); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e("View", "Could not dump recycler traces"); 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerViews.clear(); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerViews = null; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerTraces.clear(); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerTraces = null; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sRecyclerOwnerView = null; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Outputs a trace to the currently opened traces file. The trace contains the class name 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and instance's hashcode of the specified view as well as the supplied trace type. 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view the view to trace 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param type the type of the trace 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void trace(View view, HierarchyTraceType type) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sHierarchyTraces == null) { 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces.write(type.name()); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces.write(' '); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces.write(view.getClass().getName()); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces.write('@'); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces.write(Integer.toHexString(view.hashCode())); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces.newLine(); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w("View", "Error while dumping trace of type " + type + " for view " + view); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Starts tracing the view hierarchy of the specified view. The trace is identified by a prefix, 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * used to build the traces files names: <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code> and 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>/EXTERNAL/view-hierarchy/PREFIX.tree</code>. 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Only one view hierarchy can be traced at the same time. After calling this method, any 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * other invocation will result in a <code>IllegalStateException</code> unless 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #stopHierarchyTracing()} is invoked before. 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calling this method creates the file <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code> 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * containing all the traces (or method calls) relative to the specified view's hierarchy. 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method will return immediately if TRACE_HIERARCHY is false. 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param prefix the traces files name prefix 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view the view whose hierarchy must be traced 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #stopHierarchyTracing() 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #trace(View, android.view.ViewDebug.HierarchyTraceType) 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void startHierarchyTracing(String prefix, View view) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection PointlessBooleanExpression,ConstantConditions 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TRACE_HIERARCHY) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sHierarhcyRoot != null) { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("You must call stopHierarchyTracing() before running" + 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " a new trace!"); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/"); 601c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project //noinspection ResultOfMethodCallIgnored 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hierarchyDump.mkdirs(); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hierarchyDump = new File(hierarchyDump, prefix + ".traces"); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTracePrefix = prefix; 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e("View", "Could not dump view hierarchy"); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarhcyRoot = (ViewRoot) view.getRootView().getParent(); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Stops the current view hierarchy tracing. This method closes the file 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>/EXTERNAL/view-hierarchy/PREFIX.traces</code>. 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calling this method creates the file <code>/EXTERNAL/view-hierarchy/PREFIX.tree</code> 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * containing the view hierarchy of the view supplied to 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #startHierarchyTracing(String, View)}. 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method will return immediately if TRACE_HIERARCHY is false. 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 627a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * @see #startHierarchyTracing(String, View) 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #trace(View, android.view.ViewDebug.HierarchyTraceType) 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stopHierarchyTracing() { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection PointlessBooleanExpression,ConstantConditions 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!TRACE_HIERARCHY) { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sHierarhcyRoot == null || sHierarchyTraces == null) { 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("You must call startHierarchyTracing() before" + 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " stopHierarchyTracing()!"); 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces.close(); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e("View", "Could not write view traces"); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarchyTraces = null; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/"); 649c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project //noinspection ResultOfMethodCallIgnored 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hierarchyDump.mkdirs(); 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hierarchyDump = new File(hierarchyDump, sHierarchyTracePrefix + ".tree"); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedWriter out; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e("View", "Could not dump view hierarchy"); 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View view = sHierarhcyRoot.getView(); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup group = (ViewGroup) view; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpViewHierarchy(group, out, 0); 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e("View", "Could not dump view hierarchy"); 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sHierarhcyRoot = null; 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 674a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static void dispatchCommand(View view, String command, String parameters, 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OutputStream clientStream) throws IOException { 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Paranoid but safe... 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view = view.getRootView(); 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) { 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dump(view, clientStream); 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String[] params = parameters.split(" "); 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project capture(view, clientStream, params[0]); 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(view, params[0]); 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) { 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(view, params[0]); 691c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (REMOTE_PROFILE.equalsIgnoreCase(command)) { 692c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project profile(view, clientStream, params[0]); 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 697c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static View findView(View root, String parameter) { 698c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // Look by type/hashcode 699c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (parameter.indexOf('@') != -1) { 700c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String[] ids = parameter.split("@"); 701c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String className = ids[0]; 702c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int hashCode = Integer.parseInt(ids[1], 16); 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 704c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project View view = root.getRootView(); 705c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (view instanceof ViewGroup) { 706c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return findView((ViewGroup) view, className, hashCode); 707c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 708c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 709c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // Look by id 710c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int id = root.getResources().getIdentifier(parameter, null, null); 711c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return root.getRootView().findViewById(id); 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void invalidate(View root, String parameter) { 718c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view.postInvalidate(); 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void requestLayout(View root, String parameter) { 725c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project root.post(new Runnable() { 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view.requestLayout(); 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 735c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void profile(View root, OutputStream clientStream, String parameter) 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 738c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 739c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project BufferedWriter out = null; 740c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 741c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024); 742c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 743c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (view != null) { 744c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final long durationMeasure = profileViewOperation(view, new ViewOperation<Void>() { 745c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public Void[] pre() { 746c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project forceLayout(view); 747c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return null; 748c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 749c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 750c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private void forceLayout(View view) { 751c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.forceLayout(); 752c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (view instanceof ViewGroup) { 753c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project ViewGroup group = (ViewGroup) view; 754c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int count = group.getChildCount(); 755c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int i = 0; i < count; i++) { 756c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project forceLayout(group.getChildAt(i)); 757c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 758c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 759c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 760c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 761c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void run(Void... data) { 762c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.measure(view.mOldWidthMeasureSpec, view.mOldHeightMeasureSpec); 763c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 764c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 765c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void post(Void... data) { 766c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 767c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project }); 768c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 769c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final long durationLayout = profileViewOperation(view, new ViewOperation<Void>() { 770c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public Void[] pre() { 771c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return null; 772c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 773c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 774c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void run(Void... data) { 775c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom); 776c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 777c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 778c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void post(Void... data) { 779c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 780c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project }); 781c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 782c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final long durationDraw = profileViewOperation(view, new ViewOperation<Object>() { 783c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public Object[] pre() { 784c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final DisplayMetrics metrics = view.getResources().getDisplayMetrics(); 785c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final Bitmap bitmap = Bitmap.createBitmap(metrics.widthPixels, 786ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project metrics.heightPixels, Bitmap.Config.RGB_565); 787c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final Canvas canvas = new Canvas(bitmap); 788c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return new Object[] { bitmap, canvas }; 789c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 790c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 791c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void run(Object... data) { 792c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.draw((Canvas) data[1]); 793c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 794c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 795c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void post(Object... data) { 796c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project ((Bitmap) data[0]).recycle(); 797c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 798c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project }); 799c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 800c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(String.valueOf(durationMeasure)); 801c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(' '); 802c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(String.valueOf(durationLayout)); 803c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(' '); 804c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(String.valueOf(durationDraw)); 805c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.newLine(); 806c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 807c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write("-1 -1 -1"); 808c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.newLine(); 809c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 810c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (Exception e) { 811c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project android.util.Log.w("View", "Problem profiling the view:", e); 812c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } finally { 813c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (out != null) { 814c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.close(); 815c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 816c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 817c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 818c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 819c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project interface ViewOperation<T> { 820c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project T[] pre(); 821c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project void run(T... data); 822c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project void post(T... data); 823c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 824c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 825c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static <T> long profileViewOperation(View view, final ViewOperation<T> operation) { 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final CountDownLatch latch = new CountDownLatch(1); 827c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final long[] duration = new long[1]; 828c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 829c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.post(new Runnable() { 830c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void run() { 831c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 832c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project T[] data = operation.pre(); 833c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project long start = Debug.threadCpuTimeNanos(); 834c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project operation.run(data); 835c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project duration[0] = Debug.threadCpuTimeNanos() - start; 836c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project operation.post(data); 837c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } finally { 838c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project latch.countDown(); 839c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 840c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 841c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project }); 842c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 843c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 844c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); 845c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (InterruptedException e) { 846c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w("View", "Could not complete the profiling of the view " + view); 847c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Thread.currentThread().interrupt(); 848c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return -1; 849c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 850c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 851c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return duration[0]; 852c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 853c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 854c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void capture(View root, final OutputStream clientStream, String parameter) 855c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project throws IOException { 856c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 857c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View captureView = findView(root, parameter); 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (captureView != null) { 860c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final CountDownLatch latch = new CountDownLatch(1); 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Bitmap[] cache = new Bitmap[1]; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project root.post(new Runnable() { 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 866958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn cache[0] = captureView.createSnapshot( 867958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn Bitmap.Config.ARGB_8888, 0); 868958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn } catch (OutOfMemoryError e) { 869958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn try { 870958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn cache[0] = captureView.createSnapshot( 871958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn Bitmap.Config.ARGB_4444, 0); 872958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn } catch (OutOfMemoryError e2) { 873958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn Log.w("View", "Out of memory for bitmap"); 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project latch.countDown(); 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cache[0] != null) { 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedOutputStream out = null; 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out = new BufferedOutputStream(clientStream, 32 * 1024); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cache[0].compress(Bitmap.CompressFormat.PNG, 100, out); 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.flush(); 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (out != null) { 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 894958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn cache[0].recycle(); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 896958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn } else { 897958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn Log.w("View", "Failed to create capture bitmap!"); 898958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn clientStream.close(); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 901c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w("View", "Could not complete the capture of the view " + captureView); 902c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Thread.currentThread().interrupt(); 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void dump(View root, OutputStream clientStream) throws IOException { 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedWriter out = null; 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024); 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View view = root.getRootView(); 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup group = (ViewGroup) view; 914105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewHierarchyWithProperties(group.getContext(), group, out, 0); 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write("DONE."); 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 918c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (Exception e) { 919c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project android.util.Log.w("View", "Problem dumping the view:", e); 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (out != null) { 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static View findView(ViewGroup group, String className, int hashCode) { 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isRequestedView(group, className, hashCode)) { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return group; 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = group.getChildCount(); 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = group.getChildAt(i); 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View found = findView((ViewGroup) view, className, hashCode); 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (found != null) { 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return found; 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (isRequestedView(view, className, hashCode)) { 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view; 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean isRequestedView(View view, String className, int hashCode) { 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view.getClass().getName().equals(className) && view.hashCode() == hashCode; 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 952105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewHierarchyWithProperties(Context context, ViewGroup group, 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedWriter out, int level) { 954105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (!dumpViewWithProperties(context, group, out, level)) { 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = group.getChildCount(); 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = group.getChildAt(i); 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 962105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewHierarchyWithProperties(context, (ViewGroup) view, out, level + 1); 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 964105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewWithProperties(context, view, out, level + 1); 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static boolean dumpViewWithProperties(Context context, View view, 970105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out, int level) { 971105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < level; i++) { 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(' '); 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(view.getClass().getName()); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write('@'); 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(Integer.toHexString(view.hashCode())); 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(' '); 980105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, view, out); 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w("View", "Error while dumping hierarchy tree"); 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Field[] getExportedPropertyFields(Class<?> klass) { 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sFieldsForClasses == null) { 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sFieldsForClasses = new HashMap<Class<?>, Field[]>(); 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 993c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (sAnnotations == null) { 994c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); 995c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 996c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Field[]> map = sFieldsForClasses; 998c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations; 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Field[] fields = map.get(klass); 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fields != null) { 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Field> foundFields = new ArrayList<Field>(); 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = klass.getDeclaredFields(); 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field.isAnnotationPresent(ExportedProperty.class)) { 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.setAccessible(true); 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundFields.add(field); 1014c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project annotations.put(field, field.getAnnotation(ExportedProperty.class)); 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = foundFields.toArray(new Field[foundFields.size()]); 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, fields); 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Method[] getExportedPropertyMethods(Class<?> klass) { 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sMethodsForClasses == null) { 1026c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sMethodsForClasses = new HashMap<Class<?>, Method[]>(100); 1027c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1028c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (sAnnotations == null) { 1029c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1031c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Method[]> map = sMethodsForClasses; 1033c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations; 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Method[] methods = map.get(klass); 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methods != null) { 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Method> foundMethods = new ArrayList<Method>(); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = klass.getDeclaredMethods(); 1042a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 1045a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final Method method = methods[i]; 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method.getParameterTypes().length == 0 && 1047c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project method.isAnnotationPresent(ExportedProperty.class) && 1048c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project method.getReturnType() != Void.class) { 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.setAccessible(true); 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundMethods.add(method); 1051c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project annotations.put(method, method.getAnnotation(ExportedProperty.class)); 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = foundMethods.toArray(new Method[foundMethods.size()]); 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, methods); 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1061105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewProperties(Context context, Object view, 1062105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out) throws IOException { 1063105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 1064105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, view, out, ""); 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1067105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewProperties(Context context, Object view, 1068105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out, String prefix) throws IOException { 1069105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Class<?> klass = view.getClass(); 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 1073105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportFields(context, view, out, klass, prefix); 1074105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportMethods(context, view, out, klass, prefix); 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project klass = klass.getSuperclass(); 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (klass != Object.class); 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1078a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 1079105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportMethods(Context context, Object view, BufferedWriter out, 1080105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Class<?> klass, String prefix) throws IOException { 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method[] methods = getExportedPropertyMethods(klass); 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method method = methods[i]; 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection EmptyCatchBlock 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: This should happen on the UI thread 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object methodValue = method.invoke(view, (Object[]) null); 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> returnType = method.getReturnType(); 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (returnType == int.class) { 1094c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final ExportedProperty property = sAnnotations.get(method); 1095105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (property.resolveId() && context != null) { 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int id = (Integer) methodValue; 1097105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project methodValue = resolveId(context, id); 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1099809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString[] flagsMapping = property.flagMapping(); 1100809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (flagsMapping.length > 0) { 1101809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int intValue = (Integer) methodValue; 1102809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final String valuePrefix = prefix + method.getName() + '_'; 1103809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix); 1104809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1105809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString[] mapping = property.mapping(); 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapping.length > 0) { 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int intValue = (Integer) methodValue; 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mapped = false; 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mappingCount = mapping.length; 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mappingCount; j++) { 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString mapper = mapping[j]; 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapper.from() == intValue) { 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methodValue = mapper.to(); 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mapped = true; 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mapped) { 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methodValue = intValue; 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1125c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (returnType == int[].class) { 1126c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final ExportedProperty property = sAnnotations.get(method); 1127c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int[] array = (int[]) methodValue; 1128c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String valuePrefix = prefix + method.getName() + '_'; 1129c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String suffix = "()"; 1130c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1131105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportUnrolledArray(context, out, property, array, valuePrefix, suffix); 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!returnType.isPrimitive()) { 1133c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final ExportedProperty property = sAnnotations.get(method); 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.deepExport()) { 1135105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, methodValue, out, prefix + property.prefix()); 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1140c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeEntry(out, prefix, method.getName(), "()", methodValue); 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InvocationTargetException e) { 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1147105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportFields(Context context, Object view, BufferedWriter out, 1148105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Class<?> klass, String prefix) throws IOException { 1149105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field[] fields = getExportedPropertyFields(klass); 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection EmptyCatchBlock 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object fieldValue = null; 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> type = field.getType(); 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type == int.class) { 1162c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final ExportedProperty property = sAnnotations.get(field); 1163105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (property.resolveId() && context != null) { 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int id = field.getInt(view); 1165105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project fieldValue = resolveId(context, id); 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1167809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString[] flagsMapping = property.flagMapping(); 1168809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (flagsMapping.length > 0) { 1169809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int intValue = field.getInt(view); 1170809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final String valuePrefix = prefix + field.getName() + '_'; 1171809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix); 1172809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1173809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString[] mapping = property.mapping(); 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapping.length > 0) { 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int intValue = field.getInt(view); 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mappingCount = mapping.length; 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mappingCount; j++) { 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString mapped = mapping[j]; 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapped.from() == intValue) { 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = mapped.to(); 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue == null) { 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = intValue; 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1191c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (type == int[].class) { 1192c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final ExportedProperty property = sAnnotations.get(field); 1193c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int[] array = (int[]) field.get(view); 1194c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String valuePrefix = prefix + field.getName() + '_'; 1195c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String suffix = ""; 1196c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1197105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportUnrolledArray(context, out, property, array, valuePrefix, suffix); 1198c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1199c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // We exit here! 1200c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return; 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!type.isPrimitive()) { 1202c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final ExportedProperty property = sAnnotations.get(field); 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.deepExport()) { 1204105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, field.get(view), out, 1205105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project prefix + property.prefix()); 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue == null) { 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = field.get(view); 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1214c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeEntry(out, prefix, field.getName(), "", fieldValue); 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1220c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void writeEntry(BufferedWriter out, String prefix, String name, 1221c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String suffix, Object value) throws IOException { 1222c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1223c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(prefix); 1224c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(name); 1225c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(suffix); 1226c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write("="); 1227c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeValue(out, value); 1228c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(' '); 1229c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1230c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1231809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy private static void exportUnrolledFlags(BufferedWriter out, FlagToString[] mapping, 1232809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int intValue, String prefix) throws IOException { 1233809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 1234809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int count = mapping.length; 1235809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy for (int j = 0; j < count; j++) { 1236809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString flagMapping = mapping[j]; 1237809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final boolean ifTrue = flagMapping.outputIf(); 12385bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final int maskResult = intValue & flagMapping.mask(); 12395bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final boolean test = maskResult == flagMapping.equals(); 1240809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if ((test && ifTrue) || (!test && !ifTrue)) { 1241809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final String name = flagMapping.name(); 12425bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final String value = "0x" + Integer.toHexString(maskResult); 1243809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy writeEntry(out, prefix, name, "", value); 1244809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1245809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1246809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1247809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 1248105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportUnrolledArray(Context context, BufferedWriter out, 1249c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project ExportedProperty property, int[] array, String prefix, String suffix) 1250c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project throws IOException { 1251c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1252c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString[] indexMapping = property.indexMapping(); 1253c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final boolean hasIndexMapping = indexMapping.length > 0; 1254c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1255c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString[] mapping = property.mapping(); 1256c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final boolean hasMapping = mapping.length > 0; 1257c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1258105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project final boolean resolveId = property.resolveId() && context != null; 1259c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int valuesCount = array.length; 1260c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1261c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int j = 0; j < valuesCount; j++) { 1262c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String name; 1263a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy String value = null; 1264c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1265c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int intValue = array[j]; 1266c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1267c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project name = String.valueOf(j); 1268c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (hasIndexMapping) { 1269c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mappingCount = indexMapping.length; 1270c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int k = 0; k < mappingCount; k++) { 1271c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString mapped = indexMapping[k]; 1272c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (mapped.from() == j) { 1273c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project name = mapped.to(); 1274c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project break; 1275c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1276c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1277c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1278c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1279c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (hasMapping) { 1280c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mappingCount = mapping.length; 1281c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int k = 0; k < mappingCount; k++) { 1282c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString mapped = mapping[k]; 1283c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (mapped.from() == intValue) { 1284c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project value = mapped.to(); 1285c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project break; 1286c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1287c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1288c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1289c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1290c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (resolveId) { 1291a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy if (value == null) value = (String) resolveId(context, intValue); 1292a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } else { 1293a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy value = String.valueOf(intValue); 1294c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1295c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1296c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeEntry(out, prefix, name, suffix, value); 1297c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1298c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1299c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1300105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static Object resolveId(Context context, int id) { 1301c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Object fieldValue; 1302105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project final Resources resources = context.getResources(); 1303c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (id >= 0) { 1304c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 1305c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = resources.getResourceTypeName(id) + '/' + 1306c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project resources.getResourceEntryName(id); 1307c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (Resources.NotFoundException e) { 1308c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = "id/0x" + Integer.toHexString(id); 1309c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1310c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 1311c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = "NO_ID"; 1312c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1313c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return fieldValue; 1314c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1315c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1316c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void writeValue(BufferedWriter out, Object value) throws IOException { 1317c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (value != null) { 1318c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String output = value.toString().replace("\n", "\\n"); 1319c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(String.valueOf(output.length())); 1320c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(","); 1321c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(output); 1322c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 1323c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write("4,null"); 1324c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1325c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1326c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void dumpViewHierarchy(ViewGroup group, BufferedWriter out, int level) { 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!dumpView(group, out, level)) { 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = group.getChildCount(); 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = group.getChildAt(i); 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpViewHierarchy((ViewGroup) view, out, level + 1); 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dumpView(view, out, level + 1); 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean dumpView(Object view, BufferedWriter out, int level) { 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < level; i++) { 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(' '); 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(view.getClass().getName()); 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write('@'); 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(Integer.toHexString(view.hashCode())); 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w("View", "Error while dumping hierarchy tree"); 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Field[] capturedViewGetPropertyFields(Class<?> klass) { 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCapturedViewFieldsForClasses == null) { 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCapturedViewFieldsForClasses = new HashMap<Class<?>, Field[]>(); 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Field[]> map = mCapturedViewFieldsForClasses; 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Field[] fields = map.get(klass); 13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fields != null) { 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Field> foundFields = new ArrayList<Field>(); 13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = klass.getFields(); 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field.isAnnotationPresent(CapturedViewProperty.class)) { 13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.setAccessible(true); 13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundFields.add(field); 13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = foundFields.toArray(new Field[foundFields.size()]); 13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, fields); 13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Method[] capturedViewGetPropertyMethods(Class<?> klass) { 13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCapturedViewMethodsForClasses == null) { 13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCapturedViewMethodsForClasses = new HashMap<Class<?>, Method[]>(); 13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Method[]> map = mCapturedViewMethodsForClasses; 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Method[] methods = map.get(klass); 13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methods != null) { 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Method> foundMethods = new ArrayList<Method>(); 14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = klass.getMethods(); 1401a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 1404a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final Method method = methods[i]; 14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method.getParameterTypes().length == 0 && 14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.isAnnotationPresent(CapturedViewProperty.class) && 14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.getReturnType() != Void.class) { 14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.setAccessible(true); 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundMethods.add(method); 14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = foundMethods.toArray(new Method[foundMethods.size()]); 14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, methods); 14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1418a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 1419a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy private static String capturedViewExportMethods(Object obj, Class<?> klass, 14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String prefix) { 14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj == null) { 14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "null"; 14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1425a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method[] methods = capturedViewGetPropertyMethods(klass); 14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method method = methods[i]; 14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object methodValue = method.invoke(obj, (Object[]) null); 14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> returnType = method.getReturnType(); 1435a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class); 14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.retrieveReturn()) { 14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we are interested in the second level data only 14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#")); 1440a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } else { 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(method.getName()); 14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("()="); 1444a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methodValue != null) { 1446a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final String value = methodValue.toString().replace("\n", "\\n"); 1447a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy sb.append(value); 14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("null"); 14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("; "); 14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 1454a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception IllegalAccess, it is OK here 14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this method 14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InvocationTargetException e) { 1457a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception InvocationTarget, it is OK here 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this method 1459a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 1460a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) { 1465a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj == null) { 14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "null"; 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field[] fields = capturedViewGetPropertyFields(klass); 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object fieldValue = field.get(obj); 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(field.getName()); 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("="); 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue != null) { 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String value = fieldValue.toString().replace("\n", "\\n"); 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(value); 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("null"); 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(' '); 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 1491a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception IllegalAccess, it is OK here 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this field 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1497a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1499a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * Dump view info for id based instrument test generation 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (and possibly further data analysis). The results are dumped 1501a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * to the log. 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param tag for log 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view for dump 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1505a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy public static void dumpCapturedView(String tag, Object view) { 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Class<?> klass = view.getClass(); 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(klass.getName() + ": "); 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(capturedViewExportFields(view, klass, "")); 1509a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy sb.append(capturedViewExportMethods(view, klass, "")); 1510a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy Log.d(tag, sb.toString()); 15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1513