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 ;
2013-07-23 16:11:54 +02:00
2013-09-03 17:58:59 +02:00
import android.app.Notification ;
import android.app.NotificationManager ;
import android.app.PendingIntent ;
2013-08-16 10:31:01 +02:00
import android.content.Context ;
2013-09-03 17:58:59 +02:00
import android.content.Intent ;
2013-08-16 10:31:01 +02:00
import android.content.SharedPreferences ;
2013-09-05 01:33:54 +02:00
import android.content.res.Resources ;
2015-04-12 00:06:47 -07:00
import android.graphics.drawable.Drawable ;
2018-01-03 20:49:51 +01:00
import android.os.Build ;
2013-08-16 10:31:01 +02:00
import android.preference.PreferenceManager ;
2013-09-03 17:58:59 +02:00
import android.util.Base64 ;
2013-07-23 16:11:54 +02:00
import android.util.Log ;
2013-09-16 17:36:26 +02:00
import org.kde.kdeconnect.Backends.BaseLink ;
2015-08-13 14:55:00 +05:30
import org.kde.kdeconnect.Backends.BasePairingHandler ;
2016-06-14 17:39:20 +02:00
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider ;
2016-12-05 23:42:58 +01:00
import org.kde.kdeconnect.Helpers.NotificationHelper ;
2016-03-03 15:42:39 -08:00
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper ;
2013-09-05 01:37:59 +02:00
import org.kde.kdeconnect.Plugins.Plugin ;
import org.kde.kdeconnect.Plugins.PluginFactory ;
2018-03-03 17:21:16 +01:00
import org.kde.kdeconnect.UserInterface.MainActivity ;
2013-09-05 01:37:59 +02:00
import org.kde.kdeconnect_tp.R ;
2013-09-03 17:58:59 +02:00
import java.security.KeyFactory ;
import java.security.PrivateKey ;
import java.security.PublicKey ;
2015-08-24 02:03:55 +05:30
import java.security.cert.Certificate ;
2013-09-03 17:58:59 +02:00
import java.security.spec.PKCS8EncodedKeySpec ;
import java.security.spec.X509EncodedKeySpec ;
2013-07-23 16:11:54 +02:00
import java.util.ArrayList ;
2016-06-02 15:35:44 +02:00
import java.util.Collection ;
2013-08-16 10:31:01 +02:00
import java.util.HashMap ;
2016-06-28 21:52:58 +02:00
import java.util.List ;
2015-08-13 14:55:00 +05:30
import java.util.Map ;
2013-08-16 10:31:01 +02:00
import java.util.Set ;
2016-07-06 17:45:01 +02:00
import java.util.Vector ;
2015-09-14 04:19:13 -07:00
import java.util.concurrent.ConcurrentHashMap ;
2015-09-10 07:49:28 -07:00
import java.util.concurrent.CopyOnWriteArrayList ;
2013-07-23 16:11:54 +02:00
2018-12-27 15:40:57 +01:00
import androidx.core.app.NotificationCompat ;
import androidx.core.content.ContextCompat ;
2018-03-04 11:31:37 +01:00
public class Device implements BaseLink . PacketReceiver {
2013-07-23 16:11:54 +02:00
2014-03-29 01:47:15 +01:00
private final Context context ;
2013-09-03 17:58:59 +02:00
2014-03-29 01:47:15 +01:00
private final String deviceId ;
2015-03-01 20:57:45 -08:00
private String name ;
2014-01-16 09:51:32 +04:00
public PublicKey publicKey ;
2015-08-24 02:03:55 +05:30
public Certificate certificate ;
2013-09-03 17:58:59 +02:00
private int notificationId ;
2013-10-01 03:24:42 +02:00
private int protocolVersion ;
2013-09-03 17:58:59 +02:00
2015-09-08 15:05:32 -07:00
private DeviceType deviceType ;
private PairStatus pairStatus ;
2015-09-10 07:52:37 -07:00
2015-09-10 07:49:28 -07:00
private final CopyOnWriteArrayList < PairingCallback > pairingCallback = new CopyOnWriteArrayList < > ( ) ;
2018-10-27 00:01:30 +02:00
private final Map < String , BasePairingHandler > pairingHandlers = new HashMap < > ( ) ;
2015-09-08 15:05:32 -07:00
2015-09-10 07:49:28 -07:00
private final CopyOnWriteArrayList < BaseLink > links = new CopyOnWriteArrayList < > ( ) ;
2015-09-08 15:05:32 -07:00
2016-07-06 17:45:01 +02:00
private List < String > m_supportedPlugins = new ArrayList < > ( ) ;
2015-09-14 04:19:13 -07:00
private final ConcurrentHashMap < String , Plugin > plugins = new ConcurrentHashMap < > ( ) ;
2017-05-31 15:51:07 +02:00
private final ConcurrentHashMap < String , Plugin > pluginsWithoutPermissions = new ConcurrentHashMap < > ( ) ;
2017-07-11 13:50:40 +02:00
private final ConcurrentHashMap < String , Plugin > pluginsWithoutOptionalPermissions = new ConcurrentHashMap < > ( ) ;
2017-05-25 22:18:32 +02:00
private Map < String , ArrayList < String > > pluginsByIncomingInterface = new HashMap < > ( ) ;
2015-09-08 15:05:32 -07:00
private final SharedPreferences settings ;
2015-09-10 07:49:28 -07:00
private final CopyOnWriteArrayList < PluginsChangedListener > pluginsChangedListeners = new CopyOnWriteArrayList < > ( ) ;
public interface PluginsChangedListener {
void onPluginsChanged ( Device device ) ;
}
2015-06-10 12:29:53 +05:30
public enum PairStatus {
2013-09-03 17:58:59 +02:00
NotPaired ,
Paired
}
2015-06-10 12:29:53 +05:30
public enum DeviceType {
2015-04-12 00:06:47 -07:00
Phone ,
Tablet ,
2018-05-10 12:34:28 +02:00
Computer ,
Tv ;
2015-04-12 00:06:47 -07:00
2018-10-26 23:53:58 +02:00
static DeviceType FromString ( String s ) {
2015-04-12 00:06:47 -07:00
if ( " tablet " . equals ( s ) ) return Tablet ;
2015-09-09 01:11:46 -07:00
if ( " phone " . equals ( s ) ) return Phone ;
2018-05-10 12:34:28 +02:00
if ( " tv " . equals ( s ) ) return Tv ;
2015-09-09 01:11:46 -07:00
return Computer ; //Default
2015-04-12 00:06:47 -07:00
}
2018-03-03 16:06:52 +01:00
2015-04-12 00:06:47 -07:00
public String toString ( ) {
switch ( this ) {
2018-03-03 16:06:52 +01:00
case Tablet :
return " tablet " ;
case Phone :
return " phone " ;
2018-05-10 12:34:28 +02:00
case Tv :
return " tv " ;
2018-03-03 16:06:52 +01:00
default :
return " desktop " ;
2015-04-12 00:06:47 -07:00
}
}
}
2013-09-03 17:58:59 +02:00
public interface PairingCallback {
2015-08-13 14:55:00 +05:30
void incomingRequest ( ) ;
2018-03-03 16:06:52 +01:00
2015-08-13 14:55:00 +05:30
void pairingSuccessful ( ) ;
2018-03-03 16:06:52 +01:00
2015-08-13 14:55:00 +05:30
void pairingFailed ( String error ) ;
2018-03-03 16:06:52 +01:00
2015-08-13 14:55:00 +05:30
void unpaired ( ) ;
2013-09-03 17:58:59 +02:00
}
2013-08-16 10:31:01 +02:00
//Remembered trusted device, we need to wait for a incoming devicelink to communicate
Device ( Context context , String deviceId ) {
2013-08-20 00:37:08 +02:00
settings = context . getSharedPreferences ( deviceId , Context . MODE_PRIVATE ) ;
2013-08-16 10:31:01 +02:00
//Log.e("Device","Constructor A");
this . context = context ;
2013-07-23 16:11:54 +02:00
this . deviceId = deviceId ;
2015-03-01 20:57:45 -08:00
this . name = settings . getString ( " deviceName " , context . getString ( R . string . unknown_device ) ) ;
2013-09-03 17:58:59 +02:00
this . pairStatus = PairStatus . Paired ;
2018-03-04 11:31:37 +01:00
this . protocolVersion = NetworkPacket . ProtocolVersion ; //We don't know it yet
2015-09-09 01:07:17 -07:00
this . deviceType = DeviceType . FromString ( settings . getString ( " deviceType " , " desktop " ) ) ;
2013-09-03 17:58:59 +02:00
try {
2016-02-12 08:37:47 -08:00
String publicKeyStr = settings . getString ( " publicKey " , null ) ;
if ( publicKeyStr ! = null ) {
byte [ ] publicKeyBytes = Base64 . decode ( publicKeyStr , 0 ) ;
publicKey = KeyFactory . getInstance ( " RSA " ) . generatePublic ( new X509EncodedKeySpec ( publicKeyBytes ) ) ;
}
2013-09-03 17:58:59 +02:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
2018-03-03 16:06:52 +01:00
Log . e ( " KDE/Device " , " Exception deserializing stored public key for device " ) ;
2013-09-03 17:58:59 +02:00
}
2013-08-16 10:31:01 +02:00
2016-09-06 00:47:59 +02:00
//Assume every plugin is supported until addLink is called and we can get the actual list
m_supportedPlugins = new Vector < > ( PluginFactory . getAvailablePlugins ( ) ) ;
2016-07-06 17:45:01 +02:00
//Do not load plugins yet, the device is not present
//reloadPluginsFromSettings();
2013-08-16 10:31:01 +02:00
}
//Device known via an incoming connection sent to us via a devicelink, we know everything but we don't trust it yet
2018-03-04 11:31:37 +01:00
Device ( Context context , NetworkPacket np , BaseLink dl ) {
2013-08-16 10:31:01 +02:00
//Log.e("Device","Constructor B");
this . context = context ;
2013-10-01 03:24:42 +02:00
this . deviceId = np . getString ( " deviceId " ) ;
2015-09-09 01:07:17 -07:00
this . name = context . getString ( R . string . unknown_device ) ; //We read it in addLink
2013-09-03 17:58:59 +02:00
this . pairStatus = PairStatus . NotPaired ;
2015-09-09 01:07:17 -07:00
this . protocolVersion = 0 ;
this . deviceType = DeviceType . Computer ;
2013-09-03 17:58:59 +02:00
this . publicKey = null ;
2013-08-16 10:31:01 +02:00
2013-10-29 19:44:07 +01:00
settings = context . getSharedPreferences ( deviceId , Context . MODE_PRIVATE ) ;
2013-10-01 03:24:42 +02:00
addLink ( np , dl ) ;
2013-07-23 16:11:54 +02:00
}
public String getName ( ) {
2018-03-03 16:06:52 +01:00
return name ! = null ? name : context . getString ( R . string . unknown_device ) ;
2013-07-23 16:11:54 +02:00
}
2018-03-03 16:06:52 +01:00
public Drawable getIcon ( ) {
2015-08-10 00:26:58 -07:00
int drawableId ;
2015-04-12 00:06:47 -07:00
switch ( deviceType ) {
2018-03-03 16:06:52 +01:00
case Phone :
drawableId = R . drawable . ic_device_phone ;
break ;
case Tablet :
drawableId = R . drawable . ic_device_tablet ;
break ;
2018-05-10 12:34:28 +02:00
case Tv :
drawableId = R . drawable . ic_device_tv ;
break ;
2018-03-03 16:06:52 +01:00
default :
drawableId = R . drawable . ic_device_laptop ;
2015-04-12 00:06:47 -07:00
}
2015-08-10 00:26:58 -07:00
return ContextCompat . getDrawable ( context , drawableId ) ;
2015-04-12 00:06:47 -07:00
}
public DeviceType getDeviceType ( ) {
return deviceType ;
}
2013-07-23 16:11:54 +02:00
public String getDeviceId ( ) {
return deviceId ;
}
2015-06-25 04:20:03 +05:30
public Context getContext ( ) {
return context ;
}
2013-10-01 03:24:42 +02:00
//Returns 0 if the version matches, < 0 if it is older or > 0 if it is newer
public int compareProtocolVersion ( ) {
2018-03-04 11:31:37 +01:00
return protocolVersion - NetworkPacket . ProtocolVersion ;
2013-10-01 03:24:42 +02:00
}
2013-09-03 17:58:59 +02:00
//
// Pairing-related functions
//
public boolean isPaired ( ) {
return pairStatus = = PairStatus . Paired ;
2013-08-16 10:31:01 +02:00
}
2015-08-13 14:55:00 +05:30
/* Asks all pairing handlers that, is pair requested? */
2013-09-03 17:58:59 +02:00
public boolean isPairRequested ( ) {
2015-08-13 14:55:00 +05:30
boolean pairRequested = false ;
2018-03-03 16:06:52 +01:00
for ( BasePairingHandler ph : pairingHandlers . values ( ) ) {
2015-08-13 14:55:00 +05:30
pairRequested = pairRequested | | ph . isPairRequested ( ) ;
}
return pairRequested ;
}
/* Asks all pairing handlers that, is pair requested by peer? */
public boolean isPairRequestedByPeer ( ) {
boolean pairRequestedByPeer = false ;
for ( BasePairingHandler ph : pairingHandlers . values ( ) ) {
pairRequestedByPeer = pairRequestedByPeer | | ph . isPairRequestedByPeer ( ) ;
}
return pairRequestedByPeer ;
2013-08-16 10:31:01 +02:00
}
2013-09-03 17:58:59 +02:00
public void addPairingCallback ( PairingCallback callback ) {
pairingCallback . add ( callback ) ;
}
2015-08-13 14:55:00 +05:30
2013-09-03 17:58:59 +02:00
public void removePairingCallback ( PairingCallback callback ) {
pairingCallback . remove ( callback ) ;
}
2013-08-16 10:31:01 +02:00
2013-09-03 17:58:59 +02:00
public void requestPairing ( ) {
2013-08-16 10:31:01 +02:00
2013-09-05 01:33:54 +02:00
Resources res = context . getResources ( ) ;
2018-03-03 16:23:53 +01:00
if ( isPaired ( ) ) {
for ( PairingCallback cb : pairingCallback ) {
cb . pairingFailed ( res . getString ( R . string . error_already_paired ) ) ;
}
return ;
2013-09-03 17:58:59 +02:00
}
2015-06-14 19:23:02 -07:00
2013-09-03 17:58:59 +02:00
if ( ! isReachable ( ) ) {
2013-10-29 19:44:07 +01:00
for ( PairingCallback cb : pairingCallback ) {
cb . pairingFailed ( res . getString ( R . string . error_not_reachable ) ) ;
}
2013-09-03 17:58:59 +02:00
return ;
}
2013-08-16 10:31:01 +02:00
2015-08-13 14:55:00 +05:30
for ( BasePairingHandler ph : pairingHandlers . values ( ) ) {
ph . requestPairing ( ) ;
2015-07-01 03:25:16 +05:30
}
2013-09-03 17:58:59 +02:00
}
2015-08-13 14:55:00 +05:30
public void unpair ( ) {
for ( BasePairingHandler ph : pairingHandlers . values ( ) ) {
ph . unpair ( ) ;
}
unpairInternal ( ) ; // Even if there are no pairing handlers, unpair
2013-09-03 17:58:59 +02:00
}
2015-08-13 14:55:00 +05:30
/ * *
* This method does not send an unpair package , instead it unpairs internally by deleting trusted device info . . Likely to be called after sending package from
* pairing handler
* /
private void unpairInternal ( ) {
2013-09-03 17:58:59 +02:00
2015-08-13 14:55:00 +05:30
//Log.e("Device","Unpairing (unpairInternal)");
2013-09-03 17:58:59 +02:00
pairStatus = PairStatus . NotPaired ;
SharedPreferences preferences = context . getSharedPreferences ( " trusted_devices " , Context . MODE_PRIVATE ) ;
2015-01-31 00:16:06 -08:00
preferences . edit ( ) . remove ( deviceId ) . apply ( ) ;
2013-09-03 17:58:59 +02:00
2015-06-25 04:20:03 +05:30
SharedPreferences devicePreferences = context . getSharedPreferences ( deviceId , Context . MODE_PRIVATE ) ;
devicePreferences . edit ( ) . clear ( ) . apply ( ) ;
2013-09-03 17:58:59 +02:00
for ( PairingCallback cb : pairingCallback ) cb . unpaired ( ) ;
reloadPluginsFromSettings ( ) ;
}
2015-08-13 14:55:00 +05:30
/* This method should be called after pairing is done from pairing handler. Calling this method again should not create any problem as most of the things will get over writter*/
2013-10-29 19:44:07 +01:00
private void pairingDone ( ) {
2013-09-03 17:58:59 +02:00
2013-11-06 21:13:37 +01:00
//Log.e("Device", "Storing as trusted, deviceId: "+deviceId);
2015-09-12 13:21:06 -07:00
hidePairingNotification ( ) ;
2013-11-06 21:13:37 +01:00
2013-09-03 17:58:59 +02:00
pairStatus = PairStatus . Paired ;
//Store as trusted device
SharedPreferences preferences = context . getSharedPreferences ( " trusted_devices " , Context . MODE_PRIVATE ) ;
2018-03-03 16:06:52 +01:00
preferences . edit ( ) . putBoolean ( deviceId , true ) . apply ( ) ;
2013-09-03 17:58:59 +02:00
2015-07-01 03:25:16 +05:30
SharedPreferences . Editor editor = context . getSharedPreferences ( deviceId , Context . MODE_PRIVATE ) . edit ( ) ;
editor . putString ( " deviceName " , name ) ;
editor . putString ( " deviceType " , deviceType . toString ( ) ) ;
editor . apply ( ) ;
2013-08-16 10:31:01 +02:00
reloadPluginsFromSettings ( ) ;
2013-10-29 19:44:07 +01:00
for ( PairingCallback cb : pairingCallback ) {
cb . pairingSuccessful ( ) ;
}
}
2015-08-13 14:55:00 +05:30
/* This method is called after accepting pair request form GUI */
2013-10-29 19:44:07 +01:00
public void acceptPairing ( ) {
2015-06-25 04:20:03 +05:30
Log . i ( " KDE/Device " , " Accepted pair request started by the other device " ) ;
2015-08-13 14:55:00 +05:30
for ( BasePairingHandler ph : pairingHandlers . values ( ) ) {
ph . acceptPairing ( ) ;
2015-07-01 03:25:16 +05:30
}
2013-09-03 17:58:59 +02:00
}
2015-08-13 14:55:00 +05:30
/* This method is called after rejecting pairing from GUI */
2013-09-03 17:58:59 +02:00
public void rejectPairing ( ) {
2015-07-01 03:25:16 +05:30
Log . i ( " KDE/Device " , " Rejected pair request started by the other device " ) ;
2013-09-03 17:58:59 +02:00
2013-11-06 21:13:37 +01:00
//Log.e("Device","Unpairing (rejectPairing)");
2013-09-03 17:58:59 +02:00
pairStatus = PairStatus . NotPaired ;
2015-08-13 14:55:00 +05:30
for ( BasePairingHandler ph : pairingHandlers . values ( ) ) {
ph . rejectPairing ( ) ;
2015-06-25 04:20:03 +05:30
}
2013-09-03 17:58:59 +02:00
2013-10-29 19:44:07 +01:00
for ( PairingCallback cb : pairingCallback ) {
cb . pairingFailed ( context . getString ( R . string . error_canceled_by_user ) ) ;
}
2013-09-03 17:58:59 +02:00
2013-08-16 10:31:01 +02:00
}
2015-08-13 14:55:00 +05:30
//
// Notification related methods used during pairing
//
public int getNotificationId ( ) {
return notificationId ;
}
public void displayPairingNotification ( ) {
2015-12-02 09:46:22 -08:00
hidePairingNotification ( ) ;
2018-03-03 16:06:52 +01:00
notificationId = ( int ) System . currentTimeMillis ( ) ;
2015-08-13 14:55:00 +05:30
2018-03-03 17:21:16 +01:00
Intent intent = new Intent ( getContext ( ) , MainActivity . class ) ;
2019-01-06 13:10:58 +01:00
intent . putExtra ( MainActivity . EXTRA_DEVICE_ID , getDeviceId ( ) ) ;
intent . putExtra ( MainActivity . PAIR_REQUEST_STATUS , MainActivity . PAIRING_PENDING ) ;
PendingIntent pendingIntent = PendingIntent . getActivity ( getContext ( ) , 1 , intent , PendingIntent . FLAG_CANCEL_CURRENT ) ;
2017-02-05 15:19:46 +01:00
2018-03-03 17:21:16 +01:00
Intent acceptIntent = new Intent ( getContext ( ) , MainActivity . class ) ;
Intent rejectIntent = new Intent ( getContext ( ) , MainActivity . class ) ;
2017-02-05 15:19:46 +01:00
2019-01-06 13:10:58 +01:00
acceptIntent . putExtra ( MainActivity . EXTRA_DEVICE_ID , getDeviceId ( ) ) ;
//acceptIntent.putExtra("notificationId", notificationId);
2018-03-03 17:21:16 +01:00
acceptIntent . putExtra ( MainActivity . PAIR_REQUEST_STATUS , MainActivity . PAIRING_ACCEPTED ) ;
2017-02-05 15:19:46 +01:00
2019-01-06 13:10:58 +01:00
rejectIntent . putExtra ( MainActivity . EXTRA_DEVICE_ID , getDeviceId ( ) ) ;
//rejectIntent.putExtra("notificationId", notificationId);
2018-03-03 17:21:16 +01:00
rejectIntent . putExtra ( MainActivity . PAIR_REQUEST_STATUS , MainActivity . PAIRING_REJECTED ) ;
2017-02-05 15:19:46 +01:00
PendingIntent acceptedPendingIntent = PendingIntent . getActivity ( getContext ( ) , 2 , acceptIntent , PendingIntent . FLAG_ONE_SHOT ) ;
PendingIntent rejectedPendingIntent = PendingIntent . getActivity ( getContext ( ) , 4 , rejectIntent , PendingIntent . FLAG_ONE_SHOT ) ;
2015-08-13 14:55:00 +05:30
Resources res = getContext ( ) . getResources ( ) ;
2018-03-24 01:02:25 +01:00
final NotificationManager notificationManager = ( NotificationManager ) getContext ( ) . getSystemService ( Context . NOTIFICATION_SERVICE ) ;
2018-05-15 00:32:51 +02:00
Notification noti = new NotificationCompat . Builder ( getContext ( ) , NotificationHelper . Channels . DEFAULT )
2015-08-13 14:55:00 +05:30
. setContentTitle ( res . getString ( R . string . pairing_request_from , getName ( ) ) )
. setContentText ( res . getString ( R . string . tap_to_answer ) )
. setContentIntent ( pendingIntent )
. setTicker ( res . getString ( R . string . pair_requested ) )
2015-09-11 09:24:35 -07:00
. setSmallIcon ( R . drawable . ic_notification )
2017-02-05 15:19:46 +01:00
. addAction ( R . drawable . ic_accept_pairing , res . getString ( R . string . pairing_accept ) , acceptedPendingIntent )
. addAction ( R . drawable . ic_reject_pairing , res . getString ( R . string . pairing_reject ) , rejectedPendingIntent )
2015-08-13 14:55:00 +05:30
. setAutoCancel ( true )
. setDefaults ( Notification . DEFAULT_ALL )
. build ( ) ;
2013-08-16 10:31:01 +02:00
2016-12-05 23:42:58 +01:00
NotificationHelper . notifyCompat ( notificationManager , notificationId , noti ) ;
2015-08-13 14:55:00 +05:30
2016-12-05 23:42:58 +01:00
BackgroundService . addGuiInUseCounter ( context ) ;
2015-08-13 14:55:00 +05:30
}
2015-12-02 09:46:22 -08:00
public void hidePairingNotification ( ) {
2015-08-13 14:55:00 +05:30
final NotificationManager notificationManager = ( NotificationManager ) getContext ( ) . getSystemService ( Context . NOTIFICATION_SERVICE ) ;
notificationManager . cancel ( notificationId ) ;
2015-12-02 09:46:22 -08:00
BackgroundService . removeGuiInUseCounter ( context ) ;
2015-08-13 14:55:00 +05:30
}
2013-08-16 10:31:01 +02:00
//
2013-09-03 17:58:59 +02:00
// ComputerLink-related functions
2013-08-16 10:31:01 +02:00
//
2013-09-03 17:58:59 +02:00
public boolean isReachable ( ) {
return ! links . isEmpty ( ) ;
}
2018-03-04 11:31:37 +01:00
public void addLink ( NetworkPacket identityPacket , BaseLink link ) {
2015-04-04 11:37:12 -07:00
//FilesHelper.LogOpenFileCount();
2013-10-01 03:24:42 +02:00
2018-03-04 11:31:37 +01:00
this . protocolVersion = identityPacket . getInt ( " protocolVersion " ) ;
2013-08-16 10:31:01 +02:00
2018-03-04 11:31:37 +01:00
if ( identityPacket . has ( " deviceName " ) ) {
this . name = identityPacket . getString ( " deviceName " , this . name ) ;
2015-03-01 20:57:45 -08:00
SharedPreferences . Editor editor = settings . edit ( ) ;
editor . putString ( " deviceName " , this . name ) ;
editor . apply ( ) ;
}
2018-03-04 11:31:37 +01:00
if ( identityPacket . has ( " deviceType " ) ) {
this . deviceType = DeviceType . FromString ( identityPacket . getString ( " deviceType " , " desktop " ) ) ;
2015-04-12 00:06:47 -07:00
}
2018-03-04 11:31:37 +01:00
if ( identityPacket . has ( " certificate " ) ) {
String certificateString = identityPacket . getString ( " certificate " ) ;
2015-06-20 04:09:02 +05:30
try {
byte [ ] certificateBytes = Base64 . decode ( certificateString , 0 ) ;
2016-03-03 15:42:39 -08:00
certificate = SslHelper . parseCertificate ( certificateBytes ) ;
2015-06-28 20:07:05 +05:30
Log . i ( " KDE/Device " , " Got certificate " ) ;
2015-06-20 04:09:02 +05:30
} catch ( Exception e ) {
e . printStackTrace ( ) ;
Log . e ( " KDE/Device " , " Error getting certificate " ) ;
}
}
2015-03-01 20:57:45 -08:00
2013-07-23 16:11:54 +02:00
links . add ( link ) ;
2013-08-16 10:31:01 +02:00
2013-09-16 17:36:26 +02:00
try {
SharedPreferences globalSettings = PreferenceManager . getDefaultSharedPreferences ( context ) ;
byte [ ] privateKeyBytes = Base64 . decode ( globalSettings . getString ( " privateKey " , " " ) , 0 ) ;
PrivateKey privateKey = KeyFactory . getInstance ( " RSA " ) . generatePrivate ( new PKCS8EncodedKeySpec ( privateKeyBytes ) ) ;
link . setPrivateKey ( privateKey ) ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
2015-04-04 11:37:12 -07:00
Log . e ( " KDE/Device " , " Exception reading our own private key " ) ; //Should not happen
2013-09-16 17:36:26 +02:00
}
2018-03-03 16:06:52 +01:00
Log . i ( " KDE/Device " , " addLink " + link . getLinkProvider ( ) . getName ( ) + " -> " + getName ( ) + " active links: " + links . size ( ) ) ;
2013-08-19 23:59:13 +02:00
2015-08-13 14:55:00 +05:30
if ( ! pairingHandlers . containsKey ( link . getName ( ) ) ) {
BasePairingHandler . PairingHandlerCallback callback = new BasePairingHandler . PairingHandlerCallback ( ) {
@Override
public void incomingRequest ( ) {
for ( PairingCallback cb : pairingCallback ) {
cb . incomingRequest ( ) ;
}
}
@Override
public void pairingDone ( ) {
Device . this . pairingDone ( ) ;
}
@Override
public void pairingFailed ( String error ) {
for ( PairingCallback cb : pairingCallback ) {
cb . pairingFailed ( error ) ;
}
}
@Override
public void unpaired ( ) {
unpairInternal ( ) ;
}
} ;
pairingHandlers . put ( link . getName ( ) , link . getPairingHandler ( this , callback ) ) ;
}
2018-03-04 11:31:37 +01:00
Set < String > outgoingCapabilities = identityPacket . getStringSet ( " outgoingCapabilities " , null ) ;
Set < String > incomingCapabilities = identityPacket . getStringSet ( " incomingCapabilities " , null ) ;
2016-07-06 17:45:01 +02:00
if ( incomingCapabilities ! = null & & outgoingCapabilities ! = null ) {
2019-02-11 20:04:40 +01:00
m_supportedPlugins = new Vector < > ( PluginFactory . pluginsForCapabilities ( incomingCapabilities , outgoingCapabilities ) ) ;
2016-07-06 17:45:01 +02:00
} else {
m_supportedPlugins = new Vector < > ( PluginFactory . getAvailablePlugins ( ) ) ;
}
2013-07-23 16:11:54 +02:00
2018-03-04 11:31:37 +01:00
link . addPacketReceiver ( this ) ;
2013-08-16 10:31:01 +02:00
2016-07-06 17:45:01 +02:00
reloadPluginsFromSettings ( ) ;
2013-07-23 16:11:54 +02:00
}
2013-09-16 17:36:26 +02:00
public void removeLink ( BaseLink link ) {
2015-04-04 11:37:12 -07:00
//FilesHelper.LogOpenFileCount();
2015-08-13 14:55:00 +05:30
/* Remove pairing handler corresponding to that link too if it was the only link*/
boolean linkPresent = false ;
for ( BaseLink bl : links ) {
if ( bl . getName ( ) . equals ( link . getName ( ) ) ) {
linkPresent = true ;
break ;
}
}
if ( ! linkPresent ) {
pairingHandlers . remove ( link . getName ( ) ) ;
}
2018-03-04 11:31:37 +01:00
link . removePacketReceiver ( this ) ;
2013-07-23 16:11:54 +02:00
links . remove ( link ) ;
2015-06-25 04:20:03 +05:30
Log . i ( " KDE/Device " , " removeLink: " + link . getLinkProvider ( ) . getName ( ) + " -> " + getName ( ) + " active links: " + links . size ( ) ) ;
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
2018-03-04 11:31:37 +01:00
public void onPacketReceived ( NetworkPacket np ) {
2013-09-03 17:58:59 +02:00
2016-07-14 07:13:50 +02:00
hackToMakeRetrocompatiblePacketTypes ( np ) ;
2018-03-04 11:31:37 +01:00
if ( NetworkPacket . PACKET_TYPE_PAIR . equals ( np . getType ( ) ) ) {
2013-09-03 17:58:59 +02:00
2015-06-25 04:20:03 +05:30
Log . i ( " KDE/Device " , " Pair package " ) ;
2015-08-15 18:44:49 +05:30
2018-03-03 16:06:52 +01:00
for ( BasePairingHandler ph : pairingHandlers . values ( ) ) {
2015-08-13 14:55:00 +05:30
try {
ph . packageReceived ( np ) ;
} catch ( Exception e ) {
2016-02-12 08:37:47 -08:00
e . printStackTrace ( ) ;
2018-03-04 11:31:37 +01:00
Log . e ( " PairingPacketReceived " , " Exception " ) ;
2013-09-03 17:58:59 +02:00
}
}
2015-03-22 22:44:17 -07:00
} else if ( isPaired ( ) ) {
2013-09-03 17:58:59 +02:00
2016-06-02 15:22:21 +02:00
//If capabilities are not supported, iterate all plugins
2016-06-02 15:35:44 +02:00
Collection < String > targetPlugins = pluginsByIncomingInterface . get ( np . getType ( ) ) ;
2016-06-02 13:56:46 +02:00
if ( targetPlugins ! = null & & ! targetPlugins . isEmpty ( ) ) {
2016-05-31 21:02:17 +02:00
for ( String pluginKey : targetPlugins ) {
Plugin plugin = plugins . get ( pluginKey ) ;
try {
2018-03-04 11:31:37 +01:00
plugin . onPacketReceived ( np ) ;
2016-05-31 21:02:17 +02:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
2018-03-04 11:31:37 +01:00
Log . e ( " KDE/Device " , " Exception in " + plugin . getPluginKey ( ) + " 's onPacketReceived() " ) ;
//try { Log.e("KDE/Device", "NetworkPacket:" + np.serialize()); } catch (Exception _) { }
2016-05-31 21:02:17 +02:00
}
2014-06-18 22:53:52 +02:00
}
2016-06-02 13:56:46 +02:00
} else {
2016-06-21 13:38:21 +02:00
Log . w ( " Device " , " Ignoring packet with type " + np . getType ( ) + " because no plugin can handle it " ) ;
2013-09-03 17:58:59 +02:00
}
2015-03-22 22:44:17 -07:00
} else {
2018-03-04 11:31:37 +01:00
//Log.e("KDE/onPacketReceived","Device not paired, will pass package to unpairedPacketListeners");
2015-03-22 22:44:17 -07:00
2015-08-13 14:55:00 +05:30
// If it is pair package, it should be captured by "if" at start
// If not and device is paired, it should be captured by isPaired
// Else unpair, this handles the situation when one device unpairs, but other dont know like unpairing when wi-fi is off
unpair ( ) ;
2015-03-22 22:44:17 -07:00
2016-06-02 15:22:21 +02:00
//If capabilities are not supported, iterate all plugins
2016-06-02 15:35:44 +02:00
Collection < String > targetPlugins = pluginsByIncomingInterface . get ( np . getType ( ) ) ;
2016-06-02 13:56:46 +02:00
if ( targetPlugins ! = null & & ! targetPlugins . isEmpty ( ) ) {
2016-05-31 21:02:17 +02:00
for ( String pluginKey : targetPlugins ) {
Plugin plugin = plugins . get ( pluginKey ) ;
try {
2018-03-04 11:31:37 +01:00
plugin . onUnpairedDevicePacketReceived ( np ) ;
2016-05-31 21:02:17 +02:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
2018-03-04 11:31:37 +01:00
Log . e ( " KDE/Device " , " Exception in " + plugin . getDisplayName ( ) + " 's onPacketReceived() in unPairedPacketListeners " ) ;
2016-05-31 21:02:17 +02:00
}
2015-08-19 21:27:27 +05:30
}
2016-06-02 13:56:46 +02:00
} else {
Log . e ( " Device " , " Ignoring packet with type " + np . getType ( ) + " because no plugin can handle it " ) ;
2015-08-19 21:27:27 +05:30
}
2013-08-16 10:31:01 +02:00
}
2013-09-03 17:58:59 +02:00
2013-07-23 16:11:54 +02:00
}
2018-03-04 11:31:37 +01:00
public static abstract class SendPacketStatusCallback {
2016-12-05 22:15:27 +01:00
public abstract void onSuccess ( ) ;
2018-03-03 16:06:52 +01:00
2016-12-05 22:15:27 +01:00
public abstract void onFailure ( Throwable e ) ;
2018-03-03 16:06:52 +01:00
public void onProgressChanged ( int percent ) {
}
2016-12-05 22:15:27 +01:00
}
2018-10-27 00:01:30 +02:00
private final SendPacketStatusCallback defaultCallback = new SendPacketStatusCallback ( ) {
2016-12-05 22:15:27 +01:00
@Override
2018-03-03 16:06:52 +01:00
public void onSuccess ( ) {
}
2016-12-05 22:15:27 +01:00
@Override
public void onFailure ( Throwable e ) {
2015-01-29 23:57:58 -08:00
if ( e ! = null ) {
e . printStackTrace ( ) ;
} else {
2018-03-04 11:31:37 +01:00
Log . e ( " KDE/sendPacket " , " Unknown (null) exception " ) ;
2015-01-29 23:57:58 -08:00
}
}
2016-12-05 22:15:27 +01:00
} ;
2015-01-29 23:57:58 -08:00
2018-03-04 11:31:37 +01:00
public void sendPacket ( NetworkPacket np ) {
sendPacket ( np , defaultCallback ) ;
2016-12-05 22:15:27 +01:00
}
2018-03-04 11:31:37 +01:00
public boolean sendPacketBlocking ( NetworkPacket np ) {
return sendPacketBlocking ( np , defaultCallback ) ;
2013-09-27 02:58:16 +02:00
}
2013-10-05 17:25:59 +02:00
//Async
2018-03-04 11:31:37 +01:00
public void sendPacket ( final NetworkPacket np , final SendPacketStatusCallback callback ) {
2018-05-09 14:02:56 +02:00
new Thread ( ( ) - > sendPacketBlocking ( np , callback ) ) . start ( ) ;
2016-12-05 22:15:27 +01:00
}
2013-09-03 17:58:59 +02:00
2018-03-04 11:31:37 +01:00
public boolean sendPacketBlocking ( final NetworkPacket np , final SendPacketStatusCallback callback ) {
2016-07-14 07:13:50 +02:00
2016-07-06 17:45:01 +02:00
/ *
2018-03-04 11:31:37 +01:00
if ( ! m_outgoingCapabilities . contains ( np . getType ( ) ) & & ! NetworkPacket . protocolPacketTypes . contains ( np . getType ( ) ) ) {
Log . e ( " Device/sendPacket " , " Plugin tried to send an undeclared package: " + np . getType ( ) ) ;
Log . w ( " Device/sendPacket " , " Declared outgoing package types: " + Arrays . toString ( m_outgoingCapabilities . toArray ( ) ) ) ;
2016-06-02 15:23:34 +02:00
}
2016-07-06 17:45:01 +02:00
* /
2016-06-02 15:23:34 +02:00
2016-12-05 22:15:27 +01:00
hackToMakeRetrocompatiblePacketTypes ( np ) ;
2013-09-16 17:36:26 +02:00
2018-03-04 11:31:37 +01:00
boolean useEncryption = ( protocolVersion < LanLinkProvider . MIN_VERSION_WITH_SSL_SUPPORT & & ( ! np . getType ( ) . equals ( NetworkPacket . PACKET_TYPE_PAIR ) & & isPaired ( ) ) ) ;
2013-09-16 17:36:26 +02:00
2016-12-05 22:15:27 +01:00
boolean success = false ;
//Make a copy to avoid concurrent modification exception if the original list changes
for ( final BaseLink link : links ) {
2018-03-03 16:06:52 +01:00
if ( link = = null )
continue ; //Since we made a copy, maybe somebody destroyed the link in the meanwhile
2016-12-05 22:15:27 +01:00
if ( useEncryption ) {
2018-03-04 11:31:37 +01:00
success = link . sendPacketEncrypted ( np , callback , publicKey ) ;
2016-12-05 22:15:27 +01:00
} else {
2018-03-04 11:31:37 +01:00
success = link . sendPacket ( np , callback ) ;
2016-12-05 22:15:27 +01:00
}
if ( success ) break ; //If the link didn't call sendSuccess(), try the next one
}
2013-09-16 17:36:26 +02:00
2016-12-05 22:15:27 +01:00
if ( ! success ) {
2018-03-04 11:31:37 +01:00
Log . e ( " KDE/sendPacket " , " No device link (of " + links . size ( ) + " available) could send the package. Packet " + np . getType ( ) + " to " + name + " lost! " ) ;
2016-12-05 22:15:27 +01:00
}
2015-01-31 00:16:06 -08:00
2016-12-05 22:15:27 +01:00
return success ;
2013-09-03 17:58:59 +02:00
2013-07-23 16:11:54 +02:00
}
2013-08-16 10:31:01 +02:00
//
// Plugin-related functions
//
2015-06-06 00:38:51 -07:00
public < T extends Plugin > T getPlugin ( Class < T > pluginClass ) {
2019-02-12 13:10:22 +01:00
Plugin plugin = getPlugin ( Plugin . getPluginKey ( pluginClass ) ) ;
return ( T ) plugin ;
2015-01-10 00:31:07 -08:00
}
2019-02-12 13:10:22 +01:00
public Plugin getPlugin ( String pluginKey ) {
return plugins . get ( pluginKey ) ;
2013-08-16 10:31:01 +02:00
}
2015-09-12 07:29:45 -07:00
private synchronized boolean addPlugin ( final String pluginKey ) {
2015-06-06 00:38:51 -07:00
Plugin existing = plugins . get ( pluginKey ) ;
2013-08-16 10:31:01 +02:00
if ( existing ! = null ) {
2018-01-03 20:49:51 +01:00
if ( existing . getMinSdk ( ) > Build . VERSION . SDK_INT ) {
Log . i ( " KDE/addPlugin " , " Min API level not fulfilled " + pluginKey ) ;
return false ;
}
2015-09-08 15:05:32 -07:00
//Log.w("KDE/addPlugin","plugin already present:" + pluginKey);
2017-07-11 13:50:40 +02:00
if ( existing . checkOptionalPermissions ( ) ) {
Log . i ( " KDE/addPlugin " , " Optional Permissions OK " + pluginKey ) ;
pluginsWithoutOptionalPermissions . remove ( pluginKey ) ;
} else {
Log . e ( " KDE/addPlugin " , " No optional permission " + pluginKey ) ;
pluginsWithoutOptionalPermissions . put ( pluginKey , existing ) ;
}
2016-01-05 20:35:52 +01:00
return true ;
2013-08-16 10:31:01 +02:00
}
2015-06-06 00:38:51 -07:00
final Plugin plugin = PluginFactory . instantiatePluginForDevice ( context , pluginKey , this ) ;
2013-08-16 10:31:01 +02:00
if ( plugin = = null ) {
2018-03-03 16:06:52 +01:00
Log . e ( " KDE/addPlugin " , " could not instantiate plugin: " + pluginKey ) ;
2015-09-12 07:29:45 -07:00
return false ;
2013-08-16 10:31:01 +02:00
}
2018-01-03 20:49:51 +01:00
if ( plugin . getMinSdk ( ) > Build . VERSION . SDK_INT ) {
Log . i ( " KDE/addPlugin " , " Min API level not fulfilled " + pluginKey ) ;
return false ;
}
2015-09-12 07:29:45 -07:00
boolean success ;
try {
success = plugin . onCreate ( ) ;
} catch ( Exception e ) {
success = false ;
e . printStackTrace ( ) ;
}
2019-02-12 13:10:22 +01:00
if ( ! success ) {
2015-09-12 07:29:45 -07:00
Log . e ( " KDE/addPlugin " , " plugin failed to load " + pluginKey ) ;
}
2013-08-19 19:57:29 +02:00
2019-02-12 13:10:22 +01:00
plugins . put ( pluginKey , plugin ) ;
2018-03-03 16:06:52 +01:00
if ( ! plugin . checkRequiredPermissions ( ) ) {
2017-05-31 15:51:07 +02:00
Log . e ( " KDE/addPlugin " , " No permission " + pluginKey ) ;
plugins . remove ( pluginKey ) ;
pluginsWithoutPermissions . put ( pluginKey , plugin ) ;
success = false ;
} else {
2017-07-11 13:50:40 +02:00
Log . i ( " KDE/addPlugin " , " Permissions OK " + pluginKey ) ;
2017-05-31 15:51:07 +02:00
pluginsWithoutPermissions . remove ( pluginKey ) ;
2017-07-11 13:50:40 +02:00
if ( plugin . checkOptionalPermissions ( ) ) {
Log . i ( " KDE/addPlugin " , " Optional Permissions OK " + pluginKey ) ;
pluginsWithoutOptionalPermissions . remove ( pluginKey ) ;
} else {
Log . e ( " KDE/addPlugin " , " No optional permission " + pluginKey ) ;
pluginsWithoutOptionalPermissions . put ( pluginKey , plugin ) ;
}
2017-05-31 15:51:07 +02:00
}
2015-09-12 07:29:45 -07:00
return success ;
2013-08-16 10:31:01 +02:00
}
2015-06-06 00:38:51 -07:00
private synchronized boolean removePlugin ( String pluginKey ) {
2013-08-19 19:57:29 +02:00
2015-06-06 00:38:51 -07:00
Plugin plugin = plugins . remove ( pluginKey ) ;
2013-08-19 19:57:29 +02:00
2013-08-16 10:31:01 +02:00
if ( plugin = = null ) {
2019-02-12 13:10:22 +01:00
return false ;
2013-08-16 10:31:01 +02:00
}
try {
plugin . onDestroy ( ) ;
2015-06-06 00:38:51 -07:00
//Log.e("removePlugin","removed " + pluginKey);
2013-08-16 10:31:01 +02:00
} catch ( Exception e ) {
e . printStackTrace ( ) ;
2018-03-03 16:06:52 +01:00
Log . e ( " KDE/removePlugin " , " Exception calling onDestroy for plugin " + pluginKey ) ;
2013-08-16 10:31:01 +02:00
}
return true ;
}
2015-06-06 00:38:51 -07:00
public void setPluginEnabled ( String pluginKey , boolean value ) {
2018-03-03 16:06:52 +01:00
settings . edit ( ) . putBoolean ( pluginKey , value ) . apply ( ) ;
2015-09-08 15:05:32 -07:00
reloadPluginsFromSettings ( ) ;
2013-08-16 10:31:01 +02:00
}
2015-06-06 00:38:51 -07:00
public boolean isPluginEnabled ( String pluginKey ) {
2019-02-11 20:04:40 +01:00
boolean enabledByDefault = PluginFactory . getPluginInfo ( pluginKey ) . isEnabledByDefault ( ) ;
2018-03-03 15:51:35 +01:00
return settings . getBoolean ( pluginKey , enabledByDefault ) ;
2013-08-19 19:57:29 +02:00
}
2013-08-16 10:31:01 +02:00
public void reloadPluginsFromSettings ( ) {
2015-09-08 15:05:32 -07:00
HashMap < String , ArrayList < String > > newPluginsByIncomingInterface = new HashMap < > ( ) ;
2015-09-12 12:25:22 +02:00
2016-07-06 17:45:01 +02:00
for ( String pluginKey : m_supportedPlugins ) {
2015-09-08 15:05:32 -07:00
2019-02-11 20:04:40 +01:00
PluginFactory . PluginInfo pluginInfo = PluginFactory . getPluginInfo ( pluginKey ) ;
2015-09-08 15:05:32 -07:00
boolean pluginEnabled = false ;
boolean listenToUnpaired = pluginInfo . listenToUnpaired ( ) ;
2015-08-27 13:06:24 +05:30
if ( ( isPaired ( ) | | listenToUnpaired ) & & isReachable ( ) ) {
2015-09-08 15:05:32 -07:00
pluginEnabled = isPluginEnabled ( pluginKey ) ;
2013-08-16 10:31:01 +02:00
}
2015-08-27 13:06:24 +05:30
2015-09-08 15:05:32 -07:00
if ( pluginEnabled ) {
2015-09-12 07:29:45 -07:00
boolean success = addPlugin ( pluginKey ) ;
if ( success ) {
2018-03-04 11:31:37 +01:00
for ( String packageType : pluginInfo . getSupportedPacketTypes ( ) ) {
2016-07-14 14:43:39 +02:00
packageType = hackToMakeRetrocompatiblePacketTypes ( packageType ) ;
2015-09-12 07:29:45 -07:00
ArrayList < String > plugins = newPluginsByIncomingInterface . get ( packageType ) ;
if ( plugins = = null ) plugins = new ArrayList < > ( ) ;
plugins . add ( pluginKey ) ;
newPluginsByIncomingInterface . put ( packageType , plugins ) ;
}
2015-09-08 15:05:32 -07:00
}
2013-08-16 10:31:01 +02:00
} else {
2015-06-06 00:38:51 -07:00
removePlugin ( pluginKey ) ;
2013-08-16 10:31:01 +02:00
}
2015-09-08 15:05:32 -07:00
}
pluginsByIncomingInterface = newPluginsByIncomingInterface ;
2016-06-02 12:28:33 +02:00
2015-09-12 12:24:11 +02:00
onPluginsChanged ( ) ;
2013-08-16 10:31:01 +02:00
}
2015-09-12 12:24:11 +02:00
public void onPluginsChanged ( ) {
for ( PluginsChangedListener listener : pluginsChangedListeners ) {
listener . onPluginsChanged ( Device . this ) ;
}
}
2018-03-03 16:06:52 +01:00
public ConcurrentHashMap < String , Plugin > getLoadedPlugins ( ) {
2013-09-03 17:58:59 +02:00
return plugins ;
}
2017-05-31 15:51:07 +02:00
public ConcurrentHashMap < String , Plugin > getPluginsWithoutPermissions ( ) {
return pluginsWithoutPermissions ;
}
2018-03-03 16:06:52 +01:00
public ConcurrentHashMap < String , Plugin > getPluginsWithoutOptionalPermissions ( ) {
2017-07-11 13:50:40 +02:00
return pluginsWithoutOptionalPermissions ;
}
2013-08-19 19:57:29 +02:00
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
}
2015-09-09 00:45:56 +02:00
public void disconnect ( ) {
2018-03-03 16:06:52 +01:00
for ( BaseLink link : links ) {
2015-09-09 00:45:56 +02:00
link . disconnect ( ) ;
}
}
2015-09-12 13:21:06 -07:00
2016-03-02 11:39:49 -08:00
public boolean deviceShouldBeKeptAlive ( ) {
2016-06-17 09:59:31 +02:00
SharedPreferences preferences = context . getSharedPreferences ( " trusted_devices " , Context . MODE_PRIVATE ) ;
if ( preferences . contains ( getDeviceId ( ) ) ) {
//Log.e("DeviceShouldBeKeptAlive", "because it's a paired device");
return true ; //Already paired
}
2018-03-03 16:06:52 +01:00
for ( BaseLink l : links ) {
2016-03-02 11:39:49 -08:00
if ( l . linkShouldBeKeptAlive ( ) ) {
return true ;
2015-09-12 13:21:06 -07:00
}
}
2016-03-02 11:39:49 -08:00
return false ;
2015-09-12 13:21:06 -07:00
}
2016-07-06 17:45:01 +02:00
public List < String > getSupportedPlugins ( ) {
return m_supportedPlugins ;
2016-06-02 15:22:40 +02:00
}
2018-10-26 23:53:58 +02:00
private void hackToMakeRetrocompatiblePacketTypes ( NetworkPacket np ) {
2016-07-14 07:13:50 +02:00
if ( protocolVersion > = 6 ) return ;
2018-03-03 16:06:52 +01:00
np . mType = np . getType ( ) . replace ( " .request " , " " ) ;
2016-07-14 07:13:50 +02:00
}
2018-03-03 16:06:52 +01:00
2018-10-26 23:53:58 +02:00
private String hackToMakeRetrocompatiblePacketTypes ( String type ) {
2016-07-14 14:43:39 +02:00
if ( protocolVersion > = 6 ) return type ;
return type . replace ( " .request " , " " ) ;
}
2016-07-14 07:13:50 +02:00
2013-07-23 16:11:54 +02:00
}