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 /** 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This annotation can be used to mark fields and methods to be dumped by 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the view server. Only non-void methods with no arguments can be annotated 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by this annotation. 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.FIELD, ElementType.METHOD }) 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface ExportedProperty { 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When resolveId is true, and if the annotated field/method return value 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is an int, the value is converted to an Android's resource name. 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the property's value must be transformed into an Android 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * resource name, false otherwise 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean resolveId() default false; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A mapping can be defined to map int values to specific strings. For 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instance, View.getVisibility() returns 0, 4 or 8. However, these values 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * actually mean VISIBLE, INVISIBLE and GONE. A mapping can be used to see 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * these human readable values: 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.ExportedProperty(mapping = { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 0, to = "VISIBLE"), 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 4, to = "INVISIBLE"), 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @ViewDebug.IntToString(from = 8, to = "GONE") 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }) 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public int getVisibility() { ... 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An array of int to String mappings 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.ViewDebug.IntToString 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntToString[] mapping() default { }; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 110c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * A mapping can be defined to map array indices to specific strings. 111c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * A mapping can be used to see human readable values for the indices 112c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * of an array: 113c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 114c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <pre> 115809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.ExportedProperty(indexMapping = { 116c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 0, to = "INVALID"), 117c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 1, to = "FIRST"), 118c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @ViewDebug.IntToString(from = 2, to = "SECOND") 119c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * }) 120c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * private int[] mElements; 121c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * <pre> 122c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 123c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @return An array of int to String mappings 124c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * 125c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @see android.view.ViewDebug.IntToString 126c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project * @see #mapping() 127c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project */ 128c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project IntToString[] indexMapping() default { }; 129c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 130c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project /** 131809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * A flags mapping can be defined to map flags encoded in an integer to 132809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * specific strings. A mapping can be used to see human readable values 133809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * for the flags of an integer: 134809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 135809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <pre> 136809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.ExportedProperty(flagMapping = { 137809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = ENABLED, name = "ENABLED"), 138809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = DISABLED, name = "DISABLED"), 139809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * }) 140809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * private int mFlags; 141809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <pre> 142809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 143809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * A specified String is output when the following is true: 144a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * 145809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An array of int to String mappings 146809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 147809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy FlagToString[] flagMapping() default { }; 148809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 149809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When deep export is turned on, this property is not dumped. Instead, the 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * properties contained in this property are dumped. Each child property 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is prefixed with the name of this property. 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the properties of this property should be dumped 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 156a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * @see #prefix() 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean deepExport() default false; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The prefix to use on child properties when deep export is enabled 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return a prefix as a String 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #deepExport() 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String prefix() default ""; 168bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 169bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev /** 170bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * Specifies the category the property falls into, such as measurement, 171bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * layout, drawing, etc. 172bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * 173bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev * @return the category as String 174bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev */ 175bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev String category() default ""; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines a mapping from an int value to a String. Such a mapping can be used 180f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * in an @ExportedProperty to provide more meaningful values to the end user. 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.ViewDebug.ExportedProperty 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.TYPE }) 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface IntToString { 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The original int value to map to a String. 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An arbitrary int value. 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int from(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The String to use in place of the original int value. 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return An arbitrary non-null String. 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String to(); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 201809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 202809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 203f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * Defines a mapping from a flag to a String. Such a mapping can be used 204f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * in an @ExportedProperty to provide more meaningful values to the end user. 205809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 206809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @see android.view.ViewDebug.ExportedProperty 207809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 208809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy @Target({ ElementType.TYPE }) 209809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy @Retention(RetentionPolicy.RUNTIME) 210809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy public @interface FlagToString { 211809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 212809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The mask to apply to the original value. 213809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 214809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary int value. 215809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 216809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int mask(); 217809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 218809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 219809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The value to compare to the result of: 220809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * <code>original value & {@link #mask()}</code>. 221809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 222809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary value. 223809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 224809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int equals(); 225809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 226809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 227809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * The String to use in place of the original int value. 228809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * 229809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * @return An arbitrary non-null String. 230809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 231809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy String name(); 232809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 233809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy /** 234809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * Indicates whether to output the flag when the test is true, 235809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy * or false. Defaults to true. 236809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy */ 237809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy boolean outputIf() default true; 238809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 239809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This annotation can be used to mark fields and methods to be dumped when 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the view is captured. Methods with this annotation must have no arguments 243f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75Andy Stadler * and must return a valid type of data. 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Target({ ElementType.FIELD, ElementType.METHOD }) 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Retention(RetentionPolicy.RUNTIME) 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public @interface CapturedViewProperty { 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 249a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * When retrieveReturn is true, we need to retrieve second level methods 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod() 251a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * we will set retrieveReturn = true on the annotation of 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * myView.getFirstLevelMethod() 253a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * @return true if we need the second level methods 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 255a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy boolean retrieveReturn() default false; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 257a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 258926cf56676d760579573470c7848dbf119a86779John Reck /** 259926cf56676d760579573470c7848dbf119a86779John Reck * Allows a View to inject custom children into HierarchyViewer. For example, 260926cf56676d760579573470c7848dbf119a86779John Reck * WebView uses this to add its internal layer tree as a child to itself 261926cf56676d760579573470c7848dbf119a86779John Reck * @hide 262926cf56676d760579573470c7848dbf119a86779John Reck */ 263926cf56676d760579573470c7848dbf119a86779John Reck public interface HierarchyHandler { 264926cf56676d760579573470c7848dbf119a86779John Reck /** 265926cf56676d760579573470c7848dbf119a86779John Reck * Dumps custom children to hierarchy viewer. 266f2361156c4aee3dad26f25c410fcf255656922d1John Reck * See ViewDebug.dumpViewWithProperties(Context, View, BufferedWriter, int) 267926cf56676d760579573470c7848dbf119a86779John Reck * for the format 268926cf56676d760579573470c7848dbf119a86779John Reck * 269926cf56676d760579573470c7848dbf119a86779John Reck * An empty implementation should simply do nothing 270926cf56676d760579573470c7848dbf119a86779John Reck * 271926cf56676d760579573470c7848dbf119a86779John Reck * @param out The output writer 272926cf56676d760579573470c7848dbf119a86779John Reck * @param level The indentation level 273926cf56676d760579573470c7848dbf119a86779John Reck */ 274926cf56676d760579573470c7848dbf119a86779John Reck public void dumpViewHierarchyWithProperties(BufferedWriter out, int level); 275926cf56676d760579573470c7848dbf119a86779John Reck 276926cf56676d760579573470c7848dbf119a86779John Reck /** 277926cf56676d760579573470c7848dbf119a86779John Reck * Returns a View to enable grabbing screenshots from custom children 278926cf56676d760579573470c7848dbf119a86779John Reck * returned in dumpViewHierarchyWithProperties. 279926cf56676d760579573470c7848dbf119a86779John Reck * 280926cf56676d760579573470c7848dbf119a86779John Reck * @param className The className of the view to find 281926cf56676d760579573470c7848dbf119a86779John Reck * @param hashCode The hashCode of the view to find 282926cf56676d760579573470c7848dbf119a86779John Reck * @return the View to capture from, or null if not found 283926cf56676d760579573470c7848dbf119a86779John Reck */ 284926cf56676d760579573470c7848dbf119a86779John Reck public View findHierarchyView(String className, int hashCode); 285926cf56676d760579573470c7848dbf119a86779John Reck } 286926cf56676d760579573470c7848dbf119a86779John Reck 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Maximum delay in ms after which we stop trying to capture a View's drawing 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int CAPTURE_TIMEOUT = 4000; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE"; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_DUMP = "DUMP"; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; 297c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static final String REMOTE_PROFILE = "PROFILE"; 298223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS"; 299ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase private static final String REMOTE_COMMAND_OUTPUT_DISPLAYLIST = "OUTPUT_DISPLAYLIST"; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Field[]> sFieldsForClasses; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static HashMap<Class<?>, Method[]> sMethodsForClasses; 303c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static HashMap<AccessibleObject, ExportedProperty> sAnnotations; 304c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 30613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This enum is now unused 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 30813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum HierarchyTraceType { 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE, 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE_CHILD, 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project INVALIDATE_CHILD_IN_PARENT, 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project REQUEST_LAYOUT, 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ON_LAYOUT, 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ON_MEASURE, 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DRAW, 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BUILD_CACHE 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 32113b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This enum is now unused 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 32313b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum RecyclerTraceType { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NEW_VIEW, 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BIND_VIEW, 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RECYCLE_FROM_ACTIVE_HEAP, 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RECYCLE_FROM_SCRAP_HEAP, 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MOVE_TO_SCRAP_HEAP, 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MOVE_FROM_ACTIVE_TO_SCRAP_HEAP 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the number of instanciated Views. 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The number of Views instanciated in the current process. 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getViewInstanceCount() { 341c21550a8d1dfc9e5359fe994cb48049a0bd4c82cBrian Carlstrom return Debug.countInstancesOfClass(View.class); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 345c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * Returns the number of instanciated ViewAncestors. 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 347c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato * @return The number of ViewAncestors instanciated in the current process. 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35165b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy public static long getViewRootImplCount() { 3526dd005b48138708762bfade0081d031a2a4a3822Dianne Hackborn return Debug.countInstancesOfClass(ViewRootImpl.class); 353a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 35613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 35913b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings({ "UnusedParameters", "deprecation" }) 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void trace(View view, RecyclerTraceType type, int... parameters) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 36413b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 36613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 36713b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings("UnusedParameters") 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void startRecyclerTracing(String prefix, View view) { 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 37213b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 37413b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 37513b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings("UnusedParameters") 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stopRecyclerTracing() { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 38013b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 38213b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 38313b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings({ "UnusedParameters", "deprecation" }) 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void trace(View view, HierarchyTraceType type) { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 38813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 39013b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 39113b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @SuppressWarnings("UnusedParameters") 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void startHierarchyTracing(String prefix, View view) { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 39613b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy * @deprecated This method is now unused and invoking it is a no-op 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 39813b907353f18215b52b5ceda24bbf520d91d72a1Romain Guy @Deprecated 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void stopHierarchyTracing() { 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 401a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static void dispatchCommand(View view, String command, String parameters, 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OutputStream clientStream) throws IOException { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Paranoid but safe... 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view = view.getRootView(); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dump(view, clientStream); 410223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) { 411223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy captureLayers(view, new DataOutputStream(clientStream)); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String[] params = parameters.split(" "); 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project capture(view, clientStream, params[0]); 416ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase } else if (REMOTE_COMMAND_OUTPUT_DISPLAYLIST.equalsIgnoreCase(command)) { 417ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase outputDisplayList(view, params[0]); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(view, params[0]); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) { 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(view, params[0]); 422c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (REMOTE_PROFILE.equalsIgnoreCase(command)) { 423c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project profile(view, clientStream, params[0]); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 428c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static View findView(View root, String parameter) { 429c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // Look by type/hashcode 430c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (parameter.indexOf('@') != -1) { 431c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String[] ids = parameter.split("@"); 432c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String className = ids[0]; 433236092a36216c79507ec19eb207831810caced19Romain Guy final int hashCode = (int) Long.parseLong(ids[1], 16); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 435c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project View view = root.getRootView(); 436c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (view instanceof ViewGroup) { 437c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return findView((ViewGroup) view, className, hashCode); 438c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 439c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 440c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // Look by id 441c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int id = root.getResources().getIdentifier(parameter, null, null); 442c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return root.getRootView().findViewById(id); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void invalidate(View root, String parameter) { 449c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view.postInvalidate(); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void requestLayout(View root, String parameter) { 456c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view != null) { 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project root.post(new Runnable() { 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view.requestLayout(); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 466c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void profile(View root, OutputStream clientStream, String parameter) 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View view = findView(root, parameter); 470c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project BufferedWriter out = null; 471c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 472c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024); 473c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 474c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (view != null) { 475f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev profileViewAndChildren(view, out); 476f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } else { 477f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write("-1 -1 -1"); 478f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.newLine(); 479f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 480f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write("DONE."); 481f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.newLine(); 482f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } catch (Exception e) { 483f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev android.util.Log.w("View", "Problem profiling the view:", e); 484f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } finally { 485f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev if (out != null) { 486f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.close(); 487f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 488f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 489f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev } 490c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 491f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev private static void profileViewAndChildren(final View view, BufferedWriter out) 492f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev throws IOException { 493c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev profileViewAndChildren(view, out, true); 494c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 495f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev 496c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev private static void profileViewAndChildren(final View view, BufferedWriter out, boolean root) 497c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev throws IOException { 498f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev 499c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev long durationMeasure = 5004702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn (root || (view.mPrivateFlags & View.PFLAG_MEASURED_DIMENSION_SET) != 0) 5014702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn ? profileViewOperation(view, new ViewOperation<Void>() { 502c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public Void[] pre() { 503c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev forceLayout(view); 504c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return null; 505c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 506c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 507c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev private void forceLayout(View view) { 508c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view.forceLayout(); 509c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev if (view instanceof ViewGroup) { 510c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev ViewGroup group = (ViewGroup) view; 511c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev final int count = group.getChildCount(); 512c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev for (int i = 0; i < count; i++) { 513c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev forceLayout(group.getChildAt(i)); 514c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 515c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 516c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 517c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 518c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void run(Void... data) { 519c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view.measure(view.mOldWidthMeasureSpec, view.mOldHeightMeasureSpec); 520c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 521c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 522c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void post(Void... data) { 523c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 524c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }) 525c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev : 0; 526c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev long durationLayout = 5274702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn (root || (view.mPrivateFlags & View.PFLAG_LAYOUT_REQUIRED) != 0) 5284702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn ? profileViewOperation(view, new ViewOperation<Void>() { 529c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public Void[] pre() { 530c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return null; 531c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 532c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 533c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void run(Void... data) { 534c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom); 535c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 536c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 537c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void post(Void... data) { 538c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 539c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }) : 0; 540c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev long durationDraw = 5414702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn (root || !view.willNotDraw() || (view.mPrivateFlags & View.PFLAG_DRAWN) != 0) 5424702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn ? profileViewOperation(view, new ViewOperation<Object>() { 543c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public Object[] pre() { 544c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev final DisplayMetrics metrics = 545daf98e941e140e8739458126640183b9f296a2abChet Haase (view != null && view.getResources() != null) ? 546daf98e941e140e8739458126640183b9f296a2abChet Haase view.getResources().getDisplayMetrics() : null; 547daf98e941e140e8739458126640183b9f296a2abChet Haase final Bitmap bitmap = metrics != null ? 548dde331cebd87982faded6818ad5f9927ff994c96Dianne Hackborn Bitmap.createBitmap(metrics, metrics.widthPixels, 549daf98e941e140e8739458126640183b9f296a2abChet Haase metrics.heightPixels, Bitmap.Config.RGB_565) : null; 550daf98e941e140e8739458126640183b9f296a2abChet Haase final Canvas canvas = bitmap != null ? new Canvas(bitmap) : null; 551c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return new Object[] { 552c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev bitmap, canvas 553c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }; 554c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 555c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 556c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void run(Object... data) { 557daf98e941e140e8739458126640183b9f296a2abChet Haase if (data[1] != null) { 558daf98e941e140e8739458126640183b9f296a2abChet Haase view.draw((Canvas) data[1]); 559daf98e941e140e8739458126640183b9f296a2abChet Haase } 560c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 561c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev 562c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev public void post(Object... data) { 5636311d0a079702b29984c0d31937345be105e1a5eDianne Hackborn if (data[1] != null) { 5646311d0a079702b29984c0d31937345be105e1a5eDianne Hackborn ((Canvas) data[1]).setBitmap(null); 5656311d0a079702b29984c0d31937345be105e1a5eDianne Hackborn } 566daf98e941e140e8739458126640183b9f296a2abChet Haase if (data[0] != null) { 567daf98e941e140e8739458126640183b9f296a2abChet Haase ((Bitmap) data[0]).recycle(); 568daf98e941e140e8739458126640183b9f296a2abChet Haase } 569c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 570c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev }) : 0; 571f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(String.valueOf(durationMeasure)); 572f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(' '); 573f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(String.valueOf(durationLayout)); 574f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(' '); 575f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.write(String.valueOf(durationDraw)); 576f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev out.newLine(); 577f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev if (view instanceof ViewGroup) { 578f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev ViewGroup group = (ViewGroup) view; 579f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev final int count = group.getChildCount(); 580f8e1219cf8992a22d6c48c2c70d4fbbccc2494f6Konstantin Lopyrev for (int i = 0; i < count; i++) { 581c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev profileViewAndChildren(group.getChildAt(i), out, false); 582c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 583c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 584c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 585c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 586c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project interface ViewOperation<T> { 587c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project T[] pre(); 588c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project void run(T... data); 589c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project void post(T... data); 590c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 591c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 592c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static <T> long profileViewOperation(View view, final ViewOperation<T> operation) { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final CountDownLatch latch = new CountDownLatch(1); 594c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final long[] duration = new long[1]; 595c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 596c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project view.post(new Runnable() { 597c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project public void run() { 598c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 599c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project T[] data = operation.pre(); 600c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project long start = Debug.threadCpuTimeNanos(); 60188b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy //noinspection unchecked 602c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project operation.run(data); 603c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project duration[0] = Debug.threadCpuTimeNanos() - start; 60488b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy //noinspection unchecked 605c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project operation.post(data); 606c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } finally { 607c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project latch.countDown(); 608c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 609c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 610c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project }); 611c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 612c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 613c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev if (!latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS)) { 614c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev Log.w("View", "Could not complete the profiling of the view " + view); 615c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev return -1; 616c6dc45700bf0c18708b0ad2f695ea85fadcbf131Konstantin Lopyrev } 617c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (InterruptedException e) { 618c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w("View", "Could not complete the profiling of the view " + view); 619c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Thread.currentThread().interrupt(); 620c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return -1; 621c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 622c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 623c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return duration[0]; 624c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 625c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 626223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy private static void captureLayers(View root, final DataOutputStream clientStream) 627223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy throws IOException { 628223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 629223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy try { 630223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Rect outRect = new Rect(); 631223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy try { 632223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy root.mAttachInfo.mSession.getDisplayFrame(root.mAttachInfo.mWindow, outRect); 633223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } catch (RemoteException e) { 634223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy // Ignore 635223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 636223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 637223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(outRect.width()); 638223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(outRect.height()); 639223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 64065554f27855ce1764123604b061b10346f8b8404Romain Guy captureViewLayer(root, clientStream, true); 641223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 642223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.write(2); 643223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } finally { 644223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.close(); 645223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 646223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 647223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 64865554f27855ce1764123604b061b10346f8b8404Romain Guy private static void captureViewLayer(View view, DataOutputStream clientStream, boolean visible) 649223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy throws IOException { 650223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 65165554f27855ce1764123604b061b10346f8b8404Romain Guy final boolean localVisible = view.getVisibility() == View.VISIBLE && visible; 65265554f27855ce1764123604b061b10346f8b8404Romain Guy 6534702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn if ((view.mPrivateFlags & View.PFLAG_SKIP_DRAW) != View.PFLAG_SKIP_DRAW) { 654223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy final int id = view.getId(); 655223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy String name = view.getClass().getSimpleName(); 656223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy if (id != View.NO_ID) { 657223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy name = resolveId(view.getContext(), id).toString(); 658223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 659223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 660223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.write(1); 661223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeUTF(name); 66265554f27855ce1764123604b061b10346f8b8404Romain Guy clientStream.writeByte(localVisible ? 1 : 0); 663223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 664223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy int[] position = new int[2]; 665223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy // XXX: Should happen on the UI thread 666223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy view.getLocationInWindow(position); 667223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 668223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(position[0]); 669223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(position[1]); 670223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.flush(); 671223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 672223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Bitmap b = performViewCapture(view, true); 673223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy if (b != null) { 674223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(b.getWidth() * 675223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy b.getHeight() * 2); 676223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy b.compress(Bitmap.CompressFormat.PNG, 100, arrayOut); 677223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.writeInt(arrayOut.size()); 678223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy arrayOut.writeTo(clientStream); 679223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 680223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy clientStream.flush(); 681223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 682223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 683223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy if (view instanceof ViewGroup) { 684223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy ViewGroup group = (ViewGroup) view; 685223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy int count = group.getChildCount(); 686223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 687223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy for (int i = 0; i < count; i++) { 68865554f27855ce1764123604b061b10346f8b8404Romain Guy captureViewLayer(group.getChildAt(i), clientStream, localVisible); 689223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 690223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 691223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 692223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 693ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase private static void outputDisplayList(View root, String parameter) throws IOException { 694ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase final View view = findView(root, parameter); 6956dd005b48138708762bfade0081d031a2a4a3822Dianne Hackborn view.getViewRootImpl().outputDisplayList(view); 696ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase } 697ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase 698c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void capture(View root, final OutputStream clientStream, String parameter) 699c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project throws IOException { 700c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 701c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final View captureView = findView(root, parameter); 702223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Bitmap b = performViewCapture(captureView, false); 70343b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev 70443b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev if (b == null) { 705223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Log.w("View", "Failed to create capture bitmap!"); 70643b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev // Send an empty one so that it doesn't get stuck waiting for 70743b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev // something. 708dde331cebd87982faded6818ad5f9927ff994c96Dianne Hackborn b = Bitmap.createBitmap(root.getResources().getDisplayMetrics(), 709dde331cebd87982faded6818ad5f9927ff994c96Dianne Hackborn 1, 1, Bitmap.Config.ARGB_8888); 71043b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev } 71143b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev 71243b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev BufferedOutputStream out = null; 71343b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev try { 71443b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev out = new BufferedOutputStream(clientStream, 32 * 1024); 71543b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev b.compress(Bitmap.CompressFormat.PNG, 100, out); 71643b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev out.flush(); 71743b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev } finally { 71843b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev if (out != null) { 71943b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev out.close(); 72043b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev } 72143b9b48f792e0b1b166af7f7fb6a32172e7f11c2Konstantin Lopyrev b.recycle(); 722223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 723223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy } 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 725223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy private static Bitmap performViewCapture(final View captureView, final boolean skpiChildren) { 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (captureView != null) { 727c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final CountDownLatch latch = new CountDownLatch(1); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Bitmap[] cache = new Bitmap[1]; 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 730223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy captureView.post(new Runnable() { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 733958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn cache[0] = captureView.createSnapshot( 734223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy Bitmap.Config.ARGB_8888, 0, skpiChildren); 735958b9adc086f126dcd757d29f0d7f443ae9064b2Dianne Hackborn } catch (OutOfMemoryError e) { 73688b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy Log.w("View", "Out of memory for bitmap"); 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project latch.countDown(); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); 745223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy return cache[0]; 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 747c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Log.w("View", "Could not complete the capture of the view " + captureView); 748c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Thread.currentThread().interrupt(); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 751223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy 752223ff5c0586adbbd1d6d57a3a4d176222e8b7434Romain Guy return null; 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void dump(View root, OutputStream clientStream) throws IOException { 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedWriter out = null; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 75838e951b62ed956501b11f0715e23e3bf70942f6dRomain Guy out = new BufferedWriter(new OutputStreamWriter(clientStream, "utf-8"), 32 * 1024); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View view = root.getRootView(); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup group = (ViewGroup) view; 762105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewHierarchyWithProperties(group.getContext(), group, out, 0); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write("DONE."); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 766c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (Exception e) { 767c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project android.util.Log.w("View", "Problem dumping the view:", e); 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (out != null) { 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static View findView(ViewGroup group, String className, int hashCode) { 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isRequestedView(group, className, hashCode)) { 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return group; 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = group.getChildCount(); 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = group.getChildAt(i); 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View found = findView((ViewGroup) view, className, hashCode); 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (found != null) { 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return found; 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (isRequestedView(view, className, hashCode)) { 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view; 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 791926cf56676d760579573470c7848dbf119a86779John Reck if (view instanceof HierarchyHandler) { 792926cf56676d760579573470c7848dbf119a86779John Reck final View found = ((HierarchyHandler)view) 793926cf56676d760579573470c7848dbf119a86779John Reck .findHierarchyView(className, hashCode); 794926cf56676d760579573470c7848dbf119a86779John Reck if (found != null) { 795926cf56676d760579573470c7848dbf119a86779John Reck return found; 796926cf56676d760579573470c7848dbf119a86779John Reck } 797926cf56676d760579573470c7848dbf119a86779John Reck } 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean isRequestedView(View view, String className, int hashCode) { 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view.getClass().getName().equals(className) && view.hashCode() == hashCode; 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 807105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewHierarchyWithProperties(Context context, ViewGroup group, 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedWriter out, int level) { 809105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (!dumpViewWithProperties(context, group, out, level)) { 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = group.getChildCount(); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = group.getChildAt(i); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (view instanceof ViewGroup) { 817105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewHierarchyWithProperties(context, (ViewGroup) view, out, level + 1); 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 819105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewWithProperties(context, view, out, level + 1); 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 822926cf56676d760579573470c7848dbf119a86779John Reck if (group instanceof HierarchyHandler) { 823926cf56676d760579573470c7848dbf119a86779John Reck ((HierarchyHandler)group).dumpViewHierarchyWithProperties(out, level + 1); 824926cf56676d760579573470c7848dbf119a86779John Reck } 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 827105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static boolean dumpViewWithProperties(Context context, View view, 828105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out, int level) { 829105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < level; i++) { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(' '); 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(view.getClass().getName()); 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write('@'); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(Integer.toHexString(view.hashCode())); 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.write(' '); 838105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, view, out); 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.newLine(); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w("View", "Error while dumping hierarchy tree"); 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Field[] getExportedPropertyFields(Class<?> klass) { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sFieldsForClasses == null) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sFieldsForClasses = new HashMap<Class<?>, Field[]>(); 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 851c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (sAnnotations == null) { 852c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); 853c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 854c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Field[]> map = sFieldsForClasses; 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Field[] fields = map.get(klass); 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fields != null) { 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Field> foundFields = new ArrayList<Field>(); 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = klass.getDeclaredFields(); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field.isAnnotationPresent(ExportedProperty.class)) { 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.setAccessible(true); 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundFields.add(field); 87188b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy sAnnotations.put(field, field.getAnnotation(ExportedProperty.class)); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = foundFields.toArray(new Field[foundFields.size()]); 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, fields); 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Method[] getExportedPropertyMethods(Class<?> klass) { 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sMethodsForClasses == null) { 883c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sMethodsForClasses = new HashMap<Class<?>, Method[]>(100); 884c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 885c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (sAnnotations == null) { 886c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 888c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Method[]> map = sMethodsForClasses; 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Method[] methods = map.get(klass); 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methods != null) { 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Method> foundMethods = new ArrayList<Method>(); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = klass.getDeclaredMethods(); 898a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 901a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final Method method = methods[i]; 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method.getParameterTypes().length == 0 && 903c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project method.isAnnotationPresent(ExportedProperty.class) && 904c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project method.getReturnType() != Void.class) { 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.setAccessible(true); 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundMethods.add(method); 90788b4f153e2be863d79f4d7f68af95e0f9375e4ecRomain Guy sAnnotations.put(method, method.getAnnotation(ExportedProperty.class)); 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = foundMethods.toArray(new Method[foundMethods.size()]); 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, methods); 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 917105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewProperties(Context context, Object view, 918105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out) throws IOException { 919105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 920105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, view, out, ""); 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 923105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void dumpViewProperties(Context context, Object view, 924105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project BufferedWriter out, String prefix) throws IOException { 925105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 926dfab363807b3b44be4032e410f016e0a0d018426Romain Guy if (view == null) { 927dfab363807b3b44be4032e410f016e0a0d018426Romain Guy out.write(prefix + "=4,null "); 928dfab363807b3b44be4032e410f016e0a0d018426Romain Guy return; 929dfab363807b3b44be4032e410f016e0a0d018426Romain Guy } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 931dfab363807b3b44be4032e410f016e0a0d018426Romain Guy Class<?> klass = view.getClass(); 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 933105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportFields(context, view, out, klass, prefix); 934105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportMethods(context, view, out, klass, prefix); 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project klass = klass.getSuperclass(); 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (klass != Object.class); 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 938a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 939105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportMethods(Context context, Object view, BufferedWriter out, 940105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Class<?> klass, String prefix) throws IOException { 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method[] methods = getExportedPropertyMethods(klass); 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method method = methods[i]; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection EmptyCatchBlock 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: This should happen on the UI thread 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object methodValue = method.invoke(view, (Object[]) null); 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> returnType = method.getReturnType(); 952bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev final ExportedProperty property = sAnnotations.get(method); 95391a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev String categoryPrefix = 95491a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev property.category().length() != 0 ? property.category() + ":" : ""; 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (returnType == int.class) { 957bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 958105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (property.resolveId() && context != null) { 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int id = (Integer) methodValue; 960105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project methodValue = resolveId(context, id); 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 962809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString[] flagsMapping = property.flagMapping(); 963809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (flagsMapping.length > 0) { 964809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int intValue = (Integer) methodValue; 96591a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = 96691a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev categoryPrefix + prefix + method.getName() + '_'; 967809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix); 968809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 969809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString[] mapping = property.mapping(); 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapping.length > 0) { 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int intValue = (Integer) methodValue; 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mapped = false; 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mappingCount = mapping.length; 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mappingCount; j++) { 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString mapper = mapping[j]; 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapper.from() == intValue) { 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methodValue = mapper.to(); 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mapped = true; 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mapped) { 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methodValue = intValue; 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 989c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (returnType == int[].class) { 990c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int[] array = (int[]) methodValue; 99191a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = categoryPrefix + prefix + method.getName() + '_'; 992c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String suffix = "()"; 993c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 994105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportUnrolledArray(context, out, property, array, valuePrefix, suffix); 995bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 996bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev // Probably want to return here, same as for fields. 997bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev return; 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!returnType.isPrimitive()) { 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.deepExport()) { 1000105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project dumpViewProperties(context, methodValue, out, prefix + property.prefix()); 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 100591a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev writeEntry(out, categoryPrefix + prefix, method.getName(), "()", methodValue); 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InvocationTargetException e) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1012105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportFields(Context context, Object view, BufferedWriter out, 1013105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Class<?> klass, String prefix) throws IOException { 1014105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field[] fields = getExportedPropertyFields(klass); 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection EmptyCatchBlock 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object fieldValue = null; 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> type = field.getType(); 1025bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev final ExportedProperty property = sAnnotations.get(field); 102691a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev String categoryPrefix = 102791a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev property.category().length() != 0 ? property.category() + ":" : ""; 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type == int.class) { 1030bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev 1031105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (property.resolveId() && context != null) { 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int id = field.getInt(view); 1033105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project fieldValue = resolveId(context, id); 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1035809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString[] flagsMapping = property.flagMapping(); 1036809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if (flagsMapping.length > 0) { 1037809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int intValue = field.getInt(view); 103891a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = 103991a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev categoryPrefix + prefix + field.getName() + '_'; 1040809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix); 1041809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1042809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString[] mapping = property.mapping(); 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapping.length > 0) { 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int intValue = field.getInt(view); 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mappingCount = mapping.length; 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mappingCount; j++) { 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final IntToString mapped = mapping[j]; 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mapped.from() == intValue) { 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = mapped.to(); 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue == null) { 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = intValue; 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1060c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else if (type == int[].class) { 1061c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int[] array = (int[]) field.get(view); 106291a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev final String valuePrefix = categoryPrefix + prefix + field.getName() + '_'; 1063c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final String suffix = ""; 1064c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1065105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project exportUnrolledArray(context, out, property, array, valuePrefix, suffix); 1066c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1067c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project // We exit here! 1068c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return; 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!type.isPrimitive()) { 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.deepExport()) { 1071dfab363807b3b44be4032e410f016e0a0d018426Romain Guy dumpViewProperties(context, field.get(view), out, prefix + 1072dfab363807b3b44be4032e410f016e0a0d018426Romain Guy property.prefix()); 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue == null) { 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldValue = field.get(view); 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 108191a7f5fef8a9fc496acef23f513cb48139e8dff5Konstantin Lopyrev writeEntry(out, categoryPrefix + prefix, field.getName(), "", fieldValue); 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1087c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void writeEntry(BufferedWriter out, String prefix, String name, 1088c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String suffix, Object value) throws IOException { 1089c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1090c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(prefix); 1091c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(name); 1092c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(suffix); 1093c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write("="); 1094c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeValue(out, value); 1095c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write(' '); 1096c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1097c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1098809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy private static void exportUnrolledFlags(BufferedWriter out, FlagToString[] mapping, 1099809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy int intValue, String prefix) throws IOException { 1100809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 1101809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final int count = mapping.length; 1102809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy for (int j = 0; j < count; j++) { 1103809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final FlagToString flagMapping = mapping[j]; 1104809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final boolean ifTrue = flagMapping.outputIf(); 11055bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final int maskResult = intValue & flagMapping.mask(); 11065bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final boolean test = maskResult == flagMapping.equals(); 1107809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy if ((test && ifTrue) || (!test && !ifTrue)) { 1108809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy final String name = flagMapping.name(); 11095bcdff45bf4ada77ae7c95f520b795876adef75cRomain Guy final String value = "0x" + Integer.toHexString(maskResult); 1110809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy writeEntry(out, prefix, name, "", value); 1111809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1112809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1113809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy } 1114809a7f6080312f3e12f1a3a30eacf0e0c7627305Romain Guy 1115105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static void exportUnrolledArray(Context context, BufferedWriter out, 1116c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project ExportedProperty property, int[] array, String prefix, String suffix) 1117c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project throws IOException { 1118c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1119c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString[] indexMapping = property.indexMapping(); 1120c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final boolean hasIndexMapping = indexMapping.length > 0; 1121c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1122c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString[] mapping = property.mapping(); 1123c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final boolean hasMapping = mapping.length > 0; 1124c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1125105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project final boolean resolveId = property.resolveId() && context != null; 1126c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int valuesCount = array.length; 1127c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1128c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int j = 0; j < valuesCount; j++) { 1129c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project String name; 1130a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy String value = null; 1131c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1132c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final int intValue = array[j]; 1133c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1134c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project name = String.valueOf(j); 1135c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (hasIndexMapping) { 1136c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mappingCount = indexMapping.length; 1137c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int k = 0; k < mappingCount; k++) { 1138c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString mapped = indexMapping[k]; 1139c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (mapped.from() == j) { 1140c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project name = mapped.to(); 1141c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project break; 1142c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1143c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1144c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1145c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1146c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (hasMapping) { 1147c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project int mappingCount = mapping.length; 1148c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project for (int k = 0; k < mappingCount; k++) { 1149c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final IntToString mapped = mapping[k]; 1150c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (mapped.from() == intValue) { 1151c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project value = mapped.to(); 1152c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project break; 1153c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1154c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1155c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1156c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1157c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (resolveId) { 1158a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy if (value == null) value = (String) resolveId(context, intValue); 1159a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } else { 1160a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy value = String.valueOf(intValue); 1161c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1162c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1163c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project writeEntry(out, prefix, name, suffix, value); 1164c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1165c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1166c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1167237c1ceea36024cf4194212e713806e3ce8a1c49Romain Guy static Object resolveId(Context context, int id) { 1168c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project Object fieldValue; 1169105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project final Resources resources = context.getResources(); 1170c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (id >= 0) { 1171c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project try { 1172c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = resources.getResourceTypeName(id) + '/' + 1173c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project resources.getResourceEntryName(id); 1174c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } catch (Resources.NotFoundException e) { 1175c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = "id/0x" + Integer.toHexString(id); 1176c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1177c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 1178c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project fieldValue = "NO_ID"; 1179c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1180c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project return fieldValue; 1181c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1182c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 1183c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private static void writeValue(BufferedWriter out, Object value) throws IOException { 1184c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (value != null) { 118597723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy String output = "[EXCEPTION]"; 118697723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy try { 118797723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy output = value.toString().replace("\n", "\\n"); 118897723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy } finally { 118997723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy out.write(String.valueOf(output.length())); 119097723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy out.write(","); 119197723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy out.write(output); 119297723b2eb415d044d8dcee6a5ee3a2a3fb607b15Romain Guy } 1193c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } else { 1194c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project out.write("4,null"); 1195c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1196c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 1197c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Field[] capturedViewGetPropertyFields(Class<?> klass) { 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCapturedViewFieldsForClasses == null) { 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCapturedViewFieldsForClasses = new HashMap<Class<?>, Field[]>(); 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Field[]> map = mCapturedViewFieldsForClasses; 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Field[] fields = map.get(klass); 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fields != null) { 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Field> foundFields = new ArrayList<Field>(); 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = klass.getFields(); 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (field.isAnnotationPresent(CapturedViewProperty.class)) { 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field.setAccessible(true); 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundFields.add(field); 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fields = foundFields.toArray(new Field[foundFields.size()]); 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, fields); 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fields; 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Method[] capturedViewGetPropertyMethods(Class<?> klass) { 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCapturedViewMethodsForClasses == null) { 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCapturedViewMethodsForClasses = new HashMap<Class<?>, Method[]>(); 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final HashMap<Class<?>, Method[]> map = mCapturedViewMethodsForClasses; 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Method[] methods = map.get(klass); 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methods != null) { 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<Method> foundMethods = new ArrayList<Method>(); 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = klass.getMethods(); 1240a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 1243a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final Method method = methods[i]; 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (method.getParameterTypes().length == 0 && 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.isAnnotationPresent(CapturedViewProperty.class) && 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.getReturnType() != Void.class) { 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project method.setAccessible(true); 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project foundMethods.add(method); 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project methods = foundMethods.toArray(new Method[foundMethods.size()]); 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project map.put(klass, methods); 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return methods; 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1257a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 1258a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy private static String capturedViewExportMethods(Object obj, Class<?> klass, 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String prefix) { 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj == null) { 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "null"; 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1264a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method[] methods = capturedViewGetPropertyMethods(klass); 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = methods.length; 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Method method = methods[i]; 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object methodValue = method.invoke(obj, (Object[]) null); 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Class<?> returnType = method.getReturnType(); 1274a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class); 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property.retrieveReturn()) { 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we are interested in the second level data only 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#")); 1279a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } else { 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(method.getName()); 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("()="); 1283a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (methodValue != null) { 1285a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy final String value = methodValue.toString().replace("\n", "\\n"); 1286a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy sb.append(value); 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("null"); 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("; "); 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 1293a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception IllegalAccess, it is OK here 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this method 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InvocationTargetException e) { 1296a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception InvocationTarget, it is OK here 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this method 1298a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 1299a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy } 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) { 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (obj == null) { 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "null"; 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1307a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field[] fields = capturedViewGetPropertyFields(klass); 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = fields.length; 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Field field = fields[i]; 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object fieldValue = field.get(obj); 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(prefix); 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(field.getName()); 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("="); 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fieldValue != null) { 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String value = fieldValue.toString().replace("\n", "\\n"); 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(value); 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("null"); 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(' '); 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalAccessException e) { 1329a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy //Exception IllegalAccess, it is OK here 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //we simply ignore this field 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1335a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1337a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * Dump view info for id based instrument test generation 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (and possibly further data analysis). The results are dumped 1339a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy * to the log. 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param tag for log 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param view for dump 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1343a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy public static void dumpCapturedView(String tag, Object view) { 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Class<?> klass = view.getClass(); 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(klass.getName() + ": "); 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(capturedViewExportFields(view, klass, "")); 1347a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy sb.append(capturedViewExportMethods(view, klass, "")); 1348a1f3e4aef19882b4b81075d9205bd363efe1e66dRomain Guy Log.d(tag, sb.toString()); 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1351