2013-07-23 16:11:54 +02:00
|
|
|
package org.kde.connect;
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.SharedPreferences;
|
2013-07-23 16:11:54 +02:00
|
|
|
import android.os.AsyncTask;
|
2013-08-16 10:31:01 +02:00
|
|
|
import android.preference.PreferenceManager;
|
2013-07-23 16:11:54 +02:00
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
import org.kde.connect.ComputerLinks.BaseComputerLink;
|
2013-08-16 10:31:01 +02:00
|
|
|
import org.kde.connect.Plugins.Plugin;
|
2013-07-23 16:11:54 +02:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Comparator;
|
2013-08-16 10:31:01 +02:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Set;
|
2013-07-23 16:11:54 +02:00
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
public class Device implements BaseComputerLink.PackageReceiver {
|
2013-07-23 16:11:54 +02:00
|
|
|
|
|
|
|
private ArrayList<BaseComputerLink> links = new ArrayList<BaseComputerLink>();
|
2013-08-16 10:31:01 +02:00
|
|
|
private HashMap<String, Plugin> plugins = new HashMap<String, Plugin>();
|
2013-08-19 19:57:29 +02:00
|
|
|
private HashMap<String, Plugin> failedPlugins = new HashMap<String, Plugin>();
|
2013-07-23 16:11:54 +02:00
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
private Context context;
|
2013-07-23 16:11:54 +02:00
|
|
|
private String deviceId;
|
|
|
|
private String name;
|
2013-08-16 10:31:01 +02:00
|
|
|
private boolean trusted;
|
2013-07-23 16:11:54 +02:00
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
SharedPreferences settings;
|
|
|
|
|
|
|
|
//Remembered trusted device, we need to wait for a incoming devicelink to communicate
|
|
|
|
Device(Context context, String deviceId) {
|
|
|
|
settings = context.getSharedPreferences(deviceId,Context.MODE_PRIVATE);
|
|
|
|
|
|
|
|
//Log.e("Device","Constructor A");
|
|
|
|
|
|
|
|
this.context = context;
|
2013-07-23 16:11:54 +02:00
|
|
|
this.deviceId = deviceId;
|
2013-08-16 10:31:01 +02:00
|
|
|
this.name = settings.getString("deviceName",null);
|
|
|
|
this.trusted = true;
|
|
|
|
|
|
|
|
reloadPluginsFromSettings();
|
|
|
|
}
|
|
|
|
|
|
|
|
//Device known via an incoming connection sent to us via a devicelink, we know everything but we don't trust it yet
|
|
|
|
Device(Context context, String deviceId, String name, BaseComputerLink dl) {
|
|
|
|
settings = context.getSharedPreferences(deviceId,Context.MODE_PRIVATE);
|
|
|
|
|
|
|
|
//Log.e("Device","Constructor B");
|
|
|
|
|
|
|
|
this.context = context;
|
|
|
|
this.deviceId = deviceId;
|
|
|
|
setName(name);
|
|
|
|
setTrusted(false);
|
|
|
|
|
2013-07-23 16:11:54 +02:00
|
|
|
addLink(dl);
|
|
|
|
}
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
|
|
|
|
public boolean hasName() {
|
|
|
|
return name != null;
|
|
|
|
}
|
|
|
|
|
2013-07-23 16:11:54 +02:00
|
|
|
public String getName() {
|
2013-08-16 10:31:01 +02:00
|
|
|
return name != null? name : "unknown device";
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setName(String name) {
|
|
|
|
this.name = name;
|
|
|
|
settings.edit().putString("deviceName",name).commit();
|
2013-07-23 16:11:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public String getDeviceId() {
|
|
|
|
return deviceId;
|
|
|
|
}
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
public boolean isReachable() {
|
|
|
|
return !links.isEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isTrusted() {
|
|
|
|
return trusted;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTrusted(boolean b) {
|
|
|
|
trusted = b;
|
|
|
|
|
|
|
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
Set<String> trustedDevices = preferences.getStringSet("trusted", new HashSet<String>());
|
|
|
|
|
|
|
|
boolean wasTrusted = trustedDevices.contains(deviceId);
|
|
|
|
|
|
|
|
if (trusted != wasTrusted) {
|
|
|
|
if (trusted) {
|
|
|
|
//Log.e("trust",deviceId);
|
|
|
|
trustedDevices.add(deviceId);
|
|
|
|
} else {
|
|
|
|
//Log.e("untrust",deviceId);
|
|
|
|
trustedDevices.remove(deviceId);
|
|
|
|
}
|
|
|
|
SharedPreferences.Editor editor = preferences.edit();
|
|
|
|
editor.putStringSet("trusted",trustedDevices);
|
|
|
|
editor.commit();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
reloadPluginsFromSettings();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Computer link-related functions
|
|
|
|
//
|
|
|
|
|
2013-07-23 16:11:54 +02:00
|
|
|
public void addLink(BaseComputerLink link) {
|
|
|
|
Log.e("Device","addLink "+link.getLinkProvider().getName()+" -> "+getName());
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2013-07-23 16:11:54 +02:00
|
|
|
links.add(link);
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2013-07-23 16:11:54 +02:00
|
|
|
Collections.sort(links, new Comparator<BaseComputerLink>() {
|
|
|
|
@Override
|
|
|
|
public int compare(BaseComputerLink o, BaseComputerLink o2) {
|
|
|
|
return o2.getLinkProvider().getPriority() - o.getLinkProvider().getPriority();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
link.addPackageReceiver(this);
|
|
|
|
|
|
|
|
if (links.size() == 1) {
|
|
|
|
reloadPluginsFromSettings();
|
|
|
|
}
|
2013-07-23 16:11:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void removeLink(BaseComputerLink link) {
|
2013-08-16 10:31:01 +02:00
|
|
|
link.removePackageReceiver(this);
|
2013-07-23 16:11:54 +02:00
|
|
|
links.remove(link);
|
2013-08-16 10:31:01 +02:00
|
|
|
if (links.isEmpty()) {
|
|
|
|
reloadPluginsFromSettings();
|
|
|
|
}
|
2013-07-23 16:11:54 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
@Override
|
|
|
|
public void onPackageReceived(NetworkPackage np) {
|
|
|
|
for (Plugin plugin : plugins.values()) {
|
|
|
|
//Log.e("onPackageReceived",plugin.toString());
|
|
|
|
plugin.onPackageReceived(np);
|
|
|
|
}
|
2013-07-23 16:11:54 +02:00
|
|
|
}
|
|
|
|
|
2013-07-31 18:02:22 +02:00
|
|
|
|
2013-07-23 16:11:54 +02:00
|
|
|
public boolean sendPackage(final NetworkPackage np) {
|
2013-08-07 18:26:03 +02:00
|
|
|
Log.e("Device", "sendPackage "+np.getType()+". "+links.size()+" links available");
|
2013-07-23 16:11:54 +02:00
|
|
|
new AsyncTask<Void,Void,Void>() {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground(Void... voids) {
|
2013-08-07 10:44:52 +02:00
|
|
|
//Log.e("sendPackage","Do in background");
|
2013-07-23 16:11:54 +02:00
|
|
|
for(BaseComputerLink link : links) {
|
2013-08-07 10:44:52 +02:00
|
|
|
//Log.e("sendPackage","Trying "+link.getLinkProvider().getName());
|
2013-07-23 16:11:54 +02:00
|
|
|
if (link.sendPackage(np)) {
|
2013-08-07 10:44:52 +02:00
|
|
|
//Log.e("sent using", link.getLinkProvider().getName());
|
2013-07-23 16:11:54 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Log.e("sendPackage","Error: Package could not be sent");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
2013-07-26 16:23:26 +02:00
|
|
|
|
2013-07-31 18:02:22 +02:00
|
|
|
return true; //FIXME: Detect when unable to send a package and try again somehow
|
2013-07-23 16:11:54 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Plugin-related functions
|
|
|
|
//
|
|
|
|
|
|
|
|
public Plugin getPlugin(String name) {
|
|
|
|
return plugins.get(name);
|
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
private Plugin addPlugin(String name) {
|
2013-08-16 10:31:01 +02:00
|
|
|
Plugin existing = plugins.get(name);
|
|
|
|
if (existing != null) {
|
|
|
|
Log.e("addPlugin","plugin already present:" + name);
|
|
|
|
return existing;
|
|
|
|
}
|
|
|
|
|
|
|
|
Plugin plugin = PluginFactory.instantiatePluginForDevice(context, name, this);
|
|
|
|
if (plugin == null) {
|
|
|
|
Log.e("addPlugin","could not create plugin: "+name);
|
2013-08-19 19:57:29 +02:00
|
|
|
failedPlugins.put(name, plugin);
|
2013-08-16 10:31:01 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2013-08-19 19:57:29 +02:00
|
|
|
boolean success = plugin.onCreate();
|
|
|
|
if (!success) {
|
|
|
|
failedPlugins.put(name, plugin);
|
|
|
|
return null;
|
|
|
|
}
|
2013-08-16 10:31:01 +02:00
|
|
|
} catch (Exception e) {
|
2013-08-19 19:57:29 +02:00
|
|
|
failedPlugins.put(name, plugin);
|
2013-08-16 10:31:01 +02:00
|
|
|
Log.e("addPlugin","Exception calling onCreate for "+name);
|
|
|
|
e.printStackTrace();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
Log.e("addPlugin",name);
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
failedPlugins.remove(name);
|
2013-08-16 10:31:01 +02:00
|
|
|
plugins.put(name, plugin);
|
2013-08-19 19:57:29 +02:00
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
return plugin;
|
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
private boolean removePlugin(String name) {
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
Plugin plugin = plugins.remove(name);
|
2013-08-19 19:57:29 +02:00
|
|
|
Plugin failedPlugin = failedPlugins.remove(name);
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
if (plugin == null) {
|
2013-08-19 19:57:29 +02:00
|
|
|
if (failedPlugin == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
plugin = failedPlugin;
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
plugin.onDestroy();
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e("addPlugin","Exception calling onCreate for "+name);
|
|
|
|
e.printStackTrace();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Log.e("removePlugin",name);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
public void setPluginEnabled(String pluginName, boolean value) {
|
|
|
|
settings.edit().putBoolean(pluginName,value).commit();
|
|
|
|
if (value) addPlugin(pluginName);
|
|
|
|
else removePlugin(pluginName);
|
|
|
|
for (PluginsChangedListener listener : pluginsChangedListeners) {
|
|
|
|
listener.onPluginsChanged(this);
|
|
|
|
}
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
public boolean isPluginEnabled(String pluginName) {
|
|
|
|
boolean enabledByDefault = PluginFactory.getPluginInfo(context, pluginName).isEnabledByDefault();
|
|
|
|
boolean enabled = settings.getBoolean(pluginName, enabledByDefault);
|
|
|
|
return enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
public void reloadPluginsFromSettings() {
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
failedPlugins.clear();
|
|
|
|
|
2013-08-16 10:31:01 +02:00
|
|
|
Set<String> availablePlugins = PluginFactory.getAvailablePlugins();
|
|
|
|
|
|
|
|
for(String pluginName : availablePlugins) {
|
|
|
|
boolean enabled = false;
|
|
|
|
if (isTrusted() && isReachable()) {
|
2013-08-19 19:57:29 +02:00
|
|
|
enabled = isPluginEnabled(pluginName);
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|
|
|
|
//Log.e("reloadPluginsFromSettings",pluginName+"->"+enabled);
|
|
|
|
if (enabled) {
|
|
|
|
addPlugin(pluginName);
|
|
|
|
} else {
|
|
|
|
removePlugin(pluginName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
for (PluginsChangedListener listener : pluginsChangedListeners) {
|
|
|
|
listener.onPluginsChanged(this);
|
|
|
|
}
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
public HashMap<String,Plugin> getFailedPlugins() {
|
|
|
|
return failedPlugins;
|
|
|
|
}
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
interface PluginsChangedListener {
|
|
|
|
void onPluginsChanged(Device device);
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayList<PluginsChangedListener> pluginsChangedListeners = new ArrayList<PluginsChangedListener>();
|
|
|
|
|
|
|
|
public void addPluginsChangedListener(PluginsChangedListener listener) {
|
|
|
|
pluginsChangedListeners.add(listener);
|
|
|
|
}
|
2013-08-16 10:31:01 +02:00
|
|
|
|
2013-08-19 19:57:29 +02:00
|
|
|
public void removePluginsChangedListener(PluginsChangedListener listener) {
|
|
|
|
pluginsChangedListeners.remove(listener);
|
2013-08-16 10:31:01 +02:00
|
|
|
}
|
|
|
|
|
2013-07-23 16:11:54 +02:00
|
|
|
}
|