diff --git a/art/flip_camera_android-black-24dp.svg b/art/flip_camera_android-black-24dp.svg
new file mode 100644
index 000000000..f50c0d721
--- /dev/null
+++ b/art/flip_camera_android-black-24dp.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/art/render.rb b/art/render.rb
index 86a0ddf79..863a5cca3 100755
--- a/art/render.rb
+++ b/art/render.rb
@@ -27,6 +27,7 @@ images = {
'open_pdf_white.svg' => ['open_pdf_white', 128],
'conversations_mono.svg' => ['conversations/ic_notification', 24],
'quicksy_mono.svg' => ['quicksy/ic_notification', 24],
+ 'flip_camera_android-black-24dp.svg' => ['ic_flip_camera_android_black_24dp', 24],
'ic_send_text_offline.svg' => ['ic_send_text_offline', 36],
'ic_send_text_offline_white.svg' => ['ic_send_text_offline_white', 36],
'ic_send_text_online.svg' => ['ic_send_text_online', 36],
diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
index bd8972598..33c7913e7 100644
--- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
@@ -22,9 +22,14 @@ import android.widget.Toast;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.checkerframework.checker.nullness.compatqual.NullableDecl;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoTrack;
@@ -42,6 +47,7 @@ import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.services.AppRTCAudioManager;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
+import eu.siacs.conversations.ui.util.MainThreadExecutor;
import eu.siacs.conversations.utils.PermissionUtils;
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
@@ -83,7 +89,6 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
@Override
public void onCreate(Bundle savedInstanceState) {
- Log.d(Config.LOGTAG, this.getClass().getName() + ".onCreate()");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
@@ -561,18 +566,21 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
if (state == RtpEndUserState.CONNECTED && !isPictureInPicture()) {
Preconditions.checkArgument(media.size() > 0, "Media must not be empty");
if (media.contains(Media.VIDEO)) {
- updateInCallButtonConfigurationVideo(requireRtpConnection().isVideoEnabled());
+ final JingleRtpConnection rtpConnection = requireRtpConnection();
+ updateInCallButtonConfigurationVideo(rtpConnection.isVideoEnabled(), rtpConnection.isCameraSwitchable());
} else {
final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager();
updateInCallButtonConfigurationSpeaker(
audioManager.getSelectedAudioDevice(),
audioManager.getAudioDevices().size()
);
+ this.binding.inCallActionFarRight.setVisibility(View.GONE);
}
updateInCallButtonConfigurationMicrophone(requireRtpConnection().isMicrophoneEnabled());
} else {
this.binding.inCallActionLeft.setVisibility(View.GONE);
this.binding.inCallActionRight.setVisibility(View.GONE);
+ this.binding.inCallActionFarRight.setVisibility(View.GONE);
}
}
@@ -612,8 +620,15 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
}
@SuppressLint("RestrictedApi")
- private void updateInCallButtonConfigurationVideo(final boolean videoEnabled) {
+ private void updateInCallButtonConfigurationVideo(final boolean videoEnabled, final boolean isCameraSwitchable) {
this.binding.inCallActionRight.setVisibility(View.VISIBLE);
+ if (isCameraSwitchable) {
+ this.binding.inCallActionFarRight.setImageResource(R.drawable.ic_flip_camera_android_black_24dp);
+ this.binding.inCallActionFarRight.setVisibility(View.VISIBLE);
+ this.binding.inCallActionFarRight.setOnClickListener(this::switchCamera);
+ } else {
+ this.binding.inCallActionFarRight.setVisibility(View.GONE);
+ }
if (videoEnabled) {
this.binding.inCallActionRight.setImageResource(R.drawable.ic_videocam_black_24dp);
this.binding.inCallActionRight.setOnClickListener(this::disableVideo);
@@ -623,14 +638,29 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
}
}
+ private void switchCamera(final View view) {
+ Futures.addCallback(requireRtpConnection().switchCamera(), new FutureCallback() {
+ @Override
+ public void onSuccess(@NullableDecl Void result) {
+
+ }
+
+ @Override
+ public void onFailure(final Throwable throwable) {
+ Log.d(Config.LOGTAG,"could not switch camera", Throwables.getRootCause(throwable));
+ Toast.makeText(RtpSessionActivity.this, R.string.could_not_switch_camera, Toast.LENGTH_LONG).show();
+ }
+ }, MainThreadExecutor.getInstance());
+ }
+
private void enableVideo(View view) {
requireRtpConnection().setVideoEnabled(true);
- updateInCallButtonConfigurationVideo(true);
+ updateInCallButtonConfigurationVideo(true, requireRtpConnection().isCameraSwitchable());
}
private void disableVideo(View view) {
requireRtpConnection().setVideoEnabled(false);
- updateInCallButtonConfigurationVideo(false);
+ updateInCallButtonConfigurationVideo(false, requireRtpConnection().isCameraSwitchable());
}
diff --git a/src/main/java/eu/siacs/conversations/ui/util/MainThreadExecutor.java b/src/main/java/eu/siacs/conversations/ui/util/MainThreadExecutor.java
new file mode 100644
index 000000000..49f8ffdf4
--- /dev/null
+++ b/src/main/java/eu/siacs/conversations/ui/util/MainThreadExecutor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 Daniel Gultsch
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package eu.siacs.conversations.ui.util;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.concurrent.Executor;
+
+public class MainThreadExecutor implements Executor {
+
+ private static final MainThreadExecutor INSTANCE = new MainThreadExecutor();
+
+ private final Handler handler = new Handler(Looper.myLooper());
+
+ @Override
+ public void execute(final Runnable command) {
+ handler.post(command);
+ }
+
+ public static MainThreadExecutor getInstance() {
+ return INSTANCE;
+ }
+}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java
index 98b5c9aa6..9aeac835b 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java
@@ -12,6 +12,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
+import com.google.common.util.concurrent.ListenableFuture;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
@@ -1037,6 +1038,15 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
return webRTCWrapper.isVideoEnabled();
}
+
+ public boolean isCameraSwitchable() {
+ return webRTCWrapper.isCameraSwitchable();
+ }
+
+ public ListenableFuture switchCamera() {
+ return webRTCWrapper.switchCamera();
+ }
+
public void setVideoEnabled(final boolean enabled) {
webRTCWrapper.setVideoEnabled(enabled);
}
diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java
index 17c1b77fe..844ef9db8 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java
@@ -8,6 +8,8 @@ import android.util.Log;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
@@ -255,7 +257,7 @@ public class WebRTCWrapper {
try {
peerConnection.dispose();
} catch (final IllegalStateException e) {
- Log.e(Config.LOGTAG,"unable to dispose of peer connection", e);
+ Log.e(Config.LOGTAG, "unable to dispose of peer connection", e);
}
}
@@ -270,6 +272,31 @@ public class WebRTCWrapper {
}
}
+ boolean isCameraSwitchable() {
+ final CapturerChoice capturerChoice = this.capturerChoice;
+ return capturerChoice != null && capturerChoice.availableCameras.size() > 1;
+ }
+
+ ListenableFuture switchCamera() {
+ final CapturerChoice capturerChoice = this.capturerChoice;
+ if (capturerChoice == null) {
+ return Futures.immediateFailedFuture(new IllegalStateException("CameraCapturer has not been initialized"));
+ }
+ final SettableFuture future = SettableFuture.create();
+ capturerChoice.cameraVideoCapturer.switchCamera(new CameraVideoCapturer.CameraSwitchHandler() {
+ @Override
+ public void onCameraSwitchDone(boolean isFrontCamera) {
+ future.set(null);
+ }
+
+ @Override
+ public void onCameraSwitchError(final String message) {
+ future.setException(new IllegalStateException(String.format("Unable to switch camera %s", message)));
+ }
+ });
+ return future;
+ }
+
boolean isMicrophoneEnabled() {
final AudioTrack audioTrack = this.localAudioTrack;
if (audioTrack == null) {
@@ -408,21 +435,21 @@ public class WebRTCWrapper {
private Optional getVideoCapturer() {
final CameraEnumerator enumerator = getCameraEnumerator();
- final String[] deviceNames = enumerator.getDeviceNames();
+ final Set deviceNames = ImmutableSet.copyOf(enumerator.getDeviceNames());
for (final String deviceName : deviceNames) {
if (enumerator.isFrontFacing(deviceName)) {
- return Optional.fromNullable(of(enumerator, deviceName));
+ return Optional.fromNullable(of(enumerator, deviceName, deviceNames));
}
}
- if (deviceNames.length == 0) {
+ if (deviceNames.size() == 0) {
return Optional.absent();
} else {
- return Optional.fromNullable(of(enumerator, deviceNames[0]));
+ return Optional.fromNullable(of(enumerator, Iterables.get(deviceNames, 0), deviceNames));
}
}
@Nullable
- private static CapturerChoice of(CameraEnumerator enumerator, final String deviceName) {
+ private static CapturerChoice of(CameraEnumerator enumerator, final String deviceName, Set availableCameras) {
final CameraVideoCapturer capturer = enumerator.createCapturer(deviceName, null);
if (capturer == null) {
return null;
@@ -431,7 +458,7 @@ public class WebRTCWrapper {
Collections.sort(choices, (a, b) -> b.width - a.width);
for (final CameraEnumerationAndroid.CaptureFormat captureFormat : choices) {
if (captureFormat.width <= CAPTURING_RESOLUTION) {
- return new CapturerChoice(capturer, captureFormat);
+ return new CapturerChoice(capturer, captureFormat, availableCameras);
}
}
return null;
@@ -520,10 +547,12 @@ public class WebRTCWrapper {
private static class CapturerChoice {
private final CameraVideoCapturer cameraVideoCapturer;
private final CameraEnumerationAndroid.CaptureFormat captureFormat;
+ private final Set availableCameras;
- CapturerChoice(CameraVideoCapturer cameraVideoCapturer, CameraEnumerationAndroid.CaptureFormat captureFormat) {
+ CapturerChoice(CameraVideoCapturer cameraVideoCapturer, CameraEnumerationAndroid.CaptureFormat captureFormat, Set cameras) {
this.cameraVideoCapturer = cameraVideoCapturer;
this.captureFormat = captureFormat;
+ this.availableCameras = cameras;
}
int getFrameRate() {
diff --git a/src/main/res/drawable-hdpi/date_bubble_grey.9.png b/src/main/res/drawable-hdpi/date_bubble_grey.9.png
index eb64a1e22..6236855a2 100644
Binary files a/src/main/res/drawable-hdpi/date_bubble_grey.9.png and b/src/main/res/drawable-hdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-hdpi/date_bubble_white.9.png b/src/main/res/drawable-hdpi/date_bubble_white.9.png
index 23789900d..fbeac6493 100644
Binary files a/src/main/res/drawable-hdpi/date_bubble_white.9.png and b/src/main/res/drawable-hdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-hdpi/ic_flip_camera_android_black_24dp.png b/src/main/res/drawable-hdpi/ic_flip_camera_android_black_24dp.png
new file mode 100644
index 000000000..3e0e64d7b
Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_flip_camera_android_black_24dp.png differ
diff --git a/src/main/res/drawable-hdpi/message_bubble_received.9.png b/src/main/res/drawable-hdpi/message_bubble_received.9.png
index 4fb7faeb3..7f5319c8d 100644
Binary files a/src/main/res/drawable-hdpi/message_bubble_received.9.png and b/src/main/res/drawable-hdpi/message_bubble_received.9.png differ
diff --git a/src/main/res/drawable-hdpi/message_bubble_received_dark.9.png b/src/main/res/drawable-hdpi/message_bubble_received_dark.9.png
index 9bb617fa5..0bb89223c 100644
Binary files a/src/main/res/drawable-hdpi/message_bubble_received_dark.9.png and b/src/main/res/drawable-hdpi/message_bubble_received_dark.9.png differ
diff --git a/src/main/res/drawable-hdpi/message_bubble_received_grey.9.png b/src/main/res/drawable-hdpi/message_bubble_received_grey.9.png
index 9b7ce26c3..acba47c98 100644
Binary files a/src/main/res/drawable-hdpi/message_bubble_received_grey.9.png and b/src/main/res/drawable-hdpi/message_bubble_received_grey.9.png differ
diff --git a/src/main/res/drawable-hdpi/message_bubble_received_warning.9.png b/src/main/res/drawable-hdpi/message_bubble_received_warning.9.png
index 7130402e9..8bdfcc79c 100644
Binary files a/src/main/res/drawable-hdpi/message_bubble_received_warning.9.png and b/src/main/res/drawable-hdpi/message_bubble_received_warning.9.png differ
diff --git a/src/main/res/drawable-hdpi/message_bubble_received_white.9.png b/src/main/res/drawable-hdpi/message_bubble_received_white.9.png
index 933f6a52e..ed8c0273e 100644
Binary files a/src/main/res/drawable-hdpi/message_bubble_received_white.9.png and b/src/main/res/drawable-hdpi/message_bubble_received_white.9.png differ
diff --git a/src/main/res/drawable-hdpi/message_bubble_sent.9.png b/src/main/res/drawable-hdpi/message_bubble_sent.9.png
index 1bcd6e0d7..487a8f79a 100644
Binary files a/src/main/res/drawable-hdpi/message_bubble_sent.9.png and b/src/main/res/drawable-hdpi/message_bubble_sent.9.png differ
diff --git a/src/main/res/drawable-hdpi/message_bubble_sent_grey.9.png b/src/main/res/drawable-hdpi/message_bubble_sent_grey.9.png
index a2db7445c..a0e998c00 100644
Binary files a/src/main/res/drawable-hdpi/message_bubble_sent_grey.9.png and b/src/main/res/drawable-hdpi/message_bubble_sent_grey.9.png differ
diff --git a/src/main/res/drawable-mdpi/date_bubble_grey.9.png b/src/main/res/drawable-mdpi/date_bubble_grey.9.png
index 0a0ebb220..52d4daae8 100644
Binary files a/src/main/res/drawable-mdpi/date_bubble_grey.9.png and b/src/main/res/drawable-mdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-mdpi/date_bubble_white.9.png b/src/main/res/drawable-mdpi/date_bubble_white.9.png
index 40f26d399..8f8e06010 100644
Binary files a/src/main/res/drawable-mdpi/date_bubble_white.9.png and b/src/main/res/drawable-mdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-mdpi/ic_flip_camera_android_black_24dp.png b/src/main/res/drawable-mdpi/ic_flip_camera_android_black_24dp.png
new file mode 100644
index 000000000..79d201f48
Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_flip_camera_android_black_24dp.png differ
diff --git a/src/main/res/drawable-mdpi/message_bubble_received.9.png b/src/main/res/drawable-mdpi/message_bubble_received.9.png
index f56284415..3f31766ce 100644
Binary files a/src/main/res/drawable-mdpi/message_bubble_received.9.png and b/src/main/res/drawable-mdpi/message_bubble_received.9.png differ
diff --git a/src/main/res/drawable-mdpi/message_bubble_received_dark.9.png b/src/main/res/drawable-mdpi/message_bubble_received_dark.9.png
index ecfb9f427..d5c45ea9d 100644
Binary files a/src/main/res/drawable-mdpi/message_bubble_received_dark.9.png and b/src/main/res/drawable-mdpi/message_bubble_received_dark.9.png differ
diff --git a/src/main/res/drawable-mdpi/message_bubble_received_grey.9.png b/src/main/res/drawable-mdpi/message_bubble_received_grey.9.png
index f2d79acee..3e5e62c5e 100644
Binary files a/src/main/res/drawable-mdpi/message_bubble_received_grey.9.png and b/src/main/res/drawable-mdpi/message_bubble_received_grey.9.png differ
diff --git a/src/main/res/drawable-mdpi/message_bubble_received_warning.9.png b/src/main/res/drawable-mdpi/message_bubble_received_warning.9.png
index 2a81873ff..66862dbe5 100644
Binary files a/src/main/res/drawable-mdpi/message_bubble_received_warning.9.png and b/src/main/res/drawable-mdpi/message_bubble_received_warning.9.png differ
diff --git a/src/main/res/drawable-mdpi/message_bubble_received_white.9.png b/src/main/res/drawable-mdpi/message_bubble_received_white.9.png
index 5e9cb12a6..e8d69cc3f 100644
Binary files a/src/main/res/drawable-mdpi/message_bubble_received_white.9.png and b/src/main/res/drawable-mdpi/message_bubble_received_white.9.png differ
diff --git a/src/main/res/drawable-mdpi/message_bubble_sent.9.png b/src/main/res/drawable-mdpi/message_bubble_sent.9.png
index b7cc611fa..f7c63c8f7 100644
Binary files a/src/main/res/drawable-mdpi/message_bubble_sent.9.png and b/src/main/res/drawable-mdpi/message_bubble_sent.9.png differ
diff --git a/src/main/res/drawable-mdpi/message_bubble_sent_grey.9.png b/src/main/res/drawable-mdpi/message_bubble_sent_grey.9.png
index 57819cbae..e1a0bfe64 100644
Binary files a/src/main/res/drawable-mdpi/message_bubble_sent_grey.9.png and b/src/main/res/drawable-mdpi/message_bubble_sent_grey.9.png differ
diff --git a/src/main/res/drawable-xhdpi/date_bubble_grey.9.png b/src/main/res/drawable-xhdpi/date_bubble_grey.9.png
index 4c06bdf80..63225157d 100644
Binary files a/src/main/res/drawable-xhdpi/date_bubble_grey.9.png and b/src/main/res/drawable-xhdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-xhdpi/date_bubble_white.9.png b/src/main/res/drawable-xhdpi/date_bubble_white.9.png
index 2a96b9bfb..c5eaa5e0b 100644
Binary files a/src/main/res/drawable-xhdpi/date_bubble_white.9.png and b/src/main/res/drawable-xhdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-xhdpi/ic_flip_camera_android_black_24dp.png b/src/main/res/drawable-xhdpi/ic_flip_camera_android_black_24dp.png
new file mode 100644
index 000000000..7178728e3
Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_flip_camera_android_black_24dp.png differ
diff --git a/src/main/res/drawable-xhdpi/message_bubble_received.9.png b/src/main/res/drawable-xhdpi/message_bubble_received.9.png
index e479bfb39..799c2e532 100644
Binary files a/src/main/res/drawable-xhdpi/message_bubble_received.9.png and b/src/main/res/drawable-xhdpi/message_bubble_received.9.png differ
diff --git a/src/main/res/drawable-xhdpi/message_bubble_received_dark.9.png b/src/main/res/drawable-xhdpi/message_bubble_received_dark.9.png
index 6ab302b2c..26523a2a5 100644
Binary files a/src/main/res/drawable-xhdpi/message_bubble_received_dark.9.png and b/src/main/res/drawable-xhdpi/message_bubble_received_dark.9.png differ
diff --git a/src/main/res/drawable-xhdpi/message_bubble_received_grey.9.png b/src/main/res/drawable-xhdpi/message_bubble_received_grey.9.png
index 03d423b87..2acae4964 100644
Binary files a/src/main/res/drawable-xhdpi/message_bubble_received_grey.9.png and b/src/main/res/drawable-xhdpi/message_bubble_received_grey.9.png differ
diff --git a/src/main/res/drawable-xhdpi/message_bubble_received_warning.9.png b/src/main/res/drawable-xhdpi/message_bubble_received_warning.9.png
index ef2cc4fce..9b46f4656 100644
Binary files a/src/main/res/drawable-xhdpi/message_bubble_received_warning.9.png and b/src/main/res/drawable-xhdpi/message_bubble_received_warning.9.png differ
diff --git a/src/main/res/drawable-xhdpi/message_bubble_received_white.9.png b/src/main/res/drawable-xhdpi/message_bubble_received_white.9.png
index 4404bcfd4..a735ad874 100644
Binary files a/src/main/res/drawable-xhdpi/message_bubble_received_white.9.png and b/src/main/res/drawable-xhdpi/message_bubble_received_white.9.png differ
diff --git a/src/main/res/drawable-xhdpi/message_bubble_sent.9.png b/src/main/res/drawable-xhdpi/message_bubble_sent.9.png
index 5db6951e1..aa7a6d1fd 100644
Binary files a/src/main/res/drawable-xhdpi/message_bubble_sent.9.png and b/src/main/res/drawable-xhdpi/message_bubble_sent.9.png differ
diff --git a/src/main/res/drawable-xhdpi/message_bubble_sent_grey.9.png b/src/main/res/drawable-xhdpi/message_bubble_sent_grey.9.png
index 5c28d1caa..85dd6223c 100644
Binary files a/src/main/res/drawable-xhdpi/message_bubble_sent_grey.9.png and b/src/main/res/drawable-xhdpi/message_bubble_sent_grey.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/date_bubble_grey.9.png b/src/main/res/drawable-xxhdpi/date_bubble_grey.9.png
index b7e9b500e..085665b8b 100644
Binary files a/src/main/res/drawable-xxhdpi/date_bubble_grey.9.png and b/src/main/res/drawable-xxhdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/date_bubble_white.9.png b/src/main/res/drawable-xxhdpi/date_bubble_white.9.png
index 82d25540e..54b885fbe 100644
Binary files a/src/main/res/drawable-xxhdpi/date_bubble_white.9.png and b/src/main/res/drawable-xxhdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/ic_flip_camera_android_black_24dp.png b/src/main/res/drawable-xxhdpi/ic_flip_camera_android_black_24dp.png
new file mode 100644
index 000000000..1b8b1511c
Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_flip_camera_android_black_24dp.png differ
diff --git a/src/main/res/drawable-xxhdpi/message_bubble_received.9.png b/src/main/res/drawable-xxhdpi/message_bubble_received.9.png
index 4670b8296..71b8c3f1e 100644
Binary files a/src/main/res/drawable-xxhdpi/message_bubble_received.9.png and b/src/main/res/drawable-xxhdpi/message_bubble_received.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/message_bubble_received_dark.9.png b/src/main/res/drawable-xxhdpi/message_bubble_received_dark.9.png
index 415fd1573..cd7d570e5 100644
Binary files a/src/main/res/drawable-xxhdpi/message_bubble_received_dark.9.png and b/src/main/res/drawable-xxhdpi/message_bubble_received_dark.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/message_bubble_received_grey.9.png b/src/main/res/drawable-xxhdpi/message_bubble_received_grey.9.png
index 76bff006c..348b7de5c 100644
Binary files a/src/main/res/drawable-xxhdpi/message_bubble_received_grey.9.png and b/src/main/res/drawable-xxhdpi/message_bubble_received_grey.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/message_bubble_received_warning.9.png b/src/main/res/drawable-xxhdpi/message_bubble_received_warning.9.png
index e24a829be..2ff0fbaf2 100644
Binary files a/src/main/res/drawable-xxhdpi/message_bubble_received_warning.9.png and b/src/main/res/drawable-xxhdpi/message_bubble_received_warning.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/message_bubble_received_white.9.png b/src/main/res/drawable-xxhdpi/message_bubble_received_white.9.png
index 16548c294..59925addb 100644
Binary files a/src/main/res/drawable-xxhdpi/message_bubble_received_white.9.png and b/src/main/res/drawable-xxhdpi/message_bubble_received_white.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/message_bubble_sent.9.png b/src/main/res/drawable-xxhdpi/message_bubble_sent.9.png
index 521e027f6..17f85b64b 100644
Binary files a/src/main/res/drawable-xxhdpi/message_bubble_sent.9.png and b/src/main/res/drawable-xxhdpi/message_bubble_sent.9.png differ
diff --git a/src/main/res/drawable-xxhdpi/message_bubble_sent_grey.9.png b/src/main/res/drawable-xxhdpi/message_bubble_sent_grey.9.png
index 822344041..585dcacc7 100644
Binary files a/src/main/res/drawable-xxhdpi/message_bubble_sent_grey.9.png and b/src/main/res/drawable-xxhdpi/message_bubble_sent_grey.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png b/src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png
index 2eda42882..550fe2286 100644
Binary files a/src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png and b/src/main/res/drawable-xxxhdpi/date_bubble_grey.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/date_bubble_white.9.png b/src/main/res/drawable-xxxhdpi/date_bubble_white.9.png
index dfc24fadc..6f75ed33c 100644
Binary files a/src/main/res/drawable-xxxhdpi/date_bubble_white.9.png and b/src/main/res/drawable-xxxhdpi/date_bubble_white.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/ic_flip_camera_android_black_24dp.png b/src/main/res/drawable-xxxhdpi/ic_flip_camera_android_black_24dp.png
new file mode 100644
index 000000000..dd276a971
Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_flip_camera_android_black_24dp.png differ
diff --git a/src/main/res/drawable-xxxhdpi/message_bubble_received.9.png b/src/main/res/drawable-xxxhdpi/message_bubble_received.9.png
index eccc90077..79689cb63 100644
Binary files a/src/main/res/drawable-xxxhdpi/message_bubble_received.9.png and b/src/main/res/drawable-xxxhdpi/message_bubble_received.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/message_bubble_received_dark.9.png b/src/main/res/drawable-xxxhdpi/message_bubble_received_dark.9.png
index fa3ca2035..4ad74b6b2 100644
Binary files a/src/main/res/drawable-xxxhdpi/message_bubble_received_dark.9.png and b/src/main/res/drawable-xxxhdpi/message_bubble_received_dark.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/message_bubble_received_grey.9.png b/src/main/res/drawable-xxxhdpi/message_bubble_received_grey.9.png
index acfa862d6..3d0dd4734 100644
Binary files a/src/main/res/drawable-xxxhdpi/message_bubble_received_grey.9.png and b/src/main/res/drawable-xxxhdpi/message_bubble_received_grey.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/message_bubble_received_warning.9.png b/src/main/res/drawable-xxxhdpi/message_bubble_received_warning.9.png
index 555719ee6..0885149b3 100644
Binary files a/src/main/res/drawable-xxxhdpi/message_bubble_received_warning.9.png and b/src/main/res/drawable-xxxhdpi/message_bubble_received_warning.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/message_bubble_received_white.9.png b/src/main/res/drawable-xxxhdpi/message_bubble_received_white.9.png
index 9758293a7..25511916a 100644
Binary files a/src/main/res/drawable-xxxhdpi/message_bubble_received_white.9.png and b/src/main/res/drawable-xxxhdpi/message_bubble_received_white.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/message_bubble_sent.9.png b/src/main/res/drawable-xxxhdpi/message_bubble_sent.9.png
index 55fa42798..2f3049fad 100644
Binary files a/src/main/res/drawable-xxxhdpi/message_bubble_sent.9.png and b/src/main/res/drawable-xxxhdpi/message_bubble_sent.9.png differ
diff --git a/src/main/res/drawable-xxxhdpi/message_bubble_sent_grey.9.png b/src/main/res/drawable-xxxhdpi/message_bubble_sent_grey.9.png
index af45346c4..7939893ac 100644
Binary files a/src/main/res/drawable-xxxhdpi/message_bubble_sent_grey.9.png and b/src/main/res/drawable-xxxhdpi/message_bubble_sent_grey.9.png differ
diff --git a/src/main/res/layout/activity_rtp_session.xml b/src/main/res/layout/activity_rtp_session.xml
index 47bfa95ca..13e0e5d2e 100644
--- a/src/main/res/layout/activity_rtp_session.xml
+++ b/src/main/res/layout/activity_rtp_session.xml
@@ -117,34 +117,56 @@
-
+ android:layout_centerInParent="true">
+
+
+
+
+
+
-
+ app:fabSize="mini"
+ app:tint="?attr/icon_tint" />
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 066ecf612..c83db9dc3 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -920,6 +920,7 @@
Your microphone is unavailable
You can only have one call at a time.
Return to ongoing call
+ Could not switch camera
- View %1$d Participant
- View %1$d Participants