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

Commit 33ce3e1f authored by Dave Mankoff's avatar Dave Mankoff
Browse files

Remove custom MainHandler from PluginInstanceManager

Also removes the "one shot" related methods which weren't used
and complicated the MainHandler related code.

Bug: 194781951
Test: manual && atest SystemUiTests
Change-Id: Ie824442ce55fe09649373bd2fc4f6eb47988b244
parent 03262298
Loading
Loading
Loading
Loading
+50 −83
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;

public class PluginInstanceManager<T extends Plugin> {

@@ -59,8 +60,6 @@ public class PluginInstanceManager<T extends Plugin> {
    private final boolean mAllowMultiple;
    private final VersionInfo mVersion;

    @VisibleForTesting
    final MainHandler mMainHandler;
    @VisibleForTesting
    final PluginHandler mPluginHandler;
    private final boolean isDebuggable;
@@ -68,13 +67,14 @@ public class PluginInstanceManager<T extends Plugin> {
    private final PluginManagerImpl mManager;
    private final ArraySet<String> mWhitelistedPlugins = new ArraySet<>();
    private final PluginInitializer mInitializer;
    private final Executor mMainExecutor;

    PluginInstanceManager(Context context, PackageManager pm, String action,
            PluginListener<T> listener, boolean allowMultiple, Looper looper, VersionInfo version,
            PluginManagerImpl manager, boolean debuggable, String[] pluginWhitelist,
            PluginInitializer initializer) {
            PluginListener<T> listener, boolean allowMultiple, Executor mainExecutor,
            Looper looper, VersionInfo version, PluginManagerImpl manager, boolean debuggable,
            String[] pluginWhitelist, PluginInitializer initializer) {
        mInitializer = initializer;
        mMainHandler = new MainHandler(Looper.getMainLooper());
        mMainExecutor = mainExecutor;
        mPluginHandler = new PluginHandler(looper);
        mManager = manager;
        mContext = context;
@@ -87,21 +87,6 @@ public class PluginInstanceManager<T extends Plugin> {
        isDebuggable = debuggable;
    }

    public PluginInfo<T> getPlugin() {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new RuntimeException("Must be called from UI thread");
        }
        mPluginHandler.handleQueryPlugins(null /* All packages */);
        if (mPluginHandler.mPlugins.size() > 0) {
            mMainHandler.removeMessages(MainHandler.PLUGIN_CONNECTED);
            PluginInfo<T> info = mPluginHandler.mPlugins.get(0);
            PluginPrefs.setHasPlugins(mContext);
            info.mPlugin.onCreate(mContext, info.mPluginContext);
            return info;
        }
        return null;
    }

    public void loadAll() {
        if (DEBUG) Log.d(TAG, "startListening");
        mPluginHandler.sendEmptyMessage(PluginHandler.QUERY_ALL);
@@ -109,10 +94,9 @@ public class PluginInstanceManager<T extends Plugin> {

    public void destroy() {
        if (DEBUG) Log.d(TAG, "stopListening");
        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
        for (PluginInfo plugin : plugins) {
            mMainHandler.obtainMessage(MainHandler.PLUGIN_DISCONNECTED,
                    plugin.mPlugin).sendToTarget();
        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPluginHandler.mPlugins);
        for (PluginInfo<T> pluginInfo : plugins) {
            mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
        }
    }

@@ -127,8 +111,8 @@ public class PluginInstanceManager<T extends Plugin> {

    public boolean checkAndDisable(String className) {
        boolean disableAny = false;
        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
        for (PluginInfo info : plugins) {
        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPluginHandler.mPlugins);
        for (PluginInfo<T> info : plugins) {
            if (className.startsWith(info.mPackage)) {
                disableAny |= disable(info, PluginEnabler.DISABLED_FROM_EXPLICIT_CRASH);
            }
@@ -137,7 +121,7 @@ public class PluginInstanceManager<T extends Plugin> {
    }

    public boolean disableAll() {
        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPluginHandler.mPlugins);
        boolean disabledAny = false;
        for (int i = 0; i < plugins.size(); i++) {
            disabledAny |= disable(plugins.get(i), PluginEnabler.DISABLED_FROM_SYSTEM_CRASH);
@@ -161,7 +145,7 @@ public class PluginInstanceManager<T extends Plugin> {
        return false;
    }

    private boolean disable(PluginInfo info, @PluginEnabler.DisableReason int reason) {
    private boolean disable(PluginInfo<T> info, @PluginEnabler.DisableReason int reason) {
        // Live by the sword, die by the sword.
        // Misbehaving plugins get disabled and won't come back until uninstall/reinstall.

@@ -179,9 +163,9 @@ public class PluginInstanceManager<T extends Plugin> {
        return true;
    }

    public <T> boolean dependsOn(Plugin p, Class<T> cls) {
        ArrayList<PluginInfo> plugins = new ArrayList<PluginInfo>(mPluginHandler.mPlugins);
        for (PluginInfo info : plugins) {
    <C> boolean dependsOn(Plugin p, Class<C> cls) {
        ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPluginHandler.mPlugins);
        for (PluginInfo<T> info : plugins) {
            if (info.mPlugin.getClass().getName().equals(p.getClass().getName())) {
                return info.mVersion != null && info.mVersion.hasClass(cls);
            }
@@ -195,42 +179,25 @@ public class PluginInstanceManager<T extends Plugin> {
                getClass().getSimpleName(), hashCode(), mAction);
    }

    private class MainHandler extends Handler {
        private static final int PLUGIN_CONNECTED = 1;
        private static final int PLUGIN_DISCONNECTED = 2;

        public MainHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case PLUGIN_CONNECTED:
    private void onPluginConnected(PluginInfo<T> pluginInfo) {
        if (DEBUG) Log.d(TAG, "onPluginConnected");
        PluginPrefs.setHasPlugins(mContext);
                    PluginInfo<T> info = (PluginInfo<T>) msg.obj;
        mInitializer.handleWtfs();
                    if (!(msg.obj instanceof PluginFragment)) {
                        // Only call onDestroy for plugins that aren't fragments, as fragments
        if (!(pluginInfo.mPlugin instanceof PluginFragment)) {
            // Only call onCreate for plugins that aren't fragments, as fragments
            // will get the onCreate as part of the fragment lifecycle.
                        info.mPlugin.onCreate(mContext, info.mPluginContext);
            pluginInfo.mPlugin.onCreate(mContext, pluginInfo.mPluginContext);
        }
                    mListener.onPluginConnected(info.mPlugin, info.mPluginContext);
                    break;
                case PLUGIN_DISCONNECTED:
        mListener.onPluginConnected(pluginInfo.mPlugin, pluginInfo.mPluginContext);
    }

    private void onPluginDisconnected(T plugin) {
        if (DEBUG) Log.d(TAG, "onPluginDisconnected");
                    mListener.onPluginDisconnected((T) msg.obj);
                    if (!(msg.obj instanceof PluginFragment)) {
        mListener.onPluginDisconnected(plugin);
        if (!(plugin instanceof PluginFragment)) {
            // Only call onDestroy for plugins that aren't fragments, as fragments
            // will get the onDestroy as part of the fragment lifecycle.
                        ((T) msg.obj).onDestroy();
                    }
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
            plugin.onDestroy();
        }
    }

@@ -252,8 +219,7 @@ public class PluginInstanceManager<T extends Plugin> {
                    if (DEBUG) Log.d(TAG, "queryAll " + mAction);
                    for (int i = mPlugins.size() - 1; i >= 0; i--) {
                        PluginInfo<T> pluginInfo = mPlugins.get(i);
                        mMainHandler.obtainMessage(
                                MainHandler.PLUGIN_DISCONNECTED, pluginInfo.mPlugin).sendToTarget();
                        mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
                    }
                    mPlugins.clear();
                    handleQueryPlugins(null);
@@ -261,10 +227,9 @@ public class PluginInstanceManager<T extends Plugin> {
                case REMOVE_PKG:
                    String pkg = (String) msg.obj;
                    for (int i = mPlugins.size() - 1; i >= 0; i--) {
                        final PluginInfo<T> plugin = mPlugins.get(i);
                        if (plugin.mPackage.equals(pkg)) {
                            mMainHandler.obtainMessage(MainHandler.PLUGIN_DISCONNECTED,
                                    plugin.mPlugin).sendToTarget();
                        final PluginInfo<T> pluginInfo = mPlugins.get(i);
                        if (pluginInfo.mPackage.equals(pkg)) {
                            mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
                            mPlugins.remove(i);
                        }
                    }
@@ -307,12 +272,12 @@ public class PluginInstanceManager<T extends Plugin> {
            for (ResolveInfo info : result) {
                ComponentName name = new ComponentName(info.serviceInfo.packageName,
                        info.serviceInfo.name);
                PluginInfo<T> t = handleLoadPlugin(name);
                if (t == null) continue;
                PluginInfo<T> pluginInfo = handleLoadPlugin(name);
                if (pluginInfo == null) continue;

                // add plugin before sending PLUGIN_CONNECTED message
                mPlugins.add(t);
                mMainHandler.obtainMessage(mMainHandler.PLUGIN_CONNECTED, t).sendToTarget();
                mPlugins.add(pluginInfo);
                mMainExecutor.execute(() -> onPluginConnected(pluginInfo));
            }
        }

@@ -349,7 +314,7 @@ public class PluginInstanceManager<T extends Plugin> {
                try {
                    VersionInfo version = checkVersion(pluginClass, plugin, mVersion);
                    if (DEBUG) Log.d(TAG, "createPlugin");
                    return new PluginInfo(pkg, cls, plugin, pluginContext, version);
                    return new PluginInfo<>(pkg, cls, plugin, pluginContext, version);
                } catch (InvalidVersionException e) {
                    final int icon = Resources.getSystem().getIdentifier(
                            "stat_sys_warning", "drawable", "android");
@@ -419,13 +384,15 @@ public class PluginInstanceManager<T extends Plugin> {
    public static class Factory {
        private final Context mContext;
        private final PackageManager mPackageManager;
        private final Executor mMainExecutor;
        private final Looper mLooper;
        private final PluginInitializer mInitializer;

        public Factory(Context context, PackageManager packageManager, Looper looper,
                PluginInitializer initializer) {
        public Factory(Context context, PackageManager packageManager,
                Executor mainExecutor, Looper looper, PluginInitializer initializer) {
            mContext = context;
            mPackageManager = packageManager;
            mMainExecutor = mainExecutor;
            mLooper = looper;
            mInitializer = initializer;
        }
@@ -435,8 +402,8 @@ public class PluginInstanceManager<T extends Plugin> {
                PluginListener<T> listener, boolean allowMultiple, VersionInfo version,
                PluginManagerImpl manager, boolean debuggable, String[] pluginWhitelist) {
            return new PluginInstanceManager<>(mContext, mPackageManager, action, listener,
                    allowMultiple, mLooper, version, manager, debuggable, pluginWhitelist,
                    mInitializer);
                    allowMultiple, mMainExecutor, mLooper, version, manager, debuggable,
                    pluginWhitelist, mInitializer);
        }
    }

@@ -466,10 +433,10 @@ public class PluginInstanceManager<T extends Plugin> {
        }
    }

    static class PluginInfo<T> {
    static class PluginInfo<T extends Plugin> {
        private final Context mPluginContext;
        private final VersionInfo mVersion;
        private String mClass;
        private final String mClass;
        T mPlugin;
        String mPackage;

+0 −3
Original line number Diff line number Diff line
@@ -30,9 +30,6 @@ public interface PluginManager {
    /** Returns plugins that don't get disabled when an exceptoin occurs. */
    String[] getPrivilegedPlugins();

    <T extends Plugin> T getOneShotPlugin(Class<T> cls);
    <T extends Plugin> T getOneShotPlugin(String action, Class<?> cls);

    <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls);
    <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
            boolean allowMultiple);
+0 −35
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Looper;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -41,8 +40,6 @@ 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.plugins.annotations.ProvidesInterface;
import com.android.systemui.shared.plugins.PluginInstanceManager.PluginInfo;

import dalvik.system.PathClassLoader;

@@ -109,38 +106,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
        return mPluginEnabler;
    }

    // TODO(mankoff): This appears to be only called from tests. Remove?
    public <T extends Plugin> T getOneShotPlugin(Class<T> cls) {
        ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class);
        if (info == null) {
            throw new RuntimeException(cls + " doesn't provide an interface");
        }
        if (TextUtils.isEmpty(info.action())) {
            throw new RuntimeException(cls + " doesn't provide an action");
        }
        return getOneShotPlugin(info.action(), cls);
    }

    public <T extends Plugin> T getOneShotPlugin(String action, Class<?> cls) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new RuntimeException("Must be called from UI thread");
        }
        // Passing null causes compiler to complain about incompatible (generic) types.
        PluginListener<T> dummy = null;
        PluginInstanceManager<T> p = mInstanceManagerFactory.create(
                action, dummy, false, new VersionInfo().addClass(cls), this,
                isDebuggable(), getPrivilegedPlugins());
        mPluginPrefs.addAction(action);
        PluginInfo<T> info = p.getPlugin();
        if (info != null) {
            mOneShotPackages.add(info.mPackage);
            mHasOneShot = true;
            startListening();
            return info.mPlugin;
        }
        return null;
    }

    public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls) {
        addPluginListener(listener, cls, false);
    }
+7 −4
Original line number Diff line number Diff line
@@ -23,15 +23,18 @@ import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Looper;

import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.plugins.PluginEnabler;
import com.android.systemui.shared.plugins.PluginInitializer;
import com.android.systemui.shared.plugins.PluginInstanceManager;
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.util.concurrency.GlobalConcurrencyModule;
import com.android.systemui.util.concurrency.ThreadFactory;

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

import javax.inject.Named;
import javax.inject.Singleton;
@@ -46,7 +49,7 @@ import dagger.Provides;
 * Covers code both in com.android.systemui.plugins and code in
 * com.android.systemui.shared.plugins.
 */
@Module
@Module(includes = {GlobalConcurrencyModule.class})
public abstract class PluginsModule {
    public static final String PLUGIN_THREAD = "plugin_thread";
    public static final String PLUGIN_DEBUG = "plugin_debug";
@@ -67,10 +70,10 @@ public abstract class PluginsModule {
    @Provides
    @Singleton
    static PluginInstanceManager.Factory providePluginInstanceManagerFactory(Context context,
            PackageManager packageManager, @Named(PLUGIN_THREAD) Looper pluginLooper,
            PluginInitializer initializer) {
            PackageManager packageManager, @Main Executor mainExecutor,
            @Named(PLUGIN_THREAD) Looper pluginLooper, PluginInitializer initializer) {
        return new PluginInstanceManager.Factory(
                context, packageManager, pluginLooper, initializer);
                context, packageManager, mainExecutor, pluginLooper, initializer);
    }

    @Provides
+12 −0
Original line number Diff line number Diff line
@@ -67,11 +67,23 @@ public abstract class GlobalConcurrencyModule {
     * Provide a Main-Thread Executor.
     */
    @Provides
    @Singleton
    @Main
    public static Executor provideMainExecutor(Context context) {
        return context.getMainExecutor();
    }

    /**
     * Provide a Main-Thread DelayableExecutor.
     */
    @Provides
    @Singleton
    @Main
    public static DelayableExecutor provideMainDelayableExecutor(@Main Looper looper) {
        return new ExecutorImpl(looper);
    }


    /** */
    @Binds
    @Singleton
Loading