Update to 7.0.0 (2061)

This commit is contained in:
DrKLO 2020-08-15 03:01:55 +03:00
parent 321b756367
commit 6e495f54b8
22 changed files with 253 additions and 123 deletions

View file

@ -26,6 +26,7 @@ dependencies {
compileOnly 'org.checkerframework:checker-compat-qual:2.5.0'
implementation 'com.google.firebase:firebase-messaging:20.2.4'
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-auth:18.1.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 ->
variant.outputs.all { output ->

View file

@ -13,7 +13,6 @@
int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env);
int videoOnJNILoad(JavaVM *vm, JNIEnv *env);
int imageOnJNILoad(JavaVM *vm, JNIEnv *env);
int webrtcOnJNILoad(JavaVM *vm, JNIEnv *env);
int tgvoipOnJNILoad(JavaVM *vm, JNIEnv *env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@ -36,13 +35,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
return -1;
}
if (webrtcOnJNILoad(vm, env) != JNI_TRUE) {
return -1;
}
if (tgvoipOnJNILoad(vm, env) != JNI_TRUE) {
return -1;
}
tgvoipOnJNILoad(vm, env);
return JNI_VERSION_1_6;
}

View file

@ -5,6 +5,9 @@
#include <VideoCapturerInterface.h>
#include <platform/android/AndroidInterface.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 "legacy/InstanceImplLegacy.h"
@ -214,7 +217,23 @@ jobject asJavaFinalState(JNIEnv *env, const FinalState &finalState) {
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) {
initWebRTC(env);
JavaObject configObject(env, config);
JavaObject encryptionKeyObject(env, encryptionKey);
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) {
initWebRTC(env);
std::unique_ptr<VideoCaptureInterface> capture = tgcalls::VideoCaptureInterface::Create(std::make_shared<AndroidContext>(env));
capture->setOutput(webrtc::JavaToNativeVideoSink(env, localSink));
capture->setState(VideoState::Active);

View file

@ -53,7 +53,7 @@ rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> AndroidInterface::makeVide
}
bool AndroidInterface::supportsEncoding(const std::string &codecName) {
if (softwareVideoEncoderFactory == nullptr) {
if (hardwareVideoEncoderFactory == nullptr) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
webrtc::ScopedJavaLocalRef<jclass> factory_class =
webrtc::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
@ -85,15 +85,3 @@ std::unique_ptr<PlatformInterface> CreatePlatformInterface() {
}
} // namespace tgcalls
extern "C" {
int webrtcOnJNILoad(JavaVM *vm, JNIEnv *env) {
webrtc::InitAndroid(vm);
webrtc::JVM::Initialize(vm);
rtc::InitializeSSL();
return JNI_TRUE;
}
}

View file

@ -19,7 +19,7 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
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 int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View file

@ -11742,10 +11742,15 @@ public class MessagesController extends BaseController implements NotificationCe
}
continue;
}
boolean notificationsDisabled = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !NotificationManagerCompat.from(ApplicationLoader.applicationContext).areNotificationsEnabled()) {
if (BuildVars.LOGS_ENABLED)
FileLog.d("Ignoring incoming call because notifications are disabled in system");
continue;
notificationsDisabled = true;
if (ApplicationLoader.mainInterfacePaused || !ApplicationLoader.isScreenOn) {
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);
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("user_id", call.participant_id == getUserConfig().getClientUserId() ? call.admin_id : call.participant_id);
intent.putExtra("account", currentAccount);
intent.putExtra("notifications_disabled", notificationsDisabled);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!notificationsDisabled && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ApplicationLoader.applicationContext.startForegroundService(intent);
} else {
ApplicationLoader.applicationContext.startService(intent);

View file

@ -76,7 +76,7 @@ public class SharedConfig {
public static boolean saveToGallery;
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 autoplayVideo = true;
public static boolean raiseToSpeak = true;
@ -239,7 +239,7 @@ public class SharedConfig {
preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
saveToGallery = preferences.getBoolean("save_gallery", false);
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);
mapPreviewType = preferences.getInt("mapPreviewType", 2);
raiseToSpeak = preferences.getBoolean("raise_to_speak", true);

View file

@ -126,6 +126,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
protected Notification ongoingCallNotification;
protected NativeInstance tgVoip;
protected boolean isVideoAvailable;
protected boolean notificationsDisabled;
protected boolean switchingCamera;
protected boolean isFrontFaceCamera = true;
protected String lastError;
@ -370,10 +371,10 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
.setTitle(LocaleController.getString("VoipOutputDevices", R.string.VoipOutputDevices), true)
.setItems(new CharSequence[]{
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)},
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) -> {
if (getSharedInstance() == null) {
return;
@ -577,19 +578,24 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
boolean needRing = am.getRingerMode() != AudioManager.RINGER_MODE_SILENT;
if (needRing) {
if (!USE_CONNECTION_SERVICE) {
am.requestAudioFocus(this, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN);
}
ringtonePlayer = new MediaPlayer();
ringtonePlayer.setOnPreparedListener(mediaPlayer -> ringtonePlayer.start());
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 {
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());
else
} else {
notificationUri = prefs.getString("CallsRingtonePath", RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString());
}
ringtonePlayer.setDataSource(this, Uri.parse(notificationUri));
ringtonePlayer.prepareAsync();
} catch (Exception e) {
@ -1323,6 +1329,10 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
return am.isBluetoothScoOn();
}
public boolean isHeadsetPlugged() {
return isHeadsetPlugged;
}
public void onMediaStateUpdated(int audioState, int videoState) {
AndroidUtilities.runOnUIThread(() -> {
currentAudioState = audioState;

View file

@ -18,6 +18,7 @@ import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.media.audiofx.AcousticEchoCanceler;
import android.media.audiofx.NoiseSuppressor;
import android.net.Uri;
@ -25,7 +26,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat;
import android.os.SystemClock;
import android.telecom.TelecomManager;
@ -162,14 +162,21 @@ public class VoIPService extends VoIPBaseService {
isOutgoing = intent.getBooleanExtra("is_outgoing", false);
videoCall = intent.getBooleanExtra("video_call", false);
isVideoAvailable = intent.getBooleanExtra("can_video_call", false);
notificationsDisabled = intent.getBooleanExtra("notifications_disabled", false);
user = MessagesController.getInstance(currentAccount).getUser(userID);
localSink = new ProxyVideoSink();
remoteSink = new ProxyVideoSink();
try {
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
isHeadsetPlugged = am.isWiredHeadsetOn();
} catch (Exception e) {
FileLog.e(e);
}
if (videoCall) {
videoCapturer = NativeInstance.createVideoCapturer(localSink);
videoState = Instance.VIDEO_STATE_ACTIVE;
if (!isBtHeadsetConnected) {
if (!isBtHeadsetConnected && !isHeadsetPlugged) {
setAudioOutput(0);
}
}
@ -217,7 +224,7 @@ public class VoIPService extends VoIPBaseService {
} else {
videoState = Instance.VIDEO_STATE_INACTIVE;
}
if (videoCall && !isBtHeadsetConnected) {
if (videoCall && !isBtHeadsetConnected && !isHeadsetPlugged) {
setAudioOutput(0);
}
callIShouldHavePutIntoIntent = null;
@ -496,7 +503,7 @@ public class VoIPService extends VoIPBaseService {
FileLog.d("starting ringing for call " + call.id);
}
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);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("Showing incoming call notification");
@ -1226,41 +1233,6 @@ public class VoIPService extends VoIPBaseService {
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) {
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) {

View file

@ -956,7 +956,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen
RectF sizeRect = new RectF(0, 0, RESULT_SIDE, RESULT_SIDE);
private void updateCropTransform() {
if (cropTransform == null) {
if (cropTransform == null || state == null) {
return;
}
areaView.getCropRect(cropRect);

View file

@ -14,7 +14,6 @@ import androidx.core.view.ViewCompat;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
public abstract class SeekBarAccessibilityDelegate extends View.AccessibilityDelegate {

View file

@ -10,6 +10,7 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.Layout;
@ -437,7 +438,7 @@ public class AcceptDeclineView extends View {
@Override
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
AccessibilityNodeInfo nodeInfo = null;
AccessibilityNodeInfo nodeInfo;
if (virtualViewId == HOST_VIEW_ID) {
nodeInfo = AccessibilityNodeInfo.obtain(hostView);
nodeInfo.setPackageName(hostView.getContext().getPackageName());
@ -447,10 +448,14 @@ public class AcceptDeclineView extends View {
} else {
nodeInfo = AccessibilityNodeInfo.obtain(hostView, virtualViewId);
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.setClassName(Button.class.getName());
nodeInfo.setImportantForAccessibility(true);
if (Build.VERSION.SDK_INT >= 24) {
nodeInfo.setImportantForAccessibility(true);
}
nodeInfo.setVisibleToUser(true);
nodeInfo.setClickable(true);
nodeInfo.setEnabled(true);

View file

@ -1,6 +1,7 @@
package org.telegram.ui.Components.voip;
import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@ -18,6 +19,14 @@ public class VoIPButtonsLayout extends FrameLayout {
int childWidth;
int childPadding;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!isEnabled()) {
return false;
}
return super.dispatchTouchEvent(ev);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);

View file

@ -331,7 +331,7 @@ public class VoIPHelper {
onDismiss.run();
})
.create();
if (BuildVars.DEBUG_VERSION && log.exists()) {
if (BuildVars.LOGS_ENABLED && log.exists()) {
alert.setNeutralButton("Send log", (dialog, which) -> {
Intent intent = new Intent(context, LaunchActivity.class);
intent.setAction(Intent.ACTION_SEND);

View file

@ -134,7 +134,7 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
};
public static void show(Activity activity, int parentWidth, int parentHeight, int animationType) {
if (instance != null) {
if (instance != null || VideoCameraCapturer.eglBase == null) {
return;
}
WindowManager.LayoutParams windowLayoutParams = createWindowLayoutParams(activity, parentWidth, parentHeight, SCALE_NORMAL);

View file

@ -131,8 +131,12 @@ public class VoIPWindowView extends FrameLayout {
VoIPFragment.clearInstance();
if (lockOnScreen) {
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
wm.removeView(VoIPWindowView.this);
try {
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
wm.removeView(VoIPWindowView.this);
} catch (Exception e) {
}
} else {
animationIndex = NotificationCenter.getInstance(UserConfig.selectedAccount).setAnimationInProgress(animationIndex, null);
animate().translationX(getMeasuredWidth()).setListener(new AnimatorListenerAdapter() {
@ -141,9 +145,14 @@ public class VoIPWindowView extends FrameLayout {
NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(animationIndex);
if (getParent() != null) {
activity.setRequestedOrientation(orientationBefore);
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
setVisibility(View.GONE);
wm.removeView(VoIPWindowView.this);
try {
wm.removeView(VoIPWindowView.this);
} catch (Exception e) {
}
}
}
}).setDuration(animDuration).setInterpolator(CubicBezierInterpolator.DEFAULT).start();

View file

@ -2546,7 +2546,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
@Override
public void notifyDataSetChanged() {
viewPage.lastItemsCount = getItemCount();
super.notifyDataSetChanged();
try {
super.notifyDataSetChanged();
} catch (Exception e) {
FileLog.e(e);
}
}
};
if (AndroidUtilities.isTablet() && openedDialogId != 0) {

View file

@ -16,7 +16,6 @@ import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.Build;
@ -50,7 +49,6 @@ import androidx.core.graphics.ColorUtils;
import androidx.core.view.ViewCompat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
@ -70,6 +68,7 @@ import org.telegram.messenger.voip.VoIPBaseService;
import org.telegram.messenger.voip.VoIPService;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.DarkAlertDialog;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.BackgroundGradientDrawable;
import org.telegram.ui.Components.BackupImageView;
@ -195,7 +194,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
boolean hideUiRunnableWaiting;
Runnable hideUIRunnable = () -> {
hideUiRunnableWaiting = false;
if (canHideUI && uiVisible) {
if (canHideUI && uiVisible && !emojiExpanded) {
lastContentTapTime = System.currentTimeMillis();
showUi(false);
previousState = currentState;
@ -822,7 +821,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
}
public void switchToPip() {
if (isFinished || !AndroidUtilities.checkInlinePermissions(activity)) {
if (isFinished || !AndroidUtilities.checkInlinePermissions(activity) || instance == null) {
return;
}
isFinished = true;
@ -1041,11 +1040,13 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
}
private void expandEmoji(boolean expanded) {
if (!emojiLoaded || emojiExpanded == expanded) {
if (!emojiLoaded || emojiExpanded == expanded || !uiVisible) {
return;
}
emojiExpanded = expanded;
if (expanded) {
AndroidUtilities.runOnUIThread(hideUIRunnable);
hideUiRunnableWaiting = false;
float s1 = emojiLayout.getMeasuredWidth();
float s2 = windowView.getMeasuredWidth() - AndroidUtilities.dp(128);
float scale = s2 / s1;
@ -1079,6 +1080,11 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
emojiRationalTextView.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
@Override
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);
}
}).setDuration(150).start();
@ -1098,9 +1104,6 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
if (isFinished || switchingToPip) {
return;
}
if (currentState == VoIPService.DISCARD_REASON_LINE_BUSY) {
currentState = VoIPService.STATE_BUSY;
}
lockOnScreen = false;
boolean animated = previousState != -1;
boolean showAcceptDeclineView = false;
@ -1174,6 +1177,36 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
currentUserTextureView.saveCameraLastBitmap();
AndroidUtilities.runOnUIThread(() -> windowView.finish(), 200);
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) {
@ -1222,6 +1255,9 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
if (uiVisible && canHideUI && !hideUiRunnableWaiting && service != null && !service.isMicMute()) {
AndroidUtilities.runOnUIThread(hideUIRunnable, 3000);
hideUiRunnableWaiting = true;
} else if (service != null && service.isMicMute()) {
AndroidUtilities.cancelRunOnUIThread(hideUIRunnable);
hideUiRunnableWaiting = false;
}
if (!uiVisible) {
statusLayoutOffset -= AndroidUtilities.dp(50);
@ -1394,6 +1430,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
uiVisibilityAnimator.start();
AndroidUtilities.cancelRunOnUIThread(hideUIRunnable);
hideUiRunnableWaiting = false;
buttonsLayout.setEnabled(false);
} else if (show && !uiVisible) {
tapToVideoTooltip.hide();
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.setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT);
uiVisibilityAnimator.start();
buttonsLayout.setEnabled(true);
}
uiVisible = show;
@ -1706,7 +1744,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
view.announceForAccessibility(text);
}
serviceInstance.setMicMute(micMute);
updateButtons(true);
updateViewState();
}
});
}
@ -1763,7 +1801,11 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
} else if (service.isSpeakerphoneOn()) {
speakerPhoneIcon.setImageResource(R.drawable.calls_speaker);
} 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();
}
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")
private void requestInlinePermissions() {
new AlertDialog.Builder(activity).setTitle(LocaleController.getString("AppName", R.string.AppName))

View file

@ -21,6 +21,8 @@ import java.nio.ByteBuffer;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import org.telegram.messenger.FileLog;
import org.webrtc.ThreadUtils.ThreadChecker;
/**
@ -543,33 +545,37 @@ class AndroidVideoDecoder implements VideoDecoder, VideoSink {
VideoFrame.I420Buffer frameBuffer = allocateI420Buffer(width, height);
buffer.limit(yEnd);
buffer.position(yPos);
copyPlane(
buffer.slice(), stride, frameBuffer.getDataY(), frameBuffer.getStrideY(), width, height);
try { //don't crash
buffer.limit(yEnd);
buffer.position(yPos);
copyPlane(
buffer.slice(), stride, frameBuffer.getDataY(), frameBuffer.getStrideY(), width, height);
buffer.limit(uEnd);
buffer.position(uPos);
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataU(), frameBuffer.getStrideU(),
chromaWidth, chromaHeight);
if (sliceHeight % 2 == 1) {
buffer.position(uPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
buffer.limit(uEnd);
buffer.position(uPos);
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataU(), frameBuffer.getStrideU(),
chromaWidth, chromaHeight);
if (sliceHeight % 2 == 1) {
buffer.position(uPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
ByteBuffer dataU = frameBuffer.getDataU();
dataU.position(frameBuffer.getStrideU() * chromaHeight); // Seek to beginning of last row.
dataU.put(buffer); // Copy the last row.
}
ByteBuffer dataU = frameBuffer.getDataU();
dataU.position(frameBuffer.getStrideU() * chromaHeight); // Seek to beginning of last row.
dataU.put(buffer); // Copy the last row.
}
buffer.limit(vEnd);
buffer.position(vPos);
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataV(), frameBuffer.getStrideV(),
chromaWidth, chromaHeight);
if (sliceHeight % 2 == 1) {
buffer.position(vPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
buffer.limit(vEnd);
buffer.position(vPos);
copyPlane(buffer.slice(), uvStride, frameBuffer.getDataV(), frameBuffer.getStrideV(),
chromaWidth, chromaHeight);
if (sliceHeight % 2 == 1) {
buffer.position(vPos + uvStride * (chromaHeight - 1)); // Seek to beginning of last full row.
ByteBuffer dataV = frameBuffer.getDataV();
dataV.position(frameBuffer.getStrideV() * chromaHeight); // Seek to beginning of last row.
dataV.put(buffer); // Copy the last row.
ByteBuffer dataV = frameBuffer.getDataV();
dataV.position(frameBuffer.getStrideV() * chromaHeight); // Seek to beginning of last row.
dataV.put(buffer); // Copy the last row.
}
} catch (Throwable e) {
FileLog.e(e);
}
return frameBuffer;

View file

@ -39,7 +39,10 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
// HW H.264 encoder on below devices has poor bitrate control - actual
// bitrates deviates a lot from the target value.
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;
private final boolean enableIntelVp8Encoder;
@ -241,6 +244,9 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
}
private boolean isHardwareSupportedInCurrentSdkVp8(MediaCodecInfo info) {
if (VP8_HW_EXCEPTION_MODELS.contains(Build.MODEL)) {
return false;
}
String name = info.getName();
// QCOM Vp8 encoder is supported in KITKAT or later.
return (name.startsWith(QCOM_PREFIX) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)

View file

@ -12,6 +12,11 @@ package org.webrtc;
import android.graphics.Matrix;
import android.os.Handler;
import org.telegram.messenger.FileLog;
import java.nio.ByteBuffer;
import androidx.annotation.Nullable;
/**
@ -109,8 +114,48 @@ public class TextureBufferImpl implements VideoFrame.TextureBuffer {
@Override
public VideoFrame.I420Buffer toI420() {
return ThreadUtils.invokeAtFrontUninterruptibly(
toI420Handler, () -> yuvConverter.convert(this));
try {
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

View file

@ -3034,6 +3034,7 @@
<string name="CallViaTelegram">Telegram Call</string>
<string name="VideoCallViaTelegram">Telegram Video Call</string>
<string name="VoipAudioRoutingEarpiece">Earpiece</string>
<string name="VoipAudioRoutingHeadset">Headset</string>
<string name="VoipAudioRoutingSpeaker">Speaker</string>
<string name="VoipAudioRoutingBluetooth">Bluetooth</string>
<string name="VoipOutputDevices">Output Devices</string>
@ -3078,6 +3079,7 @@
<string name="AcceptCall">Accept</string>
<string name="DeclineCall">Decline</string>
<string name="RetryCall">Retry</string>
<string name="VoipVideoUnavailable">Video</string>
<!--contacts shortcuts-->
<string name="ContactShortcutMessage">Message %1$s</string>
<string name="ContactShortcutVoiceCall">Voice call %1$s</string>