Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
Expand Down Expand Up @@ -369,7 +370,7 @@
<service
android:name=".services.CallForegroundService"
android:exported="false"
android:foregroundServiceType="microphone|camera" />
android:foregroundServiceType="microphone|camera|mediaProjection" />

<service android:name=".services.UnifiedPushService"
android:exported="false">
Expand Down
328 changes: 317 additions & 11 deletions app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public abstract class CallBaseActivity extends BaseActivity {
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (isPipModePossible()) {
if (shouldEnterPipModeAutomatically()) {
enterPipMode();
} else {
moveTaskToBack(true);
Expand Down Expand Up @@ -110,7 +110,7 @@ public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
Log.d(TAG, "onTopResumedActivityChanged: isTopResumedActivity=" + isTopResumedActivity
+ " isInPictureInPictureMode=" + isInPictureInPictureMode());
if (isTopResumedActivity || isInPictureInPictureMode()
|| !isPipModePossible()
|| !shouldEnterPipModeAutomatically()
|| isChangingConfigurations()
|| isFinishing()) {
return;
Expand All @@ -129,7 +129,7 @@ public void onPause() {
// On API 29+, onTopResumedActivityChanged already handled this.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
&& !isInPictureInPictureMode()
&& isPipModePossible()
&& shouldEnterPipModeAutomatically()
&& !isChangingConfigurations()
&& !isFinishing()) {
enterPipMode();
Expand All @@ -152,7 +152,7 @@ protected void onUserLeaveHint() {
// moveTaskToBack here: onUserLeaveHint also fires when a transient overlay like the
// permission dialog appears at call start, which would throw the call to the background.
if (!isInPipMode
&& isPipModePossible()
&& shouldEnterPipModeAutomatically()
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
enterPipMode();
}
Expand All @@ -173,6 +173,35 @@ void enterPipMode() {
}
}

/**
* Whether picture in picture should not be entered when the user leaves the activity (for example, with the back
* or home buttons). Picture in picture can still be entered explicitly.
* <p>
* {@link #updatePipAutoEnter()} must be called whenever the returned value changes.
*/
protected boolean isAutomaticPipModeSuppressed() {
return false;
}

private boolean shouldEnterPipModeAutomatically() {
return isPipModePossible() && !isAutomaticPipModeSuppressed();
}

/**
* Updates whether the system enters picture in picture automatically when leaving the activity.
*/
void updatePipAutoEnter() {
// It may be called from a task posted before the activity was destroyed.
if (isFinishing() || isDestroyed()) {
return;
}
// The builder is only created if picture in picture was possible when the activity was created.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && mPictureInPictureParamsBuilder != null) {
mPictureInPictureParamsBuilder.setAutoEnterEnabled(!isAutomaticPipModeSuppressed());
setPictureInPictureParams(mPictureInPictureParamsBuilder.build());
}
}

boolean isPipModePossible() {
boolean deviceHasPipFeature = getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);

Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/nextcloud/talk/activities/CallViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ class CallViewModel @Inject constructor() : ViewModel() {
private val _activeScreenShareSession = MutableStateFlow<ParticipantUiState?>(null)
val activeScreenShareSession: StateFlow<ParticipantUiState?> = _activeScreenShareSession.asStateFlow()

private val _isLocalScreenSharing = MutableStateFlow(false)
val isLocalScreenSharing: StateFlow<Boolean> = _isLocalScreenSharing.asStateFlow()

private val _isScreenSharingAllowed = MutableStateFlow(false)
val isScreenSharingAllowed: StateFlow<Boolean> = _isScreenSharingAllowed.asStateFlow()

fun getParticipant(sessionId: String?): ParticipantHandler? {
if (sessionId == null) {
Log.w(TAG, "Attempted to get participant with null sessionId.")
Expand Down Expand Up @@ -88,6 +94,14 @@ class CallViewModel @Inject constructor() : ViewModel() {
}
}

fun setLocalScreenSharing(isSharing: Boolean) {
_isLocalScreenSharing.value = isSharing
}

fun setScreenSharingAllowed(isAllowed: Boolean) {
_isScreenSharingAllowed.value = isAllowed
}

public override fun onCleared() {
participantHandlers.values.forEach { it.destroy() }
participantHandlers.clear()
Expand Down
Loading
Loading