Fix in-call proximity lock.

This commit is contained in:
Alex Hart
2025-02-12 13:58:13 -04:00
committed by Greyson Parrelli
parent fffe8cf3c6
commit 8013da681f
4 changed files with 35 additions and 79 deletions

View File

@@ -134,11 +134,9 @@ class WebRtcCallActivity : BaseActivity(), SafetyNumberChangeDialog.Callback, Re
lifecycleDisposable.bindTo(this)
if (Build.VERSION.SDK_INT >= 27) {
setTurnScreenOn(true)
setShowWhenLocked(true)
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
}
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

View File

@@ -619,6 +619,10 @@ public abstract class WebRtcActionProcessor {
callParticipant.getVideoSink().setDeviceOrientationDegrees(sinkRotationDegrees);
}
AppDependencies.getSignalCallManager()
.getLockManager()
.updateOrientation(Orientation.fromDegrees(orientationDegrees));
return currentState.builder()
.changeLocalDeviceState()
.setOrientation(Orientation.fromDegrees(stateRotationDegrees))

View File

@@ -5,7 +5,10 @@ import android.net.wifi.WifiManager;
import android.os.PowerManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.components.sensors.Orientation;
/**
* Maintains wake lock state.
@@ -20,13 +23,12 @@ public class LockManager {
private final PowerManager.WakeLock partialLock;
private final WifiManager.WifiLock wifiLock;
private final ProximityLock proximityLock;
private final AccelerometerListener accelerometerListener;
private final boolean wifiLockEnforced;
private final boolean wifiLockEnforced;
private int orientation = AccelerometerListener.ORIENTATION_UNKNOWN;
private boolean proximityDisabled = false;
private PhoneState phoneState = PhoneState.IDLE;
private Orientation orientation = Orientation.PORTRAIT_BOTTOM_EDGE;
private boolean proximityDisabled = false;
public enum PhoneState {
IDLE,
@@ -57,15 +59,6 @@ public class LockManager {
partialLock.setReferenceCounted(false);
wifiLock.setReferenceCounted(false);
accelerometerListener = new AccelerometerListener(context, new AccelerometerListener.OrientationListener() {
@Override
public void orientationChanged(int newOrientation) {
orientation = newOrientation;
Log.d(TAG, "Orentation Update: " + newOrientation);
updateInCallLockState();
}
});
wifiLockEnforced = isWifiPowerActiveModeEnabled(context);
}
@@ -81,40 +74,45 @@ public class LockManager {
}
private void updateInCallLockState() {
if (orientation != AccelerometerListener.ORIENTATION_HORIZONTAL && wifiLockEnforced && !proximityDisabled) {
if (orientation == Orientation.PORTRAIT_BOTTOM_EDGE && wifiLockEnforced && !proximityDisabled) {
setLockState(LockState.PROXIMITY);
} else {
setLockState(LockState.FULL);
}
}
public void updateOrientation(@NonNull Orientation orientation) {
Log.d(TAG, "Update orientation: " + orientation);
this.orientation = orientation;
if (phoneState == PhoneState.IN_CALL || phoneState == PhoneState.IN_VIDEO) {
updateInCallLockState();
}
}
public void updatePhoneState(PhoneState state) {
this.phoneState = state;
switch(state) {
case IDLE:
setLockState(LockState.SLEEP);
accelerometerListener.enable(false);
break;
case PROCESSING:
setLockState(LockState.PARTIAL);
accelerometerListener.enable(false);
break;
case INTERACTIVE:
setLockState(LockState.FULL);
accelerometerListener.enable(false);
break;
case IN_HANDS_FREE_CALL:
setLockState(LockState.PARTIAL);
proximityDisabled = true;
accelerometerListener.enable(false);
break;
case IN_VIDEO:
proximityDisabled = true;
accelerometerListener.enable(false);
updateInCallLockState();
break;
case IN_CALL:
proximityDisabled = false;
accelerometerListener.enable(true);
updateInCallLockState();
break;
}

View File

@@ -1,13 +1,10 @@
package org.thoughtcrime.securesms.webrtc.locks;
import android.os.Build;
import android.os.PowerManager;
import org.signal.core.util.logging.Log;
import androidx.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Optional;
import org.signal.core.util.logging.Log;
/**
* Controls access to the proximity lock.
@@ -19,76 +16,35 @@ class ProximityLock {
private static final String TAG = Log.tag(ProximityLock.class);
private final Method wakelockParameterizedRelease = getWakelockParamterizedReleaseMethod();
private final Optional<PowerManager.WakeLock> proximityLock;
private static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
private static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
private final PowerManager.WakeLock proximityLock;
ProximityLock(PowerManager pm) {
proximityLock = getProximityLock(pm);
}
private Optional<PowerManager.WakeLock> getProximityLock(PowerManager pm) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (pm.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
return Optional.ofNullable(pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "signal:proximity"));
} else {
return Optional.empty();
}
private @Nullable PowerManager.WakeLock getProximityLock(PowerManager pm) {
if (pm.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
return pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "signal:proximity");
} else {
try {
return Optional.ofNullable(pm.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, "signal:incall"));
} catch (Throwable t) {
Log.e(TAG, "Failed to create proximity lock", t);
return Optional.empty();
}
return null;
}
}
public void acquire() {
if (!proximityLock.isPresent() || proximityLock.get().isHeld()) {
if (proximityLock == null || proximityLock.isHeld()) {
return;
}
proximityLock.get().acquire();
proximityLock.acquire();
}
public void release() {
if (!proximityLock.isPresent() || !proximityLock.get().isHeld()) {
if (proximityLock == null || !proximityLock.isHeld()) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
proximityLock.get().release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
} else {
boolean released = false;
proximityLock.release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
if (wakelockParameterizedRelease != null) {
try {
wakelockParameterizedRelease.invoke(proximityLock.get(), WAIT_FOR_PROXIMITY_NEGATIVE);
released = true;
} catch (IllegalAccessException e) {
Log.w(TAG, e);
} catch (InvocationTargetException e) {
Log.w(TAG, e);
}
}
if (!released) {
proximityLock.get().release();
}
}
Log.d(TAG, "Released proximity lock:" + proximityLock.get().isHeld());
}
private static Method getWakelockParamterizedReleaseMethod() {
try {
return PowerManager.WakeLock.class.getDeclaredMethod("release", Integer.TYPE);
} catch (NoSuchMethodException e) {
Log.d(TAG, "Parameterized WakeLock release not available on this device.");
}
return null;
Log.d(TAG, "Released proximity lock:" + proximityLock.isHeld());
}
}