mirror of
https://github.com/DrKLO/Telegram.git
synced 2024-12-22 06:25:14 +01:00
Update to 7.0.0 (2061)
This commit is contained in:
parent
321b756367
commit
6e495f54b8
22 changed files with 253 additions and 123 deletions
|
@ -26,6 +26,7 @@ dependencies {
|
||||||
compileOnly 'org.checkerframework:checker-compat-qual:2.5.0'
|
compileOnly 'org.checkerframework:checker-compat-qual:2.5.0'
|
||||||
implementation 'com.google.firebase:firebase-messaging:20.2.4'
|
implementation 'com.google.firebase:firebase-messaging:20.2.4'
|
||||||
implementation 'com.google.firebase:firebase-config:19.2.0'
|
implementation 'com.google.firebase:firebase-config:19.2.0'
|
||||||
|
implementation 'com.google.firebase:firebase-datatransport:17.0.6'
|
||||||
implementation 'com.google.android.gms:play-services-maps:17.0.0'
|
implementation 'com.google.android.gms:play-services-maps:17.0.0'
|
||||||
implementation 'com.google.android.gms:play-services-auth:18.1.0'
|
implementation 'com.google.android.gms:play-services-auth:18.1.0'
|
||||||
implementation 'com.google.android.gms:play-services-vision:16.2.0'
|
implementation 'com.google.android.gms:play-services-vision:16.2.0'
|
||||||
|
@ -279,7 +280,7 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig.versionCode = 2060
|
defaultConfig.versionCode = 2061
|
||||||
|
|
||||||
applicationVariants.all { variant ->
|
applicationVariants.all { variant ->
|
||||||
variant.outputs.all { output ->
|
variant.outputs.all { output ->
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env);
|
int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env);
|
||||||
int videoOnJNILoad(JavaVM *vm, JNIEnv *env);
|
int videoOnJNILoad(JavaVM *vm, JNIEnv *env);
|
||||||
int imageOnJNILoad(JavaVM *vm, JNIEnv *env);
|
int imageOnJNILoad(JavaVM *vm, JNIEnv *env);
|
||||||
int webrtcOnJNILoad(JavaVM *vm, JNIEnv *env);
|
|
||||||
int tgvoipOnJNILoad(JavaVM *vm, JNIEnv *env);
|
int tgvoipOnJNILoad(JavaVM *vm, JNIEnv *env);
|
||||||
|
|
||||||
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||||
|
@ -36,13 +35,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webrtcOnJNILoad(vm, env) != JNI_TRUE) {
|
tgvoipOnJNILoad(vm, env);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tgvoipOnJNILoad(vm, env) != JNI_TRUE) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JNI_VERSION_1_6;
|
return JNI_VERSION_1_6;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
#include <VideoCapturerInterface.h>
|
#include <VideoCapturerInterface.h>
|
||||||
#include <platform/android/AndroidInterface.h>
|
#include <platform/android/AndroidInterface.h>
|
||||||
#include <platform/android/AndroidContext.h>
|
#include <platform/android/AndroidContext.h>
|
||||||
|
#include <rtc_base/ssl_adapter.h>
|
||||||
|
#include <modules/utility/include/jvm_android.h>
|
||||||
|
#include <sdk/android/native_api/base/init.h>
|
||||||
|
|
||||||
#include "pc/video_track.h"
|
#include "pc/video_track.h"
|
||||||
#include "legacy/InstanceImplLegacy.h"
|
#include "legacy/InstanceImplLegacy.h"
|
||||||
|
@ -214,7 +217,23 @@ jobject asJavaFinalState(JNIEnv *env, const FinalState &finalState) {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
bool webrtcLoaded = false;
|
||||||
|
|
||||||
|
void initWebRTC(JNIEnv *env) {
|
||||||
|
if (webrtcLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JavaVM* vm;
|
||||||
|
env->GetJavaVM(&vm);
|
||||||
|
webrtc::InitAndroid(vm);
|
||||||
|
webrtc::JVM::Initialize(vm);
|
||||||
|
rtc::InitializeSSL();
|
||||||
|
webrtcLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_makeNativeInstance(JNIEnv *env, jclass clazz, jstring version, jobject instanceObj, jobject config, jstring persistentStateFilePath, jobjectArray endpoints, jobject proxyClass, jint networkType, jobject encryptionKey, jobject remoteSink, jlong videoCapturer, jfloat aspectRatio) {
|
JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_makeNativeInstance(JNIEnv *env, jclass clazz, jstring version, jobject instanceObj, jobject config, jstring persistentStateFilePath, jobjectArray endpoints, jobject proxyClass, jint networkType, jobject encryptionKey, jobject remoteSink, jlong videoCapturer, jfloat aspectRatio) {
|
||||||
|
initWebRTC(env);
|
||||||
|
|
||||||
JavaObject configObject(env, config);
|
JavaObject configObject(env, config);
|
||||||
JavaObject encryptionKeyObject(env, encryptionKey);
|
JavaObject encryptionKeyObject(env, encryptionKey);
|
||||||
std::string v = tgvoip::jni::JavaStringToStdString(env, version);
|
std::string v = tgvoip::jni::JavaStringToStdString(env, version);
|
||||||
|
@ -381,6 +400,7 @@ JNIEXPORT jobject JNICALL Java_org_telegram_messenger_voip_NativeInstance_stop(J
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT long JNICALL Java_org_telegram_messenger_voip_NativeInstance_createVideoCapturer(JNIEnv *env, jclass clazz, jobject localSink) {
|
JNIEXPORT long JNICALL Java_org_telegram_messenger_voip_NativeInstance_createVideoCapturer(JNIEnv *env, jclass clazz, jobject localSink) {
|
||||||
|
initWebRTC(env);
|
||||||
std::unique_ptr<VideoCaptureInterface> capture = tgcalls::VideoCaptureInterface::Create(std::make_shared<AndroidContext>(env));
|
std::unique_ptr<VideoCaptureInterface> capture = tgcalls::VideoCaptureInterface::Create(std::make_shared<AndroidContext>(env));
|
||||||
capture->setOutput(webrtc::JavaToNativeVideoSink(env, localSink));
|
capture->setOutput(webrtc::JavaToNativeVideoSink(env, localSink));
|
||||||
capture->setState(VideoState::Active);
|
capture->setState(VideoState::Active);
|
||||||
|
|
|
@ -53,7 +53,7 @@ rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> AndroidInterface::makeVide
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidInterface::supportsEncoding(const std::string &codecName) {
|
bool AndroidInterface::supportsEncoding(const std::string &codecName) {
|
||||||
if (softwareVideoEncoderFactory == nullptr) {
|
if (hardwareVideoEncoderFactory == nullptr) {
|
||||||
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
|
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
|
||||||
webrtc::ScopedJavaLocalRef<jclass> factory_class =
|
webrtc::ScopedJavaLocalRef<jclass> factory_class =
|
||||||
webrtc::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
|
webrtc::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
|
||||||
|
@ -85,15 +85,3 @@ std::unique_ptr<PlatformInterface> CreatePlatformInterface() {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tgcalls
|
} // namespace tgcalls
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
int webrtcOnJNILoad(JavaVM *vm, JNIEnv *env) {
|
|
||||||
webrtc::InitAndroid(vm);
|
|
||||||
webrtc::JVM::Initialize(vm);
|
|
||||||
rtc::InitializeSSL();
|
|
||||||
|
|
||||||
return JNI_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class BuildVars {
|
||||||
public static boolean USE_CLOUD_STRINGS = true;
|
public static boolean USE_CLOUD_STRINGS = true;
|
||||||
public static boolean CHECK_UPDATES = true;
|
public static boolean CHECK_UPDATES = true;
|
||||||
public static boolean TON_WALLET_STANDALONE = false;
|
public static boolean TON_WALLET_STANDALONE = false;
|
||||||
public static int BUILD_VERSION = 2060;
|
public static int BUILD_VERSION = 2061;
|
||||||
public static String BUILD_VERSION_STRING = "7.0.0";
|
public static String BUILD_VERSION_STRING = "7.0.0";
|
||||||
public static int APP_ID = 4;
|
public static int APP_ID = 4;
|
||||||
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
||||||
|
|
|
@ -11742,10 +11742,15 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
boolean notificationsDisabled = false;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !NotificationManagerCompat.from(ApplicationLoader.applicationContext).areNotificationsEnabled()) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !NotificationManagerCompat.from(ApplicationLoader.applicationContext).areNotificationsEnabled()) {
|
||||||
if (BuildVars.LOGS_ENABLED)
|
notificationsDisabled = true;
|
||||||
FileLog.d("Ignoring incoming call because notifications are disabled in system");
|
if (ApplicationLoader.mainInterfacePaused || !ApplicationLoader.isScreenOn) {
|
||||||
continue;
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
|
FileLog.d("Ignoring incoming call because notifications are disabled in system");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE);
|
TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
if (svc != null || VoIPService.callIShouldHavePutIntoIntent != null || tm.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
|
if (svc != null || VoIPService.callIShouldHavePutIntoIntent != null || tm.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
|
||||||
|
@ -11773,8 +11778,9 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
intent.putExtra("is_outgoing", false);
|
intent.putExtra("is_outgoing", false);
|
||||||
intent.putExtra("user_id", call.participant_id == getUserConfig().getClientUserId() ? call.admin_id : call.participant_id);
|
intent.putExtra("user_id", call.participant_id == getUserConfig().getClientUserId() ? call.admin_id : call.participant_id);
|
||||||
intent.putExtra("account", currentAccount);
|
intent.putExtra("account", currentAccount);
|
||||||
|
intent.putExtra("notifications_disabled", notificationsDisabled);
|
||||||
try {
|
try {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (!notificationsDisabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
ApplicationLoader.applicationContext.startForegroundService(intent);
|
ApplicationLoader.applicationContext.startForegroundService(intent);
|
||||||
} else {
|
} else {
|
||||||
ApplicationLoader.applicationContext.startService(intent);
|
ApplicationLoader.applicationContext.startService(intent);
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class SharedConfig {
|
||||||
|
|
||||||
public static boolean saveToGallery;
|
public static boolean saveToGallery;
|
||||||
public static int mapPreviewType = 2;
|
public static int mapPreviewType = 2;
|
||||||
public static boolean chatBubbles = false;
|
public static boolean chatBubbles = Build.VERSION.SDK_INT >= 30;
|
||||||
public static boolean autoplayGifs = true;
|
public static boolean autoplayGifs = true;
|
||||||
public static boolean autoplayVideo = true;
|
public static boolean autoplayVideo = true;
|
||||||
public static boolean raiseToSpeak = true;
|
public static boolean raiseToSpeak = true;
|
||||||
|
@ -239,7 +239,7 @@ public class SharedConfig {
|
||||||
preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||||
saveToGallery = preferences.getBoolean("save_gallery", false);
|
saveToGallery = preferences.getBoolean("save_gallery", false);
|
||||||
autoplayGifs = preferences.getBoolean("autoplay_gif", true);
|
autoplayGifs = preferences.getBoolean("autoplay_gif", true);
|
||||||
chatBubbles = preferences.getBoolean("chatBubbles", false);
|
chatBubbles = preferences.getBoolean("chatBubbles", Build.VERSION.SDK_INT >= 30);
|
||||||
autoplayVideo = preferences.getBoolean("autoplay_video", true);
|
autoplayVideo = preferences.getBoolean("autoplay_video", true);
|
||||||
mapPreviewType = preferences.getInt("mapPreviewType", 2);
|
mapPreviewType = preferences.getInt("mapPreviewType", 2);
|
||||||
raiseToSpeak = preferences.getBoolean("raise_to_speak", true);
|
raiseToSpeak = preferences.getBoolean("raise_to_speak", true);
|
||||||
|
|
|
@ -126,6 +126,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
|
||||||
protected Notification ongoingCallNotification;
|
protected Notification ongoingCallNotification;
|
||||||
protected NativeInstance tgVoip;
|
protected NativeInstance tgVoip;
|
||||||
protected boolean isVideoAvailable;
|
protected boolean isVideoAvailable;
|
||||||
|
protected boolean notificationsDisabled;
|
||||||
protected boolean switchingCamera;
|
protected boolean switchingCamera;
|
||||||
protected boolean isFrontFaceCamera = true;
|
protected boolean isFrontFaceCamera = true;
|
||||||
protected String lastError;
|
protected String lastError;
|
||||||
|
@ -370,10 +371,10 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
|
||||||
.setTitle(LocaleController.getString("VoipOutputDevices", R.string.VoipOutputDevices), true)
|
.setTitle(LocaleController.getString("VoipOutputDevices", R.string.VoipOutputDevices), true)
|
||||||
.setItems(new CharSequence[]{
|
.setItems(new CharSequence[]{
|
||||||
LocaleController.getString("VoipAudioRoutingSpeaker", R.string.VoipAudioRoutingSpeaker),
|
LocaleController.getString("VoipAudioRoutingSpeaker", R.string.VoipAudioRoutingSpeaker),
|
||||||
LocaleController.getString("VoipAudioRoutingEarpiece", R.string.VoipAudioRoutingEarpiece),
|
isHeadsetPlugged ? LocaleController.getString("VoipAudioRoutingHeadset", R.string.VoipAudioRoutingHeadset) : LocaleController.getString("VoipAudioRoutingEarpiece", R.string.VoipAudioRoutingEarpiece),
|
||||||
currentBluetoothDeviceName != null ? currentBluetoothDeviceName : LocaleController.getString("VoipAudioRoutingBluetooth", R.string.VoipAudioRoutingBluetooth)},
|
currentBluetoothDeviceName != null ? currentBluetoothDeviceName : LocaleController.getString("VoipAudioRoutingBluetooth", R.string.VoipAudioRoutingBluetooth)},
|
||||||
new int[]{R.drawable.calls_menu_speaker,
|
new int[]{R.drawable.calls_menu_speaker,
|
||||||
R.drawable.calls_menu_phone,
|
isHeadsetPlugged ? R.drawable.calls_menu_headset : R.drawable.calls_menu_phone,
|
||||||
R.drawable.calls_menu_bluetooth}, (dialog, which) -> {
|
R.drawable.calls_menu_bluetooth}, (dialog, which) -> {
|
||||||
if (getSharedInstance() == null) {
|
if (getSharedInstance() == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -577,19 +578,24 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
|
||||||
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
|
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
|
||||||
boolean needRing = am.getRingerMode() != AudioManager.RINGER_MODE_SILENT;
|
boolean needRing = am.getRingerMode() != AudioManager.RINGER_MODE_SILENT;
|
||||||
if (needRing) {
|
if (needRing) {
|
||||||
if (!USE_CONNECTION_SERVICE) {
|
|
||||||
am.requestAudioFocus(this, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN);
|
|
||||||
}
|
|
||||||
ringtonePlayer = new MediaPlayer();
|
ringtonePlayer = new MediaPlayer();
|
||||||
ringtonePlayer.setOnPreparedListener(mediaPlayer -> ringtonePlayer.start());
|
ringtonePlayer.setOnPreparedListener(mediaPlayer -> ringtonePlayer.start());
|
||||||
ringtonePlayer.setLooping(true);
|
ringtonePlayer.setLooping(true);
|
||||||
ringtonePlayer.setAudioStreamType(AudioManager.STREAM_RING);
|
if (isHeadsetPlugged) {
|
||||||
|
ringtonePlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
|
||||||
|
} else {
|
||||||
|
ringtonePlayer.setAudioStreamType(AudioManager.STREAM_RING);
|
||||||
|
if (!USE_CONNECTION_SERVICE) {
|
||||||
|
am.requestAudioFocus(this, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
String notificationUri;
|
String notificationUri;
|
||||||
if (prefs.getBoolean("custom_" + chatID, false))
|
if (prefs.getBoolean("custom_" + chatID, false)) {
|
||||||
notificationUri = prefs.getString("ringtone_path_" + chatID, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString());
|
notificationUri = prefs.getString("ringtone_path_" + chatID, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString());
|
||||||
else
|
} else {
|
||||||
notificationUri = prefs.getString("CallsRingtonePath", RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString());
|
notificationUri = prefs.getString("CallsRingtonePath", RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString());
|
||||||
|
}
|
||||||
ringtonePlayer.setDataSource(this, Uri.parse(notificationUri));
|
ringtonePlayer.setDataSource(this, Uri.parse(notificationUri));
|
||||||
ringtonePlayer.prepareAsync();
|
ringtonePlayer.prepareAsync();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -1323,6 +1329,10 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
|
||||||
return am.isBluetoothScoOn();
|
return am.isBluetoothScoOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHeadsetPlugged() {
|
||||||
|
return isHeadsetPlugged;
|
||||||
|
}
|
||||||
|
|
||||||
public void onMediaStateUpdated(int audioState, int videoState) {
|
public void onMediaStateUpdated(int audioState, int videoState) {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
currentAudioState = audioState;
|
currentAudioState = audioState;
|
||||||
|
|
|
@ -18,6 +18,7 @@ import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.media.AudioManager;
|
||||||
import android.media.audiofx.AcousticEchoCanceler;
|
import android.media.audiofx.AcousticEchoCanceler;
|
||||||
import android.media.audiofx.NoiseSuppressor;
|
import android.media.audiofx.NoiseSuppressor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
@ -25,7 +26,6 @@ import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
|
||||||
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.telecom.TelecomManager;
|
import android.telecom.TelecomManager;
|
||||||
|
@ -162,14 +162,21 @@ public class VoIPService extends VoIPBaseService {
|
||||||
isOutgoing = intent.getBooleanExtra("is_outgoing", false);
|
isOutgoing = intent.getBooleanExtra("is_outgoing", false);
|
||||||
videoCall = intent.getBooleanExtra("video_call", false);
|
videoCall = intent.getBooleanExtra("video_call", false);
|
||||||
isVideoAvailable = intent.getBooleanExtra("can_video_call", false);
|
isVideoAvailable = intent.getBooleanExtra("can_video_call", false);
|
||||||
|
notificationsDisabled = intent.getBooleanExtra("notifications_disabled", false);
|
||||||
user = MessagesController.getInstance(currentAccount).getUser(userID);
|
user = MessagesController.getInstance(currentAccount).getUser(userID);
|
||||||
localSink = new ProxyVideoSink();
|
localSink = new ProxyVideoSink();
|
||||||
remoteSink = new ProxyVideoSink();
|
remoteSink = new ProxyVideoSink();
|
||||||
|
try {
|
||||||
|
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
|
||||||
|
isHeadsetPlugged = am.isWiredHeadsetOn();
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
}
|
||||||
|
|
||||||
if (videoCall) {
|
if (videoCall) {
|
||||||
videoCapturer = NativeInstance.createVideoCapturer(localSink);
|
videoCapturer = NativeInstance.createVideoCapturer(localSink);
|
||||||
videoState = Instance.VIDEO_STATE_ACTIVE;
|
videoState = Instance.VIDEO_STATE_ACTIVE;
|
||||||
if (!isBtHeadsetConnected) {
|
if (!isBtHeadsetConnected && !isHeadsetPlugged) {
|
||||||
setAudioOutput(0);
|
setAudioOutput(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +224,7 @@ public class VoIPService extends VoIPBaseService {
|
||||||
} else {
|
} else {
|
||||||
videoState = Instance.VIDEO_STATE_INACTIVE;
|
videoState = Instance.VIDEO_STATE_INACTIVE;
|
||||||
}
|
}
|
||||||
if (videoCall && !isBtHeadsetConnected) {
|
if (videoCall && !isBtHeadsetConnected && !isHeadsetPlugged) {
|
||||||
setAudioOutput(0);
|
setAudioOutput(0);
|
||||||
}
|
}
|
||||||
callIShouldHavePutIntoIntent = null;
|
callIShouldHavePutIntoIntent = null;
|
||||||
|
@ -496,7 +503,7 @@ public class VoIPService extends VoIPBaseService {
|
||||||
FileLog.d("starting ringing for call " + call.id);
|
FileLog.d("starting ringing for call " + call.id);
|
||||||
}
|
}
|
||||||
dispatchStateChanged(STATE_WAITING_INCOMING);
|
dispatchStateChanged(STATE_WAITING_INCOMING);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (!notificationsDisabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
showIncomingNotification(ContactsController.formatName(user.first_name, user.last_name), null, user, call.video, 0);
|
showIncomingNotification(ContactsController.formatName(user.first_name, user.last_name), null, user, call.video, 0);
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("Showing incoming call notification");
|
FileLog.d("Showing incoming call notification");
|
||||||
|
@ -1226,41 +1233,6 @@ public class VoIPService extends VoIPBaseService {
|
||||||
return isVideoAvailable;
|
return isVideoAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUIForegroundStateChanged(boolean isForeground) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentState == STATE_WAITING_INCOMING) {
|
|
||||||
if (isForeground) {
|
|
||||||
stopForeground(true);
|
|
||||||
} else {
|
|
||||||
if (!((KeyguardManager) getSystemService(KEYGUARD_SERVICE)).inKeyguardRestrictedInputMode()) {
|
|
||||||
if (NotificationManagerCompat.from(this).areNotificationsEnabled()) {
|
|
||||||
showIncomingNotification(ContactsController.formatName(user.first_name, user.last_name), null, user, call.video, 0);
|
|
||||||
} else {
|
|
||||||
declineIncomingCall(DISCARD_REASON_LINE_BUSY, null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
|
||||||
Intent intent = new Intent(VoIPService.this, LaunchActivity.class).setAction("voip");
|
|
||||||
try {
|
|
||||||
PendingIntent.getActivity(VoIPService.this, 0, intent, 0).send();
|
|
||||||
} catch (PendingIntent.CanceledException e) {
|
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
|
||||||
FileLog.e("error restarting activity", e);
|
|
||||||
}
|
|
||||||
declineIncomingCall(DISCARD_REASON_LINE_BUSY, null);
|
|
||||||
}
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
showNotification();
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onMediaButtonEvent(KeyEvent ev) {
|
void onMediaButtonEvent(KeyEvent ev) {
|
||||||
if (ev.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK || ev.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PAUSE || ev.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
|
if (ev.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK || ev.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PAUSE || ev.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
|
||||||
if (ev.getAction() == KeyEvent.ACTION_UP) {
|
if (ev.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
|
|
@ -956,7 +956,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen
|
||||||
RectF sizeRect = new RectF(0, 0, RESULT_SIDE, RESULT_SIDE);
|
RectF sizeRect = new RectF(0, 0, RESULT_SIDE, RESULT_SIDE);
|
||||||
|
|
||||||
private void updateCropTransform() {
|
private void updateCropTransform() {
|
||||||
if (cropTransform == null) {
|
if (cropTransform == null || state == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
areaView.getCropRect(cropRect);
|
areaView.getCropRect(cropRect);
|
||||||
|
|
|
@ -14,7 +14,6 @@ import androidx.core.view.ViewCompat;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
|
||||||
|
|
||||||
public abstract class SeekBarAccessibilityDelegate extends View.AccessibilityDelegate {
|
public abstract class SeekBarAccessibilityDelegate extends View.AccessibilityDelegate {
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
|
@ -437,7 +438,7 @@ public class AcceptDeclineView extends View {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
|
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
|
||||||
AccessibilityNodeInfo nodeInfo = null;
|
AccessibilityNodeInfo nodeInfo;
|
||||||
if (virtualViewId == HOST_VIEW_ID) {
|
if (virtualViewId == HOST_VIEW_ID) {
|
||||||
nodeInfo = AccessibilityNodeInfo.obtain(hostView);
|
nodeInfo = AccessibilityNodeInfo.obtain(hostView);
|
||||||
nodeInfo.setPackageName(hostView.getContext().getPackageName());
|
nodeInfo.setPackageName(hostView.getContext().getPackageName());
|
||||||
|
@ -447,10 +448,14 @@ public class AcceptDeclineView extends View {
|
||||||
} else {
|
} else {
|
||||||
nodeInfo = AccessibilityNodeInfo.obtain(hostView, virtualViewId);
|
nodeInfo = AccessibilityNodeInfo.obtain(hostView, virtualViewId);
|
||||||
nodeInfo.setPackageName(hostView.getContext().getPackageName());
|
nodeInfo.setPackageName(hostView.getContext().getPackageName());
|
||||||
nodeInfo.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
nodeInfo.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
|
||||||
|
}
|
||||||
nodeInfo.setText(getVirtualViewText(virtualViewId));
|
nodeInfo.setText(getVirtualViewText(virtualViewId));
|
||||||
nodeInfo.setClassName(Button.class.getName());
|
nodeInfo.setClassName(Button.class.getName());
|
||||||
nodeInfo.setImportantForAccessibility(true);
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
|
nodeInfo.setImportantForAccessibility(true);
|
||||||
|
}
|
||||||
nodeInfo.setVisibleToUser(true);
|
nodeInfo.setVisibleToUser(true);
|
||||||
nodeInfo.setClickable(true);
|
nodeInfo.setClickable(true);
|
||||||
nodeInfo.setEnabled(true);
|
nodeInfo.setEnabled(true);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.telegram.ui.Components.voip;
|
package org.telegram.ui.Components.voip;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
@ -18,6 +19,14 @@ public class VoIPButtonsLayout extends FrameLayout {
|
||||||
int childWidth;
|
int childWidth;
|
||||||
int childPadding;
|
int childPadding;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||||
|
if (!isEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.dispatchTouchEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
|
|
@ -331,7 +331,7 @@ public class VoIPHelper {
|
||||||
onDismiss.run();
|
onDismiss.run();
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
if (BuildVars.DEBUG_VERSION && log.exists()) {
|
if (BuildVars.LOGS_ENABLED && log.exists()) {
|
||||||
alert.setNeutralButton("Send log", (dialog, which) -> {
|
alert.setNeutralButton("Send log", (dialog, which) -> {
|
||||||
Intent intent = new Intent(context, LaunchActivity.class);
|
Intent intent = new Intent(context, LaunchActivity.class);
|
||||||
intent.setAction(Intent.ACTION_SEND);
|
intent.setAction(Intent.ACTION_SEND);
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void show(Activity activity, int parentWidth, int parentHeight, int animationType) {
|
public static void show(Activity activity, int parentWidth, int parentHeight, int animationType) {
|
||||||
if (instance != null) {
|
if (instance != null || VideoCameraCapturer.eglBase == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WindowManager.LayoutParams windowLayoutParams = createWindowLayoutParams(activity, parentWidth, parentHeight, SCALE_NORMAL);
|
WindowManager.LayoutParams windowLayoutParams = createWindowLayoutParams(activity, parentWidth, parentHeight, SCALE_NORMAL);
|
||||||
|
|
|
@ -131,8 +131,12 @@ public class VoIPWindowView extends FrameLayout {
|
||||||
VoIPFragment.clearInstance();
|
VoIPFragment.clearInstance();
|
||||||
|
|
||||||
if (lockOnScreen) {
|
if (lockOnScreen) {
|
||||||
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
|
try {
|
||||||
wm.removeView(VoIPWindowView.this);
|
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
wm.removeView(VoIPWindowView.this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
animationIndex = NotificationCenter.getInstance(UserConfig.selectedAccount).setAnimationInProgress(animationIndex, null);
|
animationIndex = NotificationCenter.getInstance(UserConfig.selectedAccount).setAnimationInProgress(animationIndex, null);
|
||||||
animate().translationX(getMeasuredWidth()).setListener(new AnimatorListenerAdapter() {
|
animate().translationX(getMeasuredWidth()).setListener(new AnimatorListenerAdapter() {
|
||||||
|
@ -141,9 +145,14 @@ public class VoIPWindowView extends FrameLayout {
|
||||||
NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(animationIndex);
|
NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(animationIndex);
|
||||||
if (getParent() != null) {
|
if (getParent() != null) {
|
||||||
activity.setRequestedOrientation(orientationBefore);
|
activity.setRequestedOrientation(orientationBefore);
|
||||||
|
|
||||||
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
|
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
|
||||||
setVisibility(View.GONE);
|
setVisibility(View.GONE);
|
||||||
wm.removeView(VoIPWindowView.this);
|
try {
|
||||||
|
wm.removeView(VoIPWindowView.this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).setDuration(animDuration).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
|
}).setDuration(animDuration).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
|
||||||
|
|
|
@ -2546,7 +2546,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
|
||||||
@Override
|
@Override
|
||||||
public void notifyDataSetChanged() {
|
public void notifyDataSetChanged() {
|
||||||
viewPage.lastItemsCount = getItemCount();
|
viewPage.lastItemsCount = getItemCount();
|
||||||
super.notifyDataSetChanged();
|
try {
|
||||||
|
super.notifyDataSetChanged();
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (AndroidUtilities.isTablet() && openedDialogId != 0) {
|
if (AndroidUtilities.isTablet() && openedDialogId != 0) {
|
||||||
|
|
|
@ -16,7 +16,6 @@ import android.content.pm.PackageManager;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
@ -50,7 +49,6 @@ import androidx.core.graphics.ColorUtils;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.ApplicationLoader;
|
|
||||||
import org.telegram.messenger.ContactsController;
|
import org.telegram.messenger.ContactsController;
|
||||||
import org.telegram.messenger.Emoji;
|
import org.telegram.messenger.Emoji;
|
||||||
import org.telegram.messenger.FileLog;
|
import org.telegram.messenger.FileLog;
|
||||||
|
@ -70,6 +68,7 @@ import org.telegram.messenger.voip.VoIPBaseService;
|
||||||
import org.telegram.messenger.voip.VoIPService;
|
import org.telegram.messenger.voip.VoIPService;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.AlertDialog;
|
import org.telegram.ui.ActionBar.AlertDialog;
|
||||||
|
import org.telegram.ui.ActionBar.DarkAlertDialog;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.BackgroundGradientDrawable;
|
import org.telegram.ui.Components.BackgroundGradientDrawable;
|
||||||
import org.telegram.ui.Components.BackupImageView;
|
import org.telegram.ui.Components.BackupImageView;
|
||||||
|
@ -195,7 +194,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
boolean hideUiRunnableWaiting;
|
boolean hideUiRunnableWaiting;
|
||||||
Runnable hideUIRunnable = () -> {
|
Runnable hideUIRunnable = () -> {
|
||||||
hideUiRunnableWaiting = false;
|
hideUiRunnableWaiting = false;
|
||||||
if (canHideUI && uiVisible) {
|
if (canHideUI && uiVisible && !emojiExpanded) {
|
||||||
lastContentTapTime = System.currentTimeMillis();
|
lastContentTapTime = System.currentTimeMillis();
|
||||||
showUi(false);
|
showUi(false);
|
||||||
previousState = currentState;
|
previousState = currentState;
|
||||||
|
@ -822,7 +821,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
public void switchToPip() {
|
public void switchToPip() {
|
||||||
if (isFinished || !AndroidUtilities.checkInlinePermissions(activity)) {
|
if (isFinished || !AndroidUtilities.checkInlinePermissions(activity) || instance == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isFinished = true;
|
isFinished = true;
|
||||||
|
@ -1041,11 +1040,13 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expandEmoji(boolean expanded) {
|
private void expandEmoji(boolean expanded) {
|
||||||
if (!emojiLoaded || emojiExpanded == expanded) {
|
if (!emojiLoaded || emojiExpanded == expanded || !uiVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emojiExpanded = expanded;
|
emojiExpanded = expanded;
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
|
AndroidUtilities.runOnUIThread(hideUIRunnable);
|
||||||
|
hideUiRunnableWaiting = false;
|
||||||
float s1 = emojiLayout.getMeasuredWidth();
|
float s1 = emojiLayout.getMeasuredWidth();
|
||||||
float s2 = windowView.getMeasuredWidth() - AndroidUtilities.dp(128);
|
float s2 = windowView.getMeasuredWidth() - AndroidUtilities.dp(128);
|
||||||
float scale = s2 / s1;
|
float scale = s2 / s1;
|
||||||
|
@ -1079,6 +1080,11 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
emojiRationalTextView.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
|
emojiRationalTextView.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
VoIPService service = VoIPService.getSharedInstance();
|
||||||
|
if (canHideUI && !hideUiRunnableWaiting && service != null && !service.isMicMute()) {
|
||||||
|
AndroidUtilities.runOnUIThread(hideUIRunnable, 3000);
|
||||||
|
hideUiRunnableWaiting = true;
|
||||||
|
}
|
||||||
emojiRationalTextView.setVisibility(View.GONE);
|
emojiRationalTextView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}).setDuration(150).start();
|
}).setDuration(150).start();
|
||||||
|
@ -1098,9 +1104,6 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
if (isFinished || switchingToPip) {
|
if (isFinished || switchingToPip) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (currentState == VoIPService.DISCARD_REASON_LINE_BUSY) {
|
|
||||||
currentState = VoIPService.STATE_BUSY;
|
|
||||||
}
|
|
||||||
lockOnScreen = false;
|
lockOnScreen = false;
|
||||||
boolean animated = previousState != -1;
|
boolean animated = previousState != -1;
|
||||||
boolean showAcceptDeclineView = false;
|
boolean showAcceptDeclineView = false;
|
||||||
|
@ -1174,6 +1177,36 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
currentUserTextureView.saveCameraLastBitmap();
|
currentUserTextureView.saveCameraLastBitmap();
|
||||||
AndroidUtilities.runOnUIThread(() -> windowView.finish(), 200);
|
AndroidUtilities.runOnUIThread(() -> windowView.finish(), 200);
|
||||||
break;
|
break;
|
||||||
|
case VoIPBaseService.STATE_FAILED:
|
||||||
|
statusTextView.setText(LocaleController.getString("VoipFailed", R.string.VoipFailed), false, animated);
|
||||||
|
final VoIPService voipService = VoIPService.getSharedInstance();
|
||||||
|
final String lastError = voipService != null ? voipService.getLastError() : Instance.ERROR_UNKNOWN;
|
||||||
|
if (!TextUtils.equals(lastError, Instance.ERROR_UNKNOWN)) {
|
||||||
|
if (TextUtils.equals(lastError, Instance.ERROR_INCOMPATIBLE)) {
|
||||||
|
final String name = ContactsController.formatName(callingUser.first_name, callingUser.last_name);
|
||||||
|
final String message = LocaleController.formatString("VoipPeerIncompatible", R.string.VoipPeerIncompatible, name);
|
||||||
|
showErrorDialog(AndroidUtilities.replaceTags(message));
|
||||||
|
} else if (TextUtils.equals(lastError, Instance.ERROR_PEER_OUTDATED)) {
|
||||||
|
final String name = ContactsController.formatName(callingUser.first_name, callingUser.last_name);
|
||||||
|
final String message = LocaleController.formatString("VoipPeerOutdated", R.string.VoipPeerOutdated, name);
|
||||||
|
showErrorDialog(AndroidUtilities.replaceTags(message));
|
||||||
|
} else if (TextUtils.equals(lastError, Instance.ERROR_PRIVACY)) {
|
||||||
|
final String name = ContactsController.formatName(callingUser.first_name, callingUser.last_name);
|
||||||
|
final String message = LocaleController.formatString("CallNotAvailable", R.string.CallNotAvailable, name);
|
||||||
|
showErrorDialog(AndroidUtilities.replaceTags(message));
|
||||||
|
} else if (TextUtils.equals(lastError, Instance.ERROR_AUDIO_IO)) {
|
||||||
|
showErrorDialog("Error initializing audio hardware");
|
||||||
|
} else if (TextUtils.equals(lastError, Instance.ERROR_LOCALIZED)) {
|
||||||
|
windowView.finish();
|
||||||
|
} else if (TextUtils.equals(lastError, Instance.ERROR_CONNECTION_SERVICE)) {
|
||||||
|
showErrorDialog(LocaleController.getString("VoipErrorUnknown", R.string.VoipErrorUnknown));
|
||||||
|
} else {
|
||||||
|
AndroidUtilities.runOnUIThread(() -> windowView.finish(), 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AndroidUtilities.runOnUIThread(() -> windowView.finish(), 1000);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callingUserIsVideo) {
|
if (callingUserIsVideo) {
|
||||||
|
@ -1222,6 +1255,9 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
if (uiVisible && canHideUI && !hideUiRunnableWaiting && service != null && !service.isMicMute()) {
|
if (uiVisible && canHideUI && !hideUiRunnableWaiting && service != null && !service.isMicMute()) {
|
||||||
AndroidUtilities.runOnUIThread(hideUIRunnable, 3000);
|
AndroidUtilities.runOnUIThread(hideUIRunnable, 3000);
|
||||||
hideUiRunnableWaiting = true;
|
hideUiRunnableWaiting = true;
|
||||||
|
} else if (service != null && service.isMicMute()) {
|
||||||
|
AndroidUtilities.cancelRunOnUIThread(hideUIRunnable);
|
||||||
|
hideUiRunnableWaiting = false;
|
||||||
}
|
}
|
||||||
if (!uiVisible) {
|
if (!uiVisible) {
|
||||||
statusLayoutOffset -= AndroidUtilities.dp(50);
|
statusLayoutOffset -= AndroidUtilities.dp(50);
|
||||||
|
@ -1394,6 +1430,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
uiVisibilityAnimator.start();
|
uiVisibilityAnimator.start();
|
||||||
AndroidUtilities.cancelRunOnUIThread(hideUIRunnable);
|
AndroidUtilities.cancelRunOnUIThread(hideUIRunnable);
|
||||||
hideUiRunnableWaiting = false;
|
hideUiRunnableWaiting = false;
|
||||||
|
buttonsLayout.setEnabled(false);
|
||||||
} else if (show && !uiVisible) {
|
} else if (show && !uiVisible) {
|
||||||
tapToVideoTooltip.hide();
|
tapToVideoTooltip.hide();
|
||||||
speakerPhoneIcon.animate().alpha(1f).translationY(0).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
|
speakerPhoneIcon.animate().alpha(1f).translationY(0).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
|
||||||
|
@ -1407,6 +1444,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
uiVisibilityAnimator.addUpdateListener(statusbarAnimatorListener);
|
uiVisibilityAnimator.addUpdateListener(statusbarAnimatorListener);
|
||||||
uiVisibilityAnimator.setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT);
|
uiVisibilityAnimator.setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
uiVisibilityAnimator.start();
|
uiVisibilityAnimator.start();
|
||||||
|
buttonsLayout.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
uiVisible = show;
|
uiVisible = show;
|
||||||
|
@ -1706,7 +1744,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
view.announceForAccessibility(text);
|
view.announceForAccessibility(text);
|
||||||
}
|
}
|
||||||
serviceInstance.setMicMute(micMute);
|
serviceInstance.setMicMute(micMute);
|
||||||
updateButtons(true);
|
updateViewState();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1763,7 +1801,11 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
} else if (service.isSpeakerphoneOn()) {
|
} else if (service.isSpeakerphoneOn()) {
|
||||||
speakerPhoneIcon.setImageResource(R.drawable.calls_speaker);
|
speakerPhoneIcon.setImageResource(R.drawable.calls_speaker);
|
||||||
} else {
|
} else {
|
||||||
speakerPhoneIcon.setImageResource(R.drawable.calls_menu_phone);
|
if (service.isHeadsetPlugged()) {
|
||||||
|
speakerPhoneIcon.setImageResource(R.drawable.calls_menu_headset);
|
||||||
|
} else {
|
||||||
|
speakerPhoneIcon.setImageResource(R.drawable.calls_menu_phone);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1955,6 +1997,19 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
|
||||||
deviceIsLocked = ((KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE)).inKeyguardRestrictedInputMode();
|
deviceIsLocked = ((KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE)).inKeyguardRestrictedInputMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showErrorDialog(CharSequence message) {
|
||||||
|
if (activity.isFinishing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AlertDialog dlg = new DarkAlertDialog.Builder(activity)
|
||||||
|
.setTitle(LocaleController.getString("VoipFailed", R.string.VoipFailed))
|
||||||
|
.setMessage(message)
|
||||||
|
.setPositiveButton(LocaleController.getString("OK", R.string.OK), null)
|
||||||
|
.show();
|
||||||
|
dlg.setCanceledOnTouchOutside(true);
|
||||||
|
dlg.setOnDismissListener(dialog -> windowView.finish());
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
private void requestInlinePermissions() {
|
private void requestInlinePermissions() {
|
||||||
new AlertDialog.Builder(activity).setTitle(LocaleController.getString("AppName", R.string.AppName))
|
new AlertDialog.Builder(activity).setTitle(LocaleController.getString("AppName", R.string.AppName))
|
||||||
|
|
|
@ -21,6 +21,8 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.concurrent.BlockingDeque;
|
import java.util.concurrent.BlockingDeque;
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.telegram.messenger.FileLog;
|
||||||
import org.webrtc.ThreadUtils.ThreadChecker;
|
import org.webrtc.ThreadUtils.ThreadChecker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -543,33 +545,37 @@ class AndroidVideoDecoder implements VideoDecoder, VideoSink {
|
||||||
|
|
||||||
VideoFrame.I420Buffer frameBuffer = allocateI420Buffer(width, height);
|
VideoFrame.I420Buffer frameBuffer = allocateI420Buffer(width, height);
|
||||||
|
|
||||||
buffer.limit(yEnd);
|
try { //don't crash
|
||||||
buffer.position(yPos);
|
buffer.limit(yEnd);
|
||||||
copyPlane(
|
buffer.position(yPos);
|
||||||
buffer.slice(), stride, frameBuffer.getDataY(), frameBuffer.getStrideY(), width, height);
|
copyPlane(
|
||||||
|
buffer.slice(), stride, frameBuffer.getDataY(), frameBuffer.getStrideY(), width, height);
|
||||||
|
|
||||||
buffer.limit(uEnd);
|
buffer.limit(uEnd);
|
||||||
buffer.position(uPos);
|
buffer.position(uPos);
|
||||||
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataU(), frameBuffer.getStrideU(),
|
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataU(), frameBuffer.getStrideU(),
|
||||||
chromaWidth, chromaHeight);
|
chromaWidth, chromaHeight);
|
||||||
if (sliceHeight % 2 == 1) {
|
if (sliceHeight % 2 == 1) {
|
||||||
buffer.position(uPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
|
buffer.position(uPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
|
||||||
|
|
||||||
ByteBuffer dataU = frameBuffer.getDataU();
|
ByteBuffer dataU = frameBuffer.getDataU();
|
||||||
dataU.position(frameBuffer.getStrideU() * chromaHeight); // Seek to beginning of last row.
|
dataU.position(frameBuffer.getStrideU() * chromaHeight); // Seek to beginning of last row.
|
||||||
dataU.put(buffer); // Copy the last row.
|
dataU.put(buffer); // Copy the last row.
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.limit(vEnd);
|
buffer.limit(vEnd);
|
||||||
buffer.position(vPos);
|
buffer.position(vPos);
|
||||||
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataV(), frameBuffer.getStrideV(),
|
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataV(), frameBuffer.getStrideV(),
|
||||||
chromaWidth, chromaHeight);
|
chromaWidth, chromaHeight);
|
||||||
if (sliceHeight % 2 == 1) {
|
if (sliceHeight % 2 == 1) {
|
||||||
buffer.position(vPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
|
buffer.position(vPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
|
||||||
|
|
||||||
ByteBuffer dataV = frameBuffer.getDataV();
|
ByteBuffer dataV = frameBuffer.getDataV();
|
||||||
dataV.position(frameBuffer.getStrideV() * chromaHeight); // Seek to beginning of last row.
|
dataV.position(frameBuffer.getStrideV() * chromaHeight); // Seek to beginning of last row.
|
||||||
dataV.put(buffer); // Copy the last row.
|
dataV.put(buffer); // Copy the last row.
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return frameBuffer;
|
return frameBuffer;
|
||||||
|
|
|
@ -39,7 +39,10 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
|
||||||
// HW H.264 encoder on below devices has poor bitrate control - actual
|
// HW H.264 encoder on below devices has poor bitrate control - actual
|
||||||
// bitrates deviates a lot from the target value.
|
// bitrates deviates a lot from the target value.
|
||||||
private static final List<String> H264_HW_EXCEPTION_MODELS =
|
private static final List<String> H264_HW_EXCEPTION_MODELS =
|
||||||
Arrays.asList("SAMSUNG-SGH-I337", "Nexus 7", "Nexus 4");
|
Arrays.asList("SAMSUNG-SGH-I337", "Nexus 7", "Nexus 4", "Pixel 3 XL", "Pixel 3");
|
||||||
|
|
||||||
|
private static final List<String> VP8_HW_EXCEPTION_MODELS =
|
||||||
|
Arrays.asList("Pixel 3 XL", "Pixel 3");
|
||||||
|
|
||||||
@Nullable private final EglBase14.Context sharedContext;
|
@Nullable private final EglBase14.Context sharedContext;
|
||||||
private final boolean enableIntelVp8Encoder;
|
private final boolean enableIntelVp8Encoder;
|
||||||
|
@ -241,6 +244,9 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHardwareSupportedInCurrentSdkVp8(MediaCodecInfo info) {
|
private boolean isHardwareSupportedInCurrentSdkVp8(MediaCodecInfo info) {
|
||||||
|
if (VP8_HW_EXCEPTION_MODELS.contains(Build.MODEL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
String name = info.getName();
|
String name = info.getName();
|
||||||
// QCOM Vp8 encoder is supported in KITKAT or later.
|
// QCOM Vp8 encoder is supported in KITKAT or later.
|
||||||
return (name.startsWith(QCOM_PREFIX) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
return (name.startsWith(QCOM_PREFIX) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||||
|
|
|
@ -12,6 +12,11 @@ package org.webrtc;
|
||||||
|
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
||||||
|
import org.telegram.messenger.FileLog;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,8 +114,48 @@ public class TextureBufferImpl implements VideoFrame.TextureBuffer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VideoFrame.I420Buffer toI420() {
|
public VideoFrame.I420Buffer toI420() {
|
||||||
return ThreadUtils.invokeAtFrontUninterruptibly(
|
try {
|
||||||
toI420Handler, () -> yuvConverter.convert(this));
|
return ThreadUtils.invokeAtFrontUninterruptibly(
|
||||||
|
toI420Handler, () -> yuvConverter.convert(this));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
//don't crash if something fails
|
||||||
|
final int frameWidth = getWidth();
|
||||||
|
final int frameHeight = getHeight();
|
||||||
|
final int stride = ((frameWidth + 7) / 8) * 8;
|
||||||
|
final int uvHeight = (frameHeight + 1) / 2;
|
||||||
|
|
||||||
|
final int totalHeight = frameHeight + uvHeight;
|
||||||
|
final ByteBuffer i420ByteBuffer = JniCommon.nativeAllocateByteBuffer(stride * totalHeight);
|
||||||
|
|
||||||
|
while (i420ByteBuffer.hasRemaining()) {
|
||||||
|
i420ByteBuffer.put((byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int viewportWidth = stride / 4;
|
||||||
|
|
||||||
|
final int yPos = 0;
|
||||||
|
final int uPos = yPos + stride * frameHeight;
|
||||||
|
final int vPos = uPos + stride / 2;
|
||||||
|
|
||||||
|
i420ByteBuffer.position(yPos);
|
||||||
|
i420ByteBuffer.limit(yPos + stride * frameHeight);
|
||||||
|
final ByteBuffer dataY = i420ByteBuffer.slice();
|
||||||
|
|
||||||
|
i420ByteBuffer.position(uPos);
|
||||||
|
// The last row does not have padding.
|
||||||
|
final int uvSize = stride * (uvHeight - 1) + stride / 2;
|
||||||
|
i420ByteBuffer.limit(uPos + uvSize);
|
||||||
|
final ByteBuffer dataU = i420ByteBuffer.slice();
|
||||||
|
|
||||||
|
i420ByteBuffer.position(vPos);
|
||||||
|
i420ByteBuffer.limit(vPos + uvSize);
|
||||||
|
final ByteBuffer dataV = i420ByteBuffer.slice();
|
||||||
|
|
||||||
|
|
||||||
|
return JavaI420Buffer.wrap(frameWidth, frameHeight, dataY, stride, dataU, stride, dataV, stride,
|
||||||
|
() -> JniCommon.nativeFreeByteBuffer(i420ByteBuffer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3034,6 +3034,7 @@
|
||||||
<string name="CallViaTelegram">Telegram Call</string>
|
<string name="CallViaTelegram">Telegram Call</string>
|
||||||
<string name="VideoCallViaTelegram">Telegram Video Call</string>
|
<string name="VideoCallViaTelegram">Telegram Video Call</string>
|
||||||
<string name="VoipAudioRoutingEarpiece">Earpiece</string>
|
<string name="VoipAudioRoutingEarpiece">Earpiece</string>
|
||||||
|
<string name="VoipAudioRoutingHeadset">Headset</string>
|
||||||
<string name="VoipAudioRoutingSpeaker">Speaker</string>
|
<string name="VoipAudioRoutingSpeaker">Speaker</string>
|
||||||
<string name="VoipAudioRoutingBluetooth">Bluetooth</string>
|
<string name="VoipAudioRoutingBluetooth">Bluetooth</string>
|
||||||
<string name="VoipOutputDevices">Output Devices</string>
|
<string name="VoipOutputDevices">Output Devices</string>
|
||||||
|
@ -3078,6 +3079,7 @@
|
||||||
<string name="AcceptCall">Accept</string>
|
<string name="AcceptCall">Accept</string>
|
||||||
<string name="DeclineCall">Decline</string>
|
<string name="DeclineCall">Decline</string>
|
||||||
<string name="RetryCall">Retry</string>
|
<string name="RetryCall">Retry</string>
|
||||||
|
<string name="VoipVideoUnavailable">Video</string>
|
||||||
<!--contacts shortcuts-->
|
<!--contacts shortcuts-->
|
||||||
<string name="ContactShortcutMessage">Message %1$s</string>
|
<string name="ContactShortcutMessage">Message %1$s</string>
|
||||||
<string name="ContactShortcutVoiceCall">Voice call %1$s</string>
|
<string name="ContactShortcutVoiceCall">Voice call %1$s</string>
|
||||||
|
|
Loading…
Reference in a new issue