/* Hypatia: An realtime malware scanner for Android Copyright (c) 2017-2018 Divested Computing, Inc. 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 3 of the License, or (at your option) any later version. 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 . */ package us.spotco.malwarescanner; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Build; import android.preference.PreferenceManager; import java.io.File; import java.net.Socket; import java.util.HashSet; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; class Utils { public final static int MAX_SCAN_SIZE = (1000 * 1000) * 80; //80MB public final static int MAX_SCAN_SIZE_REALTIME = MAX_SCAN_SIZE / 2; //40MB public final static int MAX_HASH_LENGTH = 16; public static int FILES_SCANNED = 0; private static ThreadPoolExecutor threadPoolExecutor = null; public static ThreadPoolExecutor getThreadPoolExecutor() { if (threadPoolExecutor == null) { threadPoolExecutor = (ThreadPoolExecutor) Executors.newScheduledThreadPool(getMaxThreads()); } return threadPoolExecutor; } public static int getMaxThreads() { int maxTheads = Runtime.getRuntime().availableProcessors(); if (maxTheads >= 2) { maxTheads /= 2; } return maxTheads; } public static HashSet getFilesRecursive(File root) { HashSet filesAll = new HashSet<>(); File[] files = root.listFiles(); if (files != null && files.length > 0) { for (File f : files) { if (f.isDirectory()) { HashSet filesTmp = getFilesRecursive(f); if (filesTmp != null) { filesAll.addAll(filesTmp); } } else { if (f.length() <= MAX_SCAN_SIZE && f.canRead()) {//Exclude files larger than limit for performance filesAll.add(f); } } } } return filesAll; } //Credit: https://stackoverflow.com/a/5921190 public static boolean isServiceRunning(Class serviceClass, Context context) { ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { if (serviceClass.getName().equals(service.service.getClassName())) { return true; } } return false; } public static void considerStartService(Context context) { if (!Utils.isServiceRunning(MalwareScannerService.class, context)) { SharedPreferences prefs = context.getSharedPreferences(BuildConfig.APPLICATION_ID, Context.MODE_PRIVATE); boolean autostart = prefs.getBoolean("autostart", false); if (autostart) { Intent realtimeScanner = new Intent(context, MalwareScannerService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(realtimeScanner); } else { context.startService(realtimeScanner); } } } } //Credit: https://stackoverflow.com/a/6758962 public static boolean isPackageInstalled(Context context, String packageID) { PackageManager pm = context.getPackageManager(); try { pm.getPackageInfo(packageID, PackageManager.GET_META_DATA); } catch(PackageManager.NameNotFoundException e) { return false; } return true; } public static boolean isOrbotInstalled(Context context) { return isPackageInstalled(context, "org.torproject.android"); } //Credit: OrbotHelper/NetCipher public static void requestStartOrbot(Context context) { Intent intent = new Intent("org.torproject.android.intent.action.START"); intent.setPackage("org.torproject.android"); intent.putExtra("org.torproject.android.intent.extra.PACKAGE_NAME", context.getPackageName()); context.sendBroadcast(intent); } //Credit: https://www.geekality.net/2013/04/30/java-simple-check-to-see-if-a-server-is-listening-on-a-port/ public static boolean isPortListening(String host, int port) { Socket s = null; try { s = new Socket(host, port); return true; } catch(Exception e) { return false; } finally { if (s != null) { try { s.close(); } catch(Exception e1) { } } } } public static boolean waitUntilOrbotIsAvailable() { int tries = 0; boolean listening; while(!(listening = isPortListening("127.0.0.1", 9050)) && tries <= 60) { tries++; try { Thread.sleep(1000); } catch(Exception e) { } } return listening; } }