Skip to content

Commit

Permalink
feat: reformat log
Browse files Browse the repository at this point in the history
  • Loading branch information
y4n9b0 committed May 10, 2024
1 parent 6f89956 commit 3410447
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 49 deletions.
60 changes: 42 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,49 @@ adb logcat -s ttleosis

Example logcat output:
```text
D ttleosis: onActivityPostSaveInstanceState activity=y4n9b0.ttleosis.app.TtleosisReproduceActivity@fc1a9d2
D ttleosis: Bundle bytes=8184
D ttleosis: ├─ Bundle@android:viewHierarchyState bytes=984
D ttleosis: │ └─ SparseArray@android:views size=7
D ttleosis: ├─ [email protected] bytes=6572
D ttleosis: │ ├─ Bundle@androidx:appcompat bytes=4
D ttleosis: │ ├─ [email protected] bytes=4
D ttleosis: │ ├─ Bundle@android:support:activity-result bytes=2180
D ttleosis: │ │ ├─ ArrayList@KEY_COMPONENT_ACTIVITY_REGISTERED_KEYS size=12
D ttleosis: │ │ ├─ ArrayList@KEY_COMPONENT_ACTIVITY_REGISTERED_RCS size=12
D ttleosis: │ │ ├─ Bundle@KEY_COMPONENT_ACTIVITY_PENDING_RESULT bytes=4
D ttleosis: │ │ └─ ArrayList@KEY_COMPONENT_ACTIVITY_LAUNCHED_KEYS size=0
D ttleosis: │ └─ Bundle@android:support:fragments bytes=4076
D ttleosis: │ └─ FragmentManagerState@android:support:fragments size=3
D ttleosis: │ ├─ [email protected](4598bdc9-3e22-4971-bb46-6b2dc56af298) bytes=1208
D ttleosis: │ ├─ [email protected](13d44e6c-49c7-48e5-8ad5-7830ddf71859) bytes=1208
D ttleosis: │ └─ [email protected](af4fdee8-e074-4ee8-b590-203a93f06958) bytes=1208
D ttleosis: onActivityPostSaveInstanceState activity=y4n9b0.ttleosis.app.TtleosisReproduceActivity@4ca12a
D ttleosis: Bundle Bytes=6388
D ttleosis: ├─ Bundle@android:viewHierarchyState Bytes=984
D ttleosis: │ └─ SparseArray[7]@android:views
D ttleosis: │ ├─ android.view.AbsSavedState$1@16908290 Bytes=4
D ttleosis: │ ├─ androidx.appcompat.widget.Toolbar$SavedState@2131230773 Bytes=76
D ttleosis: │ ├─ android.view.AbsSavedState$1@2131230775 Bytes=4
D ttleosis: │ ├─ android.view.AbsSavedState$1@2131230781 Bytes=4
D ttleosis: │ ├─ android.view.AbsSavedState$1@2131230863 Bytes=4
D ttleosis: │ ├─ com.google.android.material.button.MaterialButton$SavedState@2131231040 Bytes=72
D ttleosis: │ └─ com.google.android.material.button.MaterialButton$SavedState@2131231045 Bytes=72
D ttleosis: ├─ [email protected] Bytes=4776
D ttleosis: │ ├─ Bundle@androidx:appcompat Bytes=4
D ttleosis: │ ├─ [email protected] Bytes=4
D ttleosis: │ ├─ Bundle@android:support:activity-result Bytes=1676
D ttleosis: │ │ ├─ ArrayList[9]@KEY_COMPONENT_ACTIVITY_REGISTERED_KEYS
D ttleosis: │ │ │ ├─ String=FragmentManager:StartIntentSenderForResult
D ttleosis: │ │ │ ├─ String=FragmentManager:StartActivityForResult
D ttleosis: │ │ │ ├─ String=FragmentManager:a0712bbc-9939-4523-b296-14d0377edb1e:StartIntentSenderForResult
D ttleosis: │ │ │ ├─ String=FragmentManager:1170ad3d-b798-426d-a958-f10debb3c4b6:StartActivityForResult
D ttleosis: │ │ │ ├─ String=FragmentManager:a0712bbc-9939-4523-b296-14d0377edb1e:RequestPermissions
D ttleosis: │ │ │ ├─ String=FragmentManager:1170ad3d-b798-426d-a958-f10debb3c4b6:RequestPermissions
D ttleosis: │ │ │ ├─ String=FragmentManager:RequestPermissions
D ttleosis: │ │ │ ├─ String=FragmentManager:1170ad3d-b798-426d-a958-f10debb3c4b6:StartIntentSenderForResult
D ttleosis: │ │ │ └─ String=FragmentManager:a0712bbc-9939-4523-b296-14d0377edb1e:StartActivityForResult
D ttleosis: │ │ ├─ ArrayList[9]@KEY_COMPONENT_ACTIVITY_REGISTERED_RCS
D ttleosis: │ │ │ ├─ Integer=1942165898
D ttleosis: │ │ │ ├─ Integer=356918738
D ttleosis: │ │ │ ├─ Integer=182926120
D ttleosis: │ │ │ ├─ Integer=66967503
D ttleosis: │ │ │ ├─ Integer=1726710991
D ttleosis: │ │ │ ├─ Integer=14827718
D ttleosis: │ │ │ ├─ Integer=1393861623
D ttleosis: │ │ │ ├─ Integer=1236973480
D ttleosis: │ │ │ └─ Integer=413874826
D ttleosis: │ │ ├─ Bundle@KEY_COMPONENT_ACTIVITY_PENDING_RESULT Bytes=4
D ttleosis: │ │ └─ ArrayList[0]@KEY_COMPONENT_ACTIVITY_LAUNCHED_KEYS
D ttleosis: │ └─ Bundle@android:support:fragments Bytes=2784
D ttleosis: │ └─ FragmentManagerState@android:support:fragments
D ttleosis: │ ├─ [email protected](a0712bbc-9939-4523-b296-14d0377edb1e) Bytes=1208
D ttleosis: │ └─ [email protected](1170ad3d-b798-426d-a958-f10debb3c4b6) Bytes=1208
D ttleosis: ├─ Integer@android:lastAutofillId
D ttleosis: └─ FragmentManagerState@android:fragments bytes=260
D ttleosis: └─ FragmentManagerState@android:fragments Bytes=260
```

License
Expand Down
1 change: 1 addition & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ android {

dependencies {
implementation "androidx.startup:startup-runtime:1.1.1"
implementation 'androidx.customview:customview:1.1.0'
}

ext {
Expand Down
133 changes: 102 additions & 31 deletions lib/src/main/java/y4n9b0/ttleosis/BundleLogger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,59 +16,73 @@ internal fun Bundle.log() {
val dataSize = parcel.dataSize()
parcel.recycle()
if (dataSize > 200.shl(10)) {
Log.w(TAG, "${bundle.javaClass.simpleName} bytes=$dataSize")
Log.w(TAG, "${bundle.javaClass.simpleName} Bytes=$dataSize")
} else {
Log.d(TAG, "${bundle.javaClass.simpleName} bytes=$dataSize")
Log.d(TAG, "${bundle.javaClass.simpleName} Bytes=$dataSize")
}
val stack = Stack<BundleElement>()
bundle.flat().reversed().forEach(stack::push)


while (stack.isNotEmpty()) {
val element = stack.pop()
val key = element.key
val value = element.value
val name = value.javaClass.simpleName
var name = value.javaClass.simpleName
var prefix = ""
var suffix = ""
when (value) {
is Bundle -> {
val p = Parcel.obtain()
p.writeBundle(value)
val ds = p.dataSize()
p.recycle()
suffix = "bytes=$ds"
(value as? Parcelable)?.apply {
val p = Parcel.obtain()
value.writeToParcel(p, 0)
val ds = p.dataSize()
p.recycle()
suffix = "Bytes=$ds"
}

when {
value is Bundle -> {
val indent = element.indent + if (element.isLast) " " else ""
value.flat(indent).reversed().forEach(stack::push)
}

value is SparseArray<*> -> {
prefix = "[${value.size()}]"
val indent = element.indent + if (element.isLast) " " else ""
value.flat(indent).reversed().forEach(stack::push)
}

is Array<*> -> suffix = "size=${value.size}"
is SparseArray<*> -> suffix = "size=${value.size()}"
is List<*> -> suffix = "size=${value.size}"
else -> {
if (logAndroidxFragmentManagerState(element)) {
continue
} else if (value.javaClass.name == "android.app.FragmentManagerState") {
val p = Parcel.obtain()
(value as Parcelable).writeToParcel(p, 0)
val ds = p.dataSize()
p.recycle()
suffix = "bytes=$ds"
}
androidx.customview.view.AbsSavedState::class.java.isAssignableFrom(value.javaClass)
or android.view.AbsSavedState::class.java.isAssignableFrom(value.javaClass)
-> name = value.javaClass.name

logArray(element) or logCollection(element) or logAndroidxFragmentManagerState(element) -> continue

value.javaClass.name == "android.app.FragmentManagerState" -> {
// todo
}

else -> {}
}
Log.d(TAG, "${element.indent + if (element.isLast) "└─ " else "├─ "}$name@$key $suffix")
Log.d(TAG, "${element.indent + if (element.isLast) "└─ " else "├─ "}$name$prefix@$key $suffix")
}
}

@Suppress("DEPRECATION")
private fun Bundle.flat(indent: String = ""): List<BundleElement> {
return keySet().mapNotNull { key ->
private fun Bundle.flat(indent: String = ""): List<BundleElement> =
keySet().mapNotNull { key ->
get(key)?.let { value ->
BundleElement(key, value, indent)
}
}.apply {
lastOrNull()?.isLast = true
}
}

private fun SparseArray<*>.flat(indent: String = ""): List<BundleElement> =
List(size()) {
BundleElement(keyAt(it).toString(), valueAt(it), indent)
}.apply {
lastOrNull()?.isLast = true
}

@Suppress("UNCHECKED_CAST")
private fun logAndroidxFragmentManagerState(element: BundleElement): Boolean {
Expand All @@ -81,10 +95,10 @@ private fun logAndroidxFragmentManagerState(element: BundleElement): Boolean {
it.get(fragmentManagerState) as ArrayList<Any>
}
val size = activeFragmentStates.size
if (size == 0) return false
if (size == 0) return logged
val fmsIndent = element.indent + if (element.isLast) "└─ " else "├─ "
val fmsName = fragmentManagerState.javaClass.simpleName
Log.d(TAG, "$fmsIndent$fmsName@${element.key} size=$size")
Log.d(TAG, "$fmsIndent$fmsName@${element.key}")
logged = true
val fragmentStateClass = Class.forName("androidx.fragment.app.FragmentState")
val nameField = fragmentStateClass.getDeclaredField("mClassName")
Expand All @@ -98,11 +112,68 @@ private fun logAndroidxFragmentManagerState(element: BundleElement): Boolean {
parcel.recycle()
val name = nameField.get(fragmentState) as String
val who = whoField.get(fragmentState) as String
val indent = element.indent + (if (element.isLast) " " else "") + (if (index == size - 1) "└─ " else "├─ ")
Log.d(TAG, "$indent${fragmentState.javaClass.simpleName}@$name($who) bytes=$dataSize")
val indent =
element.indent + (if (element.isLast) " " else "") + (if (index == size - 1) "└─ " else "├─ ")
Log.d(TAG, "$indent${fragmentState.javaClass.simpleName}@$name($who) Bytes=$dataSize")
}
} catch (e: Exception) {
// ignore
}
return logged
}

private fun logArray(element: BundleElement): Boolean {
val value = element.value
if (value !is Array<*>) return false
val key = element.key
val name = value.javaClass.simpleName
val size = value.size
Log.d(TAG, "${element.indent + if (element.isLast) "└─ " else "├─ "}$name[$size]@$key")

var suffix: String
value.forEachIndexed { index, item ->
val indent = element.indent + (if (element.isLast) " " else "") + (if (index == size - 1) "└─ " else "├─ ")
suffix = ""
(item as? Parcelable)?.apply {
val p = Parcel.obtain()
item.writeToParcel(p, 0)
val ds = p.dataSize()
p.recycle()
suffix = "Bytes=$ds"
}
if (item != null) {
Log.d(TAG, "$indent${item.javaClass.simpleName}=$item $suffix")
} else {
Log.d(TAG, "${indent}null")
}
}
return true
}

private fun logCollection(element: BundleElement): Boolean {
val value = element.value
if (value !is Collection<*>) return false
val key = element.key
val name = value.javaClass.simpleName
val size = value.size
Log.d(TAG, "${element.indent + if (element.isLast) "└─ " else "├─ "}$name[$size]@$key")

var suffix: String
value.forEachIndexed { index, item ->
val indent = element.indent + (if (element.isLast) " " else "") + (if (index == size - 1) "└─ " else "├─ ")
suffix = ""
(item as? Parcelable)?.apply {
val p = Parcel.obtain()
item.writeToParcel(p, 0)
val ds = p.dataSize()
p.recycle()
suffix = "Bytes=$ds"
}
if (item != null) {
Log.d(TAG, "$indent${item.javaClass.simpleName}=$item $suffix")
} else {
Log.d(TAG, "${indent}null")
}
}
return true
}

0 comments on commit 3410447

Please sign in to comment.