diff --git a/app/src/full/java/cc/mvdan/accesspoint/WifiApControl.java b/app/src/full/java/cc/mvdan/accesspoint/WifiApControl.java index 9b5020d6e..e1adaef0e 100644 --- a/app/src/full/java/cc/mvdan/accesspoint/WifiApControl.java +++ b/app/src/full/java/cc/mvdan/accesspoint/WifiApControl.java @@ -141,10 +141,6 @@ final public class WifiApControl { @TargetApi(Build.VERSION_CODES.GINGERBREAD) private static String getDeviceName(WifiManager wifiManager) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) { - Log.w(TAG, "Older device - falling back to the default device name: " + FALLBACK_DEVICE); - return FALLBACK_DEVICE; - } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Log.w(TAG, "6.0 or later, unaccessible MAC - falling back to the default device name: " + FALLBACK_DEVICE); return FALLBACK_DEVICE; diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/SDCardScannerService.java b/app/src/full/java/org/fdroid/fdroid/nearby/SDCardScannerService.java index f207054fb..eaac0a445 100644 --- a/app/src/full/java/org/fdroid/fdroid/nearby/SDCardScannerService.java +++ b/app/src/full/java/org/fdroid/fdroid/nearby/SDCardScannerService.java @@ -88,29 +88,21 @@ public class SDCardScannerService extends IntentService { Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST); HashSet files = new HashSet<>(); - if (Build.VERSION.SDK_INT < 21) { - if (Environment.isExternalStorageRemovable()) { - File sdcard = Environment.getExternalStorageDirectory(); - String state = Environment.getExternalStorageState(); - Collections.addAll(files, checkExternalStorage(sdcard, state)); + for (File f : getExternalFilesDirs(null)) { + Log.i(TAG, "getExternalFilesDirs " + f); + if (f == null || !f.isDirectory()) { + continue; } - } else { - for (File f : getExternalFilesDirs(null)) { - Log.i(TAG, "getExternalFilesDirs " + f); - if (f == null || !f.isDirectory()) { - continue; - } - Log.i(TAG, "getExternalFilesDirs " + f); - if (Environment.isExternalStorageRemovable(f)) { - String state = Environment.getExternalStorageState(f); - if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) - == PackageManager.PERMISSION_GRANTED) { - // remove Android/data/org.fdroid.fdroid/files to get root - File sdcard = f.getParentFile().getParentFile().getParentFile().getParentFile(); - Collections.addAll(files, checkExternalStorage(sdcard, state)); - } else { - Collections.addAll(files, checkExternalStorage(f, state)); - } + Log.i(TAG, "getExternalFilesDirs " + f); + if (Environment.isExternalStorageRemovable(f)) { + String state = Environment.getExternalStorageState(f); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) + == PackageManager.PERMISSION_GRANTED) { + // remove Android/data/org.fdroid.fdroid/files to get root + File sdcard = f.getParentFile().getParentFile().getParentFile().getParentFile(); + Collections.addAll(files, checkExternalStorage(sdcard, state)); + } else { + Collections.addAll(files, checkExternalStorage(f, state)); } } } diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/TreeUriScannerIntentService.java b/app/src/full/java/org/fdroid/fdroid/nearby/TreeUriScannerIntentService.java index 602a60ef8..a3b4ddcd4 100644 --- a/app/src/full/java/org/fdroid/fdroid/nearby/TreeUriScannerIntentService.java +++ b/app/src/full/java/org/fdroid/fdroid/nearby/TreeUriScannerIntentService.java @@ -106,11 +106,9 @@ public class TreeUriScannerIntentService extends IntentService { } Uri uri = intent.getData(); if (uri != null) { - if (Build.VERSION.SDK_INT >= 19) { - ContentResolver contentResolver = context.getContentResolver(); - int perms = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - contentResolver.takePersistableUriPermission(uri, perms); - } + ContentResolver contentResolver = context.getContentResolver(); + int perms = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + contentResolver.takePersistableUriPermission(uri, perms); String msg = String.format(context.getString(R.string.swap_toast_using_path), uri.toString()); Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); scan(context, uri); diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceAttachedReceiver.java b/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceAttachedReceiver.java index 3f14e4ebc..f7477098f 100644 --- a/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceAttachedReceiver.java +++ b/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceAttachedReceiver.java @@ -48,9 +48,6 @@ public class UsbDeviceAttachedReceiver extends BroadcastReceiver { @RequiresApi(api = 19) @Override public void onReceive(final Context context, Intent intent) { - if (Build.VERSION.SDK_INT < 19) { - return; - } if (intent == null || TextUtils.isEmpty(intent.getAction()) || !UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { diff --git a/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceDetachedReceiver.java b/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceDetachedReceiver.java index 7a5b27e46..7e249ec4f 100644 --- a/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceDetachedReceiver.java +++ b/app/src/full/java/org/fdroid/fdroid/nearby/UsbDeviceDetachedReceiver.java @@ -48,10 +48,6 @@ public class UsbDeviceDetachedReceiver extends BroadcastReceiver { @RequiresApi(api = 19) @Override public void onReceive(Context context, Intent intent) { - if (Build.VERSION.SDK_INT < 19) { - return; - } - if (intent == null || TextUtils.isEmpty(intent.getAction()) || !UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) { Log.i(TAG, "ignoring irrelevant intent: " + intent); diff --git a/app/src/full/java/org/fdroid/fdroid/panic/ExitActivity.java b/app/src/full/java/org/fdroid/fdroid/panic/ExitActivity.java index 3e49ac274..b291bede2 100644 --- a/app/src/full/java/org/fdroid/fdroid/panic/ExitActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/panic/ExitActivity.java @@ -12,11 +12,7 @@ public class ExitActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (Build.VERSION.SDK_INT >= 21) { - finishAndRemoveTask(); - } else { - finish(); - } + finishAndRemoveTask(); System.exit(0); } diff --git a/app/src/full/java/org/fdroid/fdroid/panic/PanicResponderActivity.java b/app/src/full/java/org/fdroid/fdroid/panic/PanicResponderActivity.java index 7a16b7235..e5accc7ff 100644 --- a/app/src/full/java/org/fdroid/fdroid/panic/PanicResponderActivity.java +++ b/app/src/full/java/org/fdroid/fdroid/panic/PanicResponderActivity.java @@ -137,8 +137,6 @@ public class PanicResponderActivity extends AppCompatActivity { private void exitAndClear() { ExitActivity.exitAndRemoveFromRecentApps(this); - if (Build.VERSION.SDK_INT >= 21) { - finishAndRemoveTask(); - } + finishAndRemoveTask(); } } diff --git a/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java b/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java index b3c39c50b..7768e9656 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java +++ b/app/src/full/java/org/fdroid/fdroid/views/main/NearbyViewBinder.java @@ -96,26 +96,19 @@ public class NearbyViewBinder { } }); - if (Build.VERSION.SDK_INT >= 21) { - File[] dirs = activity.getExternalFilesDirs(""); - if (dirs != null) { - for (File dir : dirs) { - if (dir != null && Environment.isExternalStorageRemovable(dir)) { - String state = Environment.getExternalStorageState(dir); - if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) - || Environment.MEDIA_MOUNTED.equals(state)) { - // remove Android/data/org.fdroid.fdroid/files to get root - externalStorage = dir.getParentFile().getParentFile().getParentFile().getParentFile(); - break; - } + File[] dirs = activity.getExternalFilesDirs(""); + if (dirs != null) { + for (File dir : dirs) { + if (dir != null && Environment.isExternalStorageRemovable(dir)) { + String state = Environment.getExternalStorageState(dir); + if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) + || Environment.MEDIA_MOUNTED.equals(state)) { + // remove Android/data/org.fdroid.fdroid/files to get root + externalStorage = dir.getParentFile().getParentFile().getParentFile().getParentFile(); + break; } } } - } else if (Environment.isExternalStorageRemovable() && - (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY) - || Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))) { - Log.i(TAG, "<21 isExternalStorageRemovable MEDIA_MOUNTED"); - externalStorage = Environment.getExternalStorageDirectory(); } final String writeExternalStorage = Manifest.permission.WRITE_EXTERNAL_STORAGE; diff --git a/app/src/main/java/org/fdroid/fdroid/CompatibilityChecker.java b/app/src/main/java/org/fdroid/fdroid/CompatibilityChecker.java index c4ce98cd4..5447c79ac 100644 --- a/app/src/main/java/org/fdroid/fdroid/CompatibilityChecker.java +++ b/app/src/main/java/org/fdroid/fdroid/CompatibilityChecker.java @@ -5,7 +5,6 @@ import android.content.pm.FeatureInfo; import android.content.pm.PackageManager; import android.os.Build; -import org.fdroid.fdroid.compat.SupportedArchitectures; import org.fdroid.fdroid.data.Apk; import java.util.ArrayList; @@ -45,7 +44,7 @@ public class CompatibilityChecker { } } - cpuAbis = SupportedArchitectures.getAbis(); + cpuAbis = Build.SUPPORTED_ABIS; } private boolean compatibleApi(@Nullable String[] nativecode) { diff --git a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java index b0003624c..fdcdf359a 100644 --- a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java @@ -56,7 +56,6 @@ import org.fdroid.database.FDroidDatabase; import org.fdroid.database.Repository; import org.fdroid.fdroid.Preferences.ChangeListener; import org.fdroid.fdroid.Preferences.Theme; -import org.fdroid.fdroid.compat.PRNGFixes; import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.DBHelper; import org.fdroid.fdroid.installer.ApkFileProvider; @@ -327,24 +326,10 @@ public class FDroidApp extends Application implements androidx.work.Configuratio FDroidDatabase db = DBHelper.getDb(this); db.getRepositoryDao().getLiveRepositories().observeForever(repositories -> repos = repositories); - PRNGFixes.apply(); - applyTheme(); configureProxy(preferences); - - // bug specific to exactly 5.0 makes it only work with the old index - // which includes an ugly, hacky workaround - // https://gitlab.com/fdroid/fdroidclient/issues/1014 - if (Build.VERSION.SDK_INT == 21) { - preferences.setExpertMode(true); - preferences.setForceOldIndex(true); - } - - // TODO should not be needed anymore - //InstalledAppProviderService.compareToPackageManager(this); - // If the user changes the preference to do with filtering anti-feature apps, // it is easier to just notify a change in the app provider, // so that the newly updated list will correctly filter relevant apps. @@ -393,9 +378,7 @@ public class FDroidApp extends Application implements androidx.work.Configuratio if (!TextUtils.equals(packageName, unset)) { int modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - if (Build.VERSION.SDK_INT >= 19) { - modeFlags |= Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; - } + modeFlags |= Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; grantUriPermission(packageName, InstallHistoryService.LOG_URI, modeFlags); } diff --git a/app/src/main/java/org/fdroid/fdroid/Languages.java b/app/src/main/java/org/fdroid/fdroid/Languages.java index 8871c431d..e183e6b93 100644 --- a/app/src/main/java/org/fdroid/fdroid/Languages.java +++ b/app/src/main/java/org/fdroid/fdroid/Languages.java @@ -108,11 +108,7 @@ public final class Languages { final Resources resources = contextWrapper.getBaseContext().getResources(); Configuration config = resources.getConfiguration(); - if (Build.VERSION.SDK_INT >= 17) { - config.setLocale(locale); - } else { - config.locale = locale; - } + config.setLocale(locale); resources.updateConfiguration(config, resources.getDisplayMetrics()); } diff --git a/app/src/main/java/org/fdroid/fdroid/NfcHelper.java b/app/src/main/java/org/fdroid/fdroid/NfcHelper.java index 582ebcf9a..22b62884f 100644 --- a/app/src/main/java/org/fdroid/fdroid/NfcHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/NfcHelper.java @@ -8,7 +8,6 @@ import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; -import android.os.Build; import android.util.Log; import androidx.appcompat.app.AppCompatActivity; @@ -34,9 +33,6 @@ public class NfcHelper { @TargetApi(16) public static void setAndroidBeam(AppCompatActivity activity, String packageName) { - if (Build.VERSION.SDK_INT < 16) { - return; - } PackageManager pm = activity.getPackageManager(); NfcAdapter nfcAdapter = getAdapter(activity); if (nfcAdapter != null) { @@ -55,9 +51,6 @@ public class NfcHelper { @TargetApi(16) public static void disableAndroidBeam(AppCompatActivity activity) { - if (Build.VERSION.SDK_INT < 16) { - return; - } NfcAdapter nfcAdapter = getAdapter(activity); if (nfcAdapter != null) { nfcAdapter.setBeamPushUris(null, activity); diff --git a/app/src/main/java/org/fdroid/fdroid/NfcNotEnabledActivity.java b/app/src/main/java/org/fdroid/fdroid/NfcNotEnabledActivity.java index ebe97b3ba..826f7e5a3 100644 --- a/app/src/main/java/org/fdroid/fdroid/NfcNotEnabledActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/NfcNotEnabledActivity.java @@ -3,7 +3,6 @@ package org.fdroid.fdroid; import android.annotation.TargetApi; import android.content.Intent; import android.nfc.NfcAdapter; -import android.os.Build; import android.os.Bundle; import android.provider.Settings; @@ -32,12 +31,6 @@ public class NfcNotEnabledActivity extends AppCompatActivity { } } - // this API was added in 4.0 aka Ice Cream Sandwich - @TargetApi(14) - private void doOnIceCreamSandwich(Intent intent) { - intent.setAction(Settings.ACTION_NFCSHARING_SETTINGS); - } - @Override public void onCreate(Bundle savedInstanceState) { FDroidApp fdroidApp = (FDroidApp) getApplication(); @@ -46,11 +39,7 @@ public class NfcNotEnabledActivity extends AppCompatActivity { super.onCreate(savedInstanceState); final Intent intent = new Intent(); - if (Build.VERSION.SDK_INT >= 16) { - doOnJellybean(intent); - } else { - doOnIceCreamSandwich(intent); - } + doOnJellybean(intent); startActivity(intent); finish(); } diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index 825b2c10b..151a39bd2 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -18,9 +18,7 @@ package org.fdroid.fdroid; -import android.app.AlarmManager; import android.app.NotificationManager; -import android.app.PendingIntent; import android.app.job.JobInfo; import android.app.job.JobScheduler; import android.content.BroadcastReceiver; @@ -32,7 +30,6 @@ import android.content.IntentFilter; import android.net.Uri; import android.os.Build; import android.os.Process; -import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; @@ -173,43 +170,28 @@ public class UpdateService extends JobIntentService { interval != Preferences.UPDATE_INTERVAL_DISABLED && !(data == Preferences.OVER_NETWORK_NEVER && wifi == Preferences.OVER_NETWORK_NEVER); - if (Build.VERSION.SDK_INT < 21) { - Intent intent = new Intent(context, UpdateService.class); - PendingIntent pending = PendingIntent.getService(context, 0, intent, 0); - - AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - alarm.cancel(pending); - if (scheduleNewJob) { - alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, - SystemClock.elapsedRealtime() + 5000, interval, pending); - Utils.debugLog(TAG, "Update scheduler alarm set"); - } else { - Utils.debugLog(TAG, "Update scheduler alarm not set"); - } + Utils.debugLog(TAG, "Using android-21 JobScheduler for updates"); + JobScheduler jobScheduler = ContextCompat.getSystemService(context, JobScheduler.class); + ComponentName componentName = new ComponentName(context, UpdateJobService.class); + JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, componentName) + .setRequiresDeviceIdle(true) + .setPeriodic(interval); + if (Build.VERSION.SDK_INT >= 26) { + builder.setRequiresBatteryNotLow(true) + .setRequiresStorageNotLow(true); + } + if (data == Preferences.OVER_NETWORK_ALWAYS && wifi == Preferences.OVER_NETWORK_ALWAYS) { + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); } else { - Utils.debugLog(TAG, "Using android-21 JobScheduler for updates"); - JobScheduler jobScheduler = ContextCompat.getSystemService(context, JobScheduler.class); - ComponentName componentName = new ComponentName(context, UpdateJobService.class); - JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, componentName) - .setRequiresDeviceIdle(true) - .setPeriodic(interval); - if (Build.VERSION.SDK_INT >= 26) { - builder.setRequiresBatteryNotLow(true) - .setRequiresStorageNotLow(true); - } - if (data == Preferences.OVER_NETWORK_ALWAYS && wifi == Preferences.OVER_NETWORK_ALWAYS) { - builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); - } else { - builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); - } + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); + } - jobScheduler.cancel(JOB_ID); - if (scheduleNewJob) { - jobScheduler.schedule(builder.build()); - Utils.debugLog(TAG, "Update scheduler alarm set"); - } else { - Utils.debugLog(TAG, "Update scheduler alarm not set"); - } + jobScheduler.cancel(JOB_ID); + if (scheduleNewJob) { + jobScheduler.schedule(builder.build()); + Utils.debugLog(TAG, "Update scheduler alarm set"); + } else { + Utils.debugLog(TAG, "Update scheduler alarm not set"); } } diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index 2cf2ba541..f816d57b7 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -27,7 +27,6 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Rect; import android.net.Uri; -import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.StatFs; @@ -181,11 +180,7 @@ public final class Utils { return 50 * 1024 * 1024; // just return a minimal amount } StatFs stat = new StatFs(statDir.getPath()); - if (Build.VERSION.SDK_INT < 18) { - return (long) stat.getAvailableBlocks() * (long) stat.getBlockSize(); - } else { - return stat.getAvailableBlocksLong() * stat.getBlockSizeLong(); - } + return stat.getAvailableBlocksLong() * stat.getBlockSizeLong(); } public static long getImageCacheDirTotalMemory(Context context) { @@ -197,11 +192,7 @@ public final class Utils { return 100 * 1024 * 1024; // just return a minimal amount } StatFs stat = new StatFs(statDir.getPath()); - if (Build.VERSION.SDK_INT < 18) { - return (long) stat.getBlockCount() * (long) stat.getBlockSize(); - } else { - return stat.getBlockCountLong() * stat.getBlockSizeLong(); - } + return stat.getBlockCountLong() * stat.getBlockSizeLong(); } public static void copy(InputStream input, OutputStream output) throws IOException { diff --git a/app/src/main/java/org/fdroid/fdroid/compat/FileCompat.java b/app/src/main/java/org/fdroid/fdroid/compat/FileCompat.java index 215826779..154978f85 100644 --- a/app/src/main/java/org/fdroid/fdroid/compat/FileCompat.java +++ b/app/src/main/java/org/fdroid/fdroid/compat/FileCompat.java @@ -25,15 +25,7 @@ public class FileCompat { private static final String TAG = "FileCompat"; public static boolean symlink(SanitizedFile source, SanitizedFile dest) { - - if (Build.VERSION.SDK_INT >= 21) { - symlinkOs(source, dest); - } else if (Build.VERSION.SDK_INT >= 15) { - symlinkLibcore(source, dest); - } else { - symlinkRuntime(source, dest); - } - + symlinkOs(source, dest); return dest.exists(); } diff --git a/app/src/main/java/org/fdroid/fdroid/compat/PRNGFixes.java b/app/src/main/java/org/fdroid/fdroid/compat/PRNGFixes.java deleted file mode 100644 index a17770f8c..000000000 --- a/app/src/main/java/org/fdroid/fdroid/compat/PRNGFixes.java +++ /dev/null @@ -1,326 +0,0 @@ -package org.fdroid.fdroid.compat; - -/* - * This software is provided 'as-is', without any express or implied - * warranty. In no event will Google be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, as long as the origin is not misrepresented. - */ - -import android.annotation.SuppressLint; -import android.os.Build; -import android.os.Process; -import android.util.Log; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.SecureRandom; -import java.security.SecureRandomSpi; -import java.security.Security; - -/** - * Fixes for the output of the default PRNG having low entropy. - *

- * The fixes need to be applied via {@link #apply()} before any use of Java - * Cryptography Architecture primitives. A good place to invoke them is in the - * application's {@code onCreate}. - * - * @see Some SecureRandom Thoughts - */ -public final class PRNGFixes { - - private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = - getBuildFingerprintAndDeviceSerial(); - - /** - * Hidden constructor to prevent instantiation. - */ - private PRNGFixes() { - } - - /** - * Applies all fixes. - * - * @throws SecurityException if a fix is needed but could not be applied. - */ - public static void apply() { - applyOpenSSLFix(); - installLinuxPRNGSecureRandom(); - } - - /** - * Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the - * fix is not needed. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void applyOpenSSLFix() throws SecurityException { - if (Build.VERSION.SDK_INT < 16 || Build.VERSION.SDK_INT > 18) { - // No need to apply the fix - return; - } - - try { - // Mix in the device- and invocation-specific seed. - Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_seed", byte[].class) - .invoke(null, generateSeed()); - - // Mix output of Linux PRNG into OpenSSL's PRNG - int bytesRead = (Integer) Class.forName( - "org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_load_file", String.class, long.class) - .invoke(null, "/dev/urandom", 1024); - if (bytesRead != 1024) { - throw new IOException( - "Unexpected number of bytes read from Linux PRNG: " - + bytesRead); - } - } catch (Exception e) { - throw new SecurityException("Failed to seed OpenSSL PRNG", e); - } - } - - /** - * Installs a Linux PRNG-backed {@code SecureRandom} implementation as the - * default. Does nothing if the implementation is already the default or if - * there is not need to install the implementation. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void installLinuxPRNGSecureRandom() - throws SecurityException { - if (Build.VERSION.SDK_INT > 18) { - // No need to apply the fix - return; - } - - // Install a Linux PRNG-based SecureRandom implementation as the - // default, if not yet installed. - Provider[] secureRandomProviders = Security.getProviders("SecureRandom.SHA1PRNG"); - if (secureRandomProviders == null - || secureRandomProviders.length < 1 - || !LinuxPRNGSecureRandomProvider.class.equals(secureRandomProviders[0].getClass())) { - Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1); - } - - // Assert that new SecureRandom() and - // SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed - // by the Linux PRNG-based SecureRandom implementation. - SecureRandom rng1 = new SecureRandom(); - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng1.getProvider().getClass())) { - throw new SecurityException( - "new SecureRandom() backed by wrong Provider: " - + rng1.getProvider().getClass()); - } - - SecureRandom rng2; - try { - rng2 = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException("SHA1PRNG not available", e); - } - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng2.getProvider().getClass())) { - throw new SecurityException( - "SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong" - + " Provider: " + rng2.getProvider().getClass()); - } - } - - /** - * {@code Provider} of {@code SecureRandom} engines which pass through - * all requests to the Linux PRNG. - */ - @SuppressWarnings("serial") - private static class LinuxPRNGSecureRandomProvider extends Provider { - - LinuxPRNGSecureRandomProvider() { - super("LinuxPRNG", - 1.0, - "A Linux-specific random number provider that uses" - + " /dev/urandom"); - // Although /dev/urandom is not a SHA-1 PRNG, some apps - // explicitly request a SHA1PRNG SecureRandom and we thus need to - // prevent them from getting the default implementation whose output - // may have low entropy. - put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName()); - put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); - } - } - - /** - * {@link SecureRandomSpi} which passes all requests to the Linux PRNG - * ({@code /dev/urandom}). - */ - @SuppressWarnings("serial") - public static class LinuxPRNGSecureRandom extends SecureRandomSpi { - - private static final String TAG = "PRNGFixes"; - - /* - * IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed - * are passed through to the Linux PRNG (/dev/urandom). Instances of - * this class seed themselves by mixing in the current time, PID, UID, - * build fingerprint, and hardware serial number (where available) into - * Linux PRNG. - * - * Concurrency: Read requests to the underlying Linux PRNG are - * serialized (on S_LOCK) to ensure that multiple threads do not get - * duplicated PRNG output. - */ - - private static final File URANDOM_FILE = new File("/dev/urandom"); - - private static final Object S_LOCK = new Object(); - - /** - * Input stream for reading from Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("S_LOCK") - */ - private static DataInputStream sUrandomIn; - - /** - * Output stream for writing to Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("S_LOCK") - */ - private static OutputStream sUrandomOut; - - /** - * Whether this engine instance has been seeded. This is needed because - * each instance needs to seed itself if the client does not explicitly - * seed it. - */ - private boolean seeded; - - @Override - protected void engineSetSeed(byte[] bytes) { - try { - OutputStream out; - synchronized (S_LOCK) { - out = getUrandomOutputStream(); - } - out.write(bytes); - out.flush(); - } catch (IOException e) { - // On a small fraction of devices /dev/urandom is not writable. - // Log and ignore. - Log.w(TAG, "Failed to mix seed into " + URANDOM_FILE); - } finally { - seeded = true; - } - } - - @Override - protected void engineNextBytes(byte[] bytes) { - if (!seeded) { - // Mix in the device- and invocation-specific seed. - engineSetSeed(generateSeed()); - } - - try { - DataInputStream in; - synchronized (S_LOCK) { - in = getUrandomInputStream(); - } - synchronized (in) { - in.readFully(bytes); - } - } catch (IOException e) { - throw new SecurityException( - "Failed to read from " + URANDOM_FILE, e); - } - } - - @Override - protected byte[] engineGenerateSeed(int size) { - byte[] seed = new byte[size]; - engineNextBytes(seed); - return seed; - } - - private DataInputStream getUrandomInputStream() { - synchronized (S_LOCK) { - if (sUrandomIn == null) { - // NOTE: Consider inserting a BufferedInputStream between - // DataInputStream and FileInputStream if you need higher - // PRNG output performance and can live with future PRNG - // output being pulled into this process prematurely. - try { - sUrandomIn = new DataInputStream( - new FileInputStream(URANDOM_FILE)); - } catch (IOException e) { - throw new SecurityException("Failed to open " - + URANDOM_FILE + " for reading", e); - } - } - return sUrandomIn; - } - } - - private OutputStream getUrandomOutputStream() throws IOException { - synchronized (S_LOCK) { - if (sUrandomOut == null) { - sUrandomOut = new FileOutputStream(URANDOM_FILE); - } - return sUrandomOut; - } - } - } - - /** - * Generates a device- and invocation-specific seed to be mixed into the - * Linux PRNG. - */ - private static byte[] generateSeed() { - try { - ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream(); - DataOutputStream seedBufferOut = - new DataOutputStream(seedBuffer); - seedBufferOut.writeLong(System.currentTimeMillis()); - seedBufferOut.writeLong(System.nanoTime()); - seedBufferOut.writeInt(Process.myPid()); - seedBufferOut.writeInt(Process.myUid()); - seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL); - seedBufferOut.close(); - return seedBuffer.toByteArray(); - } catch (IOException e) { - throw new SecurityException("Failed to generate seed", e); - } - } - - @SuppressLint("HardwareIds") - private static byte[] getBuildFingerprintAndDeviceSerial() { - StringBuilder result = new StringBuilder(); - String fingerprint = Build.FINGERPRINT; - if (fingerprint != null) { - result.append(fingerprint); - } - String serial = Build.SERIAL; - if (serial != null) { - result.append(serial); - } - try { - return result.toString().getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 encoding not supported"); - } - } -} diff --git a/app/src/main/java/org/fdroid/fdroid/compat/SupportedArchitectures.java b/app/src/main/java/org/fdroid/fdroid/compat/SupportedArchitectures.java deleted file mode 100644 index 12ea456c1..000000000 --- a/app/src/main/java/org/fdroid/fdroid/compat/SupportedArchitectures.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.fdroid.fdroid.compat; - -import android.annotation.TargetApi; -import android.os.Build; - -public class SupportedArchitectures { - - /** - * The most preferred ABI is the first element in the list. - */ - @TargetApi(21) - @SuppressWarnings("deprecation") - public static String[] getAbis() { - if (Build.VERSION.SDK_INT >= 21) { - return Build.SUPPORTED_ABIS; - } - return new String[]{Build.CPU_ABI, Build.CPU_ABI2}; - } - -} diff --git a/app/src/main/java/org/fdroid/fdroid/data/Apk.java b/app/src/main/java/org/fdroid/fdroid/data/Apk.java index 107076486..0f05b850d 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Apk.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Apk.java @@ -441,17 +441,14 @@ public class Apk implements Comparable, Parcelable { set.add(versions.getName()); } } - if (Build.VERSION.SDK_INT >= 16 && set.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + if (set.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { set.add(Manifest.permission.READ_EXTERNAL_STORAGE); } if (Build.VERSION.SDK_INT >= 29) { if (set.contains(Manifest.permission.ACCESS_FINE_LOCATION)) { set.add(Manifest.permission.ACCESS_COARSE_LOCATION); } - if (targetSdkVersion >= 29) { - // Do nothing. The targetSdk for the below split-permissions is set to 29, - // so we don't make any changes for apps targetting 29 or above - } else { + if (targetSdkVersion < 29) { // TODO: Change the strings below to Manifest.permission once we target SDK 29. if (set.contains(Manifest.permission.ACCESS_FINE_LOCATION)) { set.add("android.permission.ACCESS_BACKGROUND_LOCATION"); @@ -463,12 +460,11 @@ public class Apk implements Comparable, Parcelable { set.add("android.permission.ACCESS_MEDIA_LOCATION"); } } + // Else do nothing. The targetSdk for the below split-permissions is set to 29, + // so we don't make any changes for apps targetting 29 or above } if (Build.VERSION.SDK_INT >= 31) { - if (targetSdkVersion >= 31) { - // Do nothing. The targetSdk for the below split-permissions is set to 31, - // so we don't make any changes for apps targetting 31 or above - } else { + if (targetSdkVersion < 31) { // TODO: Change the strings below to Manifest.permission once we target SDK 31. if (set.contains(Manifest.permission.BLUETOOTH) || set.contains(Manifest.permission.BLUETOOTH_ADMIN)) { @@ -477,6 +473,8 @@ public class Apk implements Comparable, Parcelable { set.add("android.permission.BLUETOOTH_ADVERTISE"); } } + // Else do nothing. The targetSdk for the below split-permissions is set to 31, + // so we don't make any changes for apps targetting 31 or above } requestedPermissions = set.toArray(new String[set.size()]); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java index e41df2a3c..89721b223 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/DefaultInstallerActivity.java @@ -99,13 +99,7 @@ public class DefaultInstallerActivity extends FragmentActivity { // works only when being installed as system-app // https://code.google.com/p/android/issues/detail?id=42253 - if (Build.VERSION.SDK_INT < 16) { - intent.setAction(Intent.ACTION_INSTALL_PACKAGE); - intent.setData(uri); - intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); - intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); - intent.putExtra(Intent.EXTRA_ALLOW_REPLACE, true); - } else if (Build.VERSION.SDK_INT < 24) { + if (Build.VERSION.SDK_INT < 24) { intent.setAction(Intent.ACTION_INSTALL_PACKAGE); intent.setData(uri); intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java index ea0ef4c55..9dd6ea136 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallerService.java @@ -23,7 +23,6 @@ package org.fdroid.fdroid.installer; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.Build; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.WildcardFileFilter; @@ -150,9 +149,7 @@ public class InstallerService extends JobIntentService { * @param apk {@link Apk} instance of the app that will be uninstalled */ public static void uninstall(Context context, @NonNull Apk apk) { - if (Build.VERSION.SDK_INT >= 19) { - Objects.requireNonNull(apk); - } + Objects.requireNonNull(apk); Installer.sendBroadcastUninstall(context, apk, Installer.ACTION_UNINSTALL_STARTED); diff --git a/app/src/main/java/org/fdroid/fdroid/net/ConnectivityMonitorService.java b/app/src/main/java/org/fdroid/fdroid/net/ConnectivityMonitorService.java index f819490c3..7cb372c97 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/ConnectivityMonitorService.java +++ b/app/src/main/java/org/fdroid/fdroid/net/ConnectivityMonitorService.java @@ -6,7 +6,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; @@ -27,8 +26,7 @@ import java.util.Enumeration; * unmetered internet available, based on * {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} *

- * {@link Build.VERSION_CODES#N Android 7.0} removed - * {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} so this will + * Android 7.0 removed {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} so this will * need to be totally changed to support that. * * @see Background Optimizations @@ -53,8 +51,7 @@ public class ConnectivityMonitorService extends JobIntentService { /** * Register the {@link BroadcastReceiver} which also starts this * {@code Service} since it is a sticky broadcast. This cannot be - * registered in the manifest, since {@link Build.VERSION_CODES#N Android 7.0} - * makes that not work. + * registered in the manifest, since Android 7.0 makes that not work. */ public static void registerAndStart(Context context) { context.registerReceiver(CONNECTIVITY_RECEIVER, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); @@ -85,7 +82,7 @@ public class ConnectivityMonitorService extends JobIntentService { } NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - if (activeNetwork == null && Build.VERSION.SDK_INT >= 21 && cm.getAllNetworks().length == 0) { + if (activeNetwork == null && cm.getAllNetworks().length == 0) { try { Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); while (networkInterfaces.hasMoreElements()) { diff --git a/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java b/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java index 758511269..727711799 100644 --- a/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java +++ b/app/src/main/java/org/fdroid/fdroid/privileged/views/AppSecurityPermissions.java @@ -29,7 +29,6 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.graphics.Color; import android.graphics.drawable.Drawable; -import android.os.Build; import android.os.Parcel; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -120,7 +119,7 @@ public class AppSecurityPermissions { public Drawable loadGroupIcon(Context context, PackageManager pm) { Drawable iconDrawable; if (icon != 0) { - iconDrawable = (Build.VERSION.SDK_INT < 22) ? loadIcon(pm) : loadUnbadgedIcon(pm); + iconDrawable = loadUnbadgedIcon(pm); } else { iconDrawable = ContextCompat.getDrawable(context, R.drawable.ic_perm_device_info); } @@ -264,9 +263,6 @@ public class AppSecurityPermissions { } private int[] getRequestedPermissionFlags(PackageInfo info) { - if (Build.VERSION.SDK_INT < 16) { - return new int[info.requestedPermissions.length]; - } return info.requestedPermissionsFlags; } @@ -347,7 +343,7 @@ public class AppSecurityPermissions { */ @TargetApi(16) private static boolean isNewPermission(PackageInfo installedPkgInfo, int existingFlags) { - if (installedPkgInfo == null || Build.VERSION.SDK_INT < 16) { + if (installedPkgInfo == null) { return false; } @@ -420,8 +416,7 @@ public class AppSecurityPermissions { private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) { PermissionItemView permView = (PermissionItemView) inflater.inflate( - Build.VERSION.SDK_INT >= 17 && - (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0 + (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0 ? R.layout.app_permission_item_money : R.layout.app_permission_item, null); permView.setPermission(grp, perm, first, newPermPrefix); diff --git a/app/src/main/java/org/fdroid/fdroid/qr/CameraCharacteristicsChecker.java b/app/src/main/java/org/fdroid/fdroid/qr/CameraCharacteristicsChecker.java index 3686dbe58..cd6480c27 100644 --- a/app/src/main/java/org/fdroid/fdroid/qr/CameraCharacteristicsChecker.java +++ b/app/src/main/java/org/fdroid/fdroid/qr/CameraCharacteristicsChecker.java @@ -4,11 +4,7 @@ import android.content.Context; public abstract class CameraCharacteristicsChecker { public static CameraCharacteristicsChecker getInstance(final Context context) { - if (android.os.Build.VERSION.SDK_INT >= 21) { - return new CameraCharacteristicsMinApiLevel21(context); - } else { - return new CameraCharacteristicsMaxApiLevel20(); - } + return new CameraCharacteristicsMinApiLevel21(context); } public abstract boolean hasAutofocus(); diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java index 094e601fd..b8038ad87 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsActivity.java @@ -34,7 +34,6 @@ import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; @@ -782,9 +781,6 @@ public class AppDetailsActivity extends AppCompatActivity private BluetoothAdapter getBluetoothAdapter() { // to use the new, recommended way of getting the adapter // http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html - if (Build.VERSION.SDK_INT < 18) { - return BluetoothAdapter.getDefaultAdapter(); - } return ContextCompat.getSystemService(this, BluetoothManager.class).getAdapter(); } diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java index 6e74a431b..aa2ae0afc 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java @@ -10,7 +10,6 @@ import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.Build; import android.text.Spannable; import android.text.Spanned; import android.text.TextUtils; @@ -615,22 +614,15 @@ public class AppDetailsRecyclerViewAdapter String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( FilenameUtils.getExtension(installedFile.getName())); viewIntent.setDataAndType(uri, mimeType); - if (Build.VERSION.SDK_INT < 19) { - viewIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } else { - viewIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION - | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); - } + viewIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); if (context.getPackageManager().queryIntentActivities(viewIntent, 0).size() > 0) { buttonPrimaryView.setText(R.string.menu_open); - buttonPrimaryView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - context.startActivity(viewIntent); - } catch (ActivityNotFoundException e) { - e.printStackTrace(); - } + buttonPrimaryView.setOnClickListener(v -> { + try { + context.startActivity(viewIntent); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); } }); } else { diff --git a/app/src/main/java/org/fdroid/fdroid/views/PreferencesFragment.java b/app/src/main/java/org/fdroid/fdroid/views/PreferencesFragment.java index c143049bc..1e0bb2c0a 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/PreferencesFragment.java +++ b/app/src/main/java/org/fdroid/fdroid/views/PreferencesFragment.java @@ -470,14 +470,12 @@ public class PreferencesFragment extends PreferenceFragmentCompat // by the time the user boots, opens F-Droid, and views this settings page, then there // is no benefit showing it to them (it will only be disabled and we can't offer any // way to easily install from here. - if (Build.VERSION.SDK_INT > 19 && !installed) { - if (pref != null) { - otherPrefGroup.removePreference(pref); - } + if (!installed) { + otherPrefGroup.removePreference(pref); } else { - pref.setEnabled(installed); - pref.setDefaultValue(installed); - pref.setChecked(enabled && installed); + pref.setEnabled(true); + pref.setDefaultValue(true); + pref.setChecked(enabled); pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override @@ -581,8 +579,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat if (updateIntervalPrevious != updateIntervalSeekBar.getValue()) { UpdateService.schedule(getActivity()); - } else if (Build.VERSION.SDK_INT >= 21 && - (overWifiPrevious != overWifiSeekBar.getValue() || overDataPrevious != overDataSeekBar.getValue())) { + } else if (overWifiPrevious != overWifiSeekBar.getValue() || overDataPrevious != overDataSeekBar.getValue()) { UpdateService.schedule(getActivity()); } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/RepoDetailsActivity.java b/app/src/main/java/org/fdroid/fdroid/views/RepoDetailsActivity.java index 54cb97fe5..20161129d 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/RepoDetailsActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/RepoDetailsActivity.java @@ -9,7 +9,6 @@ import android.content.IntentFilter; import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NfcAdapter; -import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.text.TextUtils; @@ -296,11 +295,7 @@ public class RepoDetailsActivity extends AppCompatActivity { } boolean needsEnableNfcMenuItem; - if (Build.VERSION.SDK_INT < 16) { - needsEnableNfcMenuItem = !nfcAdapter.isEnabled(); - } else { - needsEnableNfcMenuItem = !nfcAdapter.isNdefPushEnabled(); - } + needsEnableNfcMenuItem = !nfcAdapter.isNdefPushEnabled(); menuItem.setVisible(needsEnableNfcMenuItem); } diff --git a/app/src/main/java/org/fdroid/fdroid/views/SeekBarForegroundThumb.java b/app/src/main/java/org/fdroid/fdroid/views/SeekBarForegroundThumb.java index fcd483a51..84b2627f1 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/SeekBarForegroundThumb.java +++ b/app/src/main/java/org/fdroid/fdroid/views/SeekBarForegroundThumb.java @@ -3,7 +3,6 @@ package org.fdroid.fdroid.views; import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; -import android.os.Build; import android.util.AttributeSet; import org.fdroid.fdroid.R; @@ -17,7 +16,6 @@ import androidx.core.content.ContextCompat; */ public class SeekBarForegroundThumb extends AppCompatSeekBar { private Drawable tickMark; - private Context context; public SeekBarForegroundThumb(Context context) { super(context); @@ -35,18 +33,9 @@ public class SeekBarForegroundThumb extends AppCompatSeekBar { } private void init(Context context) { - this.context = context; tickMark = ContextCompat.getDrawable(context, R.drawable.seekbar_tickmark); } - private Drawable getThumbCompat() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - return getThumb(); - } else { - return context.getResources().getDrawable(R.drawable.seekbar_thumb); - } - } - @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -59,7 +48,7 @@ public class SeekBarForegroundThumb extends AppCompatSeekBar { if (count > 1) { final int w = tickMark.getIntrinsicWidth(); final int h = tickMark.getIntrinsicHeight(); - final int halfThumbW = getThumbCompat().getIntrinsicWidth() / 2; + final int halfThumbW = getThumb().getIntrinsicWidth() / 2; final int halfW = w >= 0 ? w / 2 : 1; final int halfH = h >= 0 ? h / 2 : 1; tickMark.setBounds(-halfW, -halfH, halfW, halfH); diff --git a/app/src/main/java/org/fdroid/fdroid/views/appdetails/AntiFeaturesListingView.java b/app/src/main/java/org/fdroid/fdroid/views/appdetails/AntiFeaturesListingView.java index 984034a77..e88c25ebf 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/appdetails/AntiFeaturesListingView.java +++ b/app/src/main/java/org/fdroid/fdroid/views/appdetails/AntiFeaturesListingView.java @@ -21,7 +21,6 @@ package org.fdroid.fdroid.views.appdetails; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -79,11 +78,7 @@ public class AntiFeaturesListingView extends RecyclerView { @Override public void onClick(View v) { Intent i = new Intent(Intent.ACTION_VIEW); - if (Build.VERSION.SDK_INT >= 21) { - i.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); - } else { - i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - } + i.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); i.setData(Uri.parse("https://f-droid.org/docs/Anti-Features#" + antiFeatureName)); getContext().startActivity(i); } diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java index 86e3fbe5a..06df5fde2 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListItemController.java @@ -8,7 +8,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.graphics.Outline; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -137,24 +136,22 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder { } }); - if (Build.VERSION.SDK_INT >= 21) { - installButton.setOutlineProvider(new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - float density = activity.getResources().getDisplayMetrics().density; + installButton.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + float density = activity.getResources().getDisplayMetrics().density; - // This is a bit hacky/hardcoded/too-specific to the particular icons we're using. - // This is because the default "download & install" and "downloaded & ready to install" - // icons are smaller than the "downloading progress" button. Hence, we can't just use - // the width/height of the view to calculate the outline size. - int xPadding = (int) (8 * density); - int yPadding = (int) (9 * density); - int right = installButton.getWidth() - xPadding; - int bottom = installButton.getHeight() - yPadding; - outline.setOval(xPadding, yPadding, right, bottom); - } - }); - } + // This is a bit hacky/hardcoded/too-specific to the particular icons we're using. + // This is because the default "download & install" and "downloaded & ready to install" + // icons are smaller than the "downloading progress" button. Hence, we can't just use + // the width/height of the view to calculate the outline size. + int xPadding = (int) (8 * density); + int yPadding = (int) (9 * density); + int right = installButton.getWidth() - xPadding; + int bottom = installButton.getHeight() - yPadding; + outline.setOval(xPadding, yPadding, right, bottom); + } + }); } icon = (ImageView) itemView.findViewById(R.id.icon); diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/CategoryTextWatcher.java b/app/src/main/java/org/fdroid/fdroid/views/apps/CategoryTextWatcher.java index e55592913..3beca0450 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/CategoryTextWatcher.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/CategoryTextWatcher.java @@ -2,7 +2,6 @@ package org.fdroid.fdroid.views.apps; import android.annotation.TargetApi; import android.content.Context; -import android.os.Build; import android.text.Editable; import android.text.Spanned; import android.text.TextWatcher; @@ -132,23 +131,19 @@ public class CategoryTextWatcher implements TextWatcher { } removeSpans(textToSpannify, CategorySpan.class); - if (Build.VERSION.SDK_INT >= 21) { - removeSpans(textToSpannify, TtsSpan.class); - } + removeSpans(textToSpannify, TtsSpan.class); int colonIndex = textToSpannify.toString().indexOf(':'); if (colonIndex > 0) { CategorySpan span = new CategorySpan(context); textToSpannify.setSpan(span, 0, colonIndex + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - if (Build.VERSION.SDK_INT >= 21) { - // For accessibility reasons, make this more clear to screen readers that the - // span we just added semantically represents a category. - CharSequence categoryName = textToSpannify.subSequence(0, colonIndex); - TtsSpan ttsSpan = new TtsSpan.TextBuilder(context.getString(R.string.tts_category_name, - categoryName)).build(); - textToSpannify.setSpan(ttsSpan, 0, 0, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } + // For accessibility reasons, make this more clear to screen readers that the + // span we just added semantically represents a category. + CharSequence categoryName = textToSpannify.subSequence(0, colonIndex); + TtsSpan ttsSpan = new TtsSpan.TextBuilder(context.getString(R.string.tts_category_name, + categoryName)).build(); + textToSpannify.setSpan(ttsSpan, 0, 0, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index 74b7315a6..6425b67a7 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -26,10 +26,8 @@ import android.app.SearchManager; import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.text.TextUtils; -import android.view.ViewGroup; import android.widget.Toast; import androidx.annotation.NonNull; @@ -111,13 +109,6 @@ public class MainActivity extends AppCompatActivity { pager.setLayoutManager(new NonScrollingHorizontalLayoutManager(this)); pager.setAdapter(adapter); - // Without this, the focus is completely busted on pre 15 devices. Trying to use them - // without this ends up with each child view showing for a fraction of a second, then - // reverting back to the "Latest" screen again, in completely non-deterministic ways. - if (Build.VERSION.SDK_INT <= 15) { - pager.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); - } - bottomNavigation = (BottomNavigationView) findViewById(R.id.bottom_navigation); bottomNavigation.setOnNavigationItemSelectedListener(item -> { pager.scrollToPosition(item.getOrder()); diff --git a/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java b/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java index dafedf0ee..392884015 100644 --- a/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java +++ b/app/src/main/java/org/fdroid/fdroid/work/CleanCacheWorker.java @@ -7,7 +7,6 @@ import android.system.ErrnoException; import android.system.Os; import android.system.StructStat; -import org.apache.commons.io.FileUtils; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.installer.ApkCache; @@ -208,10 +207,6 @@ public class CleanCacheWorker extends Worker { clearOldFiles(file, millisAgo); } deleteFileAndLog(f); - } else if (Build.VERSION.SDK_INT <= 21) { - if (FileUtils.isFileOlder(f, olderThan)) { - deleteFileAndLog(f); - } } else { Impl21.deleteIfOld(f, olderThan); } diff --git a/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java b/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java index 9cd99b789..5a3254a5c 100644 --- a/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java +++ b/app/src/main/java/org/fdroid/fdroid/work/FDroidMetricsWorker.java @@ -50,7 +50,6 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Objects; -import java.util.Random; import java.util.concurrent.TimeUnit; import androidx.annotation.NonNull; @@ -251,9 +250,7 @@ public class FDroidMetricsWorker extends Worker { EVENTS.add(getDeviceEvent(weekStart, "isPrivilegedInstallerEnabled", Preferences.get().isPrivilegedInstallerEnabled())); EVENTS.add(getDeviceEvent(weekStart, "Build.VERSION.SDK_INT", Build.VERSION.SDK_INT)); - if (Build.VERSION.SDK_INT >= 21) { - EVENTS.add(getDeviceEvent(weekStart, "Build.SUPPORTED_ABIS", Arrays.toString(Build.SUPPORTED_ABIS))); - } + EVENTS.add(getDeviceEvent(weekStart, "Build.SUPPORTED_ABIS", Arrays.toString(Build.SUPPORTED_ABIS))); for (PackageInfo packageInfo : packageInfoList) { if (isTimestampInReportingWeek(weekStart, packageInfo.firstInstallTime)) { @@ -425,11 +422,7 @@ public class FDroidMetricsWorker extends Worker { @Override public int hashCode() { - if (Build.VERSION.SDK_INT >= 19) { - return Objects.hash(applicationId, versionCode, action); - } else { - return new Random().nextInt(); // quick kludge - } + return Objects.hash(applicationId, versionCode, action); } @Override