Log stacktrace for binder call tracer

Fix: 347752352
Flag: NONE - gated by studio build config
Test: Manual - record picture
Change-Id: I72f8fe62858a231ca5c996d880227337dccdd7a7
diff --git a/quickstep/src/com/android/quickstep/BinderTracker.java b/quickstep/src/com/android/quickstep/BinderTracker.java
index a876cd8..2a42861 100644
--- a/quickstep/src/com/android/quickstep/BinderTracker.java
+++ b/quickstep/src/com/android/quickstep/BinderTracker.java
@@ -26,11 +26,14 @@
 import android.os.Trace;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.TraceHelper;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.LinkedList;
 import java.util.Set;
 import java.util.function.Consumer;
@@ -43,6 +46,9 @@
 public class BinderTracker {
 
     private static final String TAG = "BinderTracker";
+    private static final Boolean DEBUG_STACKTRACE = false;
+
+    private static final String[] sActionablePackageKeywords = {"launcher3", "systemui"};
 
     // Common IPCs that are ok to block the main thread.
     private static final Set<String> sAllowedFrameworkClasses = Set.of(
@@ -145,13 +151,32 @@
 
             if (ipcBypass == null) {
                 mUnexpectedTransactionCallback.accept(new BinderCallSite(
-                        mMainThreadTraceStack.peekLast(), descriptor, transactionCode));
+                        mMainThreadTraceStack.peekLast(), descriptor, transactionCode,
+                        getActionableStacktrace()));
             } else {
                 Log.d(TAG, "MainThread-IPC " + descriptor + " ignored due to " + ipcBypass);
             }
             return null;
         }
 
+        @NonNull
+        private static String getActionableStacktrace() {
+            if (!DEBUG_STACKTRACE) {
+                return "DEBUG_STACKTRACE not turned on.";
+            }
+            final StringWriter sw = new StringWriter();
+            new Throwable().printStackTrace(new PrintWriter(sw));
+            final String stackTrace = sw.toString();
+
+            for (String actionablePackageKeyword : sActionablePackageKeywords) {
+                if (stackTrace.contains(actionablePackageKeyword)) {
+                    return stackTrace;
+                }
+            }
+
+            return "Not actionable to launcher";
+        }
+
         @Override
         public Object onTransactStarted(IBinder binder, int transactionCode) {
             // Do nothing
@@ -177,11 +202,14 @@
         public final String activeTrace;
         public final String descriptor;
         public final int transactionCode;
+        public final String stackTrace;
 
-        BinderCallSite(String activeTrace, String descriptor, int transactionCode) {
+        BinderCallSite(
+                String activeTrace, String descriptor, int transactionCode, String stackTrace) {
             this.activeTrace = activeTrace;
             this.descriptor = descriptor;
             this.transactionCode = transactionCode;
+            this.stackTrace = stackTrace;
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
index 3c902e6..f4e68dc 100644
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -66,7 +66,8 @@
 
         if (BuildConfig.IS_STUDIO_BUILD) {
             BinderTracker.startTracking(call ->  Log.e("BinderCall",
-                    call.descriptor + " called on mainthread under " + call.activeTrace));
+                    call.descriptor + " called on main thread under " + call.activeTrace
+                            + " stackTrace: " + call.stackTrace));
         }
     }
 }