Clear out checks for SDK < 23 as they're no longer relevant.

This commit is contained in:
Alex Hart
2025-10-31 12:50:47 -03:00
committed by Michelle Tang
parent ab9c8626c0
commit 1d7ae669b6
57 changed files with 137 additions and 387 deletions

View File

@@ -38,11 +38,7 @@ class BiometricDeviceAuthentication(
}
private fun isDeviceSecure(context: Context): Boolean {
return if (Build.VERSION.SDK_INT > 23) {
ServiceUtil.getKeyguardManager(context).isDeviceSecure
} else {
ServiceUtil.getKeyguardManager(context).isKeyguardSecure
}
return ServiceUtil.getKeyguardManager(context).isDeviceSecure
}
/**

View File

@@ -29,9 +29,11 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.BoxWithConstraintsScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.displayCutoutPadding
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material3.MaterialTheme
@@ -125,7 +127,6 @@ import org.thoughtcrime.securesms.main.MainToolbarMode
import org.thoughtcrime.securesms.main.MainToolbarState
import org.thoughtcrime.securesms.main.MainToolbarViewModel
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder
import org.thoughtcrime.securesms.main.NavigationBarSpacerCompat
import org.thoughtcrime.securesms.main.SnackbarState
import org.thoughtcrime.securesms.main.callNavGraphBuilder
import org.thoughtcrime.securesms.main.chatNavGraphBuilder
@@ -514,7 +515,7 @@ class MainActivity : PassphraseRequiredActivity(), VoiceNoteMediaControllerOwner
)
if (!windowSizeClass.isSplitPane()) {
NavigationBarSpacerCompat()
Spacer(Modifier.navigationBarsPadding())
}
}
}

View File

@@ -7,7 +7,6 @@ package org.thoughtcrime.securesms.attachments
import android.content.Context
import android.graphics.Bitmap
import android.os.Build
import org.signal.core.util.logging.Log
import org.signal.core.util.mebiBytes
import org.signal.protos.resumableuploads.ResumableUpload
@@ -93,11 +92,6 @@ object AttachmentUploadUtil {
return attachment.blurHash.hash
}
if (Build.VERSION.SDK_INT < 23) {
Log.w(TAG, "Video thumbnails not supported...")
return null
}
return MediaUtil.getVideoThumbnail(context, Objects.requireNonNull(attachment.uri), 1000)?.let { bitmap ->
val thumb = Bitmap.createScaledBitmap(bitmap, 100, 100, false)
bitmap.recycle()

View File

@@ -4,7 +4,6 @@ import android.content.Context
import android.net.Uri
import android.util.LruCache
import androidx.annotation.AnyThread
import androidx.annotation.RequiresApi
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import io.reactivex.rxjava3.subjects.SingleSubject
@@ -24,7 +23,6 @@ import kotlin.concurrent.write
*
* Maintains an in-memory cache of recently requested wave forms.
*/
@RequiresApi(23)
object AudioWaveForms {
private val TAG = Log.tag(AudioWaveForms::class.java)

View File

@@ -10,7 +10,6 @@ import android.content.res.ColorStateList
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.Build
import androidx.core.content.ContextCompat
import com.airbnb.lottie.SimpleColorFilter
import com.google.android.material.shape.MaterialShapeDrawable
@@ -58,9 +57,7 @@ class FallbackAvatarDrawable(
)
resourceIcon.bounds = iconBounds
if (Build.VERSION.SDK_INT >= 23) {
resourceIcon.setLayoutDirection(layoutDirection)
}
resourceIcon
}

View File

@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.backup;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -24,8 +23,8 @@ public final class BackupPassphrase {
String passphrase = TextSecurePreferences.getBackupPassphrase(context);
String encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context);
if (Build.VERSION.SDK_INT < 23 || (passphrase == null && encryptedPassphrase == null)) {
return stripSpaces(passphrase);
if (passphrase == null && encryptedPassphrase == null) {
return null;
}
if (encryptedPassphrase == null) {
@@ -40,8 +39,8 @@ public final class BackupPassphrase {
}
public static void set(@NonNull Context context, @Nullable String passphrase) {
if (passphrase == null || Build.VERSION.SDK_INT < 23) {
TextSecurePreferences.setBackupPassphrase(context, passphrase);
if (passphrase == null) {
TextSecurePreferences.setBackupPassphrase(context, null);
TextSecurePreferences.setEncryptedBackupPassphrase(context, null);
} else {
KeyStoreHelper.SealedData encryptedPassphrase = KeyStoreHelper.seal(passphrase.getBytes());

View File

@@ -6,7 +6,6 @@
package org.thoughtcrime.securesms.banner.banners
import android.content.Context
import android.os.Build
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
@@ -27,17 +26,13 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
class DozeBanner(private val context: Context, private val onDismissListener: () -> Unit) : Banner<Unit>() {
override val enabled: Boolean
get() = Build.VERSION.SDK_INT >= 23 && !SignalStore.account.fcmEnabled && !TextSecurePreferences.hasPromptedOptimizeDoze(context) && !ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.packageName)
get() = !SignalStore.account.fcmEnabled && !TextSecurePreferences.hasPromptedOptimizeDoze(context) && !ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.packageName)
override val dataFlow: Flow<Unit>
get() = flowOf(Unit)
@Composable
override fun DisplayBanner(model: Unit, contentPadding: PaddingValues) {
if (Build.VERSION.SDK_INT < 23) {
throw IllegalStateException("Showing a Doze banner for an OS prior to Android 6.0")
}
Banner(
contentPadding = contentPadding,
onDismissListener = {

View File

@@ -219,7 +219,6 @@ public final class AudioView extends FrameLayout {
if (seekBar instanceof WaveFormSeekBarView) {
WaveFormSeekBarView waveFormView = (WaveFormSeekBarView) seekBar;
waveFormView.setColors(waveFormPlayedBarsColor, waveFormUnplayedBarsColor, waveFormThumbTint);
if (android.os.Build.VERSION.SDK_INT >= 23) {
if (audioSlide == null || !Objects.equals(audioSlide.getUri(), audio.getUri())) {
disposable.dispose();
disposable = AudioWaveForms.getWaveForm(getContext(), audio.asAttachment())
@@ -236,12 +235,6 @@ public final class AudioView extends FrameLayout {
t -> waveFormView.setWaveMode(false)
);
}
} else {
waveFormView.setWaveMode(false);
if (duration != null) {
duration.setVisibility(GONE);
}
}
}
if (forceHideDuration && duration != null) {

View File

@@ -18,7 +18,6 @@ import androidx.lifecycle.Lifecycle
import org.signal.core.util.concurrent.LifecycleDisposable
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.DebugLogsPromptDialogFragment.Purpose.entries
import org.thoughtcrime.securesms.databinding.PromptLogsBottomSheetBinding
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -159,11 +158,7 @@ class DebugLogsPromptDialogFragment : FixedRoundedCornerBottomSheetDialogFragmen
}
private fun batteryOptimizationsString(): String {
return if (Build.VERSION.SDK_INT < 23) {
"N/A (API < 23)"
} else {
PowerManagerCompat.isIgnoringBatteryOptimizations(requireContext()).toString()
}
return PowerManagerCompat.isIgnoringBatteryOptimizations(requireContext()).toString()
}
private fun backgroundRestrictedString(): String {

View File

@@ -135,7 +135,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
rotation = getDeviceRotation();
if (Build.VERSION.SDK_INT >= 23 && getRootWindowInsets() != null) {
if (getRootWindowInsets() != null) {
int bottomInset;
WindowInsets windowInsets = getRootWindowInsets();

View File

@@ -9,7 +9,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentManager
@@ -23,7 +22,6 @@ import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.LocalMetrics
import org.thoughtcrime.securesms.util.PowerManagerCompat
@RequiresApi(23)
class PromptBatterySaverDialogFragment : FixedRoundedCornerBottomSheetDialogFragment() {
companion object {

View File

@@ -604,9 +604,7 @@ public class ThumbnailView extends FrameLayout {
.downsample(SignalDownsampleStrategy.CENTER_OUTSIDE_NO_UPSCALE)
.transition(withCrossFade()));
boolean doNotShowMissingThumbnailImage = Build.VERSION.SDK_INT < 23;
if (slide.isInProgress() || doNotShowMissingThumbnailImage) {
if (slide.isInProgress()) {
return requestBuilder;
} else {
return requestBuilder.apply(RequestOptions.errorOf(R.drawable.missing_thumbnail));

View File

@@ -117,15 +117,11 @@ public class EmojiEditText extends AppCompatEditText {
if (clipData != null) {
CharSequence label = clipData.getDescription().getLabel();
CharSequence pendingPaste = getTextFromClipData(clipData);
if (TextUtils.equals(Util.COPY_LABEL, label) && shouldPersistSignalStylingWhenPasting()) {
return super.onTextContextMenuItem(id);
} else if (Build.VERSION.SDK_INT >= 23) {
} else {
return super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
} else if (pendingPaste != null) {
Util.copyToClipboard(getContext(), pendingPaste.toString());
return super.onTextContextMenuItem(id);
}
}
} else if (id == android.R.id.copy || id == android.R.id.cut) {

View File

@@ -10,7 +10,6 @@ import android.widget.Toast
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
@@ -238,7 +237,6 @@ open class DefaultNotificationsSettingsCallbacks(
viewModel.setMessageNotificationPrivacy(selection)
}
@RequiresApi(23)
override fun onTroubleshootNotificationsClick() {
PromptBatterySaverDialogFragment.show(activity.supportFragmentManager)
}

View File

@@ -6,7 +6,6 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
@@ -106,7 +105,7 @@ object DonationErrorNotifications {
context,
0,
actionIntent,
if (Build.VERSION.SDK_INT >= 23) PendingIntentFlags.oneShot() else PendingIntentFlags.mutable()
PendingIntentFlags.oneShot()
)
}
)

View File

@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.crypto;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
@@ -60,9 +59,6 @@ public class AttachmentSecretProvider {
{
AttachmentSecret attachmentSecret = AttachmentSecret.fromString(unencryptedSecret);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return attachmentSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
@@ -70,16 +66,11 @@ public class AttachmentSecretProvider {
return attachmentSecret;
}
}
private AttachmentSecret getEncryptedAttachmentSecret(@NonNull String serializedEncryptedSecret) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret)));
}
}
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
SecureRandom random = new SecureRandom();
@@ -93,12 +84,7 @@ public class AttachmentSecretProvider {
}
private void storeAttachmentSecret(@NonNull Context context, @NonNull AttachmentSecret attachmentSecret) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setAttachmentUnencryptedSecret(context, attachmentSecret.serialize());
}
}
}

View File

@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.crypto;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
@@ -48,29 +47,21 @@ public final class DatabaseSecretProvider {
try {
DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret);
if (Build.VERSION.SDK_INT < 23) {
return databaseSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
TextSecurePreferences.setDatabaseUnencryptedSecret(context, null);
return databaseSecret;
}
} catch (IOException e) {
throw new AssertionError(e);
}
}
private static @NonNull DatabaseSecret getEncryptedDatabaseSecret(@NonNull String serializedEncryptedSecret) {
if (Build.VERSION.SDK_INT < 23) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret));
}
}
private static @NonNull DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
SecureRandom random = new SecureRandom();
@@ -79,12 +70,8 @@ public final class DatabaseSecretProvider {
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
if (Build.VERSION.SDK_INT >= 23) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setDatabaseUnencryptedSecret(context, databaseSecret.asString());
}
return databaseSecret;
}

View File

@@ -51,7 +51,6 @@ public final class KeyStoreHelper {
private static final String KEY_ALIAS = "SignalSecret";
private static final Executor executor = Executors.newSingleThreadExecutor();
@RequiresApi(23)
public static SealedData seal(@NonNull byte[] input) {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<SealedData> result = new AtomicReference<>();
@@ -83,7 +82,6 @@ public final class KeyStoreHelper {
return result.get();
}
@RequiresApi(23)
public static byte[] unseal(@NonNull SealedData sealedData) {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<byte[]> result = new AtomicReference<>();

View File

@@ -22,7 +22,6 @@ import android.database.Cursor
import android.media.MediaDataSource
import android.os.Parcelable
import android.text.TextUtils
import androidx.annotation.RequiresApi
import androidx.annotation.VisibleForTesting
import androidx.annotation.WorkerThread
import androidx.core.content.contentValuesOf
@@ -2150,7 +2149,6 @@ class AttachmentTable(
.run()
}
@RequiresApi(23)
fun mediaDataSourceFor(attachmentId: AttachmentId, allowReadingFromTempFile: Boolean): MediaDataSource? {
val dataInfo = getDataFileInfo(attachmentId)
if (dataInfo != null) {

View File

@@ -5,7 +5,6 @@
package org.thoughtcrime.securesms.jobs
import android.os.Build
import org.signal.core.util.logging.Log
import org.signal.protos.resumableuploads.ResumableUpload
import org.thoughtcrime.securesms.attachments.AttachmentId
@@ -263,7 +262,7 @@ class ArchiveThumbnailUploadJob private constructor(
return if (MediaUtil.isImageType(attachment.contentType)) {
compress(uri, attachment.contentType ?: "")
} else if (Build.VERSION.SDK_INT >= 23 && MediaUtil.isVideoType(attachment.contentType)) {
} else if (MediaUtil.isVideoType(attachment.contentType)) {
MediaUtil.getVideoThumbnail(context, attachment.uri)?.let {
compress(uri, attachment.contentType ?: "")
}

View File

@@ -1,7 +1,5 @@
package org.thoughtcrime.securesms.jobs
import android.os.Build
import androidx.annotation.RequiresApi
import org.signal.core.util.concurrent.safeBlockingGet
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.attachments.AttachmentId
@@ -28,13 +26,9 @@ class GenerateAudioWaveFormJob private constructor(private val attachmentId: Att
@JvmStatic
fun enqueue(attachmentId: AttachmentId) {
if (Build.VERSION.SDK_INT < 23) {
Log.i(TAG, "Unable to generate waveform on this version of Android")
} else {
AppDependencies.jobManager.add(GenerateAudioWaveFormJob(attachmentId))
}
}
}
private constructor(attachmentId: AttachmentId) : this(
attachmentId,
@@ -53,7 +47,6 @@ class GenerateAudioWaveFormJob private constructor(private val attachmentId: Att
override fun getFactoryKey(): String = KEY
@RequiresApi(23)
override fun onRun() {
val attachment: DatabaseAttachment? = SignalDatabase.attachments.getAttachment(attachmentId)

View File

@@ -1,12 +1,11 @@
package org.thoughtcrime.securesms.logging;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.KeyStoreHelper;
import org.signal.core.util.Base64;
import org.thoughtcrime.securesms.crypto.KeyStoreHelper;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.io.IOException;
@@ -32,12 +31,8 @@ public class LogSecretProvider {
}
private static byte[] parseEncryptedSecret(String secret) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret);
return KeyStoreHelper.unseal(encryptedSecret);
} else {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
}
}
private static byte[] createAndStoreSecret(@NonNull Context context) {
@@ -45,12 +40,8 @@ public class LogSecretProvider {
byte[] secret = new byte[32];
random.nextBytes(secret);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setLogUnencryptedSecret(context, Base64.encodeWithPadding(secret));
}
return secret;
}

View File

@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.logsubmit
import android.content.Context
import android.os.Build
import org.signal.core.util.MemoryTracker
import org.signal.core.util.bytes
import org.signal.core.util.kibiBytes
@@ -28,7 +27,6 @@ class LogSectionMemory : LogSection {
Low Memory? : ${nativeMemory.lowMemory}
""".trimIndent()
if (Build.VERSION.SDK_INT >= 23) {
val detailedMemory = MemoryTracker.getDetailedMemoryStats()
base += "\n\n"
@@ -41,7 +39,6 @@ class LogSectionMemory : LogSection {
Stack Usage : ${detailedMemory.stackUsageKb?.kbDisplay()}
Other Usage : ${detailedMemory.appOtherUsageKb?.kbDisplay()}
""".trimIndent()
}
return base
}

View File

@@ -1,32 +0,0 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.main
import android.os.Build
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import org.signal.core.util.DimensionUnit
import org.thoughtcrime.securesms.util.ViewUtil
@Composable
fun NavigationBarSpacerCompat() {
if (Build.VERSION.SDK_INT >= 23) {
Spacer(Modifier.navigationBarsPadding())
} else {
val resources = LocalContext.current.resources
val navigationBarHeight = remember(resources) {
DimensionUnit.PIXELS.toDp(ViewUtil.getNavigationBarHeight(resources).toFloat()).dp
}
Spacer(Modifier.height(navigationBarHeight))
}
}

View File

@@ -1,14 +1,12 @@
package org.thoughtcrime.securesms.mediasend
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import org.signal.core.util.logging.Log
@@ -161,7 +159,6 @@ class VideoEditorFragment : Fragment(), PositionDragListener, MediaSendPageFragm
}
}
@RequiresApi(23)
private fun bindVideoTimeline(data: VideoTrimData) {
val autoplay = isVideoGif
val slide = VideoSlide(requireContext(), uri, 0, autoplay)
@@ -213,11 +210,9 @@ class VideoEditorFragment : Fragment(), PositionDragListener, MediaSendPageFragm
}
private fun startPositionUpdates() {
if (Build.VERSION.SDK_INT >= 23) {
stopPositionUpdates()
handler.post(updatePosition)
}
}
private fun stopPositionUpdates() {
handler.removeCallbacks(updatePosition)
@@ -250,7 +245,6 @@ class VideoEditorFragment : Fragment(), PositionDragListener, MediaSendPageFragm
hud.showPlayButton()
}
@RequiresApi(23)
private fun onEditVideoDuration(data: VideoTrimData, editingComplete: Boolean) {
if (editingComplete) {
isInEdit = false

View File

@@ -19,7 +19,6 @@ package org.thoughtcrime.securesms.mms;
import android.content.Context;
import android.content.res.Resources.Theme;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
@@ -56,7 +55,7 @@ public class VideoSlide extends Slide {
@Override
public boolean hasPlayOverlay() {
return !(isVideoGif() && GiphyMp4PlaybackPolicy.autoplay()) || Build.VERSION.SDK_INT < 23;
return !(isVideoGif() && GiphyMp4PlaybackPolicy.autoplay());
}
@Override

View File

@@ -9,14 +9,13 @@ import android.os.Build;
import android.provider.ContactsContract;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.WorkerThread;
import org.signal.core.util.CursorUtil;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.signal.core.util.CursorUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
import java.util.concurrent.TimeUnit;
@@ -31,8 +30,6 @@ public final class DoNotDisturbUtil {
@WorkerThread
@SuppressLint("SwitchIntDef")
public static boolean shouldDisturbUserWithCall(@NonNull Context context) {
if (Build.VERSION.SDK_INT <= 23) return true;
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
switch (notificationManager.getCurrentInterruptionFilter()) {
@@ -47,8 +44,6 @@ public final class DoNotDisturbUtil {
@WorkerThread
@SuppressLint("SwitchIntDef")
public static boolean shouldDisturbUserWithCall(@NonNull Context context, @NonNull Recipient recipient) {
if (Build.VERSION.SDK_INT <= 23) return true;
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
switch (notificationManager.getCurrentInterruptionFilter()) {
@@ -65,7 +60,6 @@ public final class DoNotDisturbUtil {
}
}
@RequiresApi(23)
private static boolean handlePriority(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Recipient recipient) {
if (Build.VERSION.SDK_INT < 28 && !notificationManager.isNotificationPolicyAccessGranted()) {
Log.w(TAG, "Notification Policy is not granted");

View File

@@ -14,8 +14,8 @@ import com.annimon.stream.Stream;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.notifications.v2.DefaultMessageNotifier;
import org.thoughtcrime.securesms.notifications.v2.ConversationId;
import org.thoughtcrime.securesms.notifications.v2.DefaultMessageNotifier;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.BubbleUtil;
import org.thoughtcrime.securesms.util.ConversationUtil;
@@ -53,7 +53,6 @@ public final class NotificationCancellationHelper {
* bubble notifications that do not have unread messages in them.
*/
public static void cancelAllMessageNotifications(@NonNull Context context, @NonNull Set<Integer> stickyNotifications) {
if (Build.VERSION.SDK_INT >= 23) {
try {
NotificationManager notifications = ServiceUtil.getNotificationManager(context);
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
@@ -76,9 +75,6 @@ public final class NotificationCancellationHelper {
Log.w(TAG, "Canceling all notifications.", e);
ServiceUtil.getNotificationManager(context).cancelAll();
}
} else {
cancelLegacy(context, NotificationIds.MESSAGE_SUMMARY);
}
}
public static void cancelMessageSummaryIfSoleNotification(@NonNull Context context) {
@@ -110,7 +106,6 @@ public final class NotificationCancellationHelper {
/**
* @return whether this is a non-summary notification that is a member of the NOTIFICATION_GROUP group.
*/
@RequiresApi(23)
private static boolean isSingleThreadNotification(@NonNull StatusBarNotification statusBarNotification) {
return statusBarNotification.getId() != NotificationIds.MESSAGE_SUMMARY &&
Objects.equals(statusBarNotification.getNotification().getGroup(), DefaultMessageNotifier.NOTIFICATION_GROUP);

View File

@@ -5,7 +5,6 @@
package org.thoughtcrime.securesms.notifications
import android.os.Build
import android.text.TextUtils
import androidx.annotation.WorkerThread
import org.signal.core.util.logging.Log
@@ -76,10 +75,6 @@ object SlowNotificationHeuristics {
@JvmStatic
fun shouldPromptBatterySaver(): Boolean {
if (Build.VERSION.SDK_INT < 23) {
return false
}
val remoteEnabled = LocaleRemoteConfig.isBatterySaverPromptEnabled() || LocaleRemoteConfig.isDelayedNotificationPromptEnabled()
if (!remoteEnabled || SignalStore.uiHints.hasDismissedBatterySaverPrompt()) {
return false

View File

@@ -6,7 +6,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.view.Display;
@@ -16,7 +15,6 @@ import android.view.WindowManager;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
@@ -52,10 +50,6 @@ public class Permissions {
return new PermissionsBuilder(new FragmentPermissionObject(fragment));
}
public static boolean isRuntimePermissionsRequired() {
return Build.VERSION.SDK_INT >= 23;
}
public static class PermissionsBuilder {
private final PermissionObject permissionObject;
@@ -277,14 +271,12 @@ public class Permissions {
}
public static boolean hasAny(@NonNull Context context, String... permissions) {
return !isRuntimePermissionsRequired() ||
Stream.of(permissions).anyMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
return Stream.of(permissions).anyMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
}
public static boolean hasAll(@NonNull Context context, String... permissions) {
return !isRuntimePermissionsRequired() ||
Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
return Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
}

View File

@@ -10,7 +10,6 @@ import androidx.annotation.AnyThread;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
@@ -155,7 +154,6 @@ public class BlobProvider {
position));
}
@RequiresApi(23)
public synchronized @NonNull MediaDataSource getMediaDataSource(@NonNull Context context, @NonNull Uri uri) throws IOException {
waitUntilInitialized();
return getBlobRepresentation(context,

View File

@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.push
import android.content.Context
import android.net.ConnectivityManager
import android.os.Build
import androidx.core.content.ContextCompat
import com.google.i18n.phonenumbers.PhoneNumberUtil
import okhttp3.CipherSuite
@@ -33,7 +32,6 @@ import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl
import org.whispersystems.signalservice.internal.configuration.SignalSvr2Url
import java.io.IOException
import java.util.Optional
import android.net.Proxy as AndroidProxy
/**
* Provides a [SignalServiceConfiguration] to be used with our service layer.
@@ -142,24 +140,13 @@ class SignalServiceNetworkAccess(context: Context) {
@Suppress("DEPRECATION")
private fun getSystemHttpProxy(context: Context): HttpProxy? {
return if (Build.VERSION.SDK_INT >= 23) {
val connectivityManager = ContextCompat.getSystemService(context, ConnectivityManager::class.java) ?: return null
connectivityManager
return connectivityManager
.activeNetwork
?.let { connectivityManager.getLinkProperties(it)?.httpProxy }
?.takeIf { !it.exclusionList.contains(BuildConfig.SIGNAL_URL.stripProtocol()) }
?.let { proxy -> HttpProxy(proxy.host, proxy.port) }
} else {
val host: String? = AndroidProxy.getHost(context)
val port: Int = AndroidProxy.getPort(context)
if (host != null) {
HttpProxy(host, port)
} else {
null
}
}
}
}
@@ -298,9 +285,11 @@ class SignalServiceNetworkAccess(context: Context) {
SettingsValues.CensorshipCircumventionEnabled.ENABLED -> {
censorshipConfiguration[countryCode] ?: defaultCensoredConfiguration
}
SettingsValues.CensorshipCircumventionEnabled.DISABLED -> {
uncensoredConfiguration
}
SettingsValues.CensorshipCircumventionEnabled.DEFAULT -> {
if (defaultCensoredCountryCodes.contains(countryCode)) {
censorshipConfiguration[countryCode] ?: defaultCensoredConfiguration

View File

@@ -55,12 +55,7 @@ public final class SignalStrengthPhoneStateListener extends PhoneStateListener
}
private boolean isLowLevel(@NonNull SignalStrength signalStrength) {
if (Build.VERSION.SDK_INT >= 23) {
return signalStrength.getLevel() == 0;
} else {
//noinspection deprecation: False lint warning, deprecated by 29, but this else block is for < 23
return signalStrength.getGsmSignalStrength() == 0;
}
}
public interface Callback {

View File

@@ -8,7 +8,6 @@ package org.thoughtcrime.securesms.registration.ui.permissions
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat
@@ -28,7 +27,6 @@ import org.thoughtcrime.securesms.util.BackupUtil
/**
* Screen in account registration that provides rationales for the suggested runtime permissions.
*/
@RequiresApi(23)
class GrantPermissionsFragment : ComposeFragment() {
companion object {

View File

@@ -19,7 +19,6 @@ import org.thoughtcrime.securesms.LoggingFragment
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.ViewBinderDelegate
import org.thoughtcrime.securesms.databinding.FragmentRegistrationWelcomeV3Binding
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegate.setDebugLogSubmitMultiTapView
import org.thoughtcrime.securesms.registration.fragments.WelcomePermissions
import org.thoughtcrime.securesms.registration.ui.RegistrationCheckpoint
@@ -75,7 +74,6 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome_v
}
}
if (Permissions.isRuntimePermissionsRequired()) {
parentFragmentManager.setFragmentResultListener(GrantPermissionsFragment.REQUEST_KEY, viewLifecycleOwner) { requestKey, bundle ->
if (requestKey == GrantPermissionsFragment.REQUEST_KEY) {
when (val userSelection = bundle.getSerializableCompat(GrantPermissionsFragment.REQUEST_KEY, WelcomeUserSelection::class.java)) {
@@ -88,10 +86,9 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome_v
}
}
}
}
private fun onLinkDeviceClicked() {
if (Permissions.isRuntimePermissionsRequired() && !hasAllPermissions()) {
if (!hasAllPermissions()) {
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(WelcomeUserSelection.LINK))
} else {
navigateToLinkDevice()
@@ -108,7 +105,7 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome_v
}
private fun onContinueClicked() {
if (Permissions.isRuntimePermissionsRequired() && !hasAllPermissions()) {
if (!hasAllPermissions()) {
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(WelcomeUserSelection.CONTINUE))
} else {
navigateToNextScreenViaContinue()
@@ -129,7 +126,7 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome_v
}
private fun afterRestoreOrTransferClicked(userSelection: WelcomeUserSelection) {
if (Permissions.isRuntimePermissionsRequired() && !hasAllPermissions()) {
if (!hasAllPermissions()) {
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(userSelection))
} else {
navigateToNextScreenViaRestore(userSelection)

View File

@@ -24,7 +24,6 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
@@ -313,11 +312,7 @@ public class KeyCachingService extends Service {
}
private static int getPendingIntentFlags() {
if (Build.VERSION.SDK_INT >= 23) {
return PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT;
} else {
return PendingIntent.FLAG_UPDATE_CURRENT;
}
}
@Override

View File

@@ -4,7 +4,6 @@ import android.media.MediaDataSource;
import android.media.MediaMetadataRetriever;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import java.io.IOException;
@@ -16,7 +15,6 @@ public final class MediaMetadataRetrieverUtil {
* {@link MediaMetadataRetriever#setDataSource(MediaDataSource)} tends to crash in native code on
* specific devices, so this just a wrapper to convert that into an {@link IOException}.
*/
@RequiresApi(23)
public static void setDataSource(@NonNull MediaMetadataRetriever retriever,
@NonNull MediaDataSource dataSource)
throws IOException

View File

@@ -12,7 +12,6 @@ import android.media.MediaDataSource;
import android.media.MediaMetadataRetriever;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Pair;
@@ -20,7 +19,6 @@ import android.webkit.MimeTypeMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.WorkerThread;
import androidx.exifinterface.media.ExifInterface;
@@ -431,7 +429,7 @@ public class MediaUtil {
return false;
}
if (BlobProvider.isAuthority(uri) && MediaUtil.isVideo(BlobProvider.getMimeType(uri)) && Build.VERSION.SDK_INT >= 23) {
if (BlobProvider.isAuthority(uri) && MediaUtil.isVideo(BlobProvider.getMimeType(uri))) {
return true;
}
@@ -476,8 +474,7 @@ public class MediaUtil {
MediaUtil.isVideo(URLConnection.guessContentTypeFromName(uri.toString()))) {
return ThumbnailUtils.createVideoThumbnail(uri.toString().replace("file://", ""),
MediaStore.Video.Thumbnails.MINI_KIND);
} else if (Build.VERSION.SDK_INT >= 23 &&
BlobProvider.isAuthority(uri) &&
} else if (BlobProvider.isAuthority(uri) &&
MediaUtil.isVideo(BlobProvider.getMimeType(uri)))
{
try {
@@ -486,8 +483,7 @@ public class MediaUtil {
} catch (IOException e) {
Log.w(TAG, "Failed to extract frame for URI: " + uri, e);
}
} else if (Build.VERSION.SDK_INT >= 23 &&
PartAuthority.isAttachmentUri(uri) &&
} else if (PartAuthority.isAttachmentUri(uri) &&
MediaUtil.isVideoType(PartAuthority.getAttachmentContentType(context, uri)))
{
try {
@@ -502,7 +498,6 @@ public class MediaUtil {
return null;
}
@RequiresApi(23)
private static @Nullable Bitmap extractFrame(@Nullable MediaDataSource dataSource, long timeUs) throws IOException {
if (dataSource == null) {
return null;

View File

@@ -89,7 +89,6 @@ public final class NetworkUtil {
public static @NonNull NetworkStatus getNetworkStatus(@NonNull Context context) {
ConnectivityManager connectivityManager = ServiceUtil.getConnectivityManager(context);
if (Build.VERSION.SDK_INT >= 23) {
Network network = connectivityManager.getActiveNetwork();
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
@@ -97,9 +96,6 @@ public final class NetworkUtil {
boolean isNotMetered = capabilities == null || capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
return new NetworkStatus(onVpn, !isNotMetered);
} else {
return new NetworkStatus(false, false);
}
}
private static boolean useLowDataCalling(@NonNull Context context, @NonNull PeerConnection.AdapterType networkAdapter) {

View File

@@ -3,30 +3,21 @@ package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
public class PowerManagerCompat {
public static boolean isDeviceIdleMode(@NonNull PowerManager powerManager) {
if (Build.VERSION.SDK_INT >= 23) {
return powerManager.isDeviceIdleMode();
}
return false;
}
public static boolean isIgnoringBatteryOptimizations(@NonNull Context context) {
if (Build.VERSION.SDK_INT < 23) {
return true;
}
return ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.getPackageName());
}
@RequiresApi(api = 23)
public static void requestIgnoreBatteryOptimizations(@NonNull Context context) {
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
Uri.parse("package:" + context.getPackageName()));

View File

@@ -659,11 +659,7 @@ public class TextSecurePreferences {
@Deprecated
public static boolean isCallNotificationVibrateEnabled(Context context) {
boolean defaultValue = true;
if (Build.VERSION.SDK_INT >= 23) {
defaultValue = (Settings.System.getInt(context.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 1) == 1);
}
boolean defaultValue = (Settings.System.getInt(context.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 1) == 1);
return getBooleanPreference(context, CALL_VIBRATE_PREF, defaultValue);
}

View File

@@ -62,8 +62,6 @@ public final class WindowUtil {
}
public static void setLightStatusBarFromTheme(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT < 23) return;
final boolean isLightStatusBar = ThemeUtil.getThemedBoolean(activity, android.R.attr.windowLightStatusBar);
if (isLightStatusBar) setLightStatusBar(activity.getWindow());
@@ -71,14 +69,10 @@ public final class WindowUtil {
}
public static void clearLightStatusBar(@NonNull Window window) {
if (Build.VERSION.SDK_INT < 23) return;
clearSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
public static void setLightStatusBar(@NonNull Window window) {
if (Build.VERSION.SDK_INT < 23) return;
setSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}

View File

@@ -2,11 +2,8 @@ package org.thoughtcrime.securesms.video;
import android.media.MediaDataSource;
import androidx.annotation.RequiresApi;
import java.io.IOException;
@RequiresApi(23)
public class ByteArrayMediaDataSource extends MediaDataSource {
private byte[] data;

View File

@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.video;
import android.media.MediaDataSource;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
@@ -13,7 +12,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@RequiresApi(23)
final class ClassicEncryptedMediaDataSource extends MediaDataSource {
private final AttachmentSecret attachmentSecret;

View File

@@ -4,13 +4,11 @@ import android.media.MediaDataSource;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import java.io.File;
@RequiresApi(23)
public final class EncryptedMediaDataSource {
public static MediaDataSource createFor(@NonNull AttachmentSecret attachmentSecret, @NonNull File mediaFile, @Nullable byte[] random, long length) {

View File

@@ -4,7 +4,6 @@ import android.media.MediaDataSource;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
@@ -22,7 +21,6 @@ import java.io.InputStream;
* It is "modern" compared to the {@link ClassicEncryptedMediaDataSource}. And "modern" refers to
* the presence of a random part of the key supplied in the constructor.
*/
@RequiresApi(23)
final class ModernEncryptedMediaDataSource extends InputStreamMediaDataSource {
private final AttachmentSecret attachmentSecret;

View File

@@ -172,22 +172,16 @@ public abstract class AudioManagerCompat {
audioManager.clearCommunicationDevice();
}
@RequiresApi(23)
public void registerAudioDeviceCallback(@NonNull AudioDeviceCallback deviceCallback, @NonNull Handler handler) {
audioManager.registerAudioDeviceCallback(deviceCallback, handler);
}
@RequiresApi(23)
public void unregisterAudioDeviceCallback(@NonNull AudioDeviceCallback deviceCallback) {
audioManager.unregisterAudioDeviceCallback(deviceCallback);
}
@SuppressLint("WrongConstant")
public boolean isWiredHeadsetOn() {
if (Build.VERSION.SDK_INT < 23) {
//noinspection deprecation
return audioManager.isWiredHeadsetOn();
} else {
AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
for (AudioDeviceInfo device : devices) {
final int type = device.getType();
@@ -199,7 +193,6 @@ public abstract class AudioManagerCompat {
}
return false;
}
}
public float ringVolumeWithMinimum() {
int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_RING);

View File

@@ -9,7 +9,6 @@ import android.app.ActivityManager
import android.content.Context
import android.os.Debug
import android.os.Handler
import androidx.annotation.RequiresApi
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.logging.Log
import kotlin.time.Duration.Companion.milliseconds
@@ -89,7 +88,6 @@ object MemoryTracker {
* This gives us details stats, but it takes an appreciable amount of time. On an emulator, it can take ~30ms.
* As a result, we don't want to be calling this regularly for most users.
*/
@RequiresApi(23)
fun getDetailedMemoryStats(): DetailedMemoryStats {
Debug.getMemoryInfo(debugMemoryInfo)

View File

@@ -42,6 +42,6 @@ object PendingIntentFlags {
@JvmStatic
fun immutable(): Int {
return if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0
return PendingIntent.FLAG_IMMUTABLE
}
}

View File

@@ -86,7 +86,7 @@ public class MainActivity extends AppCompatActivity {
findViewById(R.id.stop).setOnClickListener(v -> DeviceToDeviceTransferService.stop(this));
findViewById(R.id.enable_permission).setOnClickListener(v -> {
if (Build.VERSION.SDK_INT >= 23 && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 420);
}
});

View File

@@ -92,12 +92,12 @@ public final class WifiDirect {
if (Build.VERSION.SDK_INT >= 33 && context.checkSelfPermission(Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Nearby Wifi permission required");
return AvailableStatus.REQUIRED_PERMISSION_NOT_GRANTED;
} else if (Build.VERSION.SDK_INT < 33 && Build.VERSION.SDK_INT >= 23 && context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
} else if (Build.VERSION.SDK_INT < 33 && context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Fine location permission required");
return AvailableStatus.REQUIRED_PERMISSION_NOT_GRANTED;
}
return Build.VERSION.SDK_INT <= 23 || wifiManager.isP2pSupported() ? AvailableStatus.AVAILABLE
return wifiManager.isP2pSupported() ? AvailableStatus.AVAILABLE
: AvailableStatus.WIFI_DIRECT_NOT_AVAILABLE;
}

View File

@@ -2,7 +2,6 @@ package org.signal.qrtest
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.EditText
@@ -73,9 +72,7 @@ class QrMainActivity : AppCompatActivity() {
text = findViewById(R.id.log)
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(arrayOf(android.Manifest.permission.CAMERA), 1)
}
val scanner = findViewById<QrScannerView>(R.id.scanner)
scanner.start(this)

View File

@@ -29,9 +29,9 @@ import androidx.annotation.StringDef;
import androidx.annotation.WorkerThread;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.video.videoconverter.exceptions.EncodingException;
import org.thoughtcrime.securesms.video.interfaces.MediaInput;
import org.thoughtcrime.securesms.video.interfaces.Muxer;
import org.thoughtcrime.securesms.video.videoconverter.exceptions.EncodingException;
import org.thoughtcrime.securesms.video.videoconverter.muxer.StreamingMuxer;
import java.io.File;
@@ -142,7 +142,6 @@ public final class MediaConverter {
* @return The total content size of the MP4 mdat box.
*/
@WorkerThread
@RequiresApi(23)
public long convert() throws EncodingException, IOException {
// Exception that may be thrown during release.
Exception exception = null;

View File

@@ -14,7 +14,6 @@ import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.video.interfaces.MediaInput;
@@ -78,7 +77,6 @@ final class VideoTrackConverter {
private Muxer mMuxer;
@RequiresApi(23)
static @Nullable VideoTrackConverter create(
final @NonNull MediaInput input,
final long timeFrom,
@@ -97,7 +95,6 @@ final class VideoTrackConverter {
}
@RequiresApi(23)
private VideoTrackConverter(
final @NonNull MediaExtractor videoExtractor,
final int videoInputTrack,

View File

@@ -6,14 +6,12 @@
package org.thoughtcrime.securesms.video.videoconverter.mediadatasource
import android.media.MediaDataSource
import androidx.annotation.RequiresApi
import java.io.IOException
import java.io.InputStream
/**
* Extend this class in order to be able to use the system media framework with any arbitrary [InputStream] of bytes.
*/
@RequiresApi(23)
abstract class InputStreamMediaDataSource : MediaDataSource() {
@Throws(IOException::class)
override fun readAt(position: Long, bytes: ByteArray?, offset: Int, length: Int): Int {

View File

@@ -7,14 +7,12 @@ package org.thoughtcrime.securesms.video.videoconverter.mediadatasource
import android.media.MediaDataSource
import android.media.MediaExtractor
import androidx.annotation.RequiresApi
import org.thoughtcrime.securesms.video.interfaces.MediaInput
import java.io.IOException
/**
* [MediaInput] implementation that adds support for the system framework's media data source.
*/
@RequiresApi(23)
class MediaDataSourceMediaInput(private val mediaDataSource: MediaDataSource) : MediaInput {
@Throws(IOException::class)
override fun createExtractor(): MediaExtractor {

View File

@@ -10,7 +10,6 @@ import android.media.MediaCodecInfo.CodecProfileLevel
import android.media.MediaCodecList
import android.media.MediaFormat
import android.os.Build
import androidx.annotation.RequiresApi
import org.signal.core.util.logging.Log
import java.io.IOException
@@ -77,9 +76,7 @@ object MediaCodecCompat {
// dolby vision profile 04/08: Base layer is H.265 Main10 High Profile, Rec709/HLG/HDR10
mediaFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_HEVC)
mediaFormat.setInteger(MediaFormat.KEY_PROFILE, CodecProfileLevel.HEVCProfileMain10)
if (Build.VERSION.SDK_INT >= 23) {
mediaFormat.setBaseCodecLevelFromDolbyVisionLevel()
}
return findDecoder(mediaFormat)
}
@@ -87,9 +84,7 @@ object MediaCodecCompat {
// dolby vision profile 09: Base layer is H.264 High/Progressive/Constrained Profile, Rec 709
mediaFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC)
mediaFormat.setInteger(MediaFormat.KEY_PROFILE, CodecProfileLevel.AVCProfileHigh)
if (Build.VERSION.SDK_INT >= 23) {
mediaFormat.setBaseCodecLevelFromDolbyVisionLevel()
}
return findDecoder(mediaFormat)
}
@@ -100,7 +95,6 @@ object MediaCodecCompat {
}
}
@RequiresApi(23)
private fun MediaFormat.setBaseCodecLevelFromDolbyVisionLevel(): Boolean {
val mimeType = this.getString(MediaFormat.KEY_MIME) ?: return false
try {