update to 9.5.8

This commit is contained in:
xaxtix 2023-04-03 17:15:52 +04:00
parent 7e6d40a77a
commit 683c4e6dcb
25 changed files with 399 additions and 336 deletions

View file

@ -435,7 +435,7 @@ target_include_directories(breakpad PUBLIC
#voip
include(${CMAKE_HOME_DIRECTORY}/voip/CMakeLists.txt)
set(NATIVE_LIB "tmessages.43")
set(NATIVE_LIB "tmessages.44")
#tmessages
add_library(${NATIVE_LIB} SHARED

View file

@ -13,47 +13,48 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <android/log.h>
#include <jni.h>
#include <stdlib.h>
#include <android/log.h>
extern "C" {
#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#ifdef _STDINT_H
#undef _STDINT_H
#endif
#include <stdint.h>
#endif
#include <libavcodec/avcodec.h>
#include <libavresample/avresample.h>
#include <libavutil/channel_layout.h>
#include <libavutil/error.h>
#include <libavutil/opt.h>
#include <libswresample/swresample.h>
}
#define LOG_TAG "ffmpeg_jni"
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
__VA_ARGS__))
#define LOGE(...) \
((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__)
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
#define AUDIO_DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__)
#define ERROR_STRING_BUFFER_LENGTH 256
@ -62,14 +63,13 @@ static const AVSampleFormat OUTPUT_FORMAT_PCM_16BIT = AV_SAMPLE_FMT_S16;
// Output format corresponding to AudioFormat.ENCODING_PCM_FLOAT.
static const AVSampleFormat OUTPUT_FORMAT_PCM_FLOAT = AV_SAMPLE_FMT_FLT;
// Error codes matching FfmpegDecoder.java.
static const int DECODER_ERROR_INVALID_DATA = -1;
static const int DECODER_ERROR_OTHER = -2;
static const int AUDIO_DECODER_ERROR_INVALID_DATA = -1;
static const int AUDIO_DECODER_ERROR_OTHER = -2;
/**
* Returns the AVCodec with the specified name, or NULL if it is not available.
*/
AVCodec *getCodecByName(JNIEnv* env, jstring codecName);
AVCodec *getCodecByName(JNIEnv *env, jstring codecName);
/**
* Allocates and opens a new AVCodecContext for the specified codec, passing the
@ -82,11 +82,17 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
/**
* Decodes the packet into the output buffer, returning the number of bytes
* written, or a negative DECODER_ERROR constant value in the case of an error.
* written, or a negative AUDIO_DECODER_ERROR constant value in the case of an
* error.
*/
int decodePacket(AVCodecContext *context, AVPacket *packet,
uint8_t *outputBuffer, int outputSize);
/**
* Transforms ffmpeg AVERROR into a negative AUDIO_DECODER_ERROR constant value.
*/
int transformError(int errorNumber);
/**
* Outputs a log message describing the avcodec error number.
*/
@ -101,12 +107,17 @@ LIBRARY_FUNC(jstring, ffmpegGetVersion) {
return env->NewStringUTF(LIBAVCODEC_IDENT);
}
LIBRARY_FUNC(jint, ffmpegGetInputBufferPaddingSize) {
return (jint)AV_INPUT_BUFFER_PADDING_SIZE;
}
LIBRARY_FUNC(jboolean, ffmpegHasDecoder, jstring codecName) {
return getCodecByName(env, codecName) != NULL;
}
DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
jboolean outputFloat, jint rawSampleRate, jint rawChannelCount) {
AUDIO_DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName,
jbyteArray extraData, jboolean outputFloat,
jint rawSampleRate, jint rawChannelCount) {
AVCodec *codec = getCodecByName(env, codecName);
if (!codec) {
LOGE("Codec not found.");
@ -116,8 +127,8 @@ DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
rawChannelCount);
}
DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
jint inputSize, jobject outputData, jint outputSize) {
AUDIO_DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
jint inputSize, jobject outputData, jint outputSize) {
if (!context) {
LOGE("Context must be non-NULL.");
return -1;
@ -134,34 +145,34 @@ DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
LOGE("Invalid output buffer length: %d", outputSize);
return -1;
}
uint8_t *inputBuffer = (uint8_t *) env->GetDirectBufferAddress(inputData);
uint8_t *outputBuffer = (uint8_t *) env->GetDirectBufferAddress(outputData);
uint8_t *inputBuffer = (uint8_t *)env->GetDirectBufferAddress(inputData);
uint8_t *outputBuffer = (uint8_t *)env->GetDirectBufferAddress(outputData);
AVPacket packet;
av_init_packet(&packet);
packet.data = inputBuffer;
packet.size = inputSize;
return decodePacket((AVCodecContext *) context, &packet, outputBuffer,
return decodePacket((AVCodecContext *)context, &packet, outputBuffer,
outputSize);
}
DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
AUDIO_DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
if (!context) {
LOGE("Context must be non-NULL.");
return -1;
}
return ((AVCodecContext *) context)->channels;
return ((AVCodecContext *)context)->channels;
}
DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
AUDIO_DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
if (!context) {
LOGE("Context must be non-NULL.");
return -1;
}
return ((AVCodecContext *) context)->sample_rate;
return ((AVCodecContext *)context)->sample_rate;
}
DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
AVCodecContext *context = (AVCodecContext *) jContext;
AUDIO_DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
AVCodecContext *context = (AVCodecContext *)jContext;
if (!context) {
LOGE("Tried to reset without a context.");
return 0L;
@ -178,23 +189,23 @@ DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
return 0L;
}
jboolean outputFloat =
(jboolean)(context->request_sample_fmt == OUTPUT_FORMAT_PCM_FLOAT);
(jboolean)(context->request_sample_fmt == OUTPUT_FORMAT_PCM_FLOAT);
return (jlong)createContext(env, codec, extraData, outputFloat,
/* rawSampleRate= */ -1,
/* rawChannelCount= */ -1);
/* rawSampleRate= */ -1,
/* rawChannelCount= */ -1);
}
avcodec_flush_buffers(context);
return (jlong) context;
return (jlong)context;
}
DECODER_FUNC(void, ffmpegRelease, jlong context) {
AUDIO_DECODER_FUNC(void, ffmpegRelease, jlong context) {
if (context) {
releaseContext((AVCodecContext *) context);
releaseContext((AVCodecContext *)context);
}
}
AVCodec *getCodecByName(JNIEnv* env, jstring codecName) {
AVCodec *getCodecByName(JNIEnv *env, jstring codecName) {
if (!codecName) {
return NULL;
}
@ -213,18 +224,18 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
return NULL;
}
context->request_sample_fmt =
outputFloat ? OUTPUT_FORMAT_PCM_FLOAT : OUTPUT_FORMAT_PCM_16BIT;
outputFloat ? OUTPUT_FORMAT_PCM_FLOAT : OUTPUT_FORMAT_PCM_16BIT;
if (extraData) {
jsize size = env->GetArrayLength(extraData);
context->extradata_size = size;
context->extradata =
(uint8_t *) av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
(uint8_t *)av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!context->extradata) {
LOGE("Failed to allocate extradata.");
releaseContext(context);
return NULL;
}
env->GetByteArrayRegion(extraData, 0, size, (jbyte *) context->extradata);
env->GetByteArrayRegion(extraData, 0, size, (jbyte *)context->extradata);
}
if (context->codec_id == AV_CODEC_ID_PCM_MULAW ||
context->codec_id == AV_CODEC_ID_PCM_ALAW) {
@ -249,8 +260,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
result = avcodec_send_packet(context, packet);
if (result) {
logError("avcodec_send_packet", result);
return result == AVERROR_INVALIDDATA ? DECODER_ERROR_INVALID_DATA
: DECODER_ERROR_OTHER;
return transformError(result);
}
// Dequeue output data until it runs out.
@ -259,7 +269,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
AVFrame *frame = av_frame_alloc();
if (!frame) {
LOGE("Failed to allocate output frame.");
return -1;
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
result = avcodec_receive_frame(context, frame);
if (result) {
@ -268,7 +278,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
break;
}
logError("avcodec_receive_frame", result);
return result;
return transformError(result);
}
// Resample output.
@ -279,50 +289,49 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
int sampleCount = frame->nb_samples;
int dataSize = av_samples_get_buffer_size(NULL, channelCount, sampleCount,
sampleFormat, 1);
AVAudioResampleContext *resampleContext;
SwrContext *resampleContext;
if (context->opaque) {
resampleContext = (AVAudioResampleContext *) context->opaque;
resampleContext = (SwrContext *)context->opaque;
} else {
resampleContext = avresample_alloc_context();
av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
resampleContext = swr_alloc();
av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
av_opt_set_int(resampleContext, "out_channel_layout", channelLayout, 0);
av_opt_set_int(resampleContext, "in_sample_rate", sampleRate, 0);
av_opt_set_int(resampleContext, "out_sample_rate", sampleRate, 0);
av_opt_set_int(resampleContext, "in_sample_fmt", sampleFormat, 0);
// The output format is always the requested format.
av_opt_set_int(resampleContext, "out_sample_fmt",
context->request_sample_fmt, 0);
result = avresample_open(resampleContext);
context->request_sample_fmt, 0);
result = swr_init(resampleContext);
if (result < 0) {
logError("avresample_open", result);
logError("swr_init", result);
av_frame_free(&frame);
return -1;
return transformError(result);
}
context->opaque = resampleContext;
}
int inSampleSize = av_get_bytes_per_sample(sampleFormat);
int outSampleSize = av_get_bytes_per_sample(context->request_sample_fmt);
int outSamples = avresample_get_out_samples(resampleContext, sampleCount);
int outSamples = swr_get_out_samples(resampleContext, sampleCount);
int bufferOutSize = outSampleSize * channelCount * outSamples;
if (outSize + bufferOutSize > outputSize) {
LOGE("Output buffer size (%d) too small for output data (%d).",
outputSize, outSize + bufferOutSize);
av_frame_free(&frame);
return -1;
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
result = avresample_convert(resampleContext, &outputBuffer, bufferOutSize,
outSamples, frame->data, frame->linesize[0],
sampleCount);
result = swr_convert(resampleContext, &outputBuffer, bufferOutSize,
(const uint8_t **)frame->data, frame->nb_samples);
av_frame_free(&frame);
if (result < 0) {
logError("avresample_convert", result);
return result;
logError("swr_convert", result);
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
int available = avresample_available(resampleContext);
int available = swr_get_out_samples(resampleContext, 0);
if (available != 0) {
LOGE("Expected no samples remaining after resampling, but found %d.",
available);
return -1;
return AUDIO_DECODER_ERROR_INVALID_DATA;
}
outputBuffer += bufferOutSize;
outSize += bufferOutSize;
@ -330,8 +339,13 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
return outSize;
}
int transformError(int errorNumber) {
return errorNumber == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA
: AUDIO_DECODER_ERROR_OTHER;
}
void logError(const char *functionName, int errorNumber) {
char *buffer = (char *) malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);
LOGE("Error in %s: %s", functionName, buffer);
free(buffer);
@ -341,11 +355,10 @@ void releaseContext(AVCodecContext *context) {
if (!context) {
return;
}
AVAudioResampleContext *resampleContext;
if ((resampleContext = (AVAudioResampleContext *) context->opaque)) {
avresample_free(&resampleContext);
SwrContext *swrContext;
if ((swrContext = (SwrContext *)context->opaque)) {
swr_free(&swrContext);
context->opaque = NULL;
}
avcodec_free_context(&context);
}

View file

@ -29,13 +29,13 @@
#define ALOGV(...) \
((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_flac_FlacDecoderJni_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_flac_FlacDecoderJni_##NAME( \
JNIEnv *env, jobject thiz, ##__VA_ARGS__)
@ -47,6 +47,7 @@ public:
if (mid == NULL) {
jclass cls = env->GetObjectClass(flacDecoderJni);
mid = env->GetMethodID(cls, "read", "(Ljava/nio/ByteBuffer;)I");
env->DeleteLocalRef(cls);
}
}
@ -57,6 +58,7 @@ public:
// Exception is thrown in Java when returning from the native call.
result = -1;
}
env->DeleteLocalRef(byteBuffer);
return result;
}
@ -147,7 +149,7 @@ DECODER_FUNC(jobject, flacDecodeMetadata, jlong jContext) {
context->parser->getStreamInfo();
jclass flacStreamMetadataClass = env->FindClass(
"com/google/android/exoplayer2/util/"
"com/google/android/exoplayer2/extractor/"
"FlacStreamMetadata");
jmethodID flacStreamMetadataConstructor =
env->GetMethodID(flacStreamMetadataClass, "<init>",

View file

@ -16,9 +16,8 @@
#include "include/flac_parser.h"
#include <jni.h>
#include <android/log.h>
#include <jni.h>
#include <cassert>
#include <cstdlib>
@ -431,7 +430,7 @@ bool FLACParser::getSeekPositions(int64_t timeUs,
targetSampleNumber = totalSamples - 1;
}
FLAC__StreamMetadata_SeekPoint* points = mSeekTable->points;
FLAC__StreamMetadata_SeekPoint *points = mSeekTable->points;
unsigned length = mSeekTable->num_points;
for (unsigned i = length; i != 0; i--) {

View file

@ -14,143 +14,166 @@
* limitations under the License.
*/
#ifdef __ANDROID__
#include <android/log.h>
#endif
#include <jni.h>
#include <android/log.h>
#include <cstdint>
#include <cstdlib>
#include "opus.h" // NOLINT
#include "opus.h" // NOLINT
#include "opus_multistream.h" // NOLINT
#ifdef __ANDROID__
#define LOG_TAG "opus_jni"
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
__VA_ARGS__))
#define LOGE(...) \
((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
#else // __ANDROID__
#define LOGE(...) \
do { \
} while (0)
#endif // __ANDROID__
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_##NAME( \
JNIEnv* env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_##NAME( \
JNIEnv* env, jobject thiz, ##__VA_ARGS__)
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_##NAME( \
JNIEnv* env, jobject thiz, ##__VA_ARGS__); \
} \
JNIEXPORT RETURN_TYPE \
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_##NAME( \
JNIEnv* env, jobject thiz, ##__VA_ARGS__)
// JNI references for SimpleOutputBuffer class.
static jmethodID outputBufferInit;
static const int kBytesPerSample = 2; // opus fixed point uses 16 bit samples.
static const int kBytesPerIntPcmSample = 2;
static const int kBytesPerFloatSample = 4;
static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
static int channelCount;
static int errorCode;
static bool outputFloat = false;
DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount,
jint numStreams, jint numCoupled, jint gain, jbyteArray jStreamMap) {
int status = OPUS_INVALID_STATE;
::channelCount = channelCount;
errorCode = 0;
jbyte* streamMapBytes = env->GetByteArrayElements(jStreamMap, 0);
uint8_t* streamMap = reinterpret_cast<uint8_t*>(streamMapBytes);
OpusMSDecoder* decoder = opus_multistream_decoder_create(
sampleRate, channelCount, numStreams, numCoupled, streamMap, &status);
env->ReleaseByteArrayElements(jStreamMap, streamMapBytes, 0);
if (!decoder || status != OPUS_OK) {
LOGE("Failed to create Opus Decoder; status=%s", opus_strerror(status));
return 0;
}
status = opus_multistream_decoder_ctl(decoder, OPUS_SET_GAIN(gain));
if (status != OPUS_OK) {
LOGE("Failed to set Opus header gain; status=%s", opus_strerror(status));
return 0;
}
jint numStreams, jint numCoupled, jint gain,
jbyteArray jStreamMap) {
int status = OPUS_INVALID_STATE;
::channelCount = channelCount;
errorCode = 0;
jbyte* streamMapBytes = env->GetByteArrayElements(jStreamMap, 0);
uint8_t* streamMap = reinterpret_cast<uint8_t*>(streamMapBytes);
OpusMSDecoder* decoder = opus_multistream_decoder_create(
sampleRate, channelCount, numStreams, numCoupled, streamMap, &status);
env->ReleaseByteArrayElements(jStreamMap, streamMapBytes, 0);
if (!decoder || status != OPUS_OK) {
LOGE("Failed to create Opus Decoder; status=%s", opus_strerror(status));
return 0;
}
status = opus_multistream_decoder_ctl(decoder, OPUS_SET_GAIN(gain));
if (status != OPUS_OK) {
LOGE("Failed to set Opus header gain; status=%s", opus_strerror(status));
return 0;
}
// Populate JNI References.
const jclass outputBufferClass = env->FindClass(
"com/google/android/exoplayer2/decoder/SimpleOutputBuffer");
outputBufferInit = env->GetMethodID(outputBufferClass, "init",
"(JI)Ljava/nio/ByteBuffer;");
// Populate JNI References.
const jclass outputBufferClass = env->FindClass(
"com/google/android/exoplayer2/decoder/SimpleDecoderOutputBuffer");
outputBufferInit =
env->GetMethodID(outputBufferClass, "init", "(JI)Ljava/nio/ByteBuffer;");
return reinterpret_cast<intptr_t>(decoder);
return reinterpret_cast<intptr_t>(decoder);
}
DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs,
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer) {
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
const uint8_t* inputBuffer =
reinterpret_cast<const uint8_t*>(
env->GetDirectBufferAddress(jInputBuffer));
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
const uint8_t* inputBuffer = reinterpret_cast<const uint8_t*>(
env->GetDirectBufferAddress(jInputBuffer));
const jint outputSize =
kMaxOpusOutputPacketSizeSamples * kBytesPerSample * channelCount;
const int byteSizePerSample =
outputFloat ? kBytesPerFloatSample : kBytesPerIntPcmSample;
const jint outputSize =
kMaxOpusOutputPacketSizeSamples * byteSizePerSample * channelCount;
env->CallObjectMethod(jOutputBuffer, outputBufferInit, jTimeUs, outputSize);
if (env->ExceptionCheck()) {
// Exception is thrown in Java when returning from the native call.
return -1;
}
const jobject jOutputBufferData = env->CallObjectMethod(jOutputBuffer,
outputBufferInit, jTimeUs, outputSize);
if (env->ExceptionCheck()) {
// Exception is thrown in Java when returning from the native call.
return -1;
}
env->CallObjectMethod(jOutputBuffer, outputBufferInit, jTimeUs, outputSize);
if (env->ExceptionCheck()) {
// Exception is thrown in Java when returning from the native call.
return -1;
}
const jobject jOutputBufferData = env->CallObjectMethod(
jOutputBuffer, outputBufferInit, jTimeUs, outputSize);
if (env->ExceptionCheck()) {
// Exception is thrown in Java when returning from the native call.
return -1;
}
int16_t* outputBufferData = reinterpret_cast<int16_t*>(
env->GetDirectBufferAddress(jOutputBufferData));
int sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize,
outputBufferData, kMaxOpusOutputPacketSizeSamples, 0);
// record error code
errorCode = (sampleCount < 0) ? sampleCount : 0;
return (sampleCount < 0) ? sampleCount
: sampleCount * kBytesPerSample * channelCount;
int sampleCount;
if (outputFloat) {
float* outputBufferData = reinterpret_cast<float*>(
env->GetDirectBufferAddress(jOutputBufferData));
sampleCount = opus_multistream_decode_float(
decoder, inputBuffer, inputSize, outputBufferData,
kMaxOpusOutputPacketSizeSamples, 0);
} else {
int16_t* outputBufferData = reinterpret_cast<int16_t*>(
env->GetDirectBufferAddress(jOutputBufferData));
sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize,
outputBufferData,
kMaxOpusOutputPacketSizeSamples, 0);
}
// record error code
errorCode = (sampleCount < 0) ? sampleCount : 0;
return (sampleCount < 0) ? sampleCount
: sampleCount * byteSizePerSample * channelCount;
}
DECODER_FUNC(jint, opusSecureDecode, jlong jDecoder, jlong jTimeUs,
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer,
jint sampleRate, jobject mediaCrypto, jint inputMode, jbyteArray key,
jbyteArray javaIv, jint inputNumSubSamples, jintArray numBytesOfClearData,
jintArray numBytesOfEncryptedData) {
// Doesn't support
// Java client should have checked vpxSupportSecureDecode
// and avoid calling this
// return -2 (DRM Error)
return -2;
jint sampleRate, jobject mediaCrypto, jint inputMode,
jbyteArray key, jbyteArray javaIv, jint inputNumSubSamples,
jintArray numBytesOfClearData, jintArray numBytesOfEncryptedData) {
// Doesn't support
// Java client should have checked vpxSupportSecureDecode
// and avoid calling this
// return -2 (DRM Error)
return -2;
}
DECODER_FUNC(void, opusClose, jlong jDecoder) {
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
opus_multistream_decoder_destroy(decoder);
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
opus_multistream_decoder_destroy(decoder);
}
DECODER_FUNC(void, opusReset, jlong jDecoder) {
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
opus_multistream_decoder_ctl(decoder, OPUS_RESET_STATE);
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
opus_multistream_decoder_ctl(decoder, OPUS_RESET_STATE);
}
DECODER_FUNC(jstring, opusGetErrorMessage, jlong jContext) {
return env->NewStringUTF(opus_strerror(errorCode));
return env->NewStringUTF(opus_strerror(errorCode));
}
DECODER_FUNC(jint, opusGetErrorCode, jlong jContext) {
return errorCode;
}
DECODER_FUNC(jint, opusGetErrorCode, jlong jContext) { return errorCode; }
DECODER_FUNC(void, opusSetFloatOutput) { outputFloat = true; }
LIBRARY_FUNC(jstring, opusIsSecureDecodeSupported) {
// Doesn't support
return 0;
// Doesn't support
return 0;
}
LIBRARY_FUNC(jstring, opusGetVersion) {
return env->NewStringUTF(opus_get_version_string());
return env->NewStringUTF(opus_get_version_string());
}

View file

@ -23,9 +23,9 @@
-keep class org.telegram.tgnet.QuickAckDelegate { *; }
-keep class org.telegram.tgnet.WriteToSocketDelegate { *; }
-keep class com.google.android.exoplayer2.ext.** { *; }
-keep class com.google.android.exoplayer2.util.FlacStreamMetadata { *; }
-keep class com.google.android.exoplayer2.extractor.FlacStreamMetadata { *; }
-keep class com.google.android.exoplayer2.metadata.flac.PictureFrame { *; }
-keep class com.google.android.exoplayer2.decoder.SimpleOutputBuffer { *; }
-keep class com.google.android.exoplayer2.decoder.SimpleDecoderOutputBuffer { *; }
# https://developers.google.com/ml-kit/known-issues#android_issues
-keep class com.google.mlkit.nl.languageid.internal.LanguageIdentificationJni { *; }
@ -42,7 +42,7 @@
}
# Some members of this class are being accessed from native methods. Keep them unobfuscated.
-keep class com.google.android.exoplayer2.video.VideoDecoderOutputBuffer {
-keep class com.google.android.exoplayer2.decoder.VideoDecoderOutputBuffer {
*;
}

View file

@ -2229,6 +2229,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements
}
}
public boolean hasPendingScrollPosition() {
return mPendingScrollPosition >= 0;
}
/**
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
* space.

View file

@ -22,6 +22,7 @@ import com.google.android.exoplayer2.util.LibraryLoader;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MimeTypes;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.telegram.messenger.NativeLoader;
/** Configures and queries the underlying native library. */
public final class FfmpegLibrary {
@ -32,14 +33,6 @@ public final class FfmpegLibrary {
private static final String TAG = "FfmpegLibrary";
private static final LibraryLoader LOADER =
new LibraryLoader("ffmpegJNI") {
@Override
protected void loadLibrary(String name) {
System.loadLibrary(name);
}
};
private static @MonotonicNonNull String version;
private static int inputBufferPaddingSize = C.LENGTH_UNSET;
@ -53,12 +46,12 @@ public final class FfmpegLibrary {
* @param libraries The names of the FFmpeg native libraries.
*/
public static void setLibraries(String... libraries) {
LOADER.setLibraries(libraries);
}
/** Returns whether the underlying library is available, loading it if necessary. */
public static boolean isAvailable() {
return LOADER.isAvailable();
return NativeLoader.loaded();
}
/** Returns the version of the underlying library if available, or null otherwise. */

View file

@ -18,6 +18,8 @@ package com.google.android.exoplayer2.ext.flac;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.util.LibraryLoader;
import org.telegram.messenger.NativeLoader;
/** Configures and queries the underlying native library. */
public final class FlacLibrary {
@ -25,13 +27,6 @@ public final class FlacLibrary {
ExoPlayerLibraryInfo.registerModule("goog.exo.flac");
}
private static final LibraryLoader LOADER =
new LibraryLoader("flacJNI") {
@Override
protected void loadLibrary(String name) {
System.loadLibrary(name);
}
};
private FlacLibrary() {}
@ -43,11 +38,10 @@ public final class FlacLibrary {
* @param libraries The names of the Flac native libraries.
*/
public static void setLibraries(String... libraries) {
LOADER.setLibraries(libraries);
}
/** Returns whether the underlying library is available, loading it if necessary. */
public static boolean isAvailable() {
return LOADER.isAvailable();
return NativeLoader.loaded();
}
}

View file

@ -20,6 +20,8 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.util.LibraryLoader;
import org.telegram.messenger.NativeLoader;
/** Configures and queries the underlying native library. */
public final class OpusLibrary {
@ -27,14 +29,6 @@ public final class OpusLibrary {
ExoPlayerLibraryInfo.registerModule("goog.exo.opus");
}
private static final LibraryLoader LOADER =
new LibraryLoader("opusV2JNI") {
@Override
protected void loadLibrary(String name) {
System.loadLibrary(name);
}
};
private static @C.CryptoType int cryptoType = C.CRYPTO_TYPE_UNSUPPORTED;
private OpusLibrary() {}
@ -51,12 +45,11 @@ public final class OpusLibrary {
*/
public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) {
OpusLibrary.cryptoType = cryptoType;
LOADER.setLibraries(libraries);
}
/** Returns whether the underlying library is available, loading it if necessary. */
public static boolean isAvailable() {
return LOADER.isAvailable();
return NativeLoader.loaded();
}
/** Returns the version of the underlying library if available, or null otherwise. */

View file

@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer2.util;
import static java.lang.System.loadLibrary;
import java.util.Arrays;
/** Configurable loader for native libraries. */
@ -72,5 +74,5 @@ public abstract class LibraryLoader {
*
* @param name The name of the library to load.
*/
protected abstract void loadLibrary(String name);
protected abstract void oadLibrary(String name);
}

View file

@ -256,7 +256,11 @@ public class ApplicationLoader extends Application {
}
NativeLoader.initNativeLibs(ApplicationLoader.applicationContext);
ConnectionsManager.native_setJava(false);
try {
ConnectionsManager.native_setJava(false);
} catch (UnsatisfiedLinkError error) {
throw new RuntimeException("can't load native libraries " + Build.CPU_ABI + " lookup folder " + NativeLoader.getAbiFolder());
}
new ForegroundDetector(this) {
@Override
public void onActivityStarted(Activity activity) {

View file

@ -24,8 +24,8 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
public static int BUILD_VERSION = 3249;
public static String BUILD_VERSION_STRING = "9.5.7";
public static int BUILD_VERSION = 3252;
public static String BUILD_VERSION_STRING = "9.5.8";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View file

@ -53,6 +53,7 @@ public final class EmuInputDevicesDetector {
}
}
}
r.close();
return lines;
} catch (IOException e) {
FileLog.e(e);

View file

@ -2277,7 +2277,8 @@ public class ImageLoader {
newPath = ApplicationLoader.applicationContext.getExternalFilesDir(null);
telegramPath = new File(newPath, "Telegram");
} else {
if (!(path.exists() ? path.isDirectory() : path.mkdirs()) || !path.canWrite()) {
boolean isSdCard = !TextUtils.isEmpty(SharedConfig.storageCacheDir) && path.getAbsolutePath().startsWith(SharedConfig.storageCacheDir);
if (!isSdCard && !(path.exists() ? path.isDirectory() : path.mkdirs()) || !path.canWrite()) {
path = ApplicationLoader.applicationContext.getExternalFilesDir(null);
}
telegramPath = new File(path, "Telegram");

View file

@ -22,7 +22,7 @@ import java.util.zip.ZipFile;
public class NativeLoader {
private final static int LIB_VERSION = 43;
private final static int LIB_VERSION = 44;
private final static String LIB_NAME = "tmessages." + LIB_VERSION;
private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so";
private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so";
@ -127,36 +127,7 @@ public class NativeLoader {
FileLog.e(e);
}
String folder;
try {
String str = Build.CPU_ABI;
if (Build.CPU_ABI.equalsIgnoreCase("x86_64")) {
folder = "x86_64";
} else if (Build.CPU_ABI.equalsIgnoreCase("arm64-v8a")) {
folder = "arm64-v8a";
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) {
folder = "armeabi-v7a";
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi")) {
folder = "armeabi";
} else if (Build.CPU_ABI.equalsIgnoreCase("x86")) {
folder = "x86";
} else if (Build.CPU_ABI.equalsIgnoreCase("mips")) {
folder = "mips";
} else {
folder = "armeabi";
if (BuildVars.LOGS_ENABLED) {
FileLog.e("Unsupported arch: " + Build.CPU_ABI);
}
}
} catch (Exception e) {
FileLog.e(e);
folder = "armeabi";
}
String javaArch = System.getProperty("os.arch");
if (javaArch != null && javaArch.contains("686")) {
folder = "x86";
}
String folder = getAbiFolder();
/*File destFile = getNativeLibraryDir(context);
if (destFile != null) {
@ -209,6 +180,40 @@ public class NativeLoader {
}
}
public static String getAbiFolder() {
String folder;
try {
String str = Build.CPU_ABI;
if (Build.CPU_ABI.equalsIgnoreCase("x86_64")) {
folder = "x86_64";
} else if (Build.CPU_ABI.equalsIgnoreCase("arm64-v8a")) {
folder = "arm64-v8a";
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) {
folder = "armeabi-v7a";
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi")) {
folder = "armeabi";
} else if (Build.CPU_ABI.equalsIgnoreCase("x86")) {
folder = "x86";
} else if (Build.CPU_ABI.equalsIgnoreCase("mips")) {
folder = "mips";
} else {
folder = "armeabi";
if (BuildVars.LOGS_ENABLED) {
FileLog.e("Unsupported arch: " + Build.CPU_ABI);
}
}
} catch (Exception e) {
FileLog.e(e);
folder = "armeabi";
}
String javaArch = System.getProperty("os.arch");
if (javaArch != null && javaArch.contains("686")) {
folder = "x86";
}
return folder;
}
private static native void init(String path, boolean enable);
public static boolean loaded() {

View file

@ -4837,7 +4837,7 @@ public class DialogCell extends BaseCell {
}
return false;
}
int messageHash = message == null ? 0 : message.getId();
int messageHash = message == null ? 0 : message.getId() + message.hashCode();
Integer printingType = null;
long readHash = dialog.read_inbox_max_id + ((long) dialog.read_outbox_max_id << 8) + ((long) (dialog.unread_count + (dialog.unread_mark ? -1 : 0)) << 16) +
(dialog.unread_reactions_count > 0 ? (1 << 18) : 0) +

View file

@ -134,7 +134,7 @@ public class DialogsRequestedEmptyCell extends LinearLayout implements Notificat
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.diceStickersDidLoad);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.diceStickersDidLoad);
}
@Override

View file

@ -3507,6 +3507,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
saveScrollPosition();
super.onMeasure(widthSpec, heightSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
@ -8748,28 +8754,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (chatListView != null && chatLayoutManager != null && chatAdapter != null) {
if (chatListView.getPaddingTop() != p) {
int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition();
int lastVisPos = chatLayoutManager.findLastVisibleItemPosition();
int top = 0;
MessageObject scrollToMessageObject = null;
if (firstVisPos != RecyclerView.NO_POSITION) {
for (int i = firstVisPos; i <= lastVisPos; i++) {
View v = chatLayoutManager.findViewByPosition(i);
if (v instanceof ChatMessageCell) {
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
break;
} else if (v instanceof ChatActionCell) {
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
break;
}
for (int i = 0; i < chatListView.getChildCount(); i++) {
View v = chatListView.getChildAt(i);
if (v instanceof ChatMessageCell) {
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
} else if (v instanceof ChatActionCell) {
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
}
}
chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset);
if (firstVisPos != RecyclerView.NO_POSITION && scrollToMessageObject != null) {
if (scrollToMessageObject != null) {
chatAdapter.updateRowsSafe();
int index = messages.indexOf(scrollToMessageObject);
if (index >= 0) {
@ -15843,22 +15845,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
startLoadFromMessageId = 0;
}
if (newRowsCount > 0) {
int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition();
int lastVisPos = chatLayoutManager.findLastVisibleItemPosition();
int top = 0;
MessageObject scrollToMessageObject = null;
if (firstVisPos != RecyclerView.NO_POSITION) {
for (int i = firstVisPos; i <= lastVisPos; i++) {
View v = chatLayoutManager.findViewByPosition(i);
if (v instanceof ChatMessageCell) {
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
break;
} else if (v instanceof ChatActionCell) {
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
break;
}
for (int i = 0; i < chatListView.getChildCount(); i++) {
View v = chatListView.getChildAt(i);
if (v instanceof ChatMessageCell) {
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
} else if (v instanceof ChatActionCell) {
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
}
}
@ -15959,22 +15957,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else {
if (newRowsCount != 0) {
int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition();
int lastVisPos = chatLayoutManager.findLastVisibleItemPosition();
int top = 0;
MessageObject scrollToMessageObject = null;
if (firstVisPos != RecyclerView.NO_POSITION) {
for (int i = firstVisPos; i <= lastVisPos; i++) {
View v = chatLayoutManager.findViewByPosition(i);
if (v instanceof ChatMessageCell) {
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
break;
} else if (v instanceof ChatActionCell) {
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
break;
}
for (int i = 0; i < chatListView.getChildCount(); i++) {
View v = chatListView.getChildAt(i);
if (v instanceof ChatMessageCell) {
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
} else if (v instanceof ChatActionCell) {
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
}
}
int insertStart = chatAdapter.messagesEndRow;
@ -18268,6 +18262,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
private int getScrollingOffsetForView(View v) {
return chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
}
private boolean updateMessageTranslation(MessageObject messageObject) {
if (messageObject == null || messageObject.messageOwner == null) {
return false;
@ -19438,7 +19436,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else {
if (child != null) {
chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom());
chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, getScrollingOffsetForView(child));
}
}
if (newMentionsCount != 0 && mentiondownButtonCounter != null) {
@ -19488,6 +19486,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
private void saveScrollPosition() {
if (chatListView == null || chatLayoutManager == null || chatLayoutManager.hasPendingScrollPosition()) {
return;
}
int top = 0;
MessageObject scrollToMessageObject = null;
for (int i = 0; i < chatListView.getChildCount(); i++) {
View v = chatListView.getChildAt(i);
if (v instanceof ChatMessageCell) {
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
} else if (v instanceof ChatActionCell) {
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
top = getScrollingOffsetForView(v);
break;
}
}
if (scrollToMessageObject != null) {
int scrollToIndex = messages.indexOf(scrollToMessageObject);
if (scrollToIndex > 0) {
chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + scrollToIndex, top);
}
}
}
private int getSponsoredMessagesCount() {
int sponsoredMessagesCount = 0;
while (sponsoredMessagesCount < messages.size()) {
@ -26123,7 +26147,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int unreadMessageIndex = messages.indexOf(unreadMessageObject);
if (unreadMessageIndex >= 0) {
lastVisibleItem = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject);
top = chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom();
top = getScrollingOffsetForView(child);
}
break;
}
@ -26185,7 +26209,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
if (lastVisibleItem != RecyclerView.NO_POSITION) {
// chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top);
chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top);
}
}
@ -28288,7 +28312,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int unreadMessageIndex = messages.indexOf(unreadMessageObject);
if (unreadMessageIndex >= 0) {
lastVisibleItem = messagesStartRow + messages.indexOf(unreadMessageObject);
top = chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom();
top = getScrollingOffsetForView(child);
}
break;
}

View file

@ -16,6 +16,7 @@ import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.util.TypedValue;
import android.view.Gravity;
@ -357,11 +358,11 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
if (isOutboundGift) {
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
subtitleView.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle, user != null ? user.first_name : ""), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
} else if (user != null && user.id == 777000) {
} else if (user == null || TextUtils.isEmpty(user.first_name) || user.id == 777000) {
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPluralSomeone, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
} else {
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user.first_name, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
}
} else {

View file

@ -294,7 +294,6 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable, Bitma
if (onAnimationEndListener != null) {
onAnimationEndListener = null;
}
invalidateInternal();
}
public void setOnFinishCallback(Runnable callback, int frame) {

View file

@ -94,7 +94,7 @@ public class StickerCategoriesListView extends RecyclerListView {
public static void preload(int account, @CategoriesType int type) {
fetcher.fetch(account, type, emojiGroups -> {
if (emojiGroups.groups == null) {
if (emojiGroups == null || emojiGroups.groups == null) {
return;
}
for (TLRPC.TL_emojiGroup group : emojiGroups.groups) {

View file

@ -8683,13 +8683,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
} else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) {
updateVisibleRows(0);
} else if (id == NotificationCenter.emojiLoaded) {
for (int i = 0; i < viewPages.length; ++i) {
final RecyclerListView listView = viewPages[i].listView;
if (listView != null) {
for (int a = 0; a < listView.getChildCount(); ++a) {
View child = listView.getChildAt(a);
if (child != null) {
child.invalidate();
if (viewPages != null) {
for (int i = 0; i < viewPages.length; ++i) {
final RecyclerListView listView = viewPages[i].listView;
if (listView != null) {
for (int a = 0; a < listView.getChildCount(); ++a) {
View child = listView.getChildAt(a);
if (child != null) {
child.invalidate();
}
}
}
}

View file

@ -1682,9 +1682,9 @@ public class LoginActivity extends BaseFragment {
if (obj.optBoolean("basicIntegrity") && obj.optBoolean("ctsProfileMatch")) {
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
needHideProgress(false);
isRequestingFirebaseSms = false;
if (response instanceof TLRPC.TL_boolTrue) {
needHideProgress(false);
isRequestingFirebaseSms = false;
res.type.verifiedFirebase = true;
AndroidUtilities.runOnUIThread(() -> fillNextCodeParams(params, res, animate));
} else {
@ -3654,19 +3654,6 @@ public class LoginActivity extends BaseFragment {
wrongCode.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4));
errorViewSwitcher.addView(wrongCode, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
if (currentType != AUTH_TYPE_FRAGMENT_SMS) {
if (currentType == AUTH_TYPE_MESSAGE) {
if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone));
} else if (nextType == 0) {
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
} else {
problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms));
}
} else {
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
}
}
if (centerContainer == null) {
bottomContainer = new FrameLayout(context);
bottomContainer.addView(errorViewSwitcher, LayoutHelper.createFrame(currentType == VIEW_CODE_FRAGMENT_SMS ? LayoutHelper.MATCH_PARENT : LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 32));
@ -3998,6 +3985,20 @@ public class LoginActivity extends BaseFragment {
}
confirmTextView.setText(str);
if (currentType != AUTH_TYPE_FRAGMENT_SMS) {
if (currentType == AUTH_TYPE_MESSAGE) {
if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone));
} else if (nextType == 0) {
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
} else {
problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms));
}
} else {
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
}
}
if (currentType != AUTH_TYPE_FLASH_CALL) {
showKeyboard(codeFieldContainer.codeField[0]);
codeFieldContainer.codeField[0].requestFocus();
@ -4015,21 +4016,23 @@ public class LoginActivity extends BaseFragment {
if (problemText != null) {
problemText.setVisibility(VISIBLE);
}
} else if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS)) {
setProblemTextVisible(false);
timeText.setVisibility(VISIBLE);
problemText.setVisibility(GONE);
if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 1, 0));
} else if (nextType == AUTH_TYPE_SMS) {
timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0));
} else if (currentType == AUTH_TYPE_FLASH_CALL) {
if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) {
setProblemTextVisible(false);
timeText.setVisibility(VISIBLE);
problemText.setVisibility(GONE);
if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 1, 0));
} else if (nextType == AUTH_TYPE_SMS) {
timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0));
}
}
String callLogNumber = restore ? AndroidUtilities.obtainLoginPhoneCall(pattern) : null;
if (callLogNumber != null) {
onNextPressed(callLogNumber);
} else if (catchedPhone != null) {
onNextPressed(catchedPhone);
} else {
} else if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) {
createTimer();
}
} else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) {

View file

@ -13,12 +13,12 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Sat Mar 12 05:53:50 MSK 2016
APP_VERSION_CODE=3249
APP_VERSION_NAME=9.5.7
APP_VERSION_CODE=3252
APP_VERSION_NAME=9.5.8
APP_PACKAGE=org.telegram.messenger
RELEASE_KEY_PASSWORD=android
RELEASE_KEY_ALIAS=androidkey
RELEASE_STORE_PASSWORD=android
RELEASE_KEY_PASSWORD=TelegramAndroidPswd
RELEASE_KEY_ALIAS=tmessages
RELEASE_STORE_PASSWORD=TelegramAndroidPswd
org.gradle.jvmargs=-Xmx4096M -XX:MaxPermSize=4096m
org.gradle.daemon=true
org.gradle.parallel=true