mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-05 01:10:48 +00:00
Clear out checks for SDK < 23 as they're no longer relevant.
This commit is contained in:
@@ -38,11 +38,7 @@ class BiometricDeviceAuthentication(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun isDeviceSecure(context: Context): Boolean {
|
private fun isDeviceSecure(context: Context): Boolean {
|
||||||
return if (Build.VERSION.SDK_INT > 23) {
|
return ServiceUtil.getKeyguardManager(context).isDeviceSecure
|
||||||
ServiceUtil.getKeyguardManager(context).isDeviceSecure
|
|
||||||
} else {
|
|
||||||
ServiceUtil.getKeyguardManager(context).isKeyguardSecure
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ import androidx.compose.foundation.layout.Box
|
|||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
import androidx.compose.foundation.layout.BoxWithConstraintsScope
|
import androidx.compose.foundation.layout.BoxWithConstraintsScope
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.displayCutoutPadding
|
import androidx.compose.foundation.layout.displayCutoutPadding
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.systemBarsPadding
|
import androidx.compose.foundation.layout.systemBarsPadding
|
||||||
import androidx.compose.material3.MaterialTheme
|
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.MainToolbarState
|
||||||
import org.thoughtcrime.securesms.main.MainToolbarViewModel
|
import org.thoughtcrime.securesms.main.MainToolbarViewModel
|
||||||
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder
|
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder
|
||||||
import org.thoughtcrime.securesms.main.NavigationBarSpacerCompat
|
|
||||||
import org.thoughtcrime.securesms.main.SnackbarState
|
import org.thoughtcrime.securesms.main.SnackbarState
|
||||||
import org.thoughtcrime.securesms.main.callNavGraphBuilder
|
import org.thoughtcrime.securesms.main.callNavGraphBuilder
|
||||||
import org.thoughtcrime.securesms.main.chatNavGraphBuilder
|
import org.thoughtcrime.securesms.main.chatNavGraphBuilder
|
||||||
@@ -514,7 +515,7 @@ class MainActivity : PassphraseRequiredActivity(), VoiceNoteMediaControllerOwner
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (!windowSizeClass.isSplitPane()) {
|
if (!windowSizeClass.isSplitPane()) {
|
||||||
NavigationBarSpacerCompat()
|
Spacer(Modifier.navigationBarsPadding())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package org.thoughtcrime.securesms.attachments
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.os.Build
|
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.signal.core.util.mebiBytes
|
import org.signal.core.util.mebiBytes
|
||||||
import org.signal.protos.resumableuploads.ResumableUpload
|
import org.signal.protos.resumableuploads.ResumableUpload
|
||||||
@@ -93,11 +92,6 @@ object AttachmentUploadUtil {
|
|||||||
return attachment.blurHash.hash
|
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 ->
|
return MediaUtil.getVideoThumbnail(context, Objects.requireNonNull(attachment.uri), 1000)?.let { bitmap ->
|
||||||
val thumb = Bitmap.createScaledBitmap(bitmap, 100, 100, false)
|
val thumb = Bitmap.createScaledBitmap(bitmap, 100, 100, false)
|
||||||
bitmap.recycle()
|
bitmap.recycle()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.LruCache
|
import android.util.LruCache
|
||||||
import androidx.annotation.AnyThread
|
import androidx.annotation.AnyThread
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import io.reactivex.rxjava3.core.Single
|
import io.reactivex.rxjava3.core.Single
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import io.reactivex.rxjava3.subjects.SingleSubject
|
import io.reactivex.rxjava3.subjects.SingleSubject
|
||||||
@@ -24,7 +23,6 @@ import kotlin.concurrent.write
|
|||||||
*
|
*
|
||||||
* Maintains an in-memory cache of recently requested wave forms.
|
* Maintains an in-memory cache of recently requested wave forms.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(23)
|
|
||||||
object AudioWaveForms {
|
object AudioWaveForms {
|
||||||
|
|
||||||
private val TAG = Log.tag(AudioWaveForms::class.java)
|
private val TAG = Log.tag(AudioWaveForms::class.java)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import android.content.res.ColorStateList
|
|||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.airbnb.lottie.SimpleColorFilter
|
import com.airbnb.lottie.SimpleColorFilter
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
@@ -58,9 +57,7 @@ class FallbackAvatarDrawable(
|
|||||||
)
|
)
|
||||||
|
|
||||||
resourceIcon.bounds = iconBounds
|
resourceIcon.bounds = iconBounds
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
resourceIcon.setLayoutDirection(layoutDirection)
|
||||||
resourceIcon.setLayoutDirection(layoutDirection)
|
|
||||||
}
|
|
||||||
resourceIcon
|
resourceIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.backup;
|
package org.thoughtcrime.securesms.backup;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -24,8 +23,8 @@ public final class BackupPassphrase {
|
|||||||
String passphrase = TextSecurePreferences.getBackupPassphrase(context);
|
String passphrase = TextSecurePreferences.getBackupPassphrase(context);
|
||||||
String encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context);
|
String encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < 23 || (passphrase == null && encryptedPassphrase == null)) {
|
if (passphrase == null && encryptedPassphrase == null) {
|
||||||
return stripSpaces(passphrase);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (encryptedPassphrase == null) {
|
if (encryptedPassphrase == null) {
|
||||||
@@ -40,8 +39,8 @@ public final class BackupPassphrase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void set(@NonNull Context context, @Nullable String passphrase) {
|
public static void set(@NonNull Context context, @Nullable String passphrase) {
|
||||||
if (passphrase == null || Build.VERSION.SDK_INT < 23) {
|
if (passphrase == null) {
|
||||||
TextSecurePreferences.setBackupPassphrase(context, passphrase);
|
TextSecurePreferences.setBackupPassphrase(context, null);
|
||||||
TextSecurePreferences.setEncryptedBackupPassphrase(context, null);
|
TextSecurePreferences.setEncryptedBackupPassphrase(context, null);
|
||||||
} else {
|
} else {
|
||||||
KeyStoreHelper.SealedData encryptedPassphrase = KeyStoreHelper.seal(passphrase.getBytes());
|
KeyStoreHelper.SealedData encryptedPassphrase = KeyStoreHelper.seal(passphrase.getBytes());
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
package org.thoughtcrime.securesms.banner.banners
|
package org.thoughtcrime.securesms.banner.banners
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
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>() {
|
class DozeBanner(private val context: Context, private val onDismissListener: () -> Unit) : Banner<Unit>() {
|
||||||
|
|
||||||
override val enabled: Boolean
|
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>
|
override val dataFlow: Flow<Unit>
|
||||||
get() = flowOf(Unit)
|
get() = flowOf(Unit)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun DisplayBanner(model: Unit, contentPadding: PaddingValues) {
|
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(
|
Banner(
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
onDismissListener = {
|
onDismissListener = {
|
||||||
|
|||||||
@@ -219,28 +219,21 @@ public final class AudioView extends FrameLayout {
|
|||||||
if (seekBar instanceof WaveFormSeekBarView) {
|
if (seekBar instanceof WaveFormSeekBarView) {
|
||||||
WaveFormSeekBarView waveFormView = (WaveFormSeekBarView) seekBar;
|
WaveFormSeekBarView waveFormView = (WaveFormSeekBarView) seekBar;
|
||||||
waveFormView.setColors(waveFormPlayedBarsColor, waveFormUnplayedBarsColor, waveFormThumbTint);
|
waveFormView.setColors(waveFormPlayedBarsColor, waveFormUnplayedBarsColor, waveFormThumbTint);
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 23) {
|
if (audioSlide == null || !Objects.equals(audioSlide.getUri(), audio.getUri())) {
|
||||||
if (audioSlide == null || !Objects.equals(audioSlide.getUri(), audio.getUri())) {
|
disposable.dispose();
|
||||||
disposable.dispose();
|
disposable = AudioWaveForms.getWaveForm(getContext(), audio.asAttachment())
|
||||||
disposable = AudioWaveForms.getWaveForm(getContext(), audio.asAttachment())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.subscribe(
|
||||||
.subscribe(
|
data -> {
|
||||||
data -> {
|
durationMillis = data.getDuration(TimeUnit.MILLISECONDS);
|
||||||
durationMillis = data.getDuration(TimeUnit.MILLISECONDS);
|
updateProgress(0, 0);
|
||||||
updateProgress(0, 0);
|
if (!forceHideDuration && duration != null) {
|
||||||
if (!forceHideDuration && duration != null) {
|
duration.setVisibility(VISIBLE);
|
||||||
duration.setVisibility(VISIBLE);
|
}
|
||||||
}
|
waveFormView.setWaveData(data.getWaveForm());
|
||||||
waveFormView.setWaveData(data.getWaveForm());
|
},
|
||||||
},
|
t -> waveFormView.setWaveMode(false)
|
||||||
t -> waveFormView.setWaveMode(false)
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
waveFormView.setWaveMode(false);
|
|
||||||
if (duration != null) {
|
|
||||||
duration.setVisibility(GONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import androidx.lifecycle.Lifecycle
|
|||||||
import org.signal.core.util.concurrent.LifecycleDisposable
|
import org.signal.core.util.concurrent.LifecycleDisposable
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.components.DebugLogsPromptDialogFragment.Purpose.entries
|
|
||||||
import org.thoughtcrime.securesms.databinding.PromptLogsBottomSheetBinding
|
import org.thoughtcrime.securesms.databinding.PromptLogsBottomSheetBinding
|
||||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||||
@@ -159,11 +158,7 @@ class DebugLogsPromptDialogFragment : FixedRoundedCornerBottomSheetDialogFragmen
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun batteryOptimizationsString(): String {
|
private fun batteryOptimizationsString(): String {
|
||||||
return if (Build.VERSION.SDK_INT < 23) {
|
return PowerManagerCompat.isIgnoringBatteryOptimizations(requireContext()).toString()
|
||||||
"N/A (API < 23)"
|
|
||||||
} else {
|
|
||||||
PowerManagerCompat.isIgnoringBatteryOptimizations(requireContext()).toString()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun backgroundRestrictedString(): String {
|
private fun backgroundRestrictedString(): String {
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
|||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
rotation = getDeviceRotation();
|
rotation = getDeviceRotation();
|
||||||
if (Build.VERSION.SDK_INT >= 23 && getRootWindowInsets() != null) {
|
if (getRootWindowInsets() != null) {
|
||||||
int bottomInset;
|
int bottomInset;
|
||||||
WindowInsets windowInsets = getRootWindowInsets();
|
WindowInsets windowInsets = getRootWindowInsets();
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.fragment.app.FragmentManager
|
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.LocalMetrics
|
||||||
import org.thoughtcrime.securesms.util.PowerManagerCompat
|
import org.thoughtcrime.securesms.util.PowerManagerCompat
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
class PromptBatterySaverDialogFragment : FixedRoundedCornerBottomSheetDialogFragment() {
|
class PromptBatterySaverDialogFragment : FixedRoundedCornerBottomSheetDialogFragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -604,9 +604,7 @@ public class ThumbnailView extends FrameLayout {
|
|||||||
.downsample(SignalDownsampleStrategy.CENTER_OUTSIDE_NO_UPSCALE)
|
.downsample(SignalDownsampleStrategy.CENTER_OUTSIDE_NO_UPSCALE)
|
||||||
.transition(withCrossFade()));
|
.transition(withCrossFade()));
|
||||||
|
|
||||||
boolean doNotShowMissingThumbnailImage = Build.VERSION.SDK_INT < 23;
|
if (slide.isInProgress()) {
|
||||||
|
|
||||||
if (slide.isInProgress() || doNotShowMissingThumbnailImage) {
|
|
||||||
return requestBuilder;
|
return requestBuilder;
|
||||||
} else {
|
} else {
|
||||||
return requestBuilder.apply(RequestOptions.errorOf(R.drawable.missing_thumbnail));
|
return requestBuilder.apply(RequestOptions.errorOf(R.drawable.missing_thumbnail));
|
||||||
|
|||||||
@@ -116,16 +116,12 @@ public class EmojiEditText extends AppCompatEditText {
|
|||||||
ClipData clipData = ServiceUtil.getClipboardManager(getContext()).getPrimaryClip();
|
ClipData clipData = ServiceUtil.getClipboardManager(getContext()).getPrimaryClip();
|
||||||
|
|
||||||
if (clipData != null) {
|
if (clipData != null) {
|
||||||
CharSequence label = clipData.getDescription().getLabel();
|
CharSequence label = clipData.getDescription().getLabel();
|
||||||
CharSequence pendingPaste = getTextFromClipData(clipData);
|
|
||||||
|
|
||||||
if (TextUtils.equals(Util.COPY_LABEL, label) && shouldPersistSignalStylingWhenPasting()) {
|
if (TextUtils.equals(Util.COPY_LABEL, label) && shouldPersistSignalStylingWhenPasting()) {
|
||||||
return super.onTextContextMenuItem(id);
|
return super.onTextContextMenuItem(id);
|
||||||
} else if (Build.VERSION.SDK_INT >= 23) {
|
} else {
|
||||||
return super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
|
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) {
|
} else if (id == android.R.id.copy || id == android.R.id.cut) {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import android.widget.Toast
|
|||||||
import androidx.activity.result.ActivityResultCallback
|
import androidx.activity.result.ActivityResultCallback
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@@ -238,7 +237,6 @@ open class DefaultNotificationsSettingsCallbacks(
|
|||||||
viewModel.setMessageNotificationPrivacy(selection)
|
viewModel.setMessageNotificationPrivacy(selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
override fun onTroubleshootNotificationsClick() {
|
override fun onTroubleshootNotificationsClick() {
|
||||||
PromptBatterySaverDialogFragment.show(activity.supportFragmentManager)
|
PromptBatterySaverDialogFragment.show(activity.supportFragmentManager)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@@ -106,7 +105,7 @@ object DonationErrorNotifications {
|
|||||||
context,
|
context,
|
||||||
0,
|
0,
|
||||||
actionIntent,
|
actionIntent,
|
||||||
if (Build.VERSION.SDK_INT >= 23) PendingIntentFlags.oneShot() else PendingIntentFlags.mutable()
|
PendingIntentFlags.oneShot()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.crypto;
|
|||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@@ -60,25 +59,17 @@ public class AttachmentSecretProvider {
|
|||||||
{
|
{
|
||||||
AttachmentSecret attachmentSecret = AttachmentSecret.fromString(unencryptedSecret);
|
AttachmentSecret attachmentSecret = AttachmentSecret.fromString(unencryptedSecret);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
|
||||||
return attachmentSecret;
|
|
||||||
} else {
|
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
|
|
||||||
|
|
||||||
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
|
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
|
||||||
TextSecurePreferences.setAttachmentUnencryptedSecret(context, null);
|
TextSecurePreferences.setAttachmentUnencryptedSecret(context, null);
|
||||||
|
|
||||||
return attachmentSecret;
|
return attachmentSecret;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AttachmentSecret getEncryptedAttachmentSecret(@NonNull String serializedEncryptedSecret) {
|
private AttachmentSecret getEncryptedAttachmentSecret(@NonNull String serializedEncryptedSecret) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
|
||||||
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
|
return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret)));
|
||||||
} else {
|
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
|
|
||||||
return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
|
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
|
||||||
@@ -93,12 +84,7 @@ public class AttachmentSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void storeAttachmentSecret(@NonNull Context context, @NonNull AttachmentSecret attachmentSecret) {
|
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());
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
|
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
|
||||||
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
|
|
||||||
} else {
|
|
||||||
TextSecurePreferences.setAttachmentUnencryptedSecret(context, attachmentSecret.serialize());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.crypto;
|
|||||||
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@@ -48,28 +47,20 @@ public final class DatabaseSecretProvider {
|
|||||||
try {
|
try {
|
||||||
DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret);
|
DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
|
||||||
return databaseSecret;
|
|
||||||
} else {
|
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
|
|
||||||
|
|
||||||
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
|
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
|
||||||
TextSecurePreferences.setDatabaseUnencryptedSecret(context, null);
|
TextSecurePreferences.setDatabaseUnencryptedSecret(context, null);
|
||||||
|
|
||||||
return databaseSecret;
|
return databaseSecret;
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull DatabaseSecret getEncryptedDatabaseSecret(@NonNull String serializedEncryptedSecret) {
|
private static @NonNull DatabaseSecret getEncryptedDatabaseSecret(@NonNull String serializedEncryptedSecret) {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
|
||||||
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
|
return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret));
|
||||||
} else {
|
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
|
|
||||||
return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
|
private static @NonNull DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
|
||||||
@@ -79,12 +70,8 @@ public final class DatabaseSecretProvider {
|
|||||||
|
|
||||||
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
|
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
|
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
|
||||||
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
|
|
||||||
} else {
|
|
||||||
TextSecurePreferences.setDatabaseUnencryptedSecret(context, databaseSecret.asString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return databaseSecret;
|
return databaseSecret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ public final class KeyStoreHelper {
|
|||||||
private static final String KEY_ALIAS = "SignalSecret";
|
private static final String KEY_ALIAS = "SignalSecret";
|
||||||
private static final Executor executor = Executors.newSingleThreadExecutor();
|
private static final Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
public static SealedData seal(@NonNull byte[] input) {
|
public static SealedData seal(@NonNull byte[] input) {
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
AtomicReference<SealedData> result = new AtomicReference<>();
|
AtomicReference<SealedData> result = new AtomicReference<>();
|
||||||
@@ -83,7 +82,6 @@ public final class KeyStoreHelper {
|
|||||||
return result.get();
|
return result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
public static byte[] unseal(@NonNull SealedData sealedData) {
|
public static byte[] unseal(@NonNull SealedData sealedData) {
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
AtomicReference<byte[]> result = new AtomicReference<>();
|
AtomicReference<byte[]> result = new AtomicReference<>();
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import android.database.Cursor
|
|||||||
import android.media.MediaDataSource
|
import android.media.MediaDataSource
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.core.content.contentValuesOf
|
import androidx.core.content.contentValuesOf
|
||||||
@@ -2150,7 +2149,6 @@ class AttachmentTable(
|
|||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
fun mediaDataSourceFor(attachmentId: AttachmentId, allowReadingFromTempFile: Boolean): MediaDataSource? {
|
fun mediaDataSourceFor(attachmentId: AttachmentId, allowReadingFromTempFile: Boolean): MediaDataSource? {
|
||||||
val dataInfo = getDataFileInfo(attachmentId)
|
val dataInfo = getDataFileInfo(attachmentId)
|
||||||
if (dataInfo != null) {
|
if (dataInfo != null) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.thoughtcrime.securesms.jobs
|
package org.thoughtcrime.securesms.jobs
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.signal.protos.resumableuploads.ResumableUpload
|
import org.signal.protos.resumableuploads.ResumableUpload
|
||||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||||
@@ -263,7 +262,7 @@ class ArchiveThumbnailUploadJob private constructor(
|
|||||||
|
|
||||||
return if (MediaUtil.isImageType(attachment.contentType)) {
|
return if (MediaUtil.isImageType(attachment.contentType)) {
|
||||||
compress(uri, 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 {
|
MediaUtil.getVideoThumbnail(context, attachment.uri)?.let {
|
||||||
compress(uri, attachment.contentType ?: "")
|
compress(uri, attachment.contentType ?: "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.thoughtcrime.securesms.jobs
|
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.concurrent.safeBlockingGet
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.attachments.AttachmentId
|
import org.thoughtcrime.securesms.attachments.AttachmentId
|
||||||
@@ -28,11 +26,7 @@ class GenerateAudioWaveFormJob private constructor(private val attachmentId: Att
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun enqueue(attachmentId: AttachmentId) {
|
fun enqueue(attachmentId: AttachmentId) {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
AppDependencies.jobManager.add(GenerateAudioWaveFormJob(attachmentId))
|
||||||
Log.i(TAG, "Unable to generate waveform on this version of Android")
|
|
||||||
} else {
|
|
||||||
AppDependencies.jobManager.add(GenerateAudioWaveFormJob(attachmentId))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +47,6 @@ class GenerateAudioWaveFormJob private constructor(private val attachmentId: Att
|
|||||||
|
|
||||||
override fun getFactoryKey(): String = KEY
|
override fun getFactoryKey(): String = KEY
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
override fun onRun() {
|
override fun onRun() {
|
||||||
val attachment: DatabaseAttachment? = SignalDatabase.attachments.getAttachment(attachmentId)
|
val attachment: DatabaseAttachment? = SignalDatabase.attachments.getAttachment(attachmentId)
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package org.thoughtcrime.securesms.logging;
|
package org.thoughtcrime.securesms.logging;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.KeyStoreHelper;
|
|
||||||
import org.signal.core.util.Base64;
|
import org.signal.core.util.Base64;
|
||||||
|
import org.thoughtcrime.securesms.crypto.KeyStoreHelper;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -32,12 +31,8 @@ public class LogSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] parseEncryptedSecret(String secret) {
|
private static byte[] parseEncryptedSecret(String secret) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret);
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret);
|
return KeyStoreHelper.unseal(encryptedSecret);
|
||||||
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) {
|
private static byte[] createAndStoreSecret(@NonNull Context context) {
|
||||||
@@ -45,12 +40,8 @@ public class LogSecretProvider {
|
|||||||
byte[] secret = new byte[32];
|
byte[] secret = new byte[32];
|
||||||
random.nextBytes(secret);
|
random.nextBytes(secret);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
|
TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize());
|
||||||
TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize());
|
|
||||||
} else {
|
|
||||||
TextSecurePreferences.setLogUnencryptedSecret(context, Base64.encodeWithPadding(secret));
|
|
||||||
}
|
|
||||||
|
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.logsubmit
|
package org.thoughtcrime.securesms.logsubmit
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
|
||||||
import org.signal.core.util.MemoryTracker
|
import org.signal.core.util.MemoryTracker
|
||||||
import org.signal.core.util.bytes
|
import org.signal.core.util.bytes
|
||||||
import org.signal.core.util.kibiBytes
|
import org.signal.core.util.kibiBytes
|
||||||
@@ -28,20 +27,18 @@ class LogSectionMemory : LogSection {
|
|||||||
Low Memory? : ${nativeMemory.lowMemory}
|
Low Memory? : ${nativeMemory.lowMemory}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
val detailedMemory = MemoryTracker.getDetailedMemoryStats()
|
||||||
val detailedMemory = MemoryTracker.getDetailedMemoryStats()
|
|
||||||
|
|
||||||
base += "\n\n"
|
base += "\n\n"
|
||||||
base += """
|
base += """
|
||||||
-- Detailed Memory (API 23+)
|
-- Detailed Memory (API 23+)
|
||||||
App JVM Heap Usage : ${detailedMemory.appJavaHeapUsageKb?.kbDisplay()}
|
App JVM Heap Usage : ${detailedMemory.appJavaHeapUsageKb?.kbDisplay()}
|
||||||
App Native Heap Usage: ${detailedMemory.appNativeHeapUsageKb?.kbDisplay()}
|
App Native Heap Usage: ${detailedMemory.appNativeHeapUsageKb?.kbDisplay()}
|
||||||
Code Usage : ${detailedMemory.codeUsageKb?.kbDisplay()}
|
Code Usage : ${detailedMemory.codeUsageKb?.kbDisplay()}
|
||||||
Graphics Usage : ${detailedMemory.graphicsUsageKb?.kbDisplay()}
|
Graphics Usage : ${detailedMemory.graphicsUsageKb?.kbDisplay()}
|
||||||
Stack Usage : ${detailedMemory.stackUsageKb?.kbDisplay()}
|
Stack Usage : ${detailedMemory.stackUsageKb?.kbDisplay()}
|
||||||
Other Usage : ${detailedMemory.appOtherUsageKb?.kbDisplay()}
|
Other Usage : ${detailedMemory.appOtherUsageKb?.kbDisplay()}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
|
||||||
|
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
package org.thoughtcrime.securesms.mediasend
|
package org.thoughtcrime.securesms.mediasend
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
@@ -161,7 +159,6 @@ class VideoEditorFragment : Fragment(), PositionDragListener, MediaSendPageFragm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
private fun bindVideoTimeline(data: VideoTrimData) {
|
private fun bindVideoTimeline(data: VideoTrimData) {
|
||||||
val autoplay = isVideoGif
|
val autoplay = isVideoGif
|
||||||
val slide = VideoSlide(requireContext(), uri, 0, autoplay)
|
val slide = VideoSlide(requireContext(), uri, 0, autoplay)
|
||||||
@@ -213,10 +210,8 @@ class VideoEditorFragment : Fragment(), PositionDragListener, MediaSendPageFragm
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startPositionUpdates() {
|
private fun startPositionUpdates() {
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
stopPositionUpdates()
|
||||||
stopPositionUpdates()
|
handler.post(updatePosition)
|
||||||
handler.post(updatePosition)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopPositionUpdates() {
|
private fun stopPositionUpdates() {
|
||||||
@@ -250,7 +245,6 @@ class VideoEditorFragment : Fragment(), PositionDragListener, MediaSendPageFragm
|
|||||||
hud.showPlayButton()
|
hud.showPlayButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
private fun onEditVideoDuration(data: VideoTrimData, editingComplete: Boolean) {
|
private fun onEditVideoDuration(data: VideoTrimData, editingComplete: Boolean) {
|
||||||
if (editingComplete) {
|
if (editingComplete) {
|
||||||
isInEdit = false
|
isInEdit = false
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources.Theme;
|
import android.content.res.Resources.Theme;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -56,7 +55,7 @@ public class VideoSlide extends Slide {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPlayOverlay() {
|
public boolean hasPlayOverlay() {
|
||||||
return !(isVideoGif() && GiphyMp4PlaybackPolicy.autoplay()) || Build.VERSION.SDK_INT < 23;
|
return !(isVideoGif() && GiphyMp4PlaybackPolicy.autoplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,14 +9,13 @@ import android.os.Build;
|
|||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
|
import org.signal.core.util.CursorUtil;
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.signal.core.util.CursorUtil;
|
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -31,8 +30,6 @@ public final class DoNotDisturbUtil {
|
|||||||
@WorkerThread
|
@WorkerThread
|
||||||
@SuppressLint("SwitchIntDef")
|
@SuppressLint("SwitchIntDef")
|
||||||
public static boolean shouldDisturbUserWithCall(@NonNull Context context) {
|
public static boolean shouldDisturbUserWithCall(@NonNull Context context) {
|
||||||
if (Build.VERSION.SDK_INT <= 23) return true;
|
|
||||||
|
|
||||||
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
||||||
|
|
||||||
switch (notificationManager.getCurrentInterruptionFilter()) {
|
switch (notificationManager.getCurrentInterruptionFilter()) {
|
||||||
@@ -47,8 +44,6 @@ public final class DoNotDisturbUtil {
|
|||||||
@WorkerThread
|
@WorkerThread
|
||||||
@SuppressLint("SwitchIntDef")
|
@SuppressLint("SwitchIntDef")
|
||||||
public static boolean shouldDisturbUserWithCall(@NonNull Context context, @NonNull Recipient recipient) {
|
public static boolean shouldDisturbUserWithCall(@NonNull Context context, @NonNull Recipient recipient) {
|
||||||
if (Build.VERSION.SDK_INT <= 23) return true;
|
|
||||||
|
|
||||||
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
||||||
|
|
||||||
switch (notificationManager.getCurrentInterruptionFilter()) {
|
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) {
|
private static boolean handlePriority(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Recipient recipient) {
|
||||||
if (Build.VERSION.SDK_INT < 28 && !notificationManager.isNotificationPolicyAccessGranted()) {
|
if (Build.VERSION.SDK_INT < 28 && !notificationManager.isNotificationPolicyAccessGranted()) {
|
||||||
Log.w(TAG, "Notification Policy is not granted");
|
Log.w(TAG, "Notification Policy is not granted");
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import com.annimon.stream.Stream;
|
|||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
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.ConversationId;
|
||||||
|
import org.thoughtcrime.securesms.notifications.v2.DefaultMessageNotifier;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.util.BubbleUtil;
|
import org.thoughtcrime.securesms.util.BubbleUtil;
|
||||||
import org.thoughtcrime.securesms.util.ConversationUtil;
|
import org.thoughtcrime.securesms.util.ConversationUtil;
|
||||||
@@ -53,31 +53,27 @@ public final class NotificationCancellationHelper {
|
|||||||
* bubble notifications that do not have unread messages in them.
|
* bubble notifications that do not have unread messages in them.
|
||||||
*/
|
*/
|
||||||
public static void cancelAllMessageNotifications(@NonNull Context context, @NonNull Set<Integer> stickyNotifications) {
|
public static void cancelAllMessageNotifications(@NonNull Context context, @NonNull Set<Integer> stickyNotifications) {
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
try {
|
||||||
try {
|
NotificationManager notifications = ServiceUtil.getNotificationManager(context);
|
||||||
NotificationManager notifications = ServiceUtil.getNotificationManager(context);
|
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
||||||
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
int activeCount = 0;
|
||||||
int activeCount = 0;
|
|
||||||
|
|
||||||
for (StatusBarNotification activeNotification : activeNotifications) {
|
for (StatusBarNotification activeNotification : activeNotifications) {
|
||||||
if (isSingleThreadNotification(activeNotification)) {
|
if (isSingleThreadNotification(activeNotification)) {
|
||||||
activeCount++;
|
activeCount++;
|
||||||
if (!stickyNotifications.contains(activeNotification.getId()) && cancel(context, activeNotification.getId())) {
|
if (!stickyNotifications.contains(activeNotification.getId()) && cancel(context, activeNotification.getId())) {
|
||||||
activeCount--;
|
activeCount--;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeCount == 0) {
|
|
||||||
cancelLegacy(context, NotificationIds.MESSAGE_SUMMARY);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
// XXX Appears to be a ROM bug, see #6043
|
|
||||||
Log.w(TAG, "Canceling all notifications.", e);
|
|
||||||
ServiceUtil.getNotificationManager(context).cancelAll();
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cancelLegacy(context, NotificationIds.MESSAGE_SUMMARY);
|
if (activeCount == 0) {
|
||||||
|
cancelLegacy(context, NotificationIds.MESSAGE_SUMMARY);
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// XXX Appears to be a ROM bug, see #6043
|
||||||
|
Log.w(TAG, "Canceling all notifications.", e);
|
||||||
|
ServiceUtil.getNotificationManager(context).cancelAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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.
|
* @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) {
|
private static boolean isSingleThreadNotification(@NonNull StatusBarNotification statusBarNotification) {
|
||||||
return statusBarNotification.getId() != NotificationIds.MESSAGE_SUMMARY &&
|
return statusBarNotification.getId() != NotificationIds.MESSAGE_SUMMARY &&
|
||||||
Objects.equals(statusBarNotification.getNotification().getGroup(), DefaultMessageNotifier.NOTIFICATION_GROUP);
|
Objects.equals(statusBarNotification.getNotification().getGroup(), DefaultMessageNotifier.NOTIFICATION_GROUP);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.thoughtcrime.securesms.notifications
|
package org.thoughtcrime.securesms.notifications
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
@@ -76,10 +75,6 @@ object SlowNotificationHeuristics {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun shouldPromptBatterySaver(): Boolean {
|
fun shouldPromptBatterySaver(): Boolean {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val remoteEnabled = LocaleRemoteConfig.isBatterySaverPromptEnabled() || LocaleRemoteConfig.isDelayedNotificationPromptEnabled()
|
val remoteEnabled = LocaleRemoteConfig.isBatterySaverPromptEnabled() || LocaleRemoteConfig.isDelayedNotificationPromptEnabled()
|
||||||
if (!remoteEnabled || SignalStore.uiHints.hasDismissedBatterySaverPrompt()) {
|
if (!remoteEnabled || SignalStore.uiHints.hasDismissedBatterySaverPrompt()) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
@@ -16,7 +15,6 @@ import android.view.WindowManager;
|
|||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
@@ -52,10 +50,6 @@ public class Permissions {
|
|||||||
return new PermissionsBuilder(new FragmentPermissionObject(fragment));
|
return new PermissionsBuilder(new FragmentPermissionObject(fragment));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isRuntimePermissionsRequired() {
|
|
||||||
return Build.VERSION.SDK_INT >= 23;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PermissionsBuilder {
|
public static class PermissionsBuilder {
|
||||||
|
|
||||||
private final PermissionObject permissionObject;
|
private final PermissionObject permissionObject;
|
||||||
@@ -277,14 +271,12 @@ public class Permissions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasAny(@NonNull Context context, String... permissions) {
|
public static boolean hasAny(@NonNull Context context, String... permissions) {
|
||||||
return !isRuntimePermissionsRequired() ||
|
return Stream.of(permissions).anyMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
|
||||||
Stream.of(permissions).anyMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasAll(@NonNull Context context, String... permissions) {
|
public static boolean hasAll(@NonNull Context context, String... permissions) {
|
||||||
return !isRuntimePermissionsRequired() ||
|
return Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
|
||||||
Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import androidx.annotation.AnyThread;
|
|||||||
import androidx.annotation.IntRange;
|
import androidx.annotation.IntRange;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
@@ -155,7 +154,6 @@ public class BlobProvider {
|
|||||||
position));
|
position));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
public synchronized @NonNull MediaDataSource getMediaDataSource(@NonNull Context context, @NonNull Uri uri) throws IOException {
|
public synchronized @NonNull MediaDataSource getMediaDataSource(@NonNull Context context, @NonNull Uri uri) throws IOException {
|
||||||
waitUntilInitialized();
|
waitUntilInitialized();
|
||||||
return getBlobRepresentation(context,
|
return getBlobRepresentation(context,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.push
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.os.Build
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||||
import okhttp3.CipherSuite
|
import okhttp3.CipherSuite
|
||||||
@@ -33,7 +32,6 @@ import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl
|
|||||||
import org.whispersystems.signalservice.internal.configuration.SignalSvr2Url
|
import org.whispersystems.signalservice.internal.configuration.SignalSvr2Url
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
import android.net.Proxy as AndroidProxy
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a [SignalServiceConfiguration] to be used with our service layer.
|
* Provides a [SignalServiceConfiguration] to be used with our service layer.
|
||||||
@@ -142,24 +140,13 @@ class SignalServiceNetworkAccess(context: Context) {
|
|||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
private fun getSystemHttpProxy(context: Context): HttpProxy? {
|
private fun getSystemHttpProxy(context: Context): HttpProxy? {
|
||||||
return if (Build.VERSION.SDK_INT >= 23) {
|
val connectivityManager = ContextCompat.getSystemService(context, ConnectivityManager::class.java) ?: return null
|
||||||
val connectivityManager = ContextCompat.getSystemService(context, ConnectivityManager::class.java) ?: return null
|
|
||||||
|
|
||||||
connectivityManager
|
return connectivityManager
|
||||||
.activeNetwork
|
.activeNetwork
|
||||||
?.let { connectivityManager.getLinkProperties(it)?.httpProxy }
|
?.let { connectivityManager.getLinkProperties(it)?.httpProxy }
|
||||||
?.takeIf { !it.exclusionList.contains(BuildConfig.SIGNAL_URL.stripProtocol()) }
|
?.takeIf { !it.exclusionList.contains(BuildConfig.SIGNAL_URL.stripProtocol()) }
|
||||||
?.let { proxy -> HttpProxy(proxy.host, proxy.port) }
|
?.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 -> {
|
SettingsValues.CensorshipCircumventionEnabled.ENABLED -> {
|
||||||
censorshipConfiguration[countryCode] ?: defaultCensoredConfiguration
|
censorshipConfiguration[countryCode] ?: defaultCensoredConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsValues.CensorshipCircumventionEnabled.DISABLED -> {
|
SettingsValues.CensorshipCircumventionEnabled.DISABLED -> {
|
||||||
uncensoredConfiguration
|
uncensoredConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsValues.CensorshipCircumventionEnabled.DEFAULT -> {
|
SettingsValues.CensorshipCircumventionEnabled.DEFAULT -> {
|
||||||
if (defaultCensoredCountryCodes.contains(countryCode)) {
|
if (defaultCensoredCountryCodes.contains(countryCode)) {
|
||||||
censorshipConfiguration[countryCode] ?: defaultCensoredConfiguration
|
censorshipConfiguration[countryCode] ?: defaultCensoredConfiguration
|
||||||
|
|||||||
@@ -55,12 +55,7 @@ public final class SignalStrengthPhoneStateListener extends PhoneStateListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLowLevel(@NonNull SignalStrength signalStrength) {
|
private boolean isLowLevel(@NonNull SignalStrength signalStrength) {
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
return signalStrength.getLevel() == 0;
|
||||||
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 {
|
public interface Callback {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ package org.thoughtcrime.securesms.registration.ui.permissions
|
|||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.core.content.ContextCompat
|
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.
|
* Screen in account registration that provides rationales for the suggested runtime permissions.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(23)
|
|
||||||
class GrantPermissionsFragment : ComposeFragment() {
|
class GrantPermissionsFragment : ComposeFragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.thoughtcrime.securesms.LoggingFragment
|
|||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.components.ViewBinderDelegate
|
import org.thoughtcrime.securesms.components.ViewBinderDelegate
|
||||||
import org.thoughtcrime.securesms.databinding.FragmentRegistrationWelcomeV3Binding
|
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.RegistrationViewDelegate.setDebugLogSubmitMultiTapView
|
||||||
import org.thoughtcrime.securesms.registration.fragments.WelcomePermissions
|
import org.thoughtcrime.securesms.registration.fragments.WelcomePermissions
|
||||||
import org.thoughtcrime.securesms.registration.ui.RegistrationCheckpoint
|
import org.thoughtcrime.securesms.registration.ui.RegistrationCheckpoint
|
||||||
@@ -75,23 +74,21 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome_v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Permissions.isRuntimePermissionsRequired()) {
|
parentFragmentManager.setFragmentResultListener(GrantPermissionsFragment.REQUEST_KEY, viewLifecycleOwner) { requestKey, bundle ->
|
||||||
parentFragmentManager.setFragmentResultListener(GrantPermissionsFragment.REQUEST_KEY, viewLifecycleOwner) { requestKey, bundle ->
|
if (requestKey == GrantPermissionsFragment.REQUEST_KEY) {
|
||||||
if (requestKey == GrantPermissionsFragment.REQUEST_KEY) {
|
when (val userSelection = bundle.getSerializableCompat(GrantPermissionsFragment.REQUEST_KEY, WelcomeUserSelection::class.java)) {
|
||||||
when (val userSelection = bundle.getSerializableCompat(GrantPermissionsFragment.REQUEST_KEY, WelcomeUserSelection::class.java)) {
|
WelcomeUserSelection.RESTORE_WITH_OLD_PHONE,
|
||||||
WelcomeUserSelection.RESTORE_WITH_OLD_PHONE,
|
WelcomeUserSelection.RESTORE_WITH_NO_PHONE -> navigateToNextScreenViaRestore(userSelection)
|
||||||
WelcomeUserSelection.RESTORE_WITH_NO_PHONE -> navigateToNextScreenViaRestore(userSelection)
|
WelcomeUserSelection.CONTINUE -> navigateToNextScreenViaContinue()
|
||||||
WelcomeUserSelection.CONTINUE -> navigateToNextScreenViaContinue()
|
WelcomeUserSelection.LINK -> navigateToLinkDevice()
|
||||||
WelcomeUserSelection.LINK -> navigateToLinkDevice()
|
null -> Unit
|
||||||
null -> Unit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onLinkDeviceClicked() {
|
private fun onLinkDeviceClicked() {
|
||||||
if (Permissions.isRuntimePermissionsRequired() && !hasAllPermissions()) {
|
if (!hasAllPermissions()) {
|
||||||
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(WelcomeUserSelection.LINK))
|
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(WelcomeUserSelection.LINK))
|
||||||
} else {
|
} else {
|
||||||
navigateToLinkDevice()
|
navigateToLinkDevice()
|
||||||
@@ -108,7 +105,7 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome_v
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onContinueClicked() {
|
private fun onContinueClicked() {
|
||||||
if (Permissions.isRuntimePermissionsRequired() && !hasAllPermissions()) {
|
if (!hasAllPermissions()) {
|
||||||
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(WelcomeUserSelection.CONTINUE))
|
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(WelcomeUserSelection.CONTINUE))
|
||||||
} else {
|
} else {
|
||||||
navigateToNextScreenViaContinue()
|
navigateToNextScreenViaContinue()
|
||||||
@@ -129,7 +126,7 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome_v
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun afterRestoreOrTransferClicked(userSelection: WelcomeUserSelection) {
|
private fun afterRestoreOrTransferClicked(userSelection: WelcomeUserSelection) {
|
||||||
if (Permissions.isRuntimePermissionsRequired() && !hasAllPermissions()) {
|
if (!hasAllPermissions()) {
|
||||||
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(userSelection))
|
findNavController().safeNavigate(WelcomeFragmentDirections.actionWelcomeFragmentToGrantPermissionsFragment(userSelection))
|
||||||
} else {
|
} else {
|
||||||
navigateToNextScreenViaRestore(userSelection)
|
navigateToNextScreenViaRestore(userSelection)
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import android.app.Service;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
|
||||||
@@ -313,11 +312,7 @@ public class KeyCachingService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int getPendingIntentFlags() {
|
private static int getPendingIntentFlags() {
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
return PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT;
|
||||||
return PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT;
|
|
||||||
} else {
|
|
||||||
return PendingIntent.FLAG_UPDATE_CURRENT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.media.MediaDataSource;
|
|||||||
import android.media.MediaMetadataRetriever;
|
import android.media.MediaMetadataRetriever;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -16,7 +15,6 @@ public final class MediaMetadataRetrieverUtil {
|
|||||||
* {@link MediaMetadataRetriever#setDataSource(MediaDataSource)} tends to crash in native code on
|
* {@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}.
|
* specific devices, so this just a wrapper to convert that into an {@link IOException}.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(23)
|
|
||||||
public static void setDataSource(@NonNull MediaMetadataRetriever retriever,
|
public static void setDataSource(@NonNull MediaMetadataRetriever retriever,
|
||||||
@NonNull MediaDataSource dataSource)
|
@NonNull MediaDataSource dataSource)
|
||||||
throws IOException
|
throws IOException
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import android.media.MediaDataSource;
|
|||||||
import android.media.MediaMetadataRetriever;
|
import android.media.MediaMetadataRetriever;
|
||||||
import android.media.ThumbnailUtils;
|
import android.media.ThumbnailUtils;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@@ -20,7 +19,6 @@ import android.webkit.MimeTypeMap;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
import androidx.exifinterface.media.ExifInterface;
|
import androidx.exifinterface.media.ExifInterface;
|
||||||
|
|
||||||
@@ -431,7 +429,7 @@ public class MediaUtil {
|
|||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,8 +474,7 @@ public class MediaUtil {
|
|||||||
MediaUtil.isVideo(URLConnection.guessContentTypeFromName(uri.toString()))) {
|
MediaUtil.isVideo(URLConnection.guessContentTypeFromName(uri.toString()))) {
|
||||||
return ThumbnailUtils.createVideoThumbnail(uri.toString().replace("file://", ""),
|
return ThumbnailUtils.createVideoThumbnail(uri.toString().replace("file://", ""),
|
||||||
MediaStore.Video.Thumbnails.MINI_KIND);
|
MediaStore.Video.Thumbnails.MINI_KIND);
|
||||||
} else if (Build.VERSION.SDK_INT >= 23 &&
|
} else if (BlobProvider.isAuthority(uri) &&
|
||||||
BlobProvider.isAuthority(uri) &&
|
|
||||||
MediaUtil.isVideo(BlobProvider.getMimeType(uri)))
|
MediaUtil.isVideo(BlobProvider.getMimeType(uri)))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -486,8 +483,7 @@ public class MediaUtil {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, "Failed to extract frame for URI: " + uri, e);
|
Log.w(TAG, "Failed to extract frame for URI: " + uri, e);
|
||||||
}
|
}
|
||||||
} else if (Build.VERSION.SDK_INT >= 23 &&
|
} else if (PartAuthority.isAttachmentUri(uri) &&
|
||||||
PartAuthority.isAttachmentUri(uri) &&
|
|
||||||
MediaUtil.isVideoType(PartAuthority.getAttachmentContentType(context, uri)))
|
MediaUtil.isVideoType(PartAuthority.getAttachmentContentType(context, uri)))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -502,7 +498,6 @@ public class MediaUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
private static @Nullable Bitmap extractFrame(@Nullable MediaDataSource dataSource, long timeUs) throws IOException {
|
private static @Nullable Bitmap extractFrame(@Nullable MediaDataSource dataSource, long timeUs) throws IOException {
|
||||||
if (dataSource == null) {
|
if (dataSource == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -89,17 +89,13 @@ public final class NetworkUtil {
|
|||||||
public static @NonNull NetworkStatus getNetworkStatus(@NonNull Context context) {
|
public static @NonNull NetworkStatus getNetworkStatus(@NonNull Context context) {
|
||||||
ConnectivityManager connectivityManager = ServiceUtil.getConnectivityManager(context);
|
ConnectivityManager connectivityManager = ServiceUtil.getConnectivityManager(context);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
Network network = connectivityManager.getActiveNetwork();
|
||||||
Network network = connectivityManager.getActiveNetwork();
|
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
|
||||||
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
|
|
||||||
|
|
||||||
boolean onVpn = capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
boolean onVpn = capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
|
||||||
boolean isNotMetered = capabilities == null || capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
boolean isNotMetered = capabilities == null || capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
|
||||||
|
|
||||||
return new NetworkStatus(onVpn, !isNotMetered);
|
return new NetworkStatus(onVpn, !isNotMetered);
|
||||||
} else {
|
|
||||||
return new NetworkStatus(false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean useLowDataCalling(@NonNull Context context, @NonNull PeerConnection.AdapterType networkAdapter) {
|
private static boolean useLowDataCalling(@NonNull Context context, @NonNull PeerConnection.AdapterType networkAdapter) {
|
||||||
|
|||||||
@@ -3,30 +3,21 @@ package org.thoughtcrime.securesms.util;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
public class PowerManagerCompat {
|
public class PowerManagerCompat {
|
||||||
|
|
||||||
public static boolean isDeviceIdleMode(@NonNull PowerManager powerManager) {
|
public static boolean isDeviceIdleMode(@NonNull PowerManager powerManager) {
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
return powerManager.isDeviceIdleMode();
|
||||||
return powerManager.isDeviceIdleMode();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isIgnoringBatteryOptimizations(@NonNull Context context) {
|
public static boolean isIgnoringBatteryOptimizations(@NonNull Context context) {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.getPackageName());
|
return ServiceUtil.getPowerManager(context).isIgnoringBatteryOptimizations(context.getPackageName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = 23)
|
|
||||||
public static void requestIgnoreBatteryOptimizations(@NonNull Context context) {
|
public static void requestIgnoreBatteryOptimizations(@NonNull Context context) {
|
||||||
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
||||||
Uri.parse("package:" + context.getPackageName()));
|
Uri.parse("package:" + context.getPackageName()));
|
||||||
|
|||||||
@@ -659,11 +659,7 @@ public class TextSecurePreferences {
|
|||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static boolean isCallNotificationVibrateEnabled(Context context) {
|
public static boolean isCallNotificationVibrateEnabled(Context context) {
|
||||||
boolean defaultValue = true;
|
boolean defaultValue = (Settings.System.getInt(context.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 1) == 1);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
defaultValue = (Settings.System.getInt(context.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 1) == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getBooleanPreference(context, CALL_VIBRATE_PREF, defaultValue);
|
return getBooleanPreference(context, CALL_VIBRATE_PREF, defaultValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,8 +62,6 @@ public final class WindowUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void setLightStatusBarFromTheme(@NonNull Activity activity) {
|
public static void setLightStatusBarFromTheme(@NonNull Activity activity) {
|
||||||
if (Build.VERSION.SDK_INT < 23) return;
|
|
||||||
|
|
||||||
final boolean isLightStatusBar = ThemeUtil.getThemedBoolean(activity, android.R.attr.windowLightStatusBar);
|
final boolean isLightStatusBar = ThemeUtil.getThemedBoolean(activity, android.R.attr.windowLightStatusBar);
|
||||||
|
|
||||||
if (isLightStatusBar) setLightStatusBar(activity.getWindow());
|
if (isLightStatusBar) setLightStatusBar(activity.getWindow());
|
||||||
@@ -71,14 +69,10 @@ public final class WindowUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void clearLightStatusBar(@NonNull Window window) {
|
public static void clearLightStatusBar(@NonNull Window window) {
|
||||||
if (Build.VERSION.SDK_INT < 23) return;
|
|
||||||
|
|
||||||
clearSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
clearSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setLightStatusBar(@NonNull Window window) {
|
public static void setLightStatusBar(@NonNull Window window) {
|
||||||
if (Build.VERSION.SDK_INT < 23) return;
|
|
||||||
|
|
||||||
setSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
setSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,8 @@ package org.thoughtcrime.securesms.video;
|
|||||||
|
|
||||||
import android.media.MediaDataSource;
|
import android.media.MediaDataSource;
|
||||||
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
public class ByteArrayMediaDataSource extends MediaDataSource {
|
public class ByteArrayMediaDataSource extends MediaDataSource {
|
||||||
|
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.video;
|
|||||||
import android.media.MediaDataSource;
|
import android.media.MediaDataSource;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
|
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
|
||||||
@@ -13,7 +12,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
final class ClassicEncryptedMediaDataSource extends MediaDataSource {
|
final class ClassicEncryptedMediaDataSource extends MediaDataSource {
|
||||||
|
|
||||||
private final AttachmentSecret attachmentSecret;
|
private final AttachmentSecret attachmentSecret;
|
||||||
|
|||||||
@@ -4,13 +4,11 @@ import android.media.MediaDataSource;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
public final class EncryptedMediaDataSource {
|
public final class EncryptedMediaDataSource {
|
||||||
|
|
||||||
public static MediaDataSource createFor(@NonNull AttachmentSecret attachmentSecret, @NonNull File mediaFile, @Nullable byte[] random, long length) {
|
public static MediaDataSource createFor(@NonNull AttachmentSecret attachmentSecret, @NonNull File mediaFile, @Nullable byte[] random, long length) {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.media.MediaDataSource;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
|
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
|
* 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.
|
* the presence of a random part of the key supplied in the constructor.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(23)
|
|
||||||
final class ModernEncryptedMediaDataSource extends InputStreamMediaDataSource {
|
final class ModernEncryptedMediaDataSource extends InputStreamMediaDataSource {
|
||||||
|
|
||||||
private final AttachmentSecret attachmentSecret;
|
private final AttachmentSecret attachmentSecret;
|
||||||
|
|||||||
@@ -172,33 +172,26 @@ public abstract class AudioManagerCompat {
|
|||||||
audioManager.clearCommunicationDevice();
|
audioManager.clearCommunicationDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
public void registerAudioDeviceCallback(@NonNull AudioDeviceCallback deviceCallback, @NonNull Handler handler) {
|
public void registerAudioDeviceCallback(@NonNull AudioDeviceCallback deviceCallback, @NonNull Handler handler) {
|
||||||
audioManager.registerAudioDeviceCallback(deviceCallback, handler);
|
audioManager.registerAudioDeviceCallback(deviceCallback, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
public void unregisterAudioDeviceCallback(@NonNull AudioDeviceCallback deviceCallback) {
|
public void unregisterAudioDeviceCallback(@NonNull AudioDeviceCallback deviceCallback) {
|
||||||
audioManager.unregisterAudioDeviceCallback(deviceCallback);
|
audioManager.unregisterAudioDeviceCallback(deviceCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("WrongConstant")
|
@SuppressLint("WrongConstant")
|
||||||
public boolean isWiredHeadsetOn() {
|
public boolean isWiredHeadsetOn() {
|
||||||
if (Build.VERSION.SDK_INT < 23) {
|
AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
|
||||||
//noinspection deprecation
|
for (AudioDeviceInfo device : devices) {
|
||||||
return audioManager.isWiredHeadsetOn();
|
final int type = device.getType();
|
||||||
} else {
|
if (type == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
|
||||||
AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
|
return true;
|
||||||
for (AudioDeviceInfo device : devices) {
|
} else if (type == AudioDeviceInfo.TYPE_USB_DEVICE) {
|
||||||
final int type = device.getType();
|
return true;
|
||||||
if (type == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
|
|
||||||
return true;
|
|
||||||
} else if (type == AudioDeviceInfo.TYPE_USB_DEVICE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float ringVolumeWithMinimum() {
|
public float ringVolumeWithMinimum() {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import android.app.ActivityManager
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Debug
|
import android.os.Debug
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import org.signal.core.util.concurrent.SignalExecutors
|
import org.signal.core.util.concurrent.SignalExecutors
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
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.
|
* 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.
|
* As a result, we don't want to be calling this regularly for most users.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(23)
|
|
||||||
fun getDetailedMemoryStats(): DetailedMemoryStats {
|
fun getDetailedMemoryStats(): DetailedMemoryStats {
|
||||||
Debug.getMemoryInfo(debugMemoryInfo)
|
Debug.getMemoryInfo(debugMemoryInfo)
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,6 @@ object PendingIntentFlags {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun immutable(): Int {
|
fun immutable(): Int {
|
||||||
return if (Build.VERSION.SDK_INT >= 23) PendingIntent.FLAG_IMMUTABLE else 0
|
return PendingIntent.FLAG_IMMUTABLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
findViewById(R.id.stop).setOnClickListener(v -> DeviceToDeviceTransferService.stop(this));
|
findViewById(R.id.stop).setOnClickListener(v -> DeviceToDeviceTransferService.stop(this));
|
||||||
|
|
||||||
findViewById(R.id.enable_permission).setOnClickListener(v -> {
|
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);
|
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 420);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -92,13 +92,13 @@ public final class WifiDirect {
|
|||||||
if (Build.VERSION.SDK_INT >= 33 && context.checkSelfPermission(Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
|
if (Build.VERSION.SDK_INT >= 33 && context.checkSelfPermission(Manifest.permission.NEARBY_WIFI_DEVICES) != PackageManager.PERMISSION_GRANTED) {
|
||||||
Log.i(TAG, "Nearby Wifi permission required");
|
Log.i(TAG, "Nearby Wifi permission required");
|
||||||
return AvailableStatus.REQUIRED_PERMISSION_NOT_GRANTED;
|
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");
|
Log.i(TAG, "Fine location permission required");
|
||||||
return AvailableStatus.REQUIRED_PERMISSION_NOT_GRANTED;
|
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;
|
: AvailableStatus.WIFI_DIRECT_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WifiDirect(@NonNull Context context) {
|
WifiDirect(@NonNull Context context) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.signal.qrtest
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
@@ -73,9 +72,7 @@ class QrMainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
text = findViewById(R.id.log)
|
text = findViewById(R.id.log)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
requestPermissions(arrayOf(android.Manifest.permission.CAMERA), 1)
|
||||||
requestPermissions(arrayOf(android.Manifest.permission.CAMERA), 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
val scanner = findViewById<QrScannerView>(R.id.scanner)
|
val scanner = findViewById<QrScannerView>(R.id.scanner)
|
||||||
scanner.start(this)
|
scanner.start(this)
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ import androidx.annotation.StringDef;
|
|||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
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.MediaInput;
|
||||||
import org.thoughtcrime.securesms.video.interfaces.Muxer;
|
import org.thoughtcrime.securesms.video.interfaces.Muxer;
|
||||||
|
import org.thoughtcrime.securesms.video.videoconverter.exceptions.EncodingException;
|
||||||
import org.thoughtcrime.securesms.video.videoconverter.muxer.StreamingMuxer;
|
import org.thoughtcrime.securesms.video.videoconverter.muxer.StreamingMuxer;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -142,7 +142,6 @@ public final class MediaConverter {
|
|||||||
* @return The total content size of the MP4 mdat box.
|
* @return The total content size of the MP4 mdat box.
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
@RequiresApi(23)
|
|
||||||
public long convert() throws EncodingException, IOException {
|
public long convert() throws EncodingException, IOException {
|
||||||
// Exception that may be thrown during release.
|
// Exception that may be thrown during release.
|
||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import android.view.Surface;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.video.interfaces.MediaInput;
|
import org.thoughtcrime.securesms.video.interfaces.MediaInput;
|
||||||
@@ -78,7 +77,6 @@ final class VideoTrackConverter {
|
|||||||
|
|
||||||
private Muxer mMuxer;
|
private Muxer mMuxer;
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
static @Nullable VideoTrackConverter create(
|
static @Nullable VideoTrackConverter create(
|
||||||
final @NonNull MediaInput input,
|
final @NonNull MediaInput input,
|
||||||
final long timeFrom,
|
final long timeFrom,
|
||||||
@@ -97,7 +95,6 @@ final class VideoTrackConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
private VideoTrackConverter(
|
private VideoTrackConverter(
|
||||||
final @NonNull MediaExtractor videoExtractor,
|
final @NonNull MediaExtractor videoExtractor,
|
||||||
final int videoInputTrack,
|
final int videoInputTrack,
|
||||||
|
|||||||
@@ -6,14 +6,12 @@
|
|||||||
package org.thoughtcrime.securesms.video.videoconverter.mediadatasource
|
package org.thoughtcrime.securesms.video.videoconverter.mediadatasource
|
||||||
|
|
||||||
import android.media.MediaDataSource
|
import android.media.MediaDataSource
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend this class in order to be able to use the system media framework with any arbitrary [InputStream] of bytes.
|
* 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() {
|
abstract class InputStreamMediaDataSource : MediaDataSource() {
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
override fun readAt(position: Long, bytes: ByteArray?, offset: Int, length: Int): Int {
|
override fun readAt(position: Long, bytes: ByteArray?, offset: Int, length: Int): Int {
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ package org.thoughtcrime.securesms.video.videoconverter.mediadatasource
|
|||||||
|
|
||||||
import android.media.MediaDataSource
|
import android.media.MediaDataSource
|
||||||
import android.media.MediaExtractor
|
import android.media.MediaExtractor
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import org.thoughtcrime.securesms.video.interfaces.MediaInput
|
import org.thoughtcrime.securesms.video.interfaces.MediaInput
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [MediaInput] implementation that adds support for the system framework's media data source.
|
* [MediaInput] implementation that adds support for the system framework's media data source.
|
||||||
*/
|
*/
|
||||||
@RequiresApi(23)
|
|
||||||
class MediaDataSourceMediaInput(private val mediaDataSource: MediaDataSource) : MediaInput {
|
class MediaDataSourceMediaInput(private val mediaDataSource: MediaDataSource) : MediaInput {
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
override fun createExtractor(): MediaExtractor {
|
override fun createExtractor(): MediaExtractor {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import android.media.MediaCodecInfo.CodecProfileLevel
|
|||||||
import android.media.MediaCodecList
|
import android.media.MediaCodecList
|
||||||
import android.media.MediaFormat
|
import android.media.MediaFormat
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import java.io.IOException
|
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
|
// 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.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_HEVC)
|
||||||
mediaFormat.setInteger(MediaFormat.KEY_PROFILE, CodecProfileLevel.HEVCProfileMain10)
|
mediaFormat.setInteger(MediaFormat.KEY_PROFILE, CodecProfileLevel.HEVCProfileMain10)
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
mediaFormat.setBaseCodecLevelFromDolbyVisionLevel()
|
||||||
mediaFormat.setBaseCodecLevelFromDolbyVisionLevel()
|
|
||||||
}
|
|
||||||
return findDecoder(mediaFormat)
|
return findDecoder(mediaFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,9 +84,7 @@ object MediaCodecCompat {
|
|||||||
// dolby vision profile 09: Base layer is H.264 High/Progressive/Constrained Profile, Rec 709
|
// 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.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC)
|
||||||
mediaFormat.setInteger(MediaFormat.KEY_PROFILE, CodecProfileLevel.AVCProfileHigh)
|
mediaFormat.setInteger(MediaFormat.KEY_PROFILE, CodecProfileLevel.AVCProfileHigh)
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
mediaFormat.setBaseCodecLevelFromDolbyVisionLevel()
|
||||||
mediaFormat.setBaseCodecLevelFromDolbyVisionLevel()
|
|
||||||
}
|
|
||||||
return findDecoder(mediaFormat)
|
return findDecoder(mediaFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +95,6 @@ object MediaCodecCompat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
|
||||||
private fun MediaFormat.setBaseCodecLevelFromDolbyVisionLevel(): Boolean {
|
private fun MediaFormat.setBaseCodecLevelFromDolbyVisionLevel(): Boolean {
|
||||||
val mimeType = this.getString(MediaFormat.KEY_MIME) ?: return false
|
val mimeType = this.getString(MediaFormat.KEY_MIME) ?: return false
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user