use of androidx.annotation.RequiresApi in project Signal-Android by WhisperSystems.
the class MediaConverter method convert.
@WorkerThread
@RequiresApi(23)
public void convert() throws EncodingException, IOException {
// Exception that may be thrown during release.
Exception exception = null;
Muxer muxer = null;
VideoTrackConverter videoTrackConverter = null;
AudioTrackConverter audioTrackConverter = null;
try {
videoTrackConverter = VideoTrackConverter.create(mInput, mTimeFrom, mTimeTo, mVideoResolution, mVideoBitrate, mVideoCodec);
audioTrackConverter = AudioTrackConverter.create(mInput, mTimeFrom, mTimeTo, mAudioBitrate);
if (videoTrackConverter == null && audioTrackConverter == null) {
throw new EncodingException("No video and audio tracks");
}
muxer = mOutput.createMuxer();
doExtractDecodeEditEncodeMux(videoTrackConverter, audioTrackConverter, muxer);
} catch (EncodingException | IOException e) {
Log.e(TAG, "error converting", e);
exception = e;
throw e;
} catch (Exception e) {
Log.e(TAG, "error converting", e);
exception = e;
} finally {
if (VERBOSE)
Log.d(TAG, "releasing extractor, decoder, encoder, and muxer");
// all other exceptions appear in the logs.
try {
if (videoTrackConverter != null) {
videoTrackConverter.release();
}
} catch (Exception e) {
if (exception == null) {
exception = e;
}
}
try {
if (audioTrackConverter != null) {
audioTrackConverter.release();
}
} catch (Exception e) {
if (exception == null) {
exception = e;
}
}
try {
if (muxer != null) {
muxer.stop();
muxer.release();
}
} catch (Exception e) {
Log.e(TAG, "error while releasing muxer", e);
if (exception == null) {
exception = e;
}
}
}
if (exception != null) {
throw new EncodingException("Transcode failed", exception);
}
}
use of androidx.annotation.RequiresApi in project Signal-Android by WhisperSystems.
the class KeyStoreHelper method unseal.
@RequiresApi(Build.VERSION_CODES.M)
public static byte[] unseal(@NonNull SealedData sealedData) {
SecretKey secretKey = getKeyStoreEntry();
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv));
return cipher.doFinal(sealedData.data);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
use of androidx.annotation.RequiresApi in project Signal-Android by WhisperSystems.
the class KeyStoreHelper method createKeyStoreEntry.
@RequiresApi(Build.VERSION_CODES.M)
private static SecretKey createKeyStoreEntry() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).setBlockModes(KeyProperties.BLOCK_MODE_GCM).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE).build();
keyGenerator.init(keyGenParameterSpec);
return keyGenerator.generateKey();
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
throw new AssertionError(e);
}
}
use of androidx.annotation.RequiresApi in project Signal-Android by WhisperSystems.
the class NotificationCancellationHelper method isCancellable.
/**
* Checks whether the conversation for the given notification is allowed to be represented as a bubble.
*
* see {@link BubbleUtil#canBubble} for more information.
*/
@RequiresApi(ConversationUtil.CONVERSATION_SUPPORT_VERSION)
private static boolean isCancellable(@NonNull Context context, int notificationId) {
NotificationManager manager = ServiceUtil.getNotificationManager(context);
StatusBarNotification[] notifications = manager.getActiveNotifications();
Notification notification = Stream.of(notifications).filter(n -> n.getId() == notificationId).findFirst().map(StatusBarNotification::getNotification).orElse(null);
if (notification == null || notification.getShortcutId() == null || notification.getBubbleMetadata() == null) {
Log.d(TAG, "isCancellable: bubbles not available or notification does not exist");
return true;
}
RecipientId recipientId = ConversationUtil.getRecipientId(notification.getShortcutId());
if (recipientId == null) {
Log.d(TAG, "isCancellable: Unable to get recipient from shortcut id");
return true;
}
Long threadId = SignalDatabase.threads().getThreadIdFor(recipientId);
long focusedThreadId = ApplicationDependencies.getMessageNotifier().getVisibleThread();
if (Objects.equals(threadId, focusedThreadId)) {
Log.d(TAG, "isCancellable: user entered full screen thread.");
return true;
}
return !BubbleUtil.canBubble(context, recipientId, threadId);
}
use of androidx.annotation.RequiresApi in project Signal-Android by WhisperSystems.
the class VideoEditorHud method setVideoSource.
@RequiresApi(api = 23)
public void setVideoSource(@NonNull VideoSlide slide, @NonNull VideoBitRateCalculator videoBitRateCalculator, long maxSendSize) throws IOException {
Uri uri = slide.getUri();
if (uri == null || !slide.hasVideo()) {
return;
}
videoTimeLine.setInput(DecryptableUriMediaInput.createForUri(getContext(), uri));
long size = tryGetUriSize(getContext(), uri, Long.MAX_VALUE);
if (size > maxSendSize) {
videoTimeLine.setTimeLimit(VideoUtil.getMaxVideoUploadDurationInSeconds(), TimeUnit.SECONDS);
}
videoTimeLine.setOnRangeChangeListener(new VideoThumbnailsRangeSelectorView.OnRangeChangeListener() {
@Override
public void onPositionDrag(long position) {
if (eventListener != null) {
eventListener.onSeek(position, false);
}
}
@Override
public void onEndPositionDrag(long position) {
if (eventListener != null) {
eventListener.onSeek(position, true);
}
}
@Override
public void onRangeDrag(long minValueUs, long maxValueUs, long durationUs, VideoThumbnailsRangeSelectorView.Thumb thumb) {
if (eventListener != null) {
eventListener.onEditVideoDuration(durationUs, minValueUs, maxValueUs, thumb == VideoThumbnailsRangeSelectorView.Thumb.MIN, false);
}
}
@Override
public void onRangeDragEnd(long minValueUs, long maxValueUs, long durationUs, VideoThumbnailsRangeSelectorView.Thumb thumb) {
if (eventListener != null) {
eventListener.onEditVideoDuration(durationUs, minValueUs, maxValueUs, thumb == VideoThumbnailsRangeSelectorView.Thumb.MIN, true);
}
}
@Override
public VideoThumbnailsRangeSelectorView.Quality getQuality(long clipDurationUs, long totalDurationUs) {
int inputBitRate = VideoBitRateCalculator.bitRate(size, TimeUnit.MICROSECONDS.toMillis(totalDurationUs));
VideoBitRateCalculator.Quality targetQuality = videoBitRateCalculator.getTargetQuality(TimeUnit.MICROSECONDS.toMillis(clipDurationUs), inputBitRate);
return new VideoThumbnailsRangeSelectorView.Quality(targetQuality.getFileSizeEstimate(), (int) (100 * targetQuality.getQuality()));
}
});
}
Aggregations