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

Commit 6bf35640 authored by Jason Monk's avatar Jason Monk Committed by Android (Google) Code Review
Browse files

Merge "Wrap all exceptions/crashes while plugins are active" into oc-mr1-dev

parents 50877231 1c319639
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -136,11 +136,12 @@ public class PluginInstanceManager<T extends Plugin> {
        return disableAny;
    }

    public void disableAll() {
    public boolean disableAll() {
        ArrayList<PluginInfo> plugins = new ArrayList<>(mPluginHandler.mPlugins);
        for (int i = 0; i < plugins.size(); i++) {
            disable(plugins.get(i));
        }
        return plugins.size() != 0;
    }

    private void disable(PluginInfo info) {
@@ -182,6 +183,7 @@ public class PluginInstanceManager<T extends Plugin> {
                    if (DEBUG) Log.d(TAG, "onPluginConnected");
                    PluginPrefs.setHasPlugins(mContext);
                    PluginInfo<T> info = (PluginInfo<T>) msg.obj;
                    mManager.handleWtfs();
                    if (!(msg.obj instanceof PluginFragment)) {
                        // Only call onDestroy for plugins that aren't fragments, as fragments
                        // will get the onCreate as part of the fragment lifecycle.
+25 −3
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@ import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Log.TerribleFailure;
import android.util.Log.TerribleFailureHandler;
import android.widget.Toast;

import com.android.internal.annotations.VisibleForTesting;
@@ -71,10 +74,11 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
    private boolean mListening;
    private boolean mHasOneShot;
    private Looper mLooper;
    private boolean mWtfsSet;

    public PluginManagerImpl(Context context) {
        this(context, new PluginInstanceManagerFactory(),
                Build.IS_DEBUGGABLE, Thread.getDefaultUncaughtExceptionHandler());
                Build.IS_DEBUGGABLE, Thread.getUncaughtExceptionPreHandler());
    }

    @VisibleForTesting
@@ -88,7 +92,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage

        PluginExceptionHandler uncaughtExceptionHandler = new PluginExceptionHandler(
                defaultHandler);
        Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
        Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler);
        if (isDebuggable) {
            new Handler(mLooper).post(() -> {
                // Plugin dependencies that don't have another good home can go here, but
@@ -290,6 +294,15 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
        return false;
    }

    public void handleWtfs() {
        if (!mWtfsSet) {
            mWtfsSet = true;
            Log.setWtfHandler((tag, what, system) -> {
                throw new CrashWhilePluginActiveException(what);
            });
        }
    }

    @VisibleForTesting
    public static class PluginInstanceManagerFactory {
        public <T extends Plugin> PluginInstanceManager createPluginInstanceManager(Context context,
@@ -339,9 +352,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
                // disable all the plugins, so we can be sure that SysUI is running as
                // best as possible.
                for (PluginInstanceManager manager : mPluginMap.values()) {
                    manager.disableAll();
                    disabledAny |= manager.disableAll();
                }
            }
            if (disabledAny) {
                throwable = new CrashWhilePluginActiveException(throwable);
            }

            // Run the normal exception handler so we can crash and cleanup our state.
            mHandler.uncaughtException(thread, throwable);
@@ -358,4 +374,10 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
            return disabledAny | checkStack(throwable.getCause());
        }
    }

    private class CrashWhilePluginActiveException extends RuntimeException {
        public CrashWhilePluginActiveException(Throwable throwable) {
            super(throwable);
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ public class PluginManagerTest extends SysuiTestCase {
    public void setup() throws Exception {
        mDependency.injectTestDependency(Dependency.BG_LOOPER,
                TestableLooper.get(this).getLooper());
        mRealExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        mRealExceptionHandler = Thread.getUncaughtExceptionPreHandler();
        mMockExceptionHandler = mock(UncaughtExceptionHandler.class);
        mMockFactory = mock(PluginInstanceManagerFactory.class);
        mMockPluginInstance = mock(PluginInstanceManager.class);
@@ -167,9 +167,9 @@ public class PluginManagerTest extends SysuiTestCase {
    }

    private void resetExceptionHandler() {
        mPluginExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        mPluginExceptionHandler = Thread.getUncaughtExceptionPreHandler();
        // Set back the real exception handler so the test can crash if it wants to.
        Thread.setDefaultUncaughtExceptionHandler(mRealExceptionHandler);
        Thread.setUncaughtExceptionPreHandler(mRealExceptionHandler);
    }

    @ProvidesInterface(action = TestPlugin.ACTION, version = TestPlugin.VERSION)