ViewDebug.java revision 13b907353f18215b52b5ceda24bbf520d91d72a1
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 19105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.Context; 20f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport android.content.res.Resources; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 22c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.graphics.Canvas; 23223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guyimport android.graphics.Rect; 24c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Projectimport android.os.Debug; 25223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guyimport android.os.RemoteException; 26f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport android.util.DisplayMetrics; 27f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport android.util.Log; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.io.BufferedOutputStream; 30f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.io.BufferedWriter; 31223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guyimport java.io.ByteArrayOutputStream; 32f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.io.DataOutputStream; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream; 35f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.io.OutputStreamWriter; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.annotation.ElementType; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.annotation.Retention; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.annotation.RetentionPolicy; 39f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.lang.annotation.Target; 40f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.lang.reflect.AccessibleObject; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Field; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.InvocationTargetException; 43f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.lang.reflect.Method; 44f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.util.ArrayList; 45f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.util.HashMap; 46f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.util.concurrent.CountDownLatch; 47f9284695e8c10dad4daf3d2c84f607483bcb56caRomain Guyimport java.util.concurrent.TimeUnit; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Various debugging/tracing tools related to {@link View} and the view hierarchy. 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ViewDebug { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5413b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This flag is now unused 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final boolean TRACE_HIERARCHY = false; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6013b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This flag is now unused 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6213b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final boolean TRACE_RECYCLER = false; 64a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 662c095f367779ef32130c72849936a2e3013c8492Christopher Tate * Enables detailed logging of drag/drop operations. 672c095f367779ef32130c72849936a2e3013c8492Christopher Tate * @hide 682c095f367779ef32130c72849936a2e3013c8492Christopher Tate */ 69994ef9296a00523de1df424b4b760b4416ead58bChristopher Tate public static final boolean DEBUG_DRAG = false; 702c095f367779ef32130c72849936a2e3013c8492Christopher Tate 712c095f367779ef32130c72849936a2e3013c8492Christopher Tate /** 724e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown * Enables logging of factors that affect the latency and responsiveness of an application. 734e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown * 744e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown * Logs the relative difference between the time an event was created and the time it 754e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown * was delivered. 764e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown * 7795db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown * Logs the time spent waiting for Surface.lockCanvas(), Surface.unlockCanvasAndPost() 7895db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown * or eglSwapBuffers(). This is time that the event loop spends blocked and unresponsive. 7995db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown * Ideally, drawing and animations should be perfectly synchronized with VSYNC so that 8095db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown * dequeuing and queueing buffers is instantaneous. 814e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown * 8295db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown * Logs the time spent in ViewRoot.performTraversals() and ViewRoot.performDraw(). 834e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown * @hide 844e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown */ 854e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown public static final boolean DEBUG_LATENCY = false; 864e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown 8795db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown /** @hide */ 8895db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown public static final String DEBUG_LATENCY_TAG = "ViewLatency"; 8995db2b20d7bc0aaf00b1d4418124f5cf0a755d74Jeff Brown 904e91a180be46c0c7c3bf398d4df4cbe2404216b5Jeff Brown /** 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This annotation can be used to mark fields and methods to be dumped by 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the view server. Only non-void methods with no arguments can be annotated 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by this annotation. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.FIELD, ElementType.METHOD }) 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface ExportedProperty { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When resolveId is true, and if the annotated field/method return value 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is an int, the value is converted to an Android's resource name. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the property's value must be transformed into an Android 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * resource name, false otherwise 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean resolveId() default false; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A mapping can be defined to map int values to specific strings. For 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance, View.getVisibility() returns 0, 4 or 8. However, these values 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * actually mean VISIBLE, INVISIBLE and GONE. A mapping can be used to see 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * these human readable values: 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.ExportedProperty(mapping = { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 0, to = "VISIBLE"), 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 4, to = "INVISIBLE"), 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 8, to = "GONE") 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }) 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public int getVisibility() { ... 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An array of int to String mappings 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.ViewDebug.IntToString 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntToString[] mapping() default { }; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 129c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * A mapping can be defined to map array indices to specific strings. 130c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * A mapping can be used to see human readable values for the indices 131c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * of an array: 132c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 133c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <pre> 134809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.ExportedProperty(indexMapping = { 135c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 0, to = "INVALID"), 136c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 1, to = "FIRST"), 137c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 2, to = "SECOND") 138c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * }) 139c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * private int[] mElements; 140c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <pre> 141c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 142c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @return An array of int to String mappings 143c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 144c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @see android.view.ViewDebug.IntToString 145c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @see #mapping() 146c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project */ 147c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project IntToString[] indexMapping() default { }; 148c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 149c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project /** 150809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * A flags mapping can be defined to map flags encoded in an integer to 151809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * specific strings. A mapping can be used to see human readable values 152809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * for the flags of an integer: 153809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 154809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <pre> 155809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.ExportedProperty(flagMapping = { 156809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = ENABLED, name = "ENABLED"), 157809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = DISABLED, name = "DISABLED"), 158809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * }) 159809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * private int mFlags; 160809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <pre> 161809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 162809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * A specified String is output when the following is true: 163a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * 164809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An array of int to String mappings 165809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 166809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy FlagToString[] flagMapping() default { }; 167809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 168809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When deep export is turned on, this property is not dumped. Instead, the 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * properties contained in this property are dumped. Each child property 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is prefixed with the name of this property. 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the properties of this property should be dumped 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 175a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * @see #prefix() 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean deepExport() default false; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The prefix to use on child properties when deep export is enabled 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a prefix as a String 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #deepExport() 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String prefix() default ""; 187bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 188bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev /** 189bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * Specifies the category the property falls into, such as measurement, 190bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * layout, drawing, etc. 191bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * 192bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * @return the category as String 193bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev */ 194bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev String category() default ""; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines a mapping from an int value to a String. Such a mapping can be used 199f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * in an @ExportedProperty to provide more meaningful values to the end user. 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.ViewDebug.ExportedProperty 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.TYPE }) 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface IntToString { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The original int value to map to a String. 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An arbitrary int value. 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int from(); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The String to use in place of the original int value. 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An arbitrary non-null String. 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String to(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 220809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 221809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 222f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * Defines a mapping from a flag to a String. Such a mapping can be used 223f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * in an @ExportedProperty to provide more meaningful values to the end user. 224809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 225809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @see android.view.ViewDebug.ExportedProperty 226809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 227809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy @Target({ ElementType.TYPE }) 228809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy @Retention(RetentionPolicy.RUNTIME) 229809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy public @interface FlagToString { 230809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 231809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The mask to apply to the original value. 232809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 233809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary int value. 234809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 235809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int mask(); 236809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 237809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 238809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The value to compare to the result of: 239809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <code>original value & {@link #mask()}</code>. 240809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 241809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary value. 242809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 243809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int equals(); 244809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 245809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 246809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The String to use in place of the original int value. 247809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 248809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary non-null String. 249809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 250809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy String name(); 251809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 252809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 253809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * Indicates whether to output the flag when the test is true, 254809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * or false. Defaults to true. 255809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 256809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy boolean outputIf() default true; 257809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 258809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This annotation can be used to mark fields and methods to be dumped when 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the view is captured. Methods with this annotation must have no arguments 262f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler * and must return a valid type of data. 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.FIELD, ElementType.METHOD }) 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface CapturedViewProperty { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 268a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * When retrieveReturn is true, we need to retrieve second level methods 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod() 270a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * we will set retrieveReturn = true on the annotation of 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * myView.getFirstLevelMethod() 272a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * @return true if we need the second level methods 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 274a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy boolean retrieveReturn() default false; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 276a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Maximum delay in ms after which we stop trying to capture a View's drawing 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int CAPTURE_TIMEOUT = 4000; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE"; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_DUMP = "DUMP"; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; 287c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static final String REMOTE_PROFILE = "PROFILE"; 288223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS"; 289ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase private static final String REMOTE_COMMAND_OUTPUT_DISPLAYLIST = "OUTPUT_DISPLAYLIST"; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Field[]> sFieldsForClasses; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Method[]> sMethodsForClasses; 293c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static HashMap<AccessibleObject, ExportedProperty> sAnnotations; 294c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 29613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This enum is now unused 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 29813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum HierarchyTraceType { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE, 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE_CHILD, 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE_CHILD_IN_PARENT, 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project REQUEST_LAYOUT, 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ON_LAYOUT, 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ON_MEASURE, 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DRAW, 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BUILD_CACHE 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 31113b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This enum is now unused 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 31313b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum RecyclerTraceType { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NEW_VIEW, 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BIND_VIEW, 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RECYCLE_FROM_ACTIVE_HEAP, 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RECYCLE_FROM_SCRAP_HEAP, 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MOVE_TO_SCRAP_HEAP, 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MOVE_FROM_ACTIVE_TO_SCRAP_HEAP 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of instanciated Views. 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The number of Views instanciated in the current process. 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getViewInstanceCount() { 331c21550a8d1dfc9e5359fe994cb48049a0bd4c82cBrian Carlstrom return Debug.countInstancesOfClass(View.class); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 335c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * Returns the number of instanciated ViewAncestors. 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 337c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * @return The number of ViewAncestors instanciated in the current process. 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 34165b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy public static long getViewRootImplCount() { 3426dd005b48138708762bfade0081d031a2a4a3822Dianne Hackborn return Debug.countInstancesOfClass(ViewRootImpl.class); 343a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 34613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 34813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 34913b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings({ "UnusedParameters", "deprecation" }) 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void trace(View view, RecyclerTraceType type, int... parameters) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 35413b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 35713b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings("UnusedParameters") 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void startRecyclerTracing(String prefix, View view) { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 36213b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 36413b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 36513b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings("UnusedParameters") 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stopRecyclerTracing() { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 37013b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 37213b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 37313b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings({ "UnusedParameters", "deprecation" }) 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void trace(View view, HierarchyTraceType type) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 37813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 38013b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 38113b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings("UnusedParameters") 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void startHierarchyTracing(String prefix, View view) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 38613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 38813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stopHierarchyTracing() { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 391a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static void dispatchCommand(View view, String command, String parameters, 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OutputStream clientStream) throws IOException { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Paranoid but safe... 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view = view.getRootView(); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dump(view, clientStream); 400223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) { 401223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy captureLayers(view, new DataOutputStream(clientStream)); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String[] params = parameters.split(" "); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project capture(view, clientStream, params[0]); 406ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase } else if (REMOTE_COMMAND_OUTPUT_DISPLAYLIST.equalsIgnoreCase(command)) { 407ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase outputDisplayList(view, params[0]); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(view, params[0]); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(view, params[0]); 412c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (REMOTE_PROFILE.equalsIgnoreCase(command)) { 413c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project profile(view, clientStream, params[0]); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 418c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static View findView(View root, String parameter) { 419c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // Look by type/hashcode 420c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (parameter.indexOf('@') != -1) { 421c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String[] ids = parameter.split("@"); 422c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String className = ids[0]; 423236092a36216c79507ec19eb207831810caced19Romain Guy final int hashCode = (int) Long.parseLong(ids[1], 16); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 425c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project View view = root.getRootView(); 426c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (view instanceof ViewGroup) { 427c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return findView((ViewGroup) view, className, hashCode); 428c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 429c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 430c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // Look by id 431c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int id = root.getResources().getIdentifier(parameter, null, null); 432c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return root.getRootView().findViewById(id); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void invalidate(View root, String parameter) { 439c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view.postInvalidate(); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void requestLayout(View root, String parameter) { 446c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project root.post(new Runnable() { 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view.requestLayout(); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 456c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void profile(View root, OutputStream clientStream, String parameter) 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 460c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project BufferedWriter out = null; 461c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 462c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024); 463c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 464c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (view != null) { 465f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev profileViewAndChildren(view, out); 466f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } else { 467f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write("-1 -1 -1"); 468f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.newLine(); 469f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 470f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write("DONE."); 471f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.newLine(); 472f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } catch (Exception e) { 473f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev android.util.Log.w("View", "Problem profiling the view:", e); 474f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } finally { 475f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev if (out != null) { 476f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.close(); 477f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 478f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 479f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 480c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 481f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev private static void profileViewAndChildren(final View view, BufferedWriter out) 482f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev throws IOException { 483c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev profileViewAndChildren(view, out, true); 484c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 485f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev 486c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev private static void profileViewAndChildren(final View view, BufferedWriter out, boolean root) 487c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev throws IOException { 488f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev 489c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev long durationMeasure = 490c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev (root || (view.mPrivateFlags & View.MEASURED_DIMENSION_SET) != 0) ? profileViewOperation( 491c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view, new ViewOperation<Void>() { 492c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public Void[] pre() { 493c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev forceLayout(view); 494c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return null; 495c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 496c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 497c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev private void forceLayout(View view) { 498c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view.forceLayout(); 499c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev if (view instanceof ViewGroup) { 500c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev ViewGroup group = (ViewGroup) view; 501c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev final int count = group.getChildCount(); 502c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev for (int i = 0; i < count; i++) { 503c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev forceLayout(group.getChildAt(i)); 504c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 505c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 506c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 507c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 508c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void run(Void... data) { 509c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view.measure(view.mOldWidthMeasureSpec, view.mOldHeightMeasureSpec); 510c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 511c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 512c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void post(Void... data) { 513c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 514c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }) 515c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev : 0; 516c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev long durationLayout = 517c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev (root || (view.mPrivateFlags & View.LAYOUT_REQUIRED) != 0) ? profileViewOperation( 518c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view, new ViewOperation<Void>() { 519c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public Void[] pre() { 520c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return null; 521c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 522c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 523c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void run(Void... data) { 524c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom); 525c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 526c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 527c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void post(Void... data) { 528c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 529c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }) : 0; 530c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev long durationDraw = 531bef337f516eafaee8f3891e22688b74388570317Konstantin Lopyrev (root || !view.willNotDraw() || (view.mPrivateFlags & View.DRAWN) != 0) ? profileViewOperation( 532bef337f516eafaee8f3891e22688b74388570317Konstantin Lopyrev view, 533c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev new ViewOperation<Object>() { 534c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public Object[] pre() { 535c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev final DisplayMetrics metrics = 536daf98e941e140e8739458126640183b9f296a2abChet Haase (view != null && view.getResources() != null) ? 537daf98e941e140e8739458126640183b9f296a2abChet Haase view.getResources().getDisplayMetrics() : null; 538daf98e941e140e8739458126640183b9f296a2abChet Haase final Bitmap bitmap = metrics != null ? 539c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev Bitmap.createBitmap(metrics.widthPixels, 540daf98e941e140e8739458126640183b9f296a2abChet Haase metrics.heightPixels, Bitmap.Config.RGB_565) : null; 541daf98e941e140e8739458126640183b9f296a2abChet Haase final Canvas canvas = bitmap != null ? new Canvas(bitmap) : null; 542c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return new Object[] { 543c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev bitmap, canvas 544c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }; 545c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 546c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 547c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void run(Object... data) { 548daf98e941e140e8739458126640183b9f296a2abChet Haase if (data[1] != null) { 549daf98e941e140e8739458126640183b9f296a2abChet Haase view.draw((Canvas) data[1]); 550daf98e941e140e8739458126640183b9f296a2abChet Haase } 551c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 552c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 553c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void post(Object... data) { 5546311d0a079702b29984c0d31937345be105e1a5eDianne Hackborn if (data[1] != null) { 5556311d0a079702b29984c0d31937345be105e1a5eDianne Hackborn ((Canvas) data[1]).setBitmap(null); 5566311d0a079702b29984c0d31937345be105e1a5eDianne Hackborn } 557daf98e941e140e8739458126640183b9f296a2abChet Haase if (data[0] != null) { 558daf98e941e140e8739458126640183b9f296a2abChet Haase ((Bitmap) data[0]).recycle(); 559daf98e941e140e8739458126640183b9f296a2abChet Haase } 560c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 561c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }) : 0; 562f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(String.valueOf(durationMeasure)); 563f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(' '); 564f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(String.valueOf(durationLayout)); 565f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(' '); 566f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(String.valueOf(durationDraw)); 567f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.newLine(); 568f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev if (view instanceof ViewGroup) { 569f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev ViewGroup group = (ViewGroup) view; 570f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev final int count = group.getChildCount(); 571f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev for (int i = 0; i < count; i++) { 572c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev profileViewAndChildren(group.getChildAt(i), out, false); 573c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 574c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 575c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 576c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 577c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project interface ViewOperation<T> { 578c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project T[] pre(); 579c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project void run(T... data); 580c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project void post(T... data); 581c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 582c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 583c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static <T> long profileViewOperation(View view, final ViewOperation<T> operation) { 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final CountDownLatch latch = new CountDownLatch(1); 585c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final long[] duration = new long[1]; 586c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 587c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.post(new Runnable() { 588c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void run() { 589c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 590c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project T[] data = operation.pre(); 591c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project long start = Debug.threadCpuTimeNanos(); 59288b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy //noinspection unchecked 593c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project operation.run(data); 594c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project duration[0] = Debug.threadCpuTimeNanos() - start; 59588b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy //noinspection unchecked 596c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project operation.post(data); 597c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } finally { 598c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project latch.countDown(); 599c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 600c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 601c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project }); 602c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 603c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 604c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev if (!latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS)) { 605c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev Log.w("View", "Could not complete the profiling of the view " + view); 606c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return -1; 607c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 608c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (InterruptedException e) { 609c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w("View", "Could not complete the profiling of the view " + view); 610c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Thread.currentThread().interrupt(); 611c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return -1; 612c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 613c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 614c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return duration[0]; 615c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 616c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 617223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy private static void captureLayers(View root, final DataOutputStream clientStream) 618223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy throws IOException { 619223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 620223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy try { 621223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Rect outRect = new Rect(); 622223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy try { 623223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy root.mAttachInfo.mSession.getDisplayFrame(root.mAttachInfo.mWindow, outRect); 624223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } catch (RemoteException e) { 625223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy // Ignore 626223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 627223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 628223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(outRect.width()); 629223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(outRect.height()); 630223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 63165554f27855ce1764123604b061b10346f8b8404Romain Guy captureViewLayer(root, clientStream, true); 632223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 633223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.write(2); 634223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } finally { 635223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.close(); 636223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 637223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 638223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 63965554f27855ce1764123604b061b10346f8b8404Romain Guy private static void captureViewLayer(View view, DataOutputStream clientStream, boolean visible) 640223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy throws IOException { 641223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 64265554f27855ce1764123604b061b10346f8b8404Romain Guy final boolean localVisible = view.getVisibility() == View.VISIBLE && visible; 64365554f27855ce1764123604b061b10346f8b8404Romain Guy 644223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) { 645223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy final int id = view.getId(); 646223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy String name = view.getClass().getSimpleName(); 647223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy if (id != View.NO_ID) { 648223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy name = resolveId(view.getContext(), id).toString(); 649223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 650223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 651223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.write(1); 652223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeUTF(name); 65365554f27855ce1764123604b061b10346f8b8404Romain Guy clientStream.writeByte(localVisible ? 1 : 0); 654223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 655223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy int[] position = new int[2]; 656223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy // XXX: Should happen on the UI thread 657223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy view.getLocationInWindow(position); 658223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 659223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(position[0]); 660223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(position[1]); 661223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.flush(); 662223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 663223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Bitmap b = performViewCapture(view, true); 664223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy if (b != null) { 665223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(b.getWidth() * 666223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy b.getHeight() * 2); 667223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy b.compress(Bitmap.CompressFormat.PNG, 100, arrayOut); 668223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(arrayOut.size()); 669223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy arrayOut.writeTo(clientStream); 670223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 671223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.flush(); 672223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 673223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 674223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy if (view instanceof ViewGroup) { 675223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy ViewGroup group = (ViewGroup) view; 676223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy int count = group.getChildCount(); 677223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 678223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy for (int i = 0; i < count; i++) { 67965554f27855ce1764123604b061b10346f8b8404Romain Guy captureViewLayer(group.getChildAt(i), clientStream, localVisible); 680223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 681223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 682223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 683223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 684ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase private static void outputDisplayList(View root, String parameter) throws IOException { 685ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase final View view = findView(root, parameter); 6866dd005b48138708762bfade0081d031a2a4a3822Dianne Hackborn view.getViewRootImpl().outputDisplayList(view); 687ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase } 688ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase 689c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void capture(View root, final OutputStream clientStream, String parameter) 690c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project throws IOException { 691c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 692c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View captureView = findView(root, parameter); 693223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Bitmap b = performViewCapture(captureView, false); 69443b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev 69543b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev if (b == null) { 696223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Log.w("View", "Failed to create capture bitmap!"); 69743b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev // Send an empty one so that it doesn't get stuck waiting for 69843b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev // something. 69943b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); 70043b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev } 70143b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev 70243b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev BufferedOutputStream out = null; 70343b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev try { 70443b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev out = new BufferedOutputStream(clientStream, 32 * 1024); 70543b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev b.compress(Bitmap.CompressFormat.PNG, 100, out); 70643b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev out.flush(); 70743b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev } finally { 70843b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev if (out != null) { 70943b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev out.close(); 71043b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev } 71143b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev b.recycle(); 712223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 713223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 715223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy private static Bitmap performViewCapture(final View captureView, final boolean skpiChildren) { 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (captureView != null) { 717c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final CountDownLatch latch = new CountDownLatch(1); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Bitmap[] cache = new Bitmap[1]; 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 720223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy captureView.post(new Runnable() { 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 723958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn cache[0] = captureView.createSnapshot( 724223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Bitmap.Config.ARGB_8888, 0, skpiChildren); 725958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn } catch (OutOfMemoryError e) { 72688b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy Log.w("View", "Out of memory for bitmap"); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project latch.countDown(); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); 735223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy return cache[0]; 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 737c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w("View", "Could not complete the capture of the view " + captureView); 738c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Thread.currentThread().interrupt(); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 741223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 742223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy return null; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void dump(View root, OutputStream clientStream) throws IOException { 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedWriter out = null; 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 74838e951b62ed956501b11f0715e23e3bf70942f6dRomain Guy out = new BufferedWriter(new OutputStreamWriter(clientStream, "utf-8"), 32 * 1024); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View view = root.getRootView(); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup group = (ViewGroup) view; 752105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewHierarchyWithProperties(group.getContext(), group, out, 0); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write("DONE."); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 756c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (Exception e) { 757c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project android.util.Log.w("View", "Problem dumping the view:", e); 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (out != null) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static View findView(ViewGroup group, String className, int hashCode) { 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isRequestedView(group, className, hashCode)) { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return group; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = group.getChildCount(); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = group.getChildAt(i); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View found = findView((ViewGroup) view, className, hashCode); 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (found != null) { 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return found; 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (isRequestedView(view, className, hashCode)) { 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view; 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean isRequestedView(View view, String className, int hashCode) { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view.getClass().getName().equals(className) && view.hashCode() == hashCode; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 790105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewHierarchyWithProperties(Context context, ViewGroup group, 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedWriter out, int level) { 792105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (!dumpViewWithProperties(context, group, out, level)) { 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = group.getChildCount(); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = group.getChildAt(i); 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 800105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewHierarchyWithProperties(context, (ViewGroup) view, out, level + 1); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 802105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewWithProperties(context, view, out, level + 1); 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 807105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static boolean dumpViewWithProperties(Context context, View view, 808105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out, int level) { 809105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < level; i++) { 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(' '); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(view.getClass().getName()); 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write('@'); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(Integer.toHexString(view.hashCode())); 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(' '); 818105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, view, out); 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w("View", "Error while dumping hierarchy tree"); 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Field[] getExportedPropertyFields(Class<?> klass) { 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sFieldsForClasses == null) { 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sFieldsForClasses = new HashMap<Class<?>, Field[]>(); 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 831c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (sAnnotations == null) { 832c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); 833c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 834c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Field[]> map = sFieldsForClasses; 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Field[] fields = map.get(klass); 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fields != null) { 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Field> foundFields = new ArrayList<Field>(); 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = klass.getDeclaredFields(); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field.isAnnotationPresent(ExportedProperty.class)) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.setAccessible(true); 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundFields.add(field); 85188b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy sAnnotations.put(field, field.getAnnotation(ExportedProperty.class)); 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = foundFields.toArray(new Field[foundFields.size()]); 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, fields); 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Method[] getExportedPropertyMethods(Class<?> klass) { 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sMethodsForClasses == null) { 863c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sMethodsForClasses = new HashMap<Class<?>, Method[]>(100); 864c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 865c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (sAnnotations == null) { 866c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 868c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Method[]> map = sMethodsForClasses; 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Method[] methods = map.get(klass); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methods != null) { 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Method> foundMethods = new ArrayList<Method>(); 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = klass.getDeclaredMethods(); 878a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 881a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final Method method = methods[i]; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method.getParameterTypes().length == 0 && 883c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project method.isAnnotationPresent(ExportedProperty.class) && 884c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project method.getReturnType() != Void.class) { 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.setAccessible(true); 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundMethods.add(method); 88788b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy sAnnotations.put(method, method.getAnnotation(ExportedProperty.class)); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = foundMethods.toArray(new Method[foundMethods.size()]); 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, methods); 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 897105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewProperties(Context context, Object view, 898105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out) throws IOException { 899105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 900105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, view, out, ""); 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 903105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewProperties(Context context, Object view, 904105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out, String prefix) throws IOException { 905105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Class<?> klass = view.getClass(); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 909105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportFields(context, view, out, klass, prefix); 910105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportMethods(context, view, out, klass, prefix); 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project klass = klass.getSuperclass(); 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (klass != Object.class); 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 914a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 915105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportMethods(Context context, Object view, BufferedWriter out, 916105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Class<?> klass, String prefix) throws IOException { 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method[] methods = getExportedPropertyMethods(klass); 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method method = methods[i]; 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection EmptyCatchBlock 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: This should happen on the UI thread 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object methodValue = method.invoke(view, (Object[]) null); 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> returnType = method.getReturnType(); 928bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev final ExportedProperty property = sAnnotations.get(method); 92991a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev String categoryPrefix = 93091a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev property.category().length() != 0 ? property.category() + ":" : ""; 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (returnType == int.class) { 933bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 934105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (property.resolveId() && context != null) { 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int id = (Integer) methodValue; 936105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project methodValue = resolveId(context, id); 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 938809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString[] flagsMapping = property.flagMapping(); 939809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (flagsMapping.length > 0) { 940809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int intValue = (Integer) methodValue; 94191a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = 94291a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev categoryPrefix + prefix + method.getName() + '_'; 943809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix); 944809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 945809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString[] mapping = property.mapping(); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapping.length > 0) { 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int intValue = (Integer) methodValue; 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mapped = false; 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mappingCount = mapping.length; 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mappingCount; j++) { 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString mapper = mapping[j]; 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapper.from() == intValue) { 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methodValue = mapper.to(); 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mapped = true; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mapped) { 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methodValue = intValue; 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 965c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (returnType == int[].class) { 966c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int[] array = (int[]) methodValue; 96791a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = categoryPrefix + prefix + method.getName() + '_'; 968c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String suffix = "()"; 969c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 970105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportUnrolledArray(context, out, property, array, valuePrefix, suffix); 971bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 972bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev // Probably want to return here, same as for fields. 973bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev return; 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!returnType.isPrimitive()) { 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.deepExport()) { 976105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, methodValue, out, prefix + property.prefix()); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 98191a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev writeEntry(out, categoryPrefix + prefix, method.getName(), "()", methodValue); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InvocationTargetException e) { 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 988105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportFields(Context context, Object view, BufferedWriter out, 989105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Class<?> klass, String prefix) throws IOException { 990105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field[] fields = getExportedPropertyFields(klass); 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection EmptyCatchBlock 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object fieldValue = null; 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> type = field.getType(); 1001bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev final ExportedProperty property = sAnnotations.get(field); 100291a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev String categoryPrefix = 100391a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev property.category().length() != 0 ? property.category() + ":" : ""; 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type == int.class) { 1006bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 1007105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (property.resolveId() && context != null) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int id = field.getInt(view); 1009105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project fieldValue = resolveId(context, id); 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1011809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString[] flagsMapping = property.flagMapping(); 1012809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (flagsMapping.length > 0) { 1013809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int intValue = field.getInt(view); 101491a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = 101591a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev categoryPrefix + prefix + field.getName() + '_'; 1016809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix); 1017809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1018809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString[] mapping = property.mapping(); 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapping.length > 0) { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int intValue = field.getInt(view); 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mappingCount = mapping.length; 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mappingCount; j++) { 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString mapped = mapping[j]; 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapped.from() == intValue) { 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = mapped.to(); 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue == null) { 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = intValue; 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1036c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (type == int[].class) { 1037c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int[] array = (int[]) field.get(view); 103891a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = categoryPrefix + prefix + field.getName() + '_'; 1039c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String suffix = ""; 1040c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1041105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportUnrolledArray(context, out, property, array, valuePrefix, suffix); 1042c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1043c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // We exit here! 1044c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return; 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!type.isPrimitive()) { 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.deepExport()) { 104791a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev dumpViewProperties(context, field.get(view), out, prefix 104891a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev + property.prefix()); 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue == null) { 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = field.get(view); 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 105791a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev writeEntry(out, categoryPrefix + prefix, field.getName(), "", fieldValue); 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1063c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void writeEntry(BufferedWriter out, String prefix, String name, 1064c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String suffix, Object value) throws IOException { 1065c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1066c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(prefix); 1067c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(name); 1068c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(suffix); 1069c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write("="); 1070c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeValue(out, value); 1071c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(' '); 1072c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1073c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1074809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy private static void exportUnrolledFlags(BufferedWriter out, FlagToString[] mapping, 1075809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int intValue, String prefix) throws IOException { 1076809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 1077809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int count = mapping.length; 1078809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy for (int j = 0; j < count; j++) { 1079809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString flagMapping = mapping[j]; 1080809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final boolean ifTrue = flagMapping.outputIf(); 10815bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final int maskResult = intValue & flagMapping.mask(); 10825bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final boolean test = maskResult == flagMapping.equals(); 1083809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if ((test && ifTrue) || (!test && !ifTrue)) { 1084809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final String name = flagMapping.name(); 10855bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final String value = "0x" + Integer.toHexString(maskResult); 1086809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy writeEntry(out, prefix, name, "", value); 1087809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1088809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1089809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1090809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 1091105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportUnrolledArray(Context context, BufferedWriter out, 1092c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project ExportedProperty property, int[] array, String prefix, String suffix) 1093c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project throws IOException { 1094c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1095c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString[] indexMapping = property.indexMapping(); 1096c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final boolean hasIndexMapping = indexMapping.length > 0; 1097c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1098c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString[] mapping = property.mapping(); 1099c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final boolean hasMapping = mapping.length > 0; 1100c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project final boolean resolveId = property.resolveId() && context != null; 1102c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int valuesCount = array.length; 1103c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1104c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int j = 0; j < valuesCount; j++) { 1105c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String name; 1106a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy String value = null; 1107c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1108c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int intValue = array[j]; 1109c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1110c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project name = String.valueOf(j); 1111c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (hasIndexMapping) { 1112c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mappingCount = indexMapping.length; 1113c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int k = 0; k < mappingCount; k++) { 1114c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString mapped = indexMapping[k]; 1115c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (mapped.from() == j) { 1116c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project name = mapped.to(); 1117c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project break; 1118c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1119c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1120c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1121c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1122c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (hasMapping) { 1123c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mappingCount = mapping.length; 1124c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int k = 0; k < mappingCount; k++) { 1125c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString mapped = mapping[k]; 1126c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (mapped.from() == intValue) { 1127c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project value = mapped.to(); 1128c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project break; 1129c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1130c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1131c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1132c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1133c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (resolveId) { 1134a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy if (value == null) value = (String) resolveId(context, intValue); 1135a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } else { 1136a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy value = String.valueOf(intValue); 1137c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1138c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1139c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeEntry(out, prefix, name, suffix, value); 1140c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1141c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1142c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1143237c1ceea36024cf4194212e713806e3ce8a1c49Romain Guy static Object resolveId(Context context, int id) { 1144c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Object fieldValue; 1145105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project final Resources resources = context.getResources(); 1146c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (id >= 0) { 1147c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 1148c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = resources.getResourceTypeName(id) + '/' + 1149c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project resources.getResourceEntryName(id); 1150c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (Resources.NotFoundException e) { 1151c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = "id/0x" + Integer.toHexString(id); 1152c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1153c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 1154c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = "NO_ID"; 1155c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1156c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return fieldValue; 1157c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1158c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1159c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void writeValue(BufferedWriter out, Object value) throws IOException { 1160c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (value != null) { 1161c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String output = value.toString().replace("\n", "\\n"); 1162c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(String.valueOf(output.length())); 1163c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(","); 1164c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(output); 1165c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 1166c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write("4,null"); 1167c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1168c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1169c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Field[] capturedViewGetPropertyFields(Class<?> klass) { 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCapturedViewFieldsForClasses == null) { 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCapturedViewFieldsForClasses = new HashMap<Class<?>, Field[]>(); 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Field[]> map = mCapturedViewFieldsForClasses; 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Field[] fields = map.get(klass); 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fields != null) { 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Field> foundFields = new ArrayList<Field>(); 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = klass.getFields(); 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field.isAnnotationPresent(CapturedViewProperty.class)) { 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.setAccessible(true); 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundFields.add(field); 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = foundFields.toArray(new Field[foundFields.size()]); 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, fields); 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Method[] capturedViewGetPropertyMethods(Class<?> klass) { 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCapturedViewMethodsForClasses == null) { 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCapturedViewMethodsForClasses = new HashMap<Class<?>, Method[]>(); 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Method[]> map = mCapturedViewMethodsForClasses; 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Method[] methods = map.get(klass); 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methods != null) { 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Method> foundMethods = new ArrayList<Method>(); 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = klass.getMethods(); 1212a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 1215a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final Method method = methods[i]; 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method.getParameterTypes().length == 0 && 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.isAnnotationPresent(CapturedViewProperty.class) && 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.getReturnType() != Void.class) { 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.setAccessible(true); 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundMethods.add(method); 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = foundMethods.toArray(new Method[foundMethods.size()]); 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, methods); 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 1230a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy private static String capturedViewExportMethods(Object obj, Class<?> klass, 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String prefix) { 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj == null) { 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "null"; 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1236a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method[] methods = capturedViewGetPropertyMethods(klass); 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method method = methods[i]; 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object methodValue = method.invoke(obj, (Object[]) null); 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> returnType = method.getReturnType(); 1246a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class); 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.retrieveReturn()) { 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we are interested in the second level data only 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#")); 1251a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } else { 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(method.getName()); 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("()="); 1255a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methodValue != null) { 1257a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final String value = methodValue.toString().replace("\n", "\\n"); 1258a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy sb.append(value); 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("null"); 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("; "); 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 1265a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception IllegalAccess, it is OK here 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this method 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InvocationTargetException e) { 1268a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception InvocationTarget, it is OK here 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this method 1270a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 1271a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) { 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj == null) { 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "null"; 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1279a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field[] fields = capturedViewGetPropertyFields(klass); 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object fieldValue = field.get(obj); 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(field.getName()); 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("="); 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue != null) { 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String value = fieldValue.toString().replace("\n", "\\n"); 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(value); 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("null"); 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(' '); 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 1301a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception IllegalAccess, it is OK here 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this field 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1307a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1309a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * Dump view info for id based instrument test generation 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (and possibly further data analysis). The results are dumped 1311a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * to the log. 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param tag for log 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view for dump 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1315a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy public static void dumpCapturedView(String tag, Object view) { 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Class<?> klass = view.getClass(); 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(klass.getName() + ": "); 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(capturedViewExportFields(view, klass, "")); 1319a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy sb.append(capturedViewExportMethods(view, klass, "")); 1320a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy Log.d(tag, sb.toString()); 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1323