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

Commit 1ebcb179 authored by Justin Weir's avatar Justin Weir Committed by Automerger Merge Worker
Browse files

Merge "Ensure log buffers are dumped to file on uncaught exceptions" into...

Merge "Ensure log buffers are dumped to file on uncaught exceptions" into tm-dev am: b41c2879 am: 844af86b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17915248



Change-Id: I3acca5dc2642a2c001d97a841834e0560cfaa139
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents a2c8ed75 844af86b
Loading
Loading
Loading
Loading
+4 −19
Original line number Diff line number Diff line
@@ -31,13 +31,13 @@ import android.widget.Toast;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @see Plugin
@@ -61,7 +61,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
    public PluginManagerImpl(Context context,
            PluginActionManager.Factory actionManagerFactory,
            boolean debuggable,
            Optional<UncaughtExceptionHandler> defaultHandlerOptional,
            UncaughtExceptionPreHandlerManager preHandlerManager,
            PluginEnabler pluginEnabler,
            PluginPrefs pluginPrefs,
            List<String> privilegedPlugins) {
@@ -72,9 +72,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
        mPluginPrefs = pluginPrefs;
        mPluginEnabler = pluginEnabler;

        PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler(
                defaultHandlerOptional);
        Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler);
        preHandlerManager.registerHandler(new PluginExceptionHandler());
    }

    public boolean isDebuggable() {
@@ -266,20 +264,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
    }

    private class PluginExceptionHandler implements UncaughtExceptionHandler {
        private final Optional<UncaughtExceptionHandler> mExceptionHandlerOptional;

        private PluginExceptionHandler(
                Optional<UncaughtExceptionHandler> exceptionHandlerOptional) {
            mExceptionHandlerOptional = exceptionHandlerOptional;
        }
        private PluginExceptionHandler() {}

        @Override
        public void uncaughtException(Thread thread, Throwable throwable) {
            if (SystemProperties.getBoolean("plugin.debugging", false)) {
                Throwable finalThrowable = throwable;
                mExceptionHandlerOptional.ifPresent(
                        handler -> handler.uncaughtException(thread, finalThrowable));

                return;
            }
            // Search for and disable plugins that may have been involved in this crash.
@@ -297,11 +287,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
            if (disabledAny) {
                throwable = new CrashWhilePluginActiveException(throwable);
            }

            // Run the normal exception handler so we can crash and cleanup our state.
            Throwable finalThrowable = throwable;
            mExceptionHandlerOptional.ifPresent(
                    handler -> handler.uncaughtException(thread, finalThrowable));
        }

        private boolean checkStack(Throwable throwable) {
+71 −0
Original line number Diff line number Diff line
package com.android.systemui.shared.system

import android.util.Log
import java.lang.Thread.UncaughtExceptionHandler
import java.util.concurrent.CopyOnWriteArrayList
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Sets the global (static var in Thread) uncaught exception pre-handler to an implementation that
 * delegates to each item in a list of registered UncaughtExceptionHandlers.
 */
@Singleton
class UncaughtExceptionPreHandlerManager @Inject constructor() {
    private val handlers: MutableList<UncaughtExceptionHandler> = CopyOnWriteArrayList()
    private val globalUncaughtExceptionPreHandler = GlobalUncaughtExceptionHandler()

    /**
     * Adds an exception pre-handler to the list of handlers. If this has not yet set the global
     * (static var in Thread) uncaught exception pre-handler yet, it will do so.
     */
    fun registerHandler(handler: UncaughtExceptionHandler) {
        checkGlobalHandlerSetup()
        addHandler(handler)
    }

    /**
     * Verifies that the global handler is set in Thread. If not, sets is up.
     */
    private fun checkGlobalHandlerSetup() {
        val currentHandler = Thread.getUncaughtExceptionPreHandler()
        if (currentHandler != globalUncaughtExceptionPreHandler) {
            if (currentHandler is GlobalUncaughtExceptionHandler) {
                throw IllegalStateException("Two UncaughtExceptionPreHandlerManagers created")
            }
            currentHandler?.let { addHandler(it) }
            Thread.setUncaughtExceptionPreHandler(globalUncaughtExceptionPreHandler)
        }
    }

    /**
     * Adds a handler if it has not already been added, preserving order.
     */
    private fun addHandler(it: UncaughtExceptionHandler) {
        if (it !in handlers) {
            handlers.add(it)
        }
    }

    /**
     * Calls uncaughtException on all registered handlers, catching and logging any new exceptions.
     */
    fun handleUncaughtException(thread: Thread?, throwable: Throwable?) {
        for (handler in handlers) {
            try {
                handler.uncaughtException(thread, throwable)
            } catch (e: Exception) {
                Log.wtf("Uncaught exception pre-handler error", e)
            }
        }
    }

    /**
     * UncaughtExceptionHandler impl that will be set as Thread's pre-handler static variable.
     */
    inner class GlobalUncaughtExceptionHandler : UncaughtExceptionHandler {
        override fun uncaughtException(thread: Thread?, throwable: Throwable?) {
            handleUncaughtException(thread, throwable)
        }
    }
}
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ public class SystemUIService extends Service {

        // Finish initializing dump logic
        mLogBufferFreezer.attach(mBroadcastDispatcher);
        mDumpHandler.init();

        // If configured, set up a battery notification
        if (getResources().getBoolean(R.bool.config_showNotificationForUnknownBatteryState)) {
+14 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_CRITICAL
import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_HIGH
import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_NORMAL
import com.android.systemui.log.LogBuffer
import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Provider
@@ -82,8 +83,20 @@ class DumpHandler @Inject constructor(
    private val context: Context,
    private val dumpManager: DumpManager,
    private val logBufferEulogizer: LogBufferEulogizer,
    private val startables: MutableMap<Class<*>, Provider<CoreStartable>>
    private val startables: MutableMap<Class<*>, Provider<CoreStartable>>,
    private val uncaughtExceptionPreHandlerManager: UncaughtExceptionPreHandlerManager
) {
    /**
     * Registers an uncaught exception handler
     */
    fun init() {
        uncaughtExceptionPreHandlerManager.registerHandler { _, e ->
            if (e is Exception) {
                logBufferEulogizer.record(e)
            }
        }
    }

    /**
     * Dump the diagnostics! Behavior can be controlled via [args].
     */
+3 −6
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.systemui.plugins;

import static com.android.systemui.util.concurrency.GlobalConcurrencyModule.PRE_HANDLER;

import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -32,12 +30,12 @@ import com.android.systemui.shared.plugins.PluginInstance;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.plugins.PluginPrefs;
import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager;
import com.android.systemui.util.concurrency.GlobalConcurrencyModule;
import com.android.systemui.util.concurrency.ThreadFactory;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;

import javax.inject.Named;
@@ -107,13 +105,12 @@ public abstract class PluginsModule {
            Context context,
            PluginActionManager.Factory instanceManagerFactory,
            @Named(PLUGIN_DEBUG) boolean debug,
            @Named(PRE_HANDLER)
                    Optional<Thread.UncaughtExceptionHandler> uncaughtExceptionHandlerOptional,
            UncaughtExceptionPreHandlerManager preHandlerManager,
            PluginEnabler pluginEnabler,
            PluginPrefs pluginPrefs,
            @Named(PLUGIN_PRIVILEGED) List<String> privilegedPlugins) {
        return new PluginManagerImpl(context, instanceManagerFactory, debug,
                uncaughtExceptionHandlerOptional, pluginEnabler, pluginPrefs,
                preHandlerManager, pluginEnabler, pluginPrefs,
                privilegedPlugins);
    }

Loading