Improved PiP while in video conference

This commit is contained in:
Sylvain Berfini 2022-06-22 17:57:22 +02:00
parent 0dd79e5ff8
commit 8f3b17bb0f
5 changed files with 50 additions and 12 deletions

View file

@ -33,7 +33,6 @@ import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R import org.linphone.R
import org.linphone.activities.* import org.linphone.activities.*
import org.linphone.activities.main.MainActivity import org.linphone.activities.main.MainActivity
import org.linphone.activities.navigateToActiveCall
import org.linphone.activities.voip.viewmodels.CallsViewModel import org.linphone.activities.voip.viewmodels.CallsViewModel
import org.linphone.activities.voip.viewmodels.ConferenceViewModel import org.linphone.activities.voip.viewmodels.ConferenceViewModel
import org.linphone.activities.voip.viewmodels.ControlsViewModel import org.linphone.activities.voip.viewmodels.ControlsViewModel
@ -106,7 +105,7 @@ class CallActivity : ProximitySensorActivity() {
controlsViewModel.isVideoEnabled.observe( controlsViewModel.isVideoEnabled.observe(
this this
) { enabled -> ) { enabled ->
Compatibility.enableAutoEnterPiP(this, enabled) Compatibility.enableAutoEnterPiP(this, enabled, conferenceViewModel.conferenceExists.value == true)
} }
controlsViewModel.callStatsVisible.observe( controlsViewModel.callStatsVisible.observe(
@ -185,7 +184,7 @@ class CallActivity : ProximitySensorActivity() {
if (coreContext.core.currentCall?.currentParams?.isVideoEnabled == true) { if (coreContext.core.currentCall?.currentParams?.isVideoEnabled == true) {
Log.i("[Call Activity] Entering PiP mode") Log.i("[Call Activity] Entering PiP mode")
Compatibility.enterPipMode(this) Compatibility.enterPipMode(this, conferenceViewModel.conferenceExists.value == true)
} }
} }

View file

@ -55,14 +55,20 @@ import org.linphone.utils.LinphoneUtils
@TargetApi(26) @TargetApi(26)
class Api26Compatibility { class Api26Compatibility {
companion object { companion object {
fun enterPipMode(activity: Activity) { fun enterPipMode(activity: Activity, conference: Boolean) {
val supportsPip = activity.packageManager val supportsPip = activity.packageManager
.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) .hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
Log.i("[Call] Is PiP supported: $supportsPip") Log.i("[Call] Is PiP supported: $supportsPip")
if (supportsPip) { if (supportsPip) {
val params = PictureInPictureParams.Builder().build() // Force portrait layout if in conference, otherwise for landscape
// Our layouts behave better in these orientation
val params = PictureInPictureParams.Builder()
.setAspectRatio(Compatibility.getPipRatio(activity, conference, !conference))
.build()
if (!activity.enterPictureInPictureMode(params)) { if (!activity.enterPictureInPictureMode(params)) {
Log.e("[Call] Failed to enter PiP mode") Log.e("[Call] Failed to enter PiP mode")
} else {
Log.i("[Call] Entering PiP mode with ${if (conference) "portrait" else "landscape"} aspect ratio")
} }
} }
} }

View file

@ -204,14 +204,19 @@ class Api31Compatibility {
} }
} }
fun enableAutoEnterPiP(activity: Activity, enable: Boolean) { fun enableAutoEnterPiP(activity: Activity, enable: Boolean, conference: Boolean) {
val supportsPip = activity.packageManager val supportsPip = activity.packageManager
.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) .hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
Log.i("[Call] Is PiP supported: $supportsPip") Log.i("[Call] Is PiP supported: $supportsPip")
if (supportsPip) { if (supportsPip) {
val params = PictureInPictureParams.Builder().setAutoEnterEnabled(enable).build() // Force portrait layout if in conference, otherwise for landscape
// Our layouts behave better in these orientation
val params = PictureInPictureParams.Builder()
.setAutoEnterEnabled(enable)
.setAspectRatio(Compatibility.getPipRatio(activity, conference, !conference))
.build()
activity.setPictureInPictureParams(params) activity.setPictureInPictureParams(params)
Log.i("[Call] PiP auto enter enabled params set to $enable") Log.i("[Call] PiP auto enter enabled params set to $enable with ${if (conference) "portrait" else "landscape"} aspect ratio")
} }
} }

View file

@ -30,6 +30,8 @@ import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Vibrator import android.os.Vibrator
import android.telephony.TelephonyManager import android.telephony.TelephonyManager
import android.util.DisplayMetrics
import android.util.Rational
import android.view.View import android.view.View
import android.view.Window import android.view.Window
import android.view.WindowManager import android.view.WindowManager
@ -266,18 +268,43 @@ class Compatibility {
return Api23Compatibility.canDrawOverlay(context) return Api23Compatibility.canDrawOverlay(context)
} }
fun enterPipMode(activity: Activity) { fun enterPipMode(activity: Activity, conference: Boolean) {
if (Version.sdkStrictlyBelow(Version.API31_ANDROID_12) && Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkStrictlyBelow(Version.API31_ANDROID_12) && Version.sdkAboveOrEqual(Version.API26_O_80)) {
Api26Compatibility.enterPipMode(activity) Api26Compatibility.enterPipMode(activity, conference)
} }
} }
fun enableAutoEnterPiP(activity: Activity, enable: Boolean) { fun enableAutoEnterPiP(activity: Activity, enable: Boolean, conference: Boolean) {
if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12)) { if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12)) {
Api31Compatibility.enableAutoEnterPiP(activity, enable) Api31Compatibility.enableAutoEnterPiP(activity, enable, conference)
} }
} }
fun getPipRatio(
activity: Activity,
forcePortrait: Boolean = false,
forceLandscape: Boolean = false
): Rational {
val displayMetrics = DisplayMetrics()
activity.windowManager.defaultDisplay.getMetrics(displayMetrics)
val height = displayMetrics.heightPixels
val width = displayMetrics.widthPixels
val ratio = if (width > height) {
if (forcePortrait) {
Rational(height, width)
} else {
Rational(width, height)
}
} else {
if (forceLandscape) {
Rational(height, width)
} else {
Rational(width, height)
}
}
return ratio
}
fun eventVibration(vibrator: Vibrator) { fun eventVibration(vibrator: Vibrator) {
if (Version.sdkAboveOrEqual(Version.API26_O_80)) { if (Version.sdkAboveOrEqual(Version.API26_O_80)) {
Api26Compatibility.eventVibration(vibrator) Api26Compatibility.eventVibration(vibrator)

View file

@ -147,6 +147,7 @@
android:id="@+id/scroll_indicator" android:id="@+id/scroll_indicator"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="@{controlsViewModel.pipMode ? View.GONE : View.VISIBLE}"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"