2014-11-16 23:14:06 -08:00
|
|
|
/*
|
|
|
|
* Copyright 2014 Albert Vaca Cintora <albertvaka@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of
|
|
|
|
* the License or (at your option) version 3 or any later version
|
|
|
|
* accepted by the membership of KDE e.V. (or its successor approved
|
|
|
|
* by the membership of KDE e.V.), which shall act as a proxy
|
|
|
|
* defined in Section 14 of version 3 of the license.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2013-09-05 01:37:59 +02:00
|
|
|
package org.kde.kdeconnect.Plugins;
|
2013-08-16 10:31:01 +02:00
|
|
|
|
|
|
|
import android.content.Context;
|
2013-08-19 19:57:29 +02:00
|
|
|
import android.graphics.drawable.Drawable;
|
2013-08-16 10:31:01 +02:00
|
|
|
import android.util.Log;
|
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
import org.atteo.classindex.ClassIndex;
|
|
|
|
import org.atteo.classindex.IndexAnnotated;
|
2013-09-05 01:37:59 +02:00
|
|
|
import org.kde.kdeconnect.Device;
|
2015-09-08 14:54:04 -07:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.HashSet;
|
2013-08-16 10:31:01 +02:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
2019-02-09 00:20:37 +01:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
2013-08-16 10:31:01 +02:00
|
|
|
|
|
|
|
public class PluginFactory {
|
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
@IndexAnnotated
|
|
|
|
public @interface LoadablePlugin { } //Annotate plugins with this so PluginFactory finds them
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
public static class PluginInfo {
|
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
PluginInfo(String displayName, String description, Drawable icon,
|
|
|
|
boolean enabledByDefault, boolean hasSettings, boolean listenToUnpaired,
|
2019-02-11 20:04:40 +01:00
|
|
|
String[] supportedPacketTypes, String[] outgoingPacketTypes,
|
|
|
|
Class<? extends Plugin> instantiableClass) {
|
2013-08-19 19:57:29 +02:00
|
|
|
this.displayName = displayName;
|
|
|
|
this.description = description;
|
|
|
|
this.icon = icon;
|
|
|
|
this.enabledByDefault = enabledByDefault;
|
2014-09-16 15:45:31 +02:00
|
|
|
this.hasSettings = hasSettings;
|
2015-08-27 13:06:24 +05:30
|
|
|
this.listenToUnpaired = listenToUnpaired;
|
2015-09-08 14:54:04 -07:00
|
|
|
HashSet<String> incoming = new HashSet<>();
|
2018-03-04 11:31:37 +01:00
|
|
|
if (supportedPacketTypes != null) Collections.addAll(incoming, supportedPacketTypes);
|
|
|
|
this.supportedPacketTypes = Collections.unmodifiableSet(incoming);
|
2015-09-08 14:54:04 -07:00
|
|
|
HashSet<String> outgoing = new HashSet<>();
|
2018-03-04 11:31:37 +01:00
|
|
|
if (outgoingPacketTypes != null) Collections.addAll(outgoing, outgoingPacketTypes);
|
|
|
|
this.outgoingPacketTypes = Collections.unmodifiableSet(outgoing);
|
2019-02-11 20:04:40 +01:00
|
|
|
this.instantiableClass = instantiableClass;
|
2013-08-19 19:57:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public String getDisplayName() {
|
|
|
|
return displayName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getDescription() {
|
|
|
|
return description;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Drawable getIcon() {
|
|
|
|
return icon;
|
|
|
|
}
|
|
|
|
|
2018-03-03 16:06:52 +01:00
|
|
|
public boolean hasSettings() {
|
|
|
|
return hasSettings;
|
|
|
|
}
|
2014-09-16 15:45:31 +02:00
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
public boolean isEnabledByDefault() {
|
|
|
|
return enabledByDefault;
|
|
|
|
}
|
|
|
|
|
2015-08-27 13:06:24 +05:30
|
|
|
public boolean listenToUnpaired() {
|
|
|
|
return listenToUnpaired;
|
|
|
|
}
|
|
|
|
|
2018-10-26 23:53:58 +02:00
|
|
|
Set<String> getOutgoingPacketTypes() {
|
2018-03-04 11:31:37 +01:00
|
|
|
return outgoingPacketTypes;
|
2015-09-08 14:54:04 -07:00
|
|
|
}
|
|
|
|
|
2018-03-04 11:31:37 +01:00
|
|
|
public Set<String> getSupportedPacketTypes() {
|
|
|
|
return supportedPacketTypes;
|
2015-09-08 14:54:04 -07:00
|
|
|
}
|
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
Class<? extends Plugin> getInstantiableClass() {
|
|
|
|
return instantiableClass;
|
|
|
|
}
|
|
|
|
|
2014-03-29 01:47:15 +01:00
|
|
|
private final String displayName;
|
|
|
|
private final String description;
|
2013-08-19 19:57:29 +02:00
|
|
|
private final Drawable icon;
|
2014-03-29 01:47:15 +01:00
|
|
|
private final boolean enabledByDefault;
|
2014-09-16 15:45:31 +02:00
|
|
|
private final boolean hasSettings;
|
2015-08-27 13:06:24 +05:30
|
|
|
private final boolean listenToUnpaired;
|
2018-03-04 11:31:37 +01:00
|
|
|
private final Set<String> supportedPacketTypes;
|
|
|
|
private final Set<String> outgoingPacketTypes;
|
2019-02-11 20:04:40 +01:00
|
|
|
private final Class<? extends Plugin> instantiableClass;
|
2015-09-08 14:54:04 -07:00
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
}
|
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
private static final Map<String, PluginInfo> pluginInfo = new ConcurrentHashMap<>();
|
2015-09-08 14:54:04 -07:00
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
public static PluginInfo getPluginInfo(String pluginKey) {
|
|
|
|
return pluginInfo.get(pluginKey);
|
|
|
|
}
|
2015-09-08 14:54:04 -07:00
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
public static void initPluginInfo(Context context) {
|
2013-08-19 19:57:29 +02:00
|
|
|
try {
|
2019-02-11 20:04:40 +01:00
|
|
|
for (Class<?> pluginClass : ClassIndex.getAnnotated(LoadablePlugin.class)) {
|
|
|
|
Plugin p = ((Plugin) pluginClass.newInstance());
|
|
|
|
p.setContext(context, null);
|
|
|
|
PluginInfo info = new PluginInfo(p.getDisplayName(), p.getDescription(), p.getIcon(),
|
|
|
|
p.isEnabledByDefault(), p.hasSettings(), p.listensToUnpairedDevices(),
|
|
|
|
p.getSupportedPacketTypes(), p.getOutgoingPacketTypes(), p.getClass());
|
|
|
|
pluginInfo.put(p.getPluginKey(), info);
|
|
|
|
}
|
2018-03-03 16:06:52 +01:00
|
|
|
} catch (Exception e) {
|
2017-07-09 18:30:20 +02:00
|
|
|
throw new RuntimeException(e);
|
2013-08-19 19:57:29 +02:00
|
|
|
}
|
2019-02-11 20:04:40 +01:00
|
|
|
Log.i("PluginFactory","Loaded "+pluginInfo.size()+" plugins");
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
public static Set<String> getAvailablePlugins() {
|
2019-02-11 20:04:40 +01:00
|
|
|
return pluginInfo.keySet();
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|
|
|
|
|
2015-06-06 00:38:51 -07:00
|
|
|
public static Plugin instantiatePluginForDevice(Context context, String pluginKey, Device device) {
|
2019-02-11 20:04:40 +01:00
|
|
|
PluginInfo info = pluginInfo.get(pluginKey);
|
2013-08-16 10:31:01 +02:00
|
|
|
try {
|
2019-02-11 20:04:40 +01:00
|
|
|
Plugin plugin = info.getInstantiableClass().newInstance();
|
2013-08-16 10:31:01 +02:00
|
|
|
plugin.setContext(context, device);
|
|
|
|
return plugin;
|
2018-03-03 16:06:52 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e("PluginFactory", "Could not instantiate plugin: " + pluginKey);
|
2015-01-22 21:30:32 -08:00
|
|
|
e.printStackTrace();
|
2013-08-16 10:31:01 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
public static Set<String> getIncomingCapabilities() {
|
2016-07-06 17:45:01 +02:00
|
|
|
HashSet<String> capabilities = new HashSet<>();
|
2019-02-11 20:04:40 +01:00
|
|
|
for (PluginInfo plugin : pluginInfo.values()) {
|
2018-03-04 11:31:37 +01:00
|
|
|
capabilities.addAll(plugin.getSupportedPacketTypes());
|
2016-07-06 17:45:01 +02:00
|
|
|
}
|
|
|
|
return capabilities;
|
|
|
|
}
|
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
public static Set<String> getOutgoingCapabilities() {
|
2016-07-06 17:45:01 +02:00
|
|
|
HashSet<String> capabilities = new HashSet<>();
|
2019-02-11 20:04:40 +01:00
|
|
|
for (PluginInfo plugin : pluginInfo.values()) {
|
2018-03-04 11:31:37 +01:00
|
|
|
capabilities.addAll(plugin.getOutgoingPacketTypes());
|
2016-07-06 17:45:01 +02:00
|
|
|
}
|
|
|
|
return capabilities;
|
|
|
|
}
|
|
|
|
|
2019-02-11 20:04:40 +01:00
|
|
|
public static Set<String> pluginsForCapabilities(Set<String> incoming, Set<String> outgoing) {
|
2016-07-06 17:45:01 +02:00
|
|
|
HashSet<String> plugins = new HashSet<>();
|
2019-02-11 20:04:40 +01:00
|
|
|
for (Map.Entry<String, PluginInfo> entry : pluginInfo.entrySet()) {
|
|
|
|
String pluginId = entry.getKey();
|
|
|
|
PluginInfo info = entry.getValue();
|
2016-07-06 17:45:01 +02:00
|
|
|
//Check incoming against outgoing
|
2019-02-11 20:04:40 +01:00
|
|
|
if (Collections.disjoint(outgoing, info.getSupportedPacketTypes())
|
|
|
|
&& Collections.disjoint(incoming, info.getOutgoingPacketTypes())) {
|
2016-07-06 17:45:01 +02:00
|
|
|
Log.i("PluginFactory", "Won't load " + pluginId + " because of unmatched capabilities");
|
|
|
|
continue; //No capabilities in common, do not load this plugin
|
|
|
|
}
|
|
|
|
plugins.add(pluginId);
|
|
|
|
}
|
|
|
|
return plugins;
|
|
|
|
}
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|