diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d454807..751b319 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -28,6 +28,12 @@ + + . */ package us.spotco.malwarescanner; -public class MalwareScannerService { -} +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Environment; +import android.os.FileObserver; +import android.os.IBinder; +import android.support.v4.app.NotificationCompat; + +import java.io.File; +import java.util.HashSet; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; + +public class MalwareScannerService extends Service { + + private final HashSet malwareMonitors = new HashSet<>(); + private ThreadPoolExecutor threadPoolExecutor = null; + private NotificationCompat.Builder foregroundNotification = null; + private NotificationManager notificationManager = null; + private int maxScanSize = 0; + + @Override + public final IBinder onBind(Intent intent) { + return null; + } + + @Override + public final int onStartCommand(Intent intent, int flags, int startId) { + maxScanSize = Utils.prefs.getInt("scanner_max_file_size", (1000 * 1000) * 80) * (1000 * 1000); + + malwareMonitors.clear(); + + if(Utils.prefs.getBoolean("scanner_realtime_path_external", false)) { + addMalwareMonitor("/storage"); + } else if(Utils.prefs.getBoolean("scanner_realtime_path_internal", true)) { + addMalwareMonitor(Environment.getExternalStorageDirectory().toString()); + } + + threadPoolExecutor = (ThreadPoolExecutor) Executors.newScheduledThreadPool(Utils.getMaxThreads() + malwareMonitors.size()); + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + DatabaseManager.loadAllAvailableDatabases(false); + } + }); + + for (final RecursiveFileObserver malwareMonitor : malwareMonitors) { + threadPoolExecutor.execute(new Runnable() { + @Override + public void run() { + malwareMonitor.startWatching(); + } + }); + } + + notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel foregroundChannel = new NotificationChannel("FOREGROUND", getString(R.string.notif_scanner_realtime), NotificationManager.IMPORTANCE_LOW); + foregroundChannel.setDescription(getString(R.string.notif_scanner_realtime_summary)); + foregroundChannel.setShowBadge(false); + notificationManager.createNotificationChannel(foregroundChannel); + } + setForeground(); + return START_STICKY; + } + + private void addMalwareMonitor(String monitorPath) { + malwareMonitors.add(new RecursiveFileObserver(monitorPath) { + @Override + public void onEvent(int event, String path) { + switch (event) { + case FileObserver.MOVED_TO: + case FileObserver.CLOSE_WRITE: + File file = new File(path); + if (file.exists() && /*file.length() > 0 &&*/ file.length() <= maxScanSize) { + HashSet filesToScan = new HashSet<>(); + filesToScan.add(file); + new MalwareScanner(false).executeOnExecutor(threadPoolExecutor, filesToScan); + } + updateForegroundNotification(); + break; + } + } + }); + } + + @Override + public final void onDestroy() { + for (RecursiveFileObserver malwareMonitor : malwareMonitors) { + malwareMonitor.stopWatching(); + } + malwareMonitors.clear(); + System.gc(); + //Toast.makeText(this, "Hypatia: Realtime Scanning Stopped", Toast.LENGTH_SHORT).show(); + } + + private void setForeground() { + foregroundNotification = + new NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle(getText(R.string.notif_scanner_realtime)) + .setContentText(getText(R.string.notif_scanner_realtime_summary)) + .setPriority(Notification.PRIORITY_MIN) + .setShowWhen(false); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + foregroundNotification.setChannelId("FOREGROUND"); + } + + startForeground(-1, foregroundNotification.build()); + } + + private void updateForegroundNotification() { + foregroundNotification.setSubText(Utils.amtFilesScanned + " files scanned"); + notificationManager.notify(-1, foregroundNotification.build()); + } + +} \ No newline at end of file diff --git a/app/src/main/java/us/spotco/malwarescanner/Utils.java b/app/src/main/java/us/spotco/malwarescanner/Utils.java index 608d63c..c30db8a 100644 --- a/app/src/main/java/us/spotco/malwarescanner/Utils.java +++ b/app/src/main/java/us/spotco/malwarescanner/Utils.java @@ -61,6 +61,7 @@ public class Utils { } public static HashSet getFilesRecursive(File root) { + int maxScanSize = prefs.getInt("scanner_max_file_size", (1000 * 1000) * 80) * (1000 * 1000); HashSet filesAll = new HashSet<>(); File[] files = root.listFiles(); @@ -72,7 +73,7 @@ public class Utils { filesAll.addAll(filesTmp); } } else { - if (f.length() <= (prefs.getInt("scanner_max_file_size", (1000 * 1000) * 80) * (1000 * 1000)) && f.canRead()) {//Exclude files larger than limit for performance + if (f.length() <= maxScanSize && f.canRead()) {//Exclude files larger than limit for performance filesAll.add(f); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ccf82ac..5745129 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,6 +8,11 @@ Settings + + Malware Detection + Used to alert when malware is detected + + Orbot is required for this feature diff --git a/app/src/main/res/xml/fragment_settings.xml b/app/src/main/res/xml/fragment_settings.xml index 9ebc9e4..2b82455 100644 --- a/app/src/main/res/xml/fragment_settings.xml +++ b/app/src/main/res/xml/fragment_settings.xml @@ -8,11 +8,11 @@ android:title="@string/settings_pref_scanner_realtime_enabled" android:summary="@string/settings_pref_scanner_realtime_enabled_summary" android:defaultValue="false" /> - + android:defaultValue="true" />--> - + android:defaultValue="true" />--> @@ -64,12 +64,12 @@ android:defaultValue="false" /> - + \ No newline at end of file