blob: a55d0a804099eb66ea7c4fd53301b78d64d3b7f3 [file] [log] [blame]
Adrien Béraud04d822c2015-04-02 17:44:36 -04001/*
Sébastien Blinab53ada2019-01-02 17:23:00 -05002 * Copyright (C) 2004-2019 Savoir-faire Linux Inc.
Adrien Béraud04d822c2015-04-02 17:44:36 -04003 *
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04004 * Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
Adrien Béraudbc0898e2018-08-23 14:31:11 -04005 * Adrien Béraud <adrien.beraud@savoirfairelinux.com>
Adrien Béraud04d822c2015-04-02 17:44:36 -04006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
Adrien Béraudda712a42015-11-22 23:45:26 -050019 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Adrien Béraud04d822c2015-04-02 17:44:36 -040020 */
Adrien Béraud04d822c2015-04-02 17:44:36 -040021package cx.ring.fragments;
22
Rayan Osseiran38206c62019-05-15 14:49:03 -040023import android.Manifest;
Adrien Béraud2d50acb2020-03-23 22:02:15 -040024import android.animation.ValueAnimator;
Adrien Béraude4f901a2019-10-25 17:26:30 -040025import android.annotation.SuppressLint;
Adrien Béraudde0d4522018-12-12 12:11:02 -050026import android.app.Activity;
Adrien Béraud79808d02018-02-20 00:16:28 +010027import android.app.PendingIntent;
28import android.app.PictureInPictureParams;
29import android.app.RemoteAction;
Rayan Osseiranf7dfe232019-06-06 10:26:10 -040030import android.content.ComponentName;
Adrien Béraud162427f2016-04-12 18:04:08 -040031import android.content.Context;
32import android.content.Intent;
ayounesc6c2c012019-11-11 11:09:51 -050033import android.content.SharedPreferences;
Rayan Osseiran38206c62019-05-15 14:49:03 -040034import android.content.pm.PackageManager;
ayounes47e93992019-10-28 12:09:53 -040035import android.content.res.Configuration;
Adrien Béraudde0d4522018-12-12 12:11:02 -050036import android.graphics.Matrix;
Adrien Béraudfb6341f2016-03-07 16:18:54 -050037import android.graphics.PixelFormat;
Adrien Béraud2d50acb2020-03-23 22:02:15 -040038import android.graphics.PointF;
Adrien Béraud79808d02018-02-20 00:16:28 +010039import android.graphics.Rect;
Adrien Béraudde0d4522018-12-12 12:11:02 -050040import android.graphics.RectF;
41import android.graphics.SurfaceTexture;
ayounes47e93992019-10-28 12:09:53 -040042import android.graphics.drawable.Drawable;
Adrien Béraud79808d02018-02-20 00:16:28 +010043import android.graphics.drawable.Icon;
Adrien Béraudade9bee2019-12-02 17:13:26 -050044import android.media.projection.MediaProjection;
45import android.media.projection.MediaProjectionManager;
Adrien Béraud8d6a4832016-04-12 18:06:11 -040046import android.os.Build;
Adrien Béraud04d822c2015-04-02 17:44:36 -040047import android.os.Bundle;
48import android.os.PowerManager;
Adrien Béraudbcbb4d42018-12-08 16:06:39 -050049import android.text.Editable;
50import android.text.TextWatcher;
Adrien Béraud79808d02018-02-20 00:16:28 +010051import android.util.Rational;
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -040052import android.view.Gravity;
Adrien Béraud86a1e372018-11-23 23:24:30 -050053import android.view.LayoutInflater;
Adrien Béraud162427f2016-04-12 18:04:08 -040054import android.view.Menu;
55import android.view.MenuInflater;
56import android.view.MenuItem;
Adrien Béraud2d50acb2020-03-23 22:02:15 -040057import android.view.MotionEvent;
Adrien Béraudeb4bb002019-03-14 15:52:48 -040058import android.view.OrientationEventListener;
Adrien Béraudde0d4522018-12-12 12:11:02 -050059import android.view.Surface;
Adrien Béraud162427f2016-04-12 18:04:08 -040060import android.view.SurfaceHolder;
Adrien Béraudde0d4522018-12-12 12:11:02 -050061import android.view.TextureView;
Adrien Béraud162427f2016-04-12 18:04:08 -040062import android.view.View;
Adrien Béraud162427f2016-04-12 18:04:08 -040063import android.view.ViewGroup;
Adrien Béraudeb4bb002019-03-14 15:52:48 -040064import android.view.WindowManager;
Adrien Béraud2d50acb2020-03-23 22:02:15 -040065import android.view.animation.DecelerateInterpolator;
Romain Bertozziad8fd842016-05-11 14:30:35 -040066import android.view.inputmethod.InputMethodManager;
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -040067import android.widget.FrameLayout;
ayounes47e93992019-10-28 12:09:53 -040068import android.widget.LinearLayout;
Adrien Béraud162427f2016-04-12 18:04:08 -040069import android.widget.RelativeLayout;
Adrien Béraud20bd7232020-03-16 11:33:23 -040070import android.widget.Toast;
Adrien Béraud04d822c2015-04-02 17:44:36 -040071
Rayan Osseiran3dd04662019-06-28 16:47:48 -040072import androidx.annotation.NonNull;
73import androidx.annotation.Nullable;
74import androidx.appcompat.app.ActionBar;
75import androidx.appcompat.app.AppCompatActivity;
Adrien Béraude4f901a2019-10-25 17:26:30 -040076import androidx.appcompat.view.menu.MenuBuilder;
77import androidx.appcompat.view.menu.MenuPopupHelper;
78import androidx.appcompat.widget.PopupMenu;
Rayan Osseiran3dd04662019-06-28 16:47:48 -040079import androidx.databinding.DataBindingUtil;
Adrien Béraude4f901a2019-10-25 17:26:30 -040080import androidx.fragment.app.FragmentActivity;
ayounesc6c2c012019-11-11 11:09:51 -050081import androidx.preference.PreferenceManager;
Rayan Osseiran3dd04662019-06-28 16:47:48 -040082
Pierre Ducheminbb833672018-03-09 16:18:33 -050083import com.rodolfonavalon.shaperipplelibrary.model.Circle;
Thibault Wittembergb70d5b02016-07-08 16:50:14 -040084
Adrien Béraud79808d02018-02-20 00:16:28 +010085import java.util.ArrayList;
Adrien Béraude4f901a2019-10-25 17:26:30 -040086import java.util.List;
Romain Bertozzi64a66782016-08-02 12:10:38 -040087import java.util.Locale;
ayounes81087472019-11-08 15:26:05 -050088import java.util.Map;
Adrien Béraud79808d02018-02-20 00:16:28 +010089import java.util.Random;
Adrien Béraud04d822c2015-04-02 17:44:36 -040090
Rayan Osseiran38206c62019-05-15 14:49:03 -040091import javax.inject.Inject;
92
Adrien Béraud162427f2016-04-12 18:04:08 -040093import cx.ring.R;
Adrien Bérauda0226ff2019-11-21 15:24:42 -050094import cx.ring.adapters.ConfParticipantAdapter;
Adrien Béraude4f901a2019-10-25 17:26:30 -040095import cx.ring.application.JamiApplication;
Hadrien De Sousaccc947d2017-04-12 14:26:52 -040096import cx.ring.call.CallPresenter;
97import cx.ring.call.CallView;
Rayan Osseiran3dd04662019-06-28 16:47:48 -040098import cx.ring.client.CallActivity;
Adrien Béraude4f901a2019-10-25 17:26:30 -040099import cx.ring.client.ContactDetailsActivity;
Adrien Béraud162427f2016-04-12 18:04:08 -0400100import cx.ring.client.ConversationActivity;
Adrien Béraude4f901a2019-10-25 17:26:30 -0400101import cx.ring.client.ConversationSelectionActivity;
Thibault Wittemberg4f33d072016-10-06 17:11:41 -0400102import cx.ring.client.HomeActivity;
ayounes019267f2020-01-13 15:14:08 -0500103import cx.ring.daemon.Ringservice;
Adrien Béraud86a1e372018-11-23 23:24:30 -0500104import cx.ring.databinding.FragCallBinding;
Adrien Béraud04d822c2015-04-02 17:44:36 -0400105import cx.ring.model.CallContact;
Adrien Béraud04d822c2015-04-02 17:44:36 -0400106import cx.ring.model.SipCall;
Adrien Bérauda373e3b2018-12-12 11:14:50 -0500107import cx.ring.mvp.BaseSupportFragment;
ayounesc6c2c012019-11-11 11:09:51 -0500108import cx.ring.plugins.PluginUtils;
109import cx.ring.plugins.RecyclerPicker.RecyclerPicker;
110import cx.ring.plugins.RecyclerPicker.RecyclerPickerLayoutManager;
Alexandre Lision5da46fa2017-08-09 10:25:50 -0400111import cx.ring.service.DRingService;
Rayan Osseiran38206c62019-05-15 14:49:03 -0400112import cx.ring.services.DeviceRuntimeService;
Adrien Béraud34a6fa22019-07-28 16:02:59 -0400113import cx.ring.services.HardwareService;
Adrien Béraud79808d02018-02-20 00:16:28 +0100114import cx.ring.services.NotificationService;
ayounes019267f2020-01-13 15:14:08 -0500115import cx.ring.settings.pluginssettings.PluginDetails;
Alexandre Lision4865f7d2016-11-16 18:03:35 -0500116import cx.ring.utils.ActionHelper;
Adrien Béraude4f901a2019-10-25 17:26:30 -0400117import cx.ring.utils.ContentUriHandler;
118import cx.ring.utils.ConversationPath;
Pierre Duchemin42788c32018-03-08 16:21:15 -0500119import cx.ring.utils.DeviceUtils;
Romain Bertozziad8fd842016-05-11 14:30:35 -0400120import cx.ring.utils.KeyboardVisibilityManager;
Adrien Béraud5f8c3f72018-03-09 14:49:39 -0500121import cx.ring.utils.Log;
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -0500122import cx.ring.utils.MediaButtonsHelper;
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -0400123import cx.ring.utils.StringUtils;
Adrien Béraud8f9d2702018-09-16 18:24:01 -0400124import cx.ring.views.AvatarDrawable;
Adrien Béraud2c378b32018-07-11 15:24:02 -0400125import io.reactivex.disposables.CompositeDisposable;
Adrien Béraud04d822c2015-04-02 17:44:36 -0400126
agsantos00e3a9d2020-07-06 15:08:43 -0400127import static cx.ring.daemon.Ringservice.getPluginsEnabled;
128import static cx.ring.daemon.Ringservice.setPluginsEnabled;
129
ayounes47e93992019-10-28 12:09:53 -0400130public class CallFragment extends BaseSupportFragment<CallPresenter> implements CallView, MediaButtonsHelper.MediaButtonsHelperCallback, RecyclerPickerLayoutManager.ItemSelectedListener {
Adrien Béraud04d822c2015-04-02 17:44:36 -0400131
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400132 public static final String TAG = CallFragment.class.getSimpleName();
Adrien Béraud04d822c2015-04-02 17:44:36 -0400133
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400134 public static final String ACTION_PLACE_CALL = "PLACE_CALL";
135 public static final String ACTION_GET_CALL = "GET_CALL";
Adrien Béraud04d822c2015-04-02 17:44:36 -0400136
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400137 public static final String KEY_ACTION = "action";
138 public static final String KEY_ACCOUNT_ID = "accountId";
139 public static final String KEY_CONF_ID = "confId";
Hadrien De Sousa203164c2017-12-05 17:41:42 -0500140 public static final String KEY_AUDIO_ONLY = "AUDIO_ONLY";
Thibault Wittembergb70d5b02016-07-08 16:50:14 -0400141
Adrien Béraude4f901a2019-10-25 17:26:30 -0400142 private static final int REQUEST_CODE_ADD_PARTICIPANT = 6;
Rayan Osseiran38206c62019-05-15 14:49:03 -0400143 private static final int REQUEST_PERMISSION_INCOMING = 1003;
144 private static final int REQUEST_PERMISSION_OUTGOING = 1004;
Adrien Béraudade9bee2019-12-02 17:13:26 -0500145 private static final int REQUEST_CODE_SCREEN_SHARE = 7;
Adrien Béraude4f901a2019-10-25 17:26:30 -0400146
Adrien Béraud86a1e372018-11-23 23:24:30 -0500147 private FragCallBinding binding;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400148 private OrientationEventListener mOrientationListener;
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400149
Romain Bertozziad8fd842016-05-11 14:30:35 -0400150 private MenuItem dialPadBtn = null;
ayounes47e93992019-10-28 12:09:53 -0400151 private MenuItem pluginsMenuBtn = null;
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400152 private boolean restartVideo = false;
Rayan Osseiranc1532d42019-06-05 13:17:53 -0400153 private boolean restartPreview = false;
Rayan Osseirande9ac142019-07-02 13:01:32 -0400154 private PowerManager.WakeLock mScreenWakeLock = null;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400155 private int mCurrentOrientation = 0;
156
157 private int mVideoWidth = -1;
158 private int mVideoHeight = -1;
Adrien Béraudde0d4522018-12-12 12:11:02 -0500159 private int mPreviewWidth = 720, mPreviewHeight = 1280;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400160 private int mPreviewSurfaceWidth = 0, mPreviewSurfaceHeight = 0;
Adrien Béraud8d6a4832016-04-12 18:06:11 -0400161
Adrien Béraudade9bee2019-12-02 17:13:26 -0500162 private MediaProjectionManager mProjectionManager;
163
Rayan Osseiranf7dfe232019-06-06 10:26:10 -0400164 private boolean mBackstackLost = false;
165
Adrien Béraude4f901a2019-10-25 17:26:30 -0400166 private ConfParticipantAdapter confAdapter = null;
167 private boolean mConferenceMode = false;
ayounes81087472019-11-08 15:26:05 -0500168 private boolean pluginsModeFirst = true;
ayounes019267f2020-01-13 15:14:08 -0500169 private List<String> callMediaHandlers;
ayounes47e93992019-10-28 12:09:53 -0400170 private int previousPluginPosition = -1;
171 private RecyclerPicker rp;
ayounesc6c2c012019-11-11 11:09:51 -0500172 private boolean toggleVideoPluginsCarousel = true;
173 private final ValueAnimator animation = new ValueAnimator();
174
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400175 private PointF previewDrag = null;
176 private final ValueAnimator previewSnapAnimation = new ValueAnimator();
177 private final int[] previewMargins = new int[4];
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400178 private float previewHiddenState = 0;
179 private enum PreviewPosition {LEFT, RIGHT}
180 private PreviewPosition previewPosition = PreviewPosition.RIGHT;
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400181
Rayan Osseiran38206c62019-05-15 14:49:03 -0400182 @Inject
183 DeviceRuntimeService mDeviceRuntimeService;
184
Adrien Béraud2c378b32018-07-11 15:24:02 -0400185 private final CompositeDisposable mCompositeDisposable = new CompositeDisposable();
186
Hadrien De Sousa203164c2017-12-05 17:41:42 -0500187 public static CallFragment newInstance(@NonNull String action, @Nullable String accountID, @Nullable String contactRingId, boolean audioOnly) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400188 Bundle bundle = new Bundle();
189 bundle.putString(KEY_ACTION, action);
190 bundle.putString(KEY_ACCOUNT_ID, accountID);
Hadrien De Sousa0dc83162017-11-10 16:15:18 -0500191 bundle.putString(ConversationFragment.KEY_CONTACT_RING_ID, contactRingId);
Hadrien De Sousa203164c2017-12-05 17:41:42 -0500192 bundle.putBoolean(KEY_AUDIO_ONLY, audioOnly);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400193 CallFragment countDownFragment = new CallFragment();
194 countDownFragment.setArguments(bundle);
195 return countDownFragment;
196 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500197
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400198 public static CallFragment newInstance(@NonNull String action, @Nullable String confId) {
199 Bundle bundle = new Bundle();
200 bundle.putString(KEY_ACTION, action);
201 bundle.putString(KEY_CONF_ID, confId);
202 CallFragment countDownFragment = new CallFragment();
203 countDownFragment.setArguments(bundle);
204 return countDownFragment;
205 }
206
Rayan Osseiran6f415662019-10-25 14:23:25 -0400207 public static int callStateToHumanState(final SipCall.CallStatus state) {
Loïc Siret0202fbf2017-09-28 16:34:28 -0400208 switch (state) {
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400209 case SEARCHING:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400210 return R.string.call_human_state_searching;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400211 case CONNECTING:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400212 return R.string.call_human_state_connecting;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400213 case RINGING:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400214 return R.string.call_human_state_ringing;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400215 case CURRENT:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400216 return R.string.call_human_state_current;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400217 case HUNGUP:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400218 return R.string.call_human_state_hungup;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400219 case BUSY:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400220 return R.string.call_human_state_busy;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400221 case FAILURE:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400222 return R.string.call_human_state_failure;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400223 case HOLD:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400224 return R.string.call_human_state_hold;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400225 case UNHOLD:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400226 return R.string.call_human_state_unhold;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400227 case OVER:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400228 return R.string.call_human_state_over;
Adrien Bérauda3f0b4b2018-08-09 11:41:53 -0400229 case NONE:
Loïc Siret0202fbf2017-09-28 16:34:28 -0400230 default:
Adrien Béraude4f901a2019-10-25 17:26:30 -0400231 return R.string.call_human_state_none;
Loïc Siret0202fbf2017-09-28 16:34:28 -0400232 }
233 }
234
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400235 @Override
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400236 protected void initPresenter(CallPresenter presenter) {
237 super.initPresenter(presenter);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400238 Bundle args = getArguments();
239 if (args != null) {
240 String action = args.getString(KEY_ACTION);
241 if (action != null) {
242 if (action.equals(ACTION_PLACE_CALL)) {
Rayan Osseiran3dd04662019-06-28 16:47:48 -0400243 prepareCall(false);
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400244 } else if (action.equals(ACTION_GET_CALL) || action.equals(CallActivity.ACTION_CALL_ACCEPT)) {
Rayan Osseiraned9feeb2019-07-05 16:04:30 -0400245 presenter.initIncomingCall(getArguments().getString(KEY_CONF_ID), action.equals(ACTION_GET_CALL));
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400246 }
Pierre Duchemin45707ca2018-01-15 15:05:23 -0500247 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500248 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500249 }
250
Adrien Béraud79808d02018-02-20 00:16:28 +0100251 public void onUserLeave() {
252 presenter.requestPipMode();
253 }
254
255 @Override
Adrien Béraude4f901a2019-10-25 17:26:30 -0400256 public void enterPipMode(String callId) {
Adrien Béraud79808d02018-02-20 00:16:28 +0100257 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
258 return;
259 }
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400260 Context context = requireContext();
Adrien Béraud79808d02018-02-20 00:16:28 +0100261 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
262 PictureInPictureParams.Builder paramBuilder = new PictureInPictureParams.Builder();
Adrien Béraud86a1e372018-11-23 23:24:30 -0500263 if (binding.videoSurface.getVisibility() == View.VISIBLE) {
Adrien Béraud79808d02018-02-20 00:16:28 +0100264 int[] l = new int[2];
Adrien Béraud86a1e372018-11-23 23:24:30 -0500265 binding.videoSurface.getLocationInWindow(l);
Adrien Béraud79808d02018-02-20 00:16:28 +0100266 int x = l[0];
267 int y = l[1];
Adrien Béraud86a1e372018-11-23 23:24:30 -0500268 int w = binding.videoSurface.getWidth();
269 int h = binding.videoSurface.getHeight();
Adrien Béraud79808d02018-02-20 00:16:28 +0100270 Rect videoBounds = new Rect(x, y, x + w, y + h);
271 paramBuilder.setAspectRatio(new Rational(w, h));
272 paramBuilder.setSourceRectHint(videoBounds);
273 }
274 ArrayList<RemoteAction> actions = new ArrayList<>(1);
275 actions.add(new RemoteAction(
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400276 Icon.createWithResource(context, R.drawable.baseline_call_end_24),
Adrien Béraud79808d02018-02-20 00:16:28 +0100277 getString(R.string.action_call_hangup),
278 getString(R.string.action_call_hangup),
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400279 PendingIntent.getService(context, new Random().nextInt(),
Adrien Béraud79808d02018-02-20 00:16:28 +0100280 new Intent(DRingService.ACTION_CALL_END)
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400281 .setClass(context, DRingService.class)
Adrien Béraude4f901a2019-10-25 17:26:30 -0400282 .putExtra(NotificationService.KEY_CALL_ID, callId), PendingIntent.FLAG_ONE_SHOT)));
Adrien Béraud79808d02018-02-20 00:16:28 +0100283 paramBuilder.setActions(actions);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400284 requireActivity().enterPictureInPictureMode(paramBuilder.build());
285 } else if (DeviceUtils.isTv(context)) {
286 requireActivity().enterPictureInPictureMode();
Adrien Béraud79808d02018-02-20 00:16:28 +0100287 }
288 }
289
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500290 @Override
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400291 public void onStart() {
292 super.onStart();
Rayan Osseiranc1532d42019-06-05 13:17:53 -0400293 if (restartVideo && restartPreview) {
294 displayVideoSurface(true, !presenter.isPipMode());
295 restartVideo = false;
296 restartPreview = false;
Rayan Osseiranf7dfe232019-06-06 10:26:10 -0400297 } else if (restartVideo) {
Rayan Osseiranc1532d42019-06-05 13:17:53 -0400298 displayVideoSurface(true, false);
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400299 restartVideo = false;
300 }
301 }
302
303 @Override
304 public void onStop() {
305 super.onStop();
Adrien Béraud86a1e372018-11-23 23:24:30 -0500306 if (binding.videoSurface.getVisibility() == View.VISIBLE) {
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400307 restartVideo = true;
308 }
agsantos00e3a9d2020-07-06 15:08:43 -0400309 if (!getPluginsEnabled()) {
AGS5ef482ce2020-06-12 13:28:51 -0400310 if (binding.previewContainer.getVisibility() == View.VISIBLE) {
311 restartPreview = true;
312 }
313 }else {
314 if (binding.pluginPreviewContainer.getVisibility() == View.VISIBLE) {
315 restartPreview = true;
316 }
Rayan Osseiranc1532d42019-06-05 13:17:53 -0400317 }
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400318 }
319
Adrien Béraud86a1e372018-11-23 23:24:30 -0500320 @Nullable
321 @Override
Adrien Béraudc14d55d2019-01-02 16:33:40 -0500322 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
AGS5ef482ce2020-06-12 13:28:51 -0400323
Adrien Béraud7307cd52020-04-13 23:29:11 -0400324 ((JamiApplication) requireActivity().getApplication()).getInjectionComponent().inject(this);
Adrien Béraud86a1e372018-11-23 23:24:30 -0500325 binding = DataBindingUtil.inflate(inflater, R.layout.frag_call, container, false);
326 binding.setPresenter(this);
ayounes47e93992019-10-28 12:09:53 -0400327 rp = new RecyclerPicker(requireActivity(),
328 binding.recyclerPicker,
ayounesc6c2c012019-11-11 11:09:51 -0500329 R.layout.item_picker,
ayounes47e93992019-10-28 12:09:53 -0400330 LinearLayout.HORIZONTAL, this);
ayounesc6c2c012019-11-11 11:09:51 -0500331 rp.setFirstLastElementsWidths(112, 112);
Adrien Béraud86a1e372018-11-23 23:24:30 -0500332 return binding.getRoot();
333 }
334
Adrien Béraudde0d4522018-12-12 12:11:02 -0500335 private TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() {
336 @Override
337 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400338 mPreviewSurfaceWidth = width;
339 mPreviewSurfaceHeight = height;
Adrien Béraudde0d4522018-12-12 12:11:02 -0500340 presenter.previewVideoSurfaceCreated(binding.previewSurface);
341 }
342
343 @Override
344 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400345 mPreviewSurfaceWidth = width;
346 mPreviewSurfaceHeight = height;
Pierre Duchemin7c125f72020-05-29 15:23:53 -0400347 configurePreview(width, 1);
Adrien Béraudde0d4522018-12-12 12:11:02 -0500348 }
349
350 @Override
351 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
352 presenter.previewVideoSurfaceDestroyed();
353 return true;
354 }
355
356 @Override
Rayan Osseiran38206c62019-05-15 14:49:03 -0400357 public void onSurfaceTextureUpdated(SurfaceTexture surface) {
358 }
Adrien Béraudde0d4522018-12-12 12:11:02 -0500359 };
360
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400361 /**
362 * @param hiddenState 0.f if fully shown, 1.f if fully hidden.
363 */
364 private void setPreviewDragHiddenState(float hiddenState) {
365 binding.previewSurface.setAlpha(1.f - (3 * hiddenState / 4));
AGS5ef482ce2020-06-12 13:28:51 -0400366 binding.pluginPreviewSurface.setAlpha(1.f - (3 * hiddenState / 4));
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400367 binding.previewHandle.setAlpha(hiddenState);
AGS5ef482ce2020-06-12 13:28:51 -0400368 binding.pluginPreviewHandle.setAlpha(hiddenState);
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400369 }
370
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400371 @SuppressLint("ClickableViewAccessibility")
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400372 @Override
Adrien Béraudc14d55d2019-01-02 16:33:40 -0500373 public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400374 setHasOptionsMenu(true);
Hadrien De Sousa73d6dd72017-09-07 10:54:51 -0400375 super.onViewCreated(view, savedInstanceState);
Adrien Béraud79808d02018-02-20 00:16:28 +0100376 mCurrentOrientation = getResources().getConfiguration().orientation;
ayounesc6c2c012019-11-11 11:09:51 -0500377 float dpRatio = requireActivity().getResources().getDisplayMetrics().density;
378
379 animation.setDuration(150);
380 animation.addUpdateListener(valueAnimator -> {
381 int upBy = (int) valueAnimator.getAnimatedValue();
382 RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) binding.previewContainer.getLayoutParams();
383 layoutParams.setMargins(0, 0, 0, (int) (upBy * dpRatio));
384 binding.previewContainer.setLayoutParams(layoutParams);
385 });
Adrien Béraud04d822c2015-04-02 17:44:36 -0400386
Adrien Béraude4f901a2019-10-25 17:26:30 -0400387 FragmentActivity activity = getActivity();
388 if (activity != null) {
389 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
390 if (activity instanceof AppCompatActivity) {
391 AppCompatActivity ac_activity = (AppCompatActivity) activity;
392 ActionBar ab = ac_activity.getSupportActionBar();
393 if (ab != null) {
394 ab.setHomeAsUpIndicator(R.drawable.baseline_chat_24);
395 ab.setDisplayHomeAsUpEnabled(true);
396 }
397 }
398 }
399
Adrien Béraudade9bee2019-12-02 17:13:26 -0500400 mProjectionManager = (MediaProjectionManager) requireContext().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
401
Adrien Béraude4f901a2019-10-25 17:26:30 -0400402 PowerManager powerManager = (PowerManager) requireContext().getSystemService(Context.POWER_SERVICE);
403 if (powerManager != null) {
404 mScreenWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "ring:callLock");
405 mScreenWakeLock.setReferenceCounted(false);
406 if (mScreenWakeLock != null && !mScreenWakeLock.isHeld()) {
407 mScreenWakeLock.acquire();
408 }
Adrien Béraud04d822c2015-04-02 17:44:36 -0400409 }
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500410
Adrien Béraud86a1e372018-11-23 23:24:30 -0500411 binding.videoSurface.getHolder().setFormat(PixelFormat.RGBA_8888);
412 binding.videoSurface.getHolder().addCallback(new SurfaceHolder.Callback() {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400413 @Override
414 public void surfaceCreated(SurfaceHolder holder) {
415 presenter.videoSurfaceCreated(holder);
416 }
417
418 @Override
419 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
420
421 }
422
423 @Override
424 public void surfaceDestroyed(SurfaceHolder holder) {
425 presenter.videoSurfaceDestroyed();
426 }
427 });
AGS5ef482ce2020-06-12 13:28:51 -0400428
429 binding.pluginPreviewSurface.getHolder().setFormat(PixelFormat.RGBA_8888);
430 binding.pluginPreviewSurface.getHolder().addCallback(new SurfaceHolder.Callback() {
431 @Override
432 public void surfaceCreated(SurfaceHolder holder) {
433 presenter.pluginSurfaceCreated(holder);
434 }
435
436 @Override
437 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
438
439 }
440
441 @Override
442 public void surfaceDestroyed(SurfaceHolder holder) {
443 presenter.pluginSurfaceDestroyed();
444 }
445 });
446
Pierre Duchemin45707ca2018-01-15 15:05:23 -0500447 view.setOnSystemUiVisibilityChangeListener(visibility -> {
448 boolean ui = (visibility & (View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN)) == 0;
449 presenter.uiVisibilityChanged(ui);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400450 });
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400451 view.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
452 resetVideoSize(mVideoWidth, mVideoHeight));
453
454 WindowManager windowManager = (WindowManager) requireContext().getSystemService(Context.WINDOW_SERVICE);
Adrien Béraude4f901a2019-10-25 17:26:30 -0400455 if (windowManager != null) {
456 mOrientationListener = new OrientationEventListener(getContext()) {
457 @Override
458 public void onOrientationChanged(int orientation) {
459 int rot = windowManager.getDefaultDisplay().getRotation();
460 if (mCurrentOrientation != rot) {
461 mCurrentOrientation = rot;
462 presenter.configurationChanged(rot);
463 }
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400464 }
Adrien Béraude4f901a2019-10-25 17:26:30 -0400465 };
466 if (mOrientationListener.canDetectOrientation()) {
467 mOrientationListener.enable();
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400468 }
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400469 }
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400470
Adrien Béraud86a1e372018-11-23 23:24:30 -0500471 binding.shapeRipple.setRippleShape(new Circle());
472 binding.callSpeakerBtn.setChecked(presenter.isSpeakerphoneOn());
Adrien Béraudec19fad2018-12-30 16:51:05 -0500473 binding.callMicBtn.setChecked(presenter.isMicrophoneMuted());
AGS5ef482ce2020-06-12 13:28:51 -0400474 binding.pluginPreviewSurface.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
475 configureTransform(mPreviewSurfaceWidth, mPreviewSurfaceHeight));
Adrien Béraudde0d4522018-12-12 12:11:02 -0500476 binding.previewSurface.setSurfaceTextureListener(listener);
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400477 binding.previewSurface.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
478 configureTransform(mPreviewSurfaceWidth, mPreviewSurfaceHeight));
Adrien Béraudbcbb4d42018-12-08 16:06:39 -0500479
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400480 previewSnapAnimation.setDuration(250);
481 previewSnapAnimation.setFloatValues(0.f, 1.f);
482 previewSnapAnimation.setInterpolator(new DecelerateInterpolator());
483 previewSnapAnimation.addUpdateListener(animation -> {
Pierre Duchemin7c125f72020-05-29 15:23:53 -0400484 float animatedFraction = animation == null ? 1 : animation.getAnimatedFraction();
485 configurePreview(mPreviewSurfaceWidth, animatedFraction);
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400486 });
487
488 binding.previewContainer.setOnTouchListener((v, event) -> {
489 int action = event.getActionMasked();
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400490 RelativeLayout parent = (RelativeLayout) v.getParent();
491 RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
492
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400493 if (action == MotionEvent.ACTION_DOWN) {
494 previewSnapAnimation.cancel();
495 previewDrag = new PointF(event.getX(), event.getY());
496 v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation_dragged));
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400497 params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
498 params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
499 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
500 params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400501 params.setMargins((int) v.getX(), (int) v.getY(), parent.getWidth() - ((int) v.getX() + v.getWidth()), parent.getHeight() - ((int) v.getY() + v.getHeight()));
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400502 v.setLayoutParams(params);
503 return true;
504 } else if (action == MotionEvent.ACTION_MOVE) {
505 if (previewDrag != null) {
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400506 int currentXPosition = params.leftMargin + (int) (event.getX() - previewDrag.x);
507 int currentYPosition = params.topMargin + (int) (event.getY() - previewDrag.y);
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400508 params.setMargins(
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400509 currentXPosition,
510 currentYPosition,
511 -((currentXPosition + v.getWidth()) - (int) event.getX()),
512 -((currentYPosition + v.getHeight()) - (int) event.getY()));
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400513 v.setLayoutParams(params);
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400514
515 float outPosition = binding.previewContainer.getWidth() * 0.85f;
516 float drapOut = 0.f;
517 if (currentXPosition < 0) {
518 drapOut = Math.min(1.f, -currentXPosition / outPosition);
519 } else if (currentXPosition + v.getWidth() > parent.getWidth()) {
520 drapOut = Math.min(1.f, (currentXPosition + v.getWidth() - parent.getWidth()) / outPosition);
521 }
522 setPreviewDragHiddenState(drapOut);
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400523 return true;
524 }
525 return false;
526 } else if (action == MotionEvent.ACTION_UP) {
527 if (previewDrag != null) {
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400528 int currentXPosition = params.leftMargin + (int) (event.getX() - previewDrag.x);
529
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400530 previewSnapAnimation.cancel();
531 previewDrag = null;
532 v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation));
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400533 int ml = 0, mr = 0, mt = 0, mb = 0;
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400534
535 FrameLayout.LayoutParams hp = (FrameLayout.LayoutParams) binding.previewHandle.getLayoutParams();
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400536 if (params.leftMargin + (v.getWidth() / 2) > parent.getWidth() / 2) {
537 params.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
538 params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
539 mr = (int) (parent.getWidth() - v.getWidth() - v.getX());
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400540 previewPosition = PreviewPosition.RIGHT;
541 hp.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400542 } else {
543 params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
544 params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
545 ml = (int) v.getX();
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400546 previewPosition = PreviewPosition.LEFT;
547 hp.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400548 }
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400549 binding.previewHandle.setLayoutParams(hp);
550
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400551 if (params.topMargin + (v.getHeight() / 2) > parent.getHeight() / 2) {
552 params.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
553 params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
554 mb = (int) (parent.getHeight() - v.getHeight() - v.getY());
555 } else {
556 params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
557 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
558 mt = (int) v.getY();
559 }
560 previewMargins[0] = ml;
561 previewMargins[1] = mt;
562 previewMargins[2] = mr;
563 previewMargins[3] = mb;
564 params.setMargins(ml, mt, mr, mb);
565 v.setLayoutParams(params);
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400566
567 float outPosition = binding.previewContainer.getWidth() * 0.85f;
568 previewHiddenState = currentXPosition < 0
569 ? Math.min(1.f, -currentXPosition / outPosition)
570 : ((currentXPosition + v.getWidth() > parent.getWidth())
571 ? Math.min(1.f, (currentXPosition + v.getWidth() - parent.getWidth()) / outPosition)
572 : 0.f);
573 setPreviewDragHiddenState(previewHiddenState);
574
Adrien Béraud2d50acb2020-03-23 22:02:15 -0400575 previewSnapAnimation.start();
576 return true;
577 }
578 return false;
579 } else {
580 return false;
581 }
582 });
583
AGS5ef482ce2020-06-12 13:28:51 -0400584 binding.pluginPreviewContainer.setOnTouchListener((v, event) -> {
585 int action = event.getActionMasked();
586 RelativeLayout parent = (RelativeLayout) v.getParent();
587 RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
588
589 if (action == MotionEvent.ACTION_DOWN) {
590 previewSnapAnimation.cancel();
591 previewDrag = new PointF(event.getX(), event.getY());
592 v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation_dragged));
593 params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
594 params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
595 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
596 params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
597 params.setMargins((int) v.getX(), (int) v.getY(), parent.getWidth() - ((int) v.getX() + v.getWidth()), parent.getHeight() - ((int) v.getY() + v.getHeight()));
598 v.setLayoutParams(params);
599 return true;
600 } else if (action == MotionEvent.ACTION_MOVE) {
601 if (previewDrag != null) {
602 int currentXPosition = params.leftMargin + (int) (event.getX() - previewDrag.x);
603 int currentYPosition = params.topMargin + (int) (event.getY() - previewDrag.y);
604 params.setMargins(
605 currentXPosition,
606 currentYPosition,
607 -((currentXPosition + v.getWidth()) - (int) event.getX()),
608 -((currentYPosition + v.getHeight()) - (int) event.getY()));
609 v.setLayoutParams(params);
610
611 float outPosition = binding.pluginPreviewContainer.getWidth() * 0.85f;
612 float drapOut = 0.f;
613 if (currentXPosition < 0) {
614 drapOut = Math.min(1.f, -currentXPosition / outPosition);
615 } else if (currentXPosition + v.getWidth() > parent.getWidth()) {
616 drapOut = Math.min(1.f, (currentXPosition + v.getWidth() - parent.getWidth()) / outPosition);
617 }
618 setPreviewDragHiddenState(drapOut);
619 return true;
620 }
621 return false;
622 } else if (action == MotionEvent.ACTION_UP) {
623 if (previewDrag != null) {
624 int currentXPosition = params.leftMargin + (int) (event.getX() - previewDrag.x);
625
626 previewSnapAnimation.cancel();
627 previewDrag = null;
628 v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation));
629 int ml = 0, mr = 0, mt = 0, mb = 0;
630
631 FrameLayout.LayoutParams hp = (FrameLayout.LayoutParams) binding.pluginPreviewHandle.getLayoutParams();
632 if (params.leftMargin + (v.getWidth() / 2) > parent.getWidth() / 2) {
633 params.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
634 params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
635 mr = (int) (parent.getWidth() - v.getWidth() - v.getX());
636 previewPosition = PreviewPosition.RIGHT;
637 hp.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;
638 } else {
639 params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
640 params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
641 ml = (int) v.getX();
642 previewPosition = PreviewPosition.LEFT;
643 hp.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
644 }
645 binding.pluginPreviewHandle.setLayoutParams(hp);
646
647 if (params.topMargin + (v.getHeight() / 2) > parent.getHeight() / 2) {
648 params.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
649 params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
650 mb = (int) (parent.getHeight() - v.getHeight() - v.getY());
651 } else {
652 params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
653 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
654 mt = (int) v.getY();
655 }
656 previewMargins[0] = ml;
657 previewMargins[1] = mt;
658 previewMargins[2] = mr;
659 previewMargins[3] = mb;
660 params.setMargins(ml, mt, mr, mb);
661 v.setLayoutParams(params);
662
663 float outPosition = binding.pluginPreviewContainer.getWidth() * 0.85f;
664 previewHiddenState = currentXPosition < 0
665 ? Math.min(1.f, -currentXPosition / outPosition)
666 : ((currentXPosition + v.getWidth() > parent.getWidth())
667 ? Math.min(1.f, (currentXPosition + v.getWidth() - parent.getWidth()) / outPosition)
668 : 0.f);
669 setPreviewDragHiddenState(previewHiddenState);
670
671 previewSnapAnimation.start();
672 return true;
673 }
674 return false;
675 } else {
676 return false;
677 }
678 });
679
Adrien Béraudbcbb4d42018-12-08 16:06:39 -0500680 binding.dialpadEditText.addTextChangedListener(new TextWatcher() {
681 @Override
Rayan Osseiran38206c62019-05-15 14:49:03 -0400682 public void beforeTextChanged(CharSequence s, int start, int count, int after) {
683 }
Adrien Béraudbcbb4d42018-12-08 16:06:39 -0500684
685 @Override
686 public void onTextChanged(CharSequence s, int start, int before, int count) {
687 presenter.sendDtmf(s.subSequence(start, start + count));
688 }
689
690 @Override
Rayan Osseiran38206c62019-05-15 14:49:03 -0400691 public void afterTextChanged(Editable s) {
692 }
Adrien Béraudbcbb4d42018-12-08 16:06:39 -0500693 });
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500694 }
695
Pierre Duchemin7c125f72020-05-29 15:23:53 -0400696 private void configurePreview(int width, float animatedFraction) {
697 float margin = getResources().getDimension(R.dimen.call_preview_margin);
698 RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.previewContainer.getLayoutParams();
699 float r = 1.f - animatedFraction;
700 float hideMargin = 0.f;
701 float targetHiddenState = 0.f;
702 if (previewHiddenState > 0.f) {
703 targetHiddenState = 1.f;
704 float v = width * 0.85f * animatedFraction;
705 hideMargin = previewPosition == PreviewPosition.RIGHT ? v : -v;
706 }
707 setPreviewDragHiddenState(previewHiddenState * r + targetHiddenState * animatedFraction);
708
709 float f = margin * animatedFraction;
710 params.setMargins(
711 (int) (previewMargins[0] * r + f + hideMargin),
712 (int) (previewMargins[1] * r + f),
713 (int) (previewMargins[2] * r + f - hideMargin),
714 (int) (previewMargins[3] * r + f));
715 binding.previewContainer.setLayoutParams(params);
AGS5ef482ce2020-06-12 13:28:51 -0400716 binding.pluginPreviewContainer.setLayoutParams(params);
Pierre Duchemin7c125f72020-05-29 15:23:53 -0400717 }
718
Rayan Osseirande9ac142019-07-02 13:01:32 -0400719 /**
720 * Releases current wakelock and acquires a new proximity wakelock if current call is audio only.
ayounesc6c2c012019-11-11 11:09:51 -0500721 *
Rayan Osseirande9ac142019-07-02 13:01:32 -0400722 * @param isAudioOnly true if it is an audio call
723 */
724 @Override
725 public void handleCallWakelock(boolean isAudioOnly) {
726 if (isAudioOnly) {
727 if (mScreenWakeLock != null && mScreenWakeLock.isHeld()) {
728 mScreenWakeLock.release();
729 }
730 PowerManager powerManager = (PowerManager) requireContext().getSystemService(Context.POWER_SERVICE);
Adrien Béraude4f901a2019-10-25 17:26:30 -0400731 if (powerManager != null) {
732 mScreenWakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "ring:callLock");
733 mScreenWakeLock.setReferenceCounted(false);
Rayan Osseirande9ac142019-07-02 13:01:32 -0400734
Adrien Béraude4f901a2019-10-25 17:26:30 -0400735 if (mScreenWakeLock != null && !mScreenWakeLock.isHeld()) {
736 mScreenWakeLock.acquire();
737 }
Rayan Osseirande9ac142019-07-02 13:01:32 -0400738 }
739 }
740 }
741
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500742 @Override
Adrien Béraud2c378b32018-07-11 15:24:02 -0400743 public void onDestroyView() {
744 super.onDestroyView();
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400745 if (mOrientationListener != null) {
746 mOrientationListener.disable();
747 mOrientationListener = null;
748 }
Adrien Béraud2c378b32018-07-11 15:24:02 -0400749 mCompositeDisposable.clear();
Adrien Béraudfb6341f2016-03-07 16:18:54 -0500750 if (mScreenWakeLock != null && mScreenWakeLock.isHeld()) {
751 mScreenWakeLock.release();
752 }
Adrien Béraud7307cd52020-04-13 23:29:11 -0400753 binding = null;
Adrien Béraud04d822c2015-04-02 17:44:36 -0400754 }
755
Adrien Béraud7307cd52020-04-13 23:29:11 -0400756 @Override
757 public void onDestroy() {
758 super.onDestroy();
759 mCompositeDisposable.dispose();
760 }
Rayan Osseiran38206c62019-05-15 14:49:03 -0400761
762 @Override
763 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
764 super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Adrien Béraud63de6042019-05-31 09:38:31 -0400765 if (requestCode != REQUEST_PERMISSION_INCOMING && requestCode != REQUEST_PERMISSION_OUTGOING)
766 return;
Rayan Osseiran38206c62019-05-15 14:49:03 -0400767 for (int i = 0, n = permissions.length; i < n; i++) {
768 boolean audioGranted = mDeviceRuntimeService.hasAudioPermission();
Adrien Béraud63de6042019-05-31 09:38:31 -0400769 boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
Rayan Osseiran38206c62019-05-15 14:49:03 -0400770 switch (permissions[i]) {
771 case Manifest.permission.CAMERA:
Adrien Béraud63de6042019-05-31 09:38:31 -0400772 presenter.cameraPermissionChanged(granted);
773 if (audioGranted) {
774 initializeCall(requestCode == REQUEST_PERMISSION_INCOMING);
Rayan Osseiran38206c62019-05-15 14:49:03 -0400775 }
776 break;
777 case Manifest.permission.RECORD_AUDIO:
Adrien Béraud63de6042019-05-31 09:38:31 -0400778 presenter.audioPermissionChanged(granted);
779 initializeCall(requestCode == REQUEST_PERMISSION_INCOMING);
Rayan Osseiran38206c62019-05-15 14:49:03 -0400780 break;
781 }
782 }
783 }
784
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400785 @Override
Adrien Béraude4f901a2019-10-25 17:26:30 -0400786 public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
787 if (requestCode == REQUEST_CODE_ADD_PARTICIPANT) {
788 if (resultCode == Activity.RESULT_OK && data != null) {
789 ConversationPath path = ConversationPath.fromUri(data.getData());
790 if (path != null) {
791 presenter.addConferenceParticipant(path.getAccountId(), path.getContactId());
792 }
793 }
Adrien Béraudade9bee2019-12-02 17:13:26 -0500794 } else if (requestCode == REQUEST_CODE_SCREEN_SHARE) {
795 if (resultCode == Activity.RESULT_OK && data != null) {
796 startScreenShare(mProjectionManager.getMediaProjection(resultCode, data));
797 } else {
798 binding.callScreenshareBtn.setChecked(false);
799 }
Adrien Béraude4f901a2019-10-25 17:26:30 -0400800 }
801 }
802
803 @Override
804 public void onCreateOptionsMenu(@NonNull Menu m, @NonNull MenuInflater inf) {
Adrien Béraudda712a42015-11-22 23:45:26 -0500805 super.onCreateOptionsMenu(m, inf);
Adrien Béraudda2eb1a2016-01-11 13:15:12 -0500806 inf.inflate(R.menu.ac_call, m);
Romain Bertozziad8fd842016-05-11 14:30:35 -0400807 dialPadBtn = m.findItem(R.id.menuitem_dialpad);
ayounes47e93992019-10-28 12:09:53 -0400808 pluginsMenuBtn = m.findItem(R.id.menuitem_video_plugins);
Adrien Béraudda712a42015-11-22 23:45:26 -0500809 }
810
811 @Override
Adrien Béraude4f901a2019-10-25 17:26:30 -0400812 public void onPrepareOptionsMenu(@NonNull Menu menu) {
Adrien Béraudda712a42015-11-22 23:45:26 -0500813 super.onPrepareOptionsMenu(menu);
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400814 presenter.prepareOptionMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400815 }
816
817 @Override
Adrien Béraude4f901a2019-10-25 17:26:30 -0400818 public boolean onOptionsItemSelected(@NonNull MenuItem item) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400819 super.onOptionsItemSelected(item);
820 switch (item.getItemId()) {
821 case android.R.id.home:
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400822 presenter.chatClick();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400823 break;
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400824 case R.id.menuitem_dialpad:
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -0400825 presenter.dialpadClick();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400826 break;
ayounes47e93992019-10-28 12:09:53 -0400827 case R.id.menuitem_video_plugins:
828 displayVideoPluginsCarousel();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400829 }
830 return true;
831 }
832
Adrien Béraud79808d02018-02-20 00:16:28 +0100833 @Override
Adrien Bérauda373e3b2018-12-12 11:14:50 -0500834 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400835 AppCompatActivity activity = (AppCompatActivity) getActivity();
836 ActionBar actionBar = activity == null ? null : activity.getSupportActionBar();
837 if (actionBar != null) {
Rayan Osseiranf7dfe232019-06-06 10:26:10 -0400838 if (isInPictureInPictureMode) {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400839 actionBar.hide();
Rayan Osseiranf7dfe232019-06-06 10:26:10 -0400840 } else {
841 mBackstackLost = true;
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400842 actionBar.show();
Rayan Osseiranf7dfe232019-06-06 10:26:10 -0400843 }
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400844 }
Adrien Béraud79808d02018-02-20 00:16:28 +0100845 presenter.pipModeChanged(isInPictureInPictureMode);
846 }
847
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400848 @Override
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400849 public void displayContactBubble(final boolean display) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500850 binding.contactBubbleLayout.getHandler().post(() -> binding.contactBubbleLayout.setVisibility(display ? View.VISIBLE : View.GONE));
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400851 }
852
853 @Override
Rayan Osseiranc1532d42019-06-05 13:17:53 -0400854 public void displayVideoSurface(final boolean displayVideoSurface, final boolean displayPreviewContainer) {
855 binding.videoSurface.setVisibility(displayVideoSurface ? View.VISIBLE : View.GONE);
agsantos00e3a9d2020-07-06 15:08:43 -0400856 if (getPluginsEnabled()) {
AGS5ef482ce2020-06-12 13:28:51 -0400857 binding.pluginPreviewSurface.setVisibility(displayPreviewContainer ? View.VISIBLE : View.GONE);
858 binding.pluginPreviewContainer.setVisibility(displayPreviewContainer ? View.VISIBLE : View.GONE);
859 binding.previewContainer.setVisibility(View.GONE);
860 } else {
861 binding.pluginPreviewSurface.setVisibility(View.GONE);
862 binding.pluginPreviewContainer.setVisibility(View.GONE);
863 binding.previewContainer.setVisibility(displayPreviewContainer ? View.VISIBLE : View.GONE);
864 }
Adrien Béraudace37a22018-06-22 14:58:36 -0400865 updateMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400866 }
867
868 @Override
Adrien Béraud79808d02018-02-20 00:16:28 +0100869 public void displayPreviewSurface(final boolean display) {
870 if (display) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500871 binding.videoSurface.setZOrderOnTop(false);
Adrien Béraud86a1e372018-11-23 23:24:30 -0500872 binding.videoSurface.setZOrderMediaOverlay(false);
Adrien Béraud79808d02018-02-20 00:16:28 +0100873 } else {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500874 binding.videoSurface.setZOrderMediaOverlay(true);
875 binding.videoSurface.setZOrderOnTop(true);
Adrien Béraud79808d02018-02-20 00:16:28 +0100876 }
877 }
878
879 @Override
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400880 public void displayHangupButton(boolean display) {
Adrien Béraude4f901a2019-10-25 17:26:30 -0400881 Log.w(TAG, "displayHangupButton " + display);
agsantos00e3a9d2020-07-06 15:08:43 -0400882 display &= !getPluginsEnabled();
Adrien Béraud86a1e372018-11-23 23:24:30 -0500883 binding.callControlGroup.setVisibility(display ? View.VISIBLE : View.GONE);
884 binding.callHangupBtn.setVisibility(display ? View.VISIBLE : View.GONE);
Adrien Béraude4f901a2019-10-25 17:26:30 -0400885 binding.confControlGroup.setVisibility((mConferenceMode && display) ? View.VISIBLE : View.GONE);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400886 }
887
888 @Override
889 public void displayDialPadKeyboard() {
Adrien Béraudbcbb4d42018-12-08 16:06:39 -0500890 KeyboardVisibilityManager.showKeyboard(getActivity(), binding.dialpadEditText, InputMethodManager.SHOW_FORCED);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400891 }
892
893 @Override
894 public void switchCameraIcon(boolean isFront) {
Adrien Béraud91f88742019-09-09 00:46:46 -0400895 binding.callCameraFlipBtn.setImageResource(isFront ? R.drawable.baseline_camera_front_24 : R.drawable.baseline_camera_rear_24);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400896 }
897
898 @Override
Adrien Béraud34a6fa22019-07-28 16:02:59 -0400899 public void updateAudioState(HardwareService.AudioState state) {
900 binding.callSpeakerBtn.setChecked(state.getOutputType() == HardwareService.AudioOutput.SPEAKERS);
901 }
902
903 @Override
Adrien Béraudd3bf4e42018-02-14 14:44:41 +0100904 public void updateMenu() {
Adrien Béraudeb4bb002019-03-14 15:52:48 -0400905 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400906 }
907
908 @Override
909 public void updateTime(final long duration) {
Pierre Duchemin37d0b3e2020-05-14 18:56:21 -0400910 if (binding != null) {
Adrien Béraude4f901a2019-10-25 17:26:30 -0400911 if (duration == 0)
912 binding.callStatusTxt.setText(null);
913 else
914 binding.callStatusTxt.setText(String.format(Locale.getDefault(), "%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60));
915 }
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400916 }
917
918 @Override
Adrien Béraude4f901a2019-10-25 17:26:30 -0400919 @SuppressLint("RestrictedApi")
920 public void updateContactBubble(@NonNull final List<SipCall> contacts) {
921 Log.w(TAG, "updateContactBubble " + contacts.size());
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400922
Adrien Béraude4f901a2019-10-25 17:26:30 -0400923 mConferenceMode = contacts.size() > 1;
924 String username = mConferenceMode ? "Conference with " + contacts.size() + " people" : contacts.get(0).getContact().getRingUsername();
925 String displayName = mConferenceMode ? null : contacts.get(0).getContact().getDisplayName();
Adrien Béraud5f8c3f72018-03-09 14:49:39 -0500926
Adrien Béraudafcdd962018-07-06 21:38:41 -0400927 boolean hasProfileName = displayName != null && !displayName.contentEquals(username);
Adrien Béraudbc0898e2018-08-23 14:31:11 -0400928
929 AppCompatActivity activity = (AppCompatActivity) getActivity();
930 if (activity != null) {
931 ActionBar ab = activity.getSupportActionBar();
932 if (ab != null) {
933 if (hasProfileName) {
934 ab.setTitle(displayName);
935 ab.setSubtitle(username);
936 } else {
937 ab.setTitle(username);
938 ab.setSubtitle(null);
939 }
940 ab.setDisplayShowTitleEnabled(true);
941 }
942 }
943
Adrien Béraudafcdd962018-07-06 21:38:41 -0400944 if (hasProfileName) {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500945 binding.contactBubbleNumTxt.setVisibility(View.VISIBLE);
946 binding.contactBubbleTxt.setText(displayName);
947 binding.contactBubbleNumTxt.setText(username);
Adrien Béraudafcdd962018-07-06 21:38:41 -0400948 } else {
Adrien Béraud86a1e372018-11-23 23:24:30 -0500949 binding.contactBubbleNumTxt.setVisibility(View.GONE);
950 binding.contactBubbleTxt.setText(username);
Adrien Béraudafcdd962018-07-06 21:38:41 -0400951 }
Adrien Béraud5f8c3f72018-03-09 14:49:39 -0500952
Andreas Traczykcee415a2019-12-03 15:45:04 -0500953 binding.contactBubble.setImageDrawable(
954 new AvatarDrawable.Builder()
955 .withContact(contacts.get(0).getContact())
956 .withCircleCrop(true)
957 .withPresence(false)
958 .build(getActivity())
959 );
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400960
Adrien Béraude4f901a2019-10-25 17:26:30 -0400961 if (!mConferenceMode) {
962 binding.confControlGroup.setVisibility(View.GONE);
963 } else {
964 binding.confControlGroup.setVisibility(View.VISIBLE);
ayounesc6c2c012019-11-11 11:09:51 -0500965 if (confAdapter == null) {
Adrien Béraude4f901a2019-10-25 17:26:30 -0400966 confAdapter = new ConfParticipantAdapter((view, call) -> {
Adrien Bérauda165bee2020-06-08 10:30:26 -0400967 PopupMenu popup = new PopupMenu(view.getContext(), view);
Adrien Béraude4f901a2019-10-25 17:26:30 -0400968 popup.inflate(R.menu.conference_participant_actions);
969 popup.setOnMenuItemClickListener(item -> {
Adrien Bérauda165bee2020-06-08 10:30:26 -0400970 if (presenter != null)
971 switch (item.getItemId()) {
972 case R.id.conv_contact_details:
973 presenter.openParticipantContact(call);
974 break;
975 case R.id.conv_contact_hangup:
976 presenter.hangupParticipant(call);
977 break;
978 default:
979 return false;
980 }
Adrien Béraude4f901a2019-10-25 17:26:30 -0400981 return true;
982 });
Adrien Bérauda165bee2020-06-08 10:30:26 -0400983 MenuPopupHelper menuHelper = new MenuPopupHelper(view.getContext(), (MenuBuilder) popup.getMenu(), view);
Adrien Béraude4f901a2019-10-25 17:26:30 -0400984 menuHelper.setForceShowIcon(true);
985 menuHelper.show();
986 });
987 }
988 confAdapter.updateFromCalls(contacts);
989 if (binding.confControlGroup.getAdapter() == null)
990 binding.confControlGroup.setAdapter(confAdapter);
Adrien Béraud3f9f6cd2018-12-12 15:05:28 -0500991 }
Hadrien De Sousaccc947d2017-04-12 14:26:52 -0400992 }
993
994 @Override
Adrien Béraude4f901a2019-10-25 17:26:30 -0400995 public void updateCallStatus(final SipCall.CallStatus callStatus) {
996 binding.callStatusTxt.setText(callStateToHumanState(callStatus));
997 }
998
999 @Override
ayounes47e93992019-10-28 12:09:53 -04001000 public void initMenu(boolean isSpeakerOn, boolean displayFlip, boolean canDial,
1001 boolean showPluginBtn, boolean onGoingCall) {
1002 if (binding.callCameraFlipBtn != null) {
Adrien Béraud86a1e372018-11-23 23:24:30 -05001003 binding.callCameraFlipBtn.setVisibility(displayFlip ? View.VISIBLE : View.GONE);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001004 }
Romain Bertozziad8fd842016-05-11 14:30:35 -04001005 if (dialPadBtn != null) {
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001006 dialPadBtn.setVisible(canDial);
Romain Bertozziad8fd842016-05-11 14:30:35 -04001007 }
ayounes47e93992019-10-28 12:09:53 -04001008
ayounesc6c2c012019-11-11 11:09:51 -05001009 if (pluginsMenuBtn != null) {
ayounes47e93992019-10-28 12:09:53 -04001010 pluginsMenuBtn.setVisible(showPluginBtn);
1011 }
1012 updateMenu();
Adrien Béraud04d822c2015-04-02 17:44:36 -04001013 }
1014
1015 @Override
Adrien Béraud34a6fa22019-07-28 16:02:59 -04001016 public void initNormalStateDisplay(final boolean audioOnly, boolean isMuted) {
Adrien Béraude4f901a2019-10-25 17:26:30 -04001017 Log.w(TAG, "initNormalStateDisplay");
Adrien Béraud86a1e372018-11-23 23:24:30 -05001018 binding.shapeRipple.stopRipple();
Pierre Ducheminbb833672018-03-09 16:18:33 -05001019
Adrien Béraud86a1e372018-11-23 23:24:30 -05001020 binding.callAcceptBtn.setVisibility(View.GONE);
1021 binding.callRefuseBtn.setVisibility(View.GONE);
1022 binding.callControlGroup.setVisibility(View.VISIBLE);
1023 binding.callHangupBtn.setVisibility(View.VISIBLE);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001024
Adrien Béraud86a1e372018-11-23 23:24:30 -05001025 binding.contactBubbleLayout.setVisibility(audioOnly ? View.VISIBLE : View.GONE);
Adrien Béraudec19fad2018-12-30 16:51:05 -05001026 binding.callMicBtn.setChecked(isMuted);
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001027
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001028 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001029 }
1030
1031 @Override
1032 public void initIncomingCallDisplay() {
Adrien Béraude4f901a2019-10-25 17:26:30 -04001033 Log.w(TAG, "initIncomingCallDisplay");
1034
Adrien Béraud86a1e372018-11-23 23:24:30 -05001035 binding.callAcceptBtn.setVisibility(View.VISIBLE);
1036 binding.callRefuseBtn.setVisibility(View.VISIBLE);
1037 binding.callControlGroup.setVisibility(View.GONE);
1038 binding.callHangupBtn.setVisibility(View.GONE);
Hadrien De Sousa841d15a2017-06-02 11:52:10 -04001039
Adrien Béraud86a1e372018-11-23 23:24:30 -05001040 binding.contactBubbleLayout.setVisibility(View.VISIBLE);
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001041 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001042 }
1043
1044 @Override
1045 public void initOutGoingCallDisplay() {
Adrien Béraude4f901a2019-10-25 17:26:30 -04001046 Log.w(TAG, "initOutGoingCallDisplay");
1047
Adrien Béraud86a1e372018-11-23 23:24:30 -05001048 binding.callAcceptBtn.setVisibility(View.GONE);
1049 binding.callRefuseBtn.setVisibility(View.VISIBLE);
1050 binding.callControlGroup.setVisibility(View.GONE);
1051 binding.callHangupBtn.setVisibility(View.GONE);
Hadrien De Sousa841d15a2017-06-02 11:52:10 -04001052
Adrien Béraud86a1e372018-11-23 23:24:30 -05001053 binding.contactBubbleLayout.setVisibility(View.VISIBLE);
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001054 requireActivity().invalidateOptionsMenu();
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001055 }
1056
1057 @Override
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001058 public void resetPreviewVideoSize(int previewWidth, int previewHeight, int rot) {
1059 if (previewWidth == -1 && previewHeight == -1)
1060 return;
1061 mPreviewWidth = previewWidth;
1062 mPreviewHeight = previewHeight;
1063 boolean flip = (rot % 180) != 0;
1064 binding.previewSurface.setAspectRatio(flip ? mPreviewHeight : mPreviewWidth, flip ? mPreviewWidth : mPreviewHeight);
1065 }
1066
1067 @Override
AGS5ef482ce2020-06-12 13:28:51 -04001068 public void resetPluginPreviewVideoSize(int previewWidth, int previewHeight, int rot) {
1069 if (previewWidth == -1 && previewHeight == -1)
1070 return;
1071 mPreviewWidth = previewWidth;
1072 mPreviewHeight = previewHeight;
1073 boolean flip = (rot % 180) != 0;
1074 binding.pluginPreviewSurface.setAspectRatio(flip ? mPreviewHeight : mPreviewWidth, flip ? mPreviewWidth : mPreviewHeight);
1075 }
1076
1077 @Override
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001078 public void resetVideoSize(int videoWidth, int videoHeight) {
Adrien Béraudace37a22018-06-22 14:58:36 -04001079 ViewGroup rootView = (ViewGroup) getView();
1080 if (rootView == null)
1081 return;
Adrien Béraudace37a22018-06-22 14:58:36 -04001082 double videoRatio = videoWidth / (double) videoHeight;
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001083 double screenRatio = rootView.getWidth() / (double) rootView.getHeight();
Adrien Béraud86a1e372018-11-23 23:24:30 -05001084 RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.videoSurface.getLayoutParams();
Adrien Béraudace37a22018-06-22 14:58:36 -04001085 int oldW = params.width;
1086 int oldH = params.height;
1087 if (videoRatio >= screenRatio) {
1088 params.width = RelativeLayout.LayoutParams.MATCH_PARENT;
1089 params.height = (int) (videoHeight * (double) rootView.getWidth() / (double) videoWidth);
1090 } else {
1091 params.height = RelativeLayout.LayoutParams.MATCH_PARENT;
1092 params.width = (int) (videoWidth * (double) rootView.getHeight() / (double) videoHeight);
1093 }
Thibault Wittembergb3280502016-12-16 17:34:53 -05001094
Adrien Béraudace37a22018-06-22 14:58:36 -04001095 if (oldW != params.width || oldH != params.height) {
Adrien Béraud86a1e372018-11-23 23:24:30 -05001096 binding.videoSurface.setLayoutParams(params);
Adrien Béraudace37a22018-06-22 14:58:36 -04001097 }
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001098 mVideoWidth = videoWidth;
1099 mVideoHeight = videoHeight;
Adrien Béraudde0d4522018-12-12 12:11:02 -05001100 }
Adrien Béraud30532a52018-09-11 15:10:05 -04001101
Adrien Béraudde0d4522018-12-12 12:11:02 -05001102 private void configureTransform(int viewWidth, int viewHeight) {
1103 Activity activity = getActivity();
Adrien Béraud3f9f6cd2018-12-12 15:05:28 -05001104 if (null == binding.previewSurface || null == activity) {
Adrien Béraudde0d4522018-12-12 12:11:02 -05001105 return;
Adrien Béraud30532a52018-09-11 15:10:05 -04001106 }
Adrien Béraudde0d4522018-12-12 12:11:02 -05001107 int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
1108 boolean rot = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation;
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001109 // Log.w(TAG, "configureTransform " + viewWidth + "x" + viewHeight + " rot=" + rot + " mPreviewWidth=" + mPreviewWidth + " mPreviewHeight=" + mPreviewHeight);
Adrien Béraudde0d4522018-12-12 12:11:02 -05001110 Matrix matrix = new Matrix();
1111 RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
1112 float centerX = viewRect.centerX();
1113 float centerY = viewRect.centerY();
1114 if (rot) {
1115 RectF bufferRect = new RectF(0, 0, mPreviewHeight, mPreviewWidth);
1116 bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
1117 matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
1118 float scale = Math.max(
1119 (float) viewHeight / mPreviewHeight,
1120 (float) viewWidth / mPreviewWidth);
1121 matrix.postScale(scale, scale, centerX, centerY);
1122 matrix.postRotate(90 * (rotation - 2), centerX, centerY);
1123 } else if (Surface.ROTATION_180 == rotation) {
1124 matrix.postRotate(180, centerX, centerY);
Adrien Béraudace37a22018-06-22 14:58:36 -04001125 }
agsantos00e3a9d2020-07-06 15:08:43 -04001126 if(!getPluginsEnabled()) {
AGS5ef482ce2020-06-12 13:28:51 -04001127// binding.pluginPreviewSurface.setTransform(matrix);
1128// }
1129// else {
1130 binding.previewSurface.setTransform(matrix);
1131 }
Adrien Béraud04d822c2015-04-02 17:44:36 -04001132 }
1133
1134 @Override
Hadrien De Sousa0dc83162017-11-10 16:15:18 -05001135 public void goToConversation(String accountId, String conversationId) {
Adrien Béraude4f901a2019-10-25 17:26:30 -04001136 Context context = requireContext();
1137 if (DeviceUtils.isTablet(context)) {
Adrien Béraud52d46a42020-05-15 14:41:08 -04001138 startActivity(new Intent(DRingService.ACTION_CONV_ACCEPT, ConversationPath.toUri(accountId, conversationId), context, HomeActivity.class));
Adrien Béraudda712a42015-11-22 23:45:26 -05001139 } else {
Adrien Béraude4f901a2019-10-25 17:26:30 -04001140 startActivityForResult(new Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, conversationId), context, ConversationActivity.class)
1141 .setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT), HomeActivity.REQUEST_CODE_CONVERSATION);
Adrien Béraudda712a42015-11-22 23:45:26 -05001142 }
Adrien Béraud04d822c2015-04-02 17:44:36 -04001143 }
1144
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001145 @Override
1146 public void goToAddContact(CallContact callContact) {
1147 startActivityForResult(ActionHelper.getAddNumberIntentForContact(callContact),
1148 ConversationFragment.REQ_ADD_CONTACT);
1149 }
1150
Adrien Béraude4f901a2019-10-25 17:26:30 -04001151 @Override
1152 public void goToContact(String accountId, CallContact contact) {
1153 startActivity(new Intent(Intent.ACTION_VIEW, android.net.Uri.withAppendedPath(android.net.Uri.withAppendedPath(ContentUriHandler.CONTACT_CONTENT_URI, accountId), contact.getPrimaryNumber()))
1154 .setClass(requireContext(), ContactDetailsActivity.class));
1155 }
1156
Rayan Osseiran38206c62019-05-15 14:49:03 -04001157 /**
1158 * Checks if permissions are accepted for camera and microphone. Takes into account whether call is incoming and outgoing, and requests permissions if not available.
Rayan Osseiran3dd04662019-06-28 16:47:48 -04001159 * Initializes the call if permissions are accepted.
Rayan Osseiran38206c62019-05-15 14:49:03 -04001160 *
1161 * @param isIncoming true if call is incoming, false for outgoing
Rayan Osseiran3dd04662019-06-28 16:47:48 -04001162 * @see #initializeCall(boolean) initializeCall
Rayan Osseiran38206c62019-05-15 14:49:03 -04001163 */
Rayan Osseiran3dd04662019-06-28 16:47:48 -04001164 @Override
1165 public void prepareCall(boolean isIncoming) {
Rayan Osseiran38206c62019-05-15 14:49:03 -04001166 boolean audioGranted = mDeviceRuntimeService.hasAudioPermission();
1167 boolean audioOnly;
1168 int permissionType;
1169
1170 if (isIncoming) {
1171 audioOnly = presenter.isAudioOnly();
1172 permissionType = REQUEST_PERMISSION_INCOMING;
Rayan Osseiran38206c62019-05-15 14:49:03 -04001173 } else {
Adrien Béraude4f901a2019-10-25 17:26:30 -04001174 Bundle args = getArguments();
1175 audioOnly = args != null && args.getBoolean(KEY_AUDIO_ONLY);
Rayan Osseiran38206c62019-05-15 14:49:03 -04001176 permissionType = REQUEST_PERMISSION_OUTGOING;
1177 }
1178 if (!audioOnly) {
1179 boolean videoGranted = mDeviceRuntimeService.hasVideoPermission();
1180
Adrien Bérauda0226ff2019-11-21 15:24:42 -05001181 if ((!audioGranted || !videoGranted) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Rayan Osseiran38206c62019-05-15 14:49:03 -04001182 ArrayList<String> perms = new ArrayList<>();
1183 if (!videoGranted) {
1184 perms.add(Manifest.permission.CAMERA);
1185 }
1186 if (!audioGranted) {
1187 perms.add(Manifest.permission.RECORD_AUDIO);
1188 }
1189 requestPermissions(perms.toArray(new String[perms.size()]), permissionType);
1190 } else if (audioGranted && videoGranted) {
Rayan Osseiran3dd04662019-06-28 16:47:48 -04001191 initializeCall(isIncoming);
Rayan Osseiran38206c62019-05-15 14:49:03 -04001192 }
1193 } else {
Adrien Bérauda0226ff2019-11-21 15:24:42 -05001194 if (!audioGranted && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Rayan Osseiran38206c62019-05-15 14:49:03 -04001195 requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, permissionType);
1196 } else if (audioGranted) {
Rayan Osseiran3dd04662019-06-28 16:47:48 -04001197 initializeCall(isIncoming);
Rayan Osseiran38206c62019-05-15 14:49:03 -04001198 }
1199 }
Rayan Osseiran38206c62019-05-15 14:49:03 -04001200 }
1201
1202 /**
1203 * Starts a call. Takes into account whether call is incoming or outgoing.
1204 *
1205 * @param isIncoming true if call is incoming, false for outgoing
1206 */
Adrien Béraude4f901a2019-10-25 17:26:30 -04001207 private void initializeCall(boolean isIncoming) {
Rayan Osseiran38206c62019-05-15 14:49:03 -04001208 if (isIncoming) {
1209 presenter.acceptCall();
1210 } else {
1211 Bundle args;
1212 args = getArguments();
1213 if (args != null) {
1214 presenter.initOutGoing(getArguments().getString(KEY_ACCOUNT_ID),
1215 getArguments().getString(ConversationFragment.KEY_CONTACT_RING_ID),
1216 getArguments().getBoolean(KEY_AUDIO_ONLY));
1217 }
1218 }
1219 }
1220
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001221 @Override
1222 public void finish() {
Adrien Béraudeb4bb002019-03-14 15:52:48 -04001223 Activity activity = getActivity();
Rayan Osseiranf7dfe232019-06-06 10:26:10 -04001224 if (activity != null) {
1225 if (mBackstackLost) {
1226 activity.finishAndRemoveTask();
1227 startActivity(
1228 Intent.makeMainActivity(
1229 new ComponentName(activity, HomeActivity.class)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
1230 } else {
1231 activity.finish();
1232 }
1233 }
Alexandre Lision1532d952016-11-17 09:41:00 -05001234 }
1235
Rayan Osseiranf7dfe232019-06-06 10:26:10 -04001236
Adrien Béraudbc0898e2018-08-23 14:31:11 -04001237 public void speakerClicked() {
Adrien Béraud86a1e372018-11-23 23:24:30 -05001238 presenter.speakerClick(binding.callSpeakerBtn.isChecked());
Adrien Béraudbc0898e2018-08-23 14:31:11 -04001239 }
1240
Adrien Béraudade9bee2019-12-02 17:13:26 -05001241 private void startScreenShare(MediaProjection mediaProjection) {
Adrien Béraud20bd7232020-03-16 11:33:23 -04001242 if (presenter.startScreenShare(mediaProjection)) {
agsantos00e3a9d2020-07-06 15:08:43 -04001243 if(getPluginsEnabled()) {
AGS5ef482ce2020-06-12 13:28:51 -04001244 binding.pluginPreviewSurface.setVisibility(View.GONE);
1245 } else {
1246 binding.previewSurface.setVisibility(View.GONE);
1247 }
Adrien Béraud20bd7232020-03-16 11:33:23 -04001248 } else {
1249 Toast.makeText(requireContext(), "Can't start screen sharing", Toast.LENGTH_SHORT).show();
1250 }
Adrien Béraudade9bee2019-12-02 17:13:26 -05001251 }
1252
1253 private void stopShareScreen() {
agsantos00e3a9d2020-07-06 15:08:43 -04001254 if(getPluginsEnabled())
AGS5ef482ce2020-06-12 13:28:51 -04001255 {
1256 binding.previewSurface.setVisibility(View.VISIBLE);
1257 }
1258 else {
1259 binding.previewSurface.setVisibility(View.VISIBLE);
1260 }
Adrien Béraudade9bee2019-12-02 17:13:26 -05001261 presenter.stopScreenShare();
1262 }
1263
1264 public void shareScreenClicked(boolean checked) {
1265 if (!checked) {
1266 stopShareScreen();
1267 } else {
1268 startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE_SCREEN_SHARE);
1269 }
1270 }
1271
Adrien Béraudbc0898e2018-08-23 14:31:11 -04001272 public void micClicked() {
Adrien Béraud86a1e372018-11-23 23:24:30 -05001273 presenter.muteMicrophoneToggled(binding.callMicBtn.isChecked());
Adrien Béraudbc0898e2018-08-23 14:31:11 -04001274 }
1275
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001276 public void hangUpClicked() {
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -04001277 presenter.hangupCall();
Alexandre Lision1532d952016-11-17 09:41:00 -05001278 }
1279
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001280 public void refuseClicked() {
Hadrien De Sousaf5774ee2017-05-17 14:04:17 -04001281 presenter.refuseCall();
Thibault Wittembergb70d5b02016-07-08 16:50:14 -04001282 }
1283
Thibault Wittembergb70d5b02016-07-08 16:50:14 -04001284 public void acceptClicked() {
Rayan Osseiran3dd04662019-06-28 16:47:48 -04001285 prepareCall(true);
Thibault Wittembergb70d5b02016-07-08 16:50:14 -04001286 }
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -05001287
Adrien Béraudbc0898e2018-08-23 14:31:11 -04001288 public void cameraFlip() {
1289 presenter.switchVideoInputClick();
1290 }
1291
Adrien Béraude4f901a2019-10-25 17:26:30 -04001292 public void addParticipant() {
1293 presenter.startAddParticipant();
1294 }
1295
1296 @Override
1297 public void startAddParticipant(String conferenceId) {
1298 startActivityForResult(
1299 new Intent(Intent.ACTION_PICK)
1300 .setClass(requireActivity(), ConversationSelectionActivity.class)
1301 .putExtra(KEY_CONF_ID, conferenceId),
1302 CallFragment.REQUEST_CODE_ADD_PARTICIPANT);
1303 }
ayounes019267f2020-01-13 15:14:08 -05001304 public void toggleCallMediaHandler(String id, boolean toggle) {
1305 Ringservice.toggleCallMediaHandler(id, toggle);
ayounes47e93992019-10-28 12:09:53 -04001306 }
1307
ayounes019267f2020-01-13 15:14:08 -05001308 public Map<String, String> getCallMediaHandlerDetails(String id) {
1309 return Ringservice.getCallMediaHandlerDetails(id).toNative();
ayounesc6c2c012019-11-11 11:09:51 -05001310 }
ayounes81087472019-11-08 15:26:05 -05001311
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -05001312 @Override
Pierre Duchemin1fa61922018-01-18 10:09:02 -05001313 public void positiveMediaButtonClicked() {
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -05001314 presenter.positiveButtonClicked();
1315 }
1316
1317 @Override
Pierre Duchemin1fa61922018-01-18 10:09:02 -05001318 public void negativeMediaButtonClicked() {
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -05001319 presenter.negativeButtonClicked();
1320 }
1321
1322 @Override
Pierre Duchemin1fa61922018-01-18 10:09:02 -05001323 public void toggleMediaButtonClicked() {
Pierre Duchemin8b2c1b52017-12-29 17:17:13 -05001324 presenter.toggleButtonClicked();
1325 }
Rayan Osseiran38206c62019-05-15 14:49:03 -04001326
ayounesc6c2c012019-11-11 11:09:51 -05001327 public boolean displayPluginsButton() {
1328 SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(requireActivity());
1329 return sharedPref.getBoolean("plugins", false);
1330 }
1331
ayounes47e93992019-10-28 12:09:53 -04001332 @Override
1333 public void onConfigurationChanged(@NonNull Configuration newConfig) {
1334 super.onConfigurationChanged(newConfig);
agsantos00e3a9d2020-07-06 15:08:43 -04001335 // Reset the padding of the RecyclerPicker on each
ayounesc6c2c012019-11-11 11:09:51 -05001336 rp.setFirstLastElementsWidths(112, 112);
ayounes47e93992019-10-28 12:09:53 -04001337 binding.recyclerPicker.setVisibility(View.GONE);
ayounesc6c2c012019-11-11 11:09:51 -05001338 Log.i("ZZZ", "Height: " + binding.recyclerPicker.getHeight());
agsantos00e3a9d2020-07-06 15:08:43 -04001339 if (getPluginsEnabled()) {
ayounes47e93992019-10-28 12:09:53 -04001340 displayHangupButton(false);
1341 binding.recyclerPicker.setVisibility(View.VISIBLE);
ayounesc6c2c012019-11-11 11:09:51 -05001342 movePreview(true);
1343 if (previousPluginPosition != -1) {
ayounes47e93992019-10-28 12:09:53 -04001344 rp.scrollToPosition(previousPluginPosition);
1345 }
1346 } else {
ayounesc6c2c012019-11-11 11:09:51 -05001347 movePreview(false);
ayounes47e93992019-10-28 12:09:53 -04001348 displayHangupButton(true);
1349 }
1350 }
1351
ayounesc6c2c012019-11-11 11:09:51 -05001352 public void toggleVideoPluginsCarousel(boolean toggle) {
1353 toggleVideoPluginsCarousel = toggle;
agsantos00e3a9d2020-07-06 15:08:43 -04001354 if (getPluginsEnabled()) {
ayounesc6c2c012019-11-11 11:09:51 -05001355 if (toggleVideoPluginsCarousel) {
1356 binding.recyclerPicker.setVisibility(View.VISIBLE);
1357 movePreview(true);
1358 } else {
1359 binding.recyclerPicker.setVisibility(View.INVISIBLE);
1360 movePreview(false);
1361 }
1362 }
1363
1364 }
1365
1366 public void movePreview(boolean up) {
1367 // Move the preview container (cardview) by a certain margin
1368 if(up) {
1369 animation.setIntValues(12, 128);
1370 } else {
1371 animation.setIntValues(128, 12);
1372 }
1373 animation.start();
1374 }
1375
1376 /**
1377 * Function that is called to show/hide the plugins recycler viewer and update UI
1378 */
ayounes47e93992019-10-28 12:09:53 -04001379 public void displayVideoPluginsCarousel() {
agsantos00e3a9d2020-07-06 15:08:43 -04001380 setPluginsEnabled(!getPluginsEnabled());
AGS5ef482ce2020-06-12 13:28:51 -04001381
ayounes81087472019-11-08 15:26:05 -05001382 Context context = requireActivity();
1383
ayounes019267f2020-01-13 15:14:08 -05001384 // Create callMediaHandlers and videoPluginsItems in a lazy manner
ayounesc6c2c012019-11-11 11:09:51 -05001385 if (pluginsModeFirst) {
1386 // Init
ayounes019267f2020-01-13 15:14:08 -05001387 callMediaHandlers = Ringservice.listCallMediaHandlers();
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001388 List<Drawable> videoPluginsItems = new ArrayList<>(callMediaHandlers.size() + 1);
ayounes47e93992019-10-28 12:09:53 -04001389
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001390 videoPluginsItems.add(context.getDrawable(R.drawable.baseline_cancel_24));
ayounes019267f2020-01-13 15:14:08 -05001391 // Search for plugin call media handlers icons
1392 // If a call media handler doesn't have an icon use a standard android icon
1393 for (String callMediaHandler : callMediaHandlers) {
1394 Map<String, String> details = getCallMediaHandlerDetails(callMediaHandler);
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001395 String drawablePath = details.get("icoPath");
1396 Drawable handlerIcon = StringUtils.isEmpty(drawablePath) ? null : Drawable.createFromPath(details.get("icoPath"));
1397 if (handlerIcon == null) {
1398 handlerIcon = context.getDrawable(R.drawable.ic_jami);
ayounes47e93992019-10-28 12:09:53 -04001399 }
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001400 videoPluginsItems.add(handlerIcon);
ayounes47e93992019-10-28 12:09:53 -04001401 }
1402
1403 rp.updateData(videoPluginsItems);
1404
ayounesc6c2c012019-11-11 11:09:51 -05001405 pluginsModeFirst = false;
1406 }
1407
agsantos00e3a9d2020-07-06 15:08:43 -04001408 if (getPluginsEnabled()) {
AGS5ef482ce2020-06-12 13:28:51 -04001409 //change preview image
1410 displayVideoSurface(true,true);
ayounesc6c2c012019-11-11 11:09:51 -05001411 // hide hang up button and other call buttons
1412 displayHangupButton(false);
1413 // Display the plugins recyclerpicker
1414 binding.recyclerPicker.setVisibility(View.VISIBLE);
1415 movePreview(true);
1416
1417 // Start loading the first or previous plugin if one was active
ayounes019267f2020-01-13 15:14:08 -05001418 if(callMediaHandlers.size() > 0) {
ayounesc6c2c012019-11-11 11:09:51 -05001419 // If no previous plugin was active, take the first, else previous
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001420 int position;
1421 if(previousPluginPosition < 1) {
1422 rp.scrollToPosition(1);
1423 position = 1;
1424 previousPluginPosition = 1;
1425 } else {
1426 position = previousPluginPosition;
1427 }
1428 if (position > 0) {
1429 String callMediaId = callMediaHandlers.get(position-1);
1430 toggleCallMediaHandler(callMediaId, true);
1431 }
ayounesc6c2c012019-11-11 11:09:51 -05001432 }
1433
ayounes47e93992019-10-28 12:09:53 -04001434 } else {
AGS5ef482ce2020-06-12 13:28:51 -04001435 //change preview image
1436 displayVideoSurface(true,true);
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001437 if (previousPluginPosition > 0) {
ayounes019267f2020-01-13 15:14:08 -05001438 String callMediaId = callMediaHandlers.
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001439 get(previousPluginPosition-1);
ayounes81087472019-11-08 15:26:05 -05001440
ayounes019267f2020-01-13 15:14:08 -05001441 toggleCallMediaHandler(callMediaId, false);
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001442 rp.scrollToPosition(previousPluginPosition);
ayounes47e93992019-10-28 12:09:53 -04001443 }
1444 binding.recyclerPicker.setVisibility(View.GONE);
ayounesc6c2c012019-11-11 11:09:51 -05001445 movePreview(false);
ayounes47e93992019-10-28 12:09:53 -04001446 displayHangupButton(true);
1447 }
ayounes47e93992019-10-28 12:09:53 -04001448 }
1449
ayounesc6c2c012019-11-11 11:09:51 -05001450 /**
1451 * Called whenever a plugin drawable in the recycler picker is clicked or scrolled to
1452 * @param position
1453 */
ayounes47e93992019-10-28 12:09:53 -04001454 @Override
1455 public void onItemSelected(int position) {
1456 Log.i(TAG, "selected position: " + position);
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001457 /** If there was a different plugin before, unload it
1458 * If previousPluginPosition = -1 or 0, there was no plugin
1459 */
1460 if (previousPluginPosition > 0) {
1461 String callMediaId = callMediaHandlers.get(previousPluginPosition-1);
1462 toggleCallMediaHandler(callMediaId, false);
1463 }
1464
1465 if (position > 0) {
1466 previousPluginPosition = position;
1467 String callMediaId = callMediaHandlers.get(position-1);
1468 toggleCallMediaHandler(callMediaId, true);
1469 }
1470 }
1471
1472
1473 /**
1474 * Called whenever a plugin drawable in the recycler picker is clicked
1475 * @param position
1476 */
1477 @Override
1478 public void onItemClicked(int position) {
1479 Log.i(TAG, "selected position: " + position);
1480 if (position == 0) {
ayounes47e93992019-10-28 12:09:53 -04001481 /** If there was a different plugin before, unload it
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001482 * If previousPluginPosition = -1 or 0, there was no plugin
ayounes47e93992019-10-28 12:09:53 -04001483 */
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001484 if (previousPluginPosition > 0) {
1485 String callMediaId = callMediaHandlers.get(previousPluginPosition-1);
ayounes019267f2020-01-13 15:14:08 -05001486 toggleCallMediaHandler(callMediaId, false);
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001487 rp.scrollToPosition(previousPluginPosition);
ayounes47e93992019-10-28 12:09:53 -04001488 }
1489
Aline Gondim Santosf781c5b2020-06-26 12:44:44 -04001490 CallActivity callActivity = (CallActivity) getActivity();
1491 callActivity.showSystemUI();
1492
1493 toggleVideoPluginsCarousel(false);
1494 displayVideoPluginsCarousel();
ayounes47e93992019-10-28 12:09:53 -04001495 }
1496 }
Hadrien De Sousaccc947d2017-04-12 14:26:52 -04001497}