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

Commit 48279602 authored by Dave Mankoff's avatar Dave Mankoff
Browse files

Fix flakes related to concurrent access of PluginManager.

Bug: 138139118
Test: atest SystemUITests
Change-Id: I53cfbf80e01c807ff6ba91f62e8afb7f9290c543
parent d851c0d8
Loading
Loading
Loading
Loading
+44 −26
Original line number Diff line number Diff line
@@ -171,17 +171,23 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
        PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener,
                allowMultiple, mLooper, cls, this);
        p.loadAll();
        synchronized (this) {
            mPluginMap.put(listener, p);
        }
        startListening();
    }

    public void removePluginListener(PluginListener<?> listener) {
        if (!mPluginMap.containsKey(listener)) return;
        synchronized (this) {
            if (!mPluginMap.containsKey(listener)) {
                return;
            }
            mPluginMap.remove(listener).destroy();
            if (mPluginMap.size() == 0) {
                stopListening();
            }
        }
    }

    private void startListening() {
        if (mListening) return;
@@ -208,9 +214,11 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
            synchronized (this) {
                for (PluginInstanceManager manager : mPluginMap.values()) {
                    manager.loadAll();
                }
            }
        } else if (DISABLE_PLUGIN.equals(intent.getAction())) {
            Uri uri = intent.getData();
            ComponentName component = ComponentName.unflattenFromString(
@@ -274,6 +282,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
                    getPluginEnabler().setEnabled(componentName);
                }
            }
            synchronized (this) {
                if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                    for (PluginInstanceManager manager : mPluginMap.values()) {
                        manager.onPackageChange(pkg);
@@ -285,6 +294,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
                }
            }
        }
    }

    /** Returns class loader specific for the given plugin. */
    public ClassLoader getClassLoader(ApplicationInfo appInfo) {
@@ -322,11 +332,13 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
    }

    public <T> boolean dependsOn(Plugin p, Class<T> cls) {
        synchronized (this) {
            for (int i = 0; i < mPluginMap.size(); i++) {
                if (mPluginMap.valueAt(i).dependsOn(p, cls)) {
                    return true;
                }
            }
        }
        return false;
    }

@@ -335,12 +347,14 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        synchronized (this) {
            pw.println(String.format("  plugin map (%d):", mPluginMap.size()));
            for (PluginListener listener : mPluginMap.keySet()) {
                pw.println(String.format("    %s -> %s",
                        listener, mPluginMap.get(listener)));
            }
        }
    }

    @VisibleForTesting
    public static class PluginInstanceManagerFactory {
@@ -418,10 +432,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
                // We couldn't find any plugins involved in this crash, just to be safe
                // disable all the plugins, so we can be sure that SysUI is running as
                // best as possible.
                synchronized (this) {
                    for (PluginInstanceManager manager : mPluginMap.values()) {
                        disabledAny |= manager.disableAll();
                    }
                }
            }
            if (disabledAny) {
                throwable = new CrashWhilePluginActiveException(throwable);
            }
@@ -433,11 +449,13 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
        private boolean checkStack(Throwable throwable) {
            if (throwable == null) return false;
            boolean disabledAny = false;
            synchronized (this) {
                for (StackTraceElement element : throwable.getStackTrace()) {
                    for (PluginInstanceManager manager : mPluginMap.values()) {
                        disabledAny |= manager.checkAndDisable(element.getClassName());
                    }
                }
            }
            return disabledAny | checkStack(throwable.getCause());
        }
    }