package org.thoughtcrime.securesms.webrtc.locks;
import android.os.Build;
import android.os.PowerManager;
import android.util.Log;
import org.whispersystems.libsignal.util.guava.Optional;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Controls access to the proximity lock.
* The proximity lock is not part of the public API.
*
* @author Stuart O. Anderson
*/
class ProximityLock {
private static final String TAG = ProximityLock.class.getSimpleName();
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;
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.fromNullable(pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
"Signal Proximity Lock"));
} else {
return Optional.absent();
}
} else {
try {
return Optional.fromNullable(pm.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, "RedPhone Incall"));
} catch (Throwable t) {
Log.e(TAG, "Failed to create proximity lock", t);
return Optional.absent();
}
}
}
public void acquire() {
if (!proximityLock.isPresent() || proximityLock.get().isHeld()) {
return;
}
proximityLock.get().acquire();
}
public void release() {
if (!proximityLock.isPresent() || !proximityLock.get().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;
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;
}
}