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

Commit ab598526 authored by Dave Mankoff's avatar Dave Mankoff Committed by Automerger Merge Worker
Browse files

Merge "Remove custom MainHandler from PluginInstanceManager" into sc-v2-dev am: b325b69f

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

Change-Id: Ieb36b3dba8ef2ed7a624da81d37814bee6011286
parents fd30f18b b325b69f
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