Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f17bbfbb authored by Louis Chang's avatar Louis Chang
Browse files

Embed the bundle states into exception message

... in order to help developers debug the binder transaction
failure due to TransactionTooLargeException.

Bug: 253942493
Test: verified locally
Change-Id: I3c048cc31165de4a0e2fde1ffa7a58eab1d642f3
parent f2432024
Loading
Loading
Loading
Loading
+30 −14
Original line number Diff line number Diff line
@@ -25,11 +25,12 @@ import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.TransactionTooLargeException;
import android.util.Log;
import android.util.LogWriter;
import android.util.Slog;

import com.android.internal.util.IndentingPrintWriter;

import java.io.StringWriter;

/**
 * Container that has data pending to be used at later stages of
 * {@link android.app.servertransaction.ClientTransaction}.
@@ -134,6 +135,16 @@ public class PendingTransactionActions {
            mDescription = description;
        }

        private String collectBundleStates() {
            final StringWriter writer = new StringWriter();
            final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
            pw.println("Bundle stats:");
            Bundle.dumpStats(pw, mState);
            pw.println("PersistableBundle stats:");
            Bundle.dumpStats(pw, mPersistentState);
            return writer.toString().stripTrailing();
        }

        @Override
        public void run() {
            // Tell activity manager we have been stopped.
@@ -142,20 +153,25 @@ public class PendingTransactionActions {
                // TODO(lifecycler): Use interface callback instead of AMS.
                ActivityClient.getInstance().activityStopped(
                        mActivity.token, mState, mPersistentState, mDescription);
            } catch (RuntimeException ex) {
                // Dump statistics about bundle to help developers debug
                final LogWriter writer = new LogWriter(Log.WARN, TAG);
                final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
                pw.println("Bundle stats:");
                Bundle.dumpStats(pw, mState);
                pw.println("PersistableBundle stats:");
                Bundle.dumpStats(pw, mPersistentState);

                if (ex.getCause() instanceof TransactionTooLargeException
                        && mActivity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
                    Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
            } catch (RuntimeException runtimeException) {
                // Collect the statistics about bundle
                final String bundleStats = collectBundleStates();

                RuntimeException ex = runtimeException;
                if (ex.getCause() instanceof TransactionTooLargeException) {
                    // Embed the stats into exception message to help developers debug if the
                    // transaction size is too large.
                    final String message = ex.getMessage() + "\n" + bundleStats;
                    ex = new RuntimeException(message, ex.getCause());
                    if (mActivity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
                        Log.e(TAG, "App sent too much data in instance state, so it was ignored",
                                ex);
                        return;
                    }
                } else {
                    // Otherwise, dump the stats anyway.
                    Log.w(TAG, bundleStats);
                }
                throw ex;
            }
        }