Skip to content

Commit

Permalink
In Camera1 we now try to split parameters into individual sub-maps of…
Browse files Browse the repository at this point in the history
… size 1 in case if updating all parameters at once fails.
  • Loading branch information
dmitry-zaitsev committed Jul 8, 2017
1 parent 82501be commit b25fadd
Show file tree
Hide file tree
Showing 9 changed files with 325 additions and 12 deletions.
36 changes: 24 additions & 12 deletions fotoapparat/src/main/java/io/fotoapparat/hardware/v1/Camera1.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@
import io.fotoapparat.hardware.CameraDevice;
import io.fotoapparat.hardware.CameraException;
import io.fotoapparat.hardware.Capabilities;
import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.hardware.orientation.OrientationUtils;
import io.fotoapparat.hardware.provider.AvailableLensPositionsProvider;
import io.fotoapparat.hardware.provider.V1AvailableLensPositionProvider;
import io.fotoapparat.hardware.v1.capabilities.CapabilitiesFactory;
import io.fotoapparat.hardware.v1.parameters.SplitParametersOperator;
import io.fotoapparat.hardware.v1.parameters.SupressExceptionsParametersOperator;
import io.fotoapparat.hardware.v1.parameters.SwitchOnFailureParametersOperator;
import io.fotoapparat.hardware.v1.parameters.UnsafeParametersOperator;
import io.fotoapparat.lens.FocusResult;
import io.fotoapparat.log.Logger;
import io.fotoapparat.parameter.LensPosition;
Expand Down Expand Up @@ -58,10 +63,6 @@ private static void throwOnFailSetDisplaySurface(Object displaySurface, IOExcept
throw new CameraException("Unable to set display surface: " + displaySurface, e);
}

private static void throwOnFailSetParameters(Parameters parameters, Exception e) {
throw new CameraException("Failed to set parameters: " + parameters, e);
}

@Override
public void open(LensPosition lensPosition) {
recordMethod();
Expand Down Expand Up @@ -188,16 +189,27 @@ private int computeImageOrientation(int screenRotationDegrees,
public void updateParameters(Parameters parameters) {
recordMethod();

Camera.Parameters cameraParameters = parametersConverter.convert(
parameters,
camera.getParameters()
parametersOperator().updateParameters(parameters);
}

@NonNull
private SwitchOnFailureParametersOperator parametersOperator() {
ParametersOperator unsafeParametersOperator = new UnsafeParametersOperator(
camera,
parametersConverter
);

try {
camera.setParameters(cameraParameters);
} catch (Exception e) {
throwOnFailSetParameters(parameters, e);
}
ParametersOperator fallbackOperator = new SplitParametersOperator(
new SupressExceptionsParametersOperator(
unsafeParametersOperator,
logger
)
);

return new SwitchOnFailureParametersOperator(
unsafeParametersOperator,
fallbackOperator
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.fotoapparat.hardware.v1.parameters;

import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.parameter.Parameters;

/**
* Instead of updating all parameters at once, updates each parameter one by one.
*/
public class SplitParametersOperator implements ParametersOperator {

private final ParametersOperator wrapped;

public SplitParametersOperator(ParametersOperator wrapped) {
this.wrapped = wrapped;
}

@Override
public void updateParameters(Parameters parameters) {
for (Parameters.Type type : parameters.storedTypes()) {
wrapped.updateParameters(
newParameters(type, parameters.getValue(type))
);
}
}

private Parameters newParameters(Parameters.Type type, Object value) {
Parameters parameters = new Parameters();
parameters.putValue(type, value);

return parameters;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.fotoapparat.hardware.v1.parameters;

import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.log.Logger;
import io.fotoapparat.parameter.Parameters;

/**
* Tries to update parameters. If that fails, suppresses the exception and writes relevant
* information to log.
*/
public class SupressExceptionsParametersOperator implements ParametersOperator {

private final ParametersOperator wrapped;
private final Logger logger;

public SupressExceptionsParametersOperator(ParametersOperator wrapped,
Logger logger) {
this.wrapped = wrapped;
this.logger = logger;
}

@Override
public void updateParameters(Parameters parameters) {
try {
wrapped.updateParameters(parameters);
} catch (Exception e) {
logger.log("Unable to set parameters: " + parameters);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.fotoapparat.hardware.v1.parameters;

import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.parameter.Parameters;

/**
* Tries to execute first operator. If that fails, tries to execute the second one.
*/
public class SwitchOnFailureParametersOperator implements ParametersOperator {

private final ParametersOperator first;
private final ParametersOperator second;

public SwitchOnFailureParametersOperator(ParametersOperator first,
ParametersOperator second) {
this.first = first;
this.second = second;
}

@Override
public void updateParameters(Parameters parameters) {
try {
first.updateParameters(parameters);
} catch (Exception e) {
second.updateParameters(parameters);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.fotoapparat.hardware.v1.parameters;

import android.hardware.Camera;

import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.hardware.v1.ParametersConverter;
import io.fotoapparat.parameter.Parameters;

/**
* Updates parameters of camera, possibly throwing a {@link RuntimeException} if something goes
* wrong. We can't really know why camera might reject parameters, so it should be expected.
*/
@SuppressWarnings("deprecation")
public class UnsafeParametersOperator implements ParametersOperator {

private final Camera camera;
private final ParametersConverter parametersConverter;

public UnsafeParametersOperator(Camera camera,
ParametersConverter parametersConverter) {
this.camera = camera;
this.parametersConverter = parametersConverter;
}

@Override
public void updateParameters(Parameters parameters) {
Camera.Parameters cameraParameters = parametersConverter.convert(
parameters,
camera.getParameters()
);

camera.setParameters(cameraParameters);
}

}
15 changes: 15 additions & 0 deletions fotoapparat/src/main/java/io/fotoapparat/parameter/Parameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,21 @@ public Set<Type> storedTypes() {
return result;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Parameters that = (Parameters) o;

return values.equals(that.values);
}

@Override
public int hashCode() {
return values.hashCode();
}

@Override
public String toString() {
return "Parameters{" +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.fotoapparat.hardware.v1.parameters;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.parameter.Parameters;
import io.fotoapparat.parameter.Size;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

@RunWith(MockitoJUnitRunner.class)
public class SplitParametersOperatorTest {

static final Size PICTURE_SIZE = new Size(100, 100);
static final Size PREVIEW_SIZE = new Size(50, 50);

@Mock
ParametersOperator wrapped;

@InjectMocks
SplitParametersOperator testee;

@Test
public void updateParameters() throws Exception {
// Given
Parameters parameters = new Parameters();
parameters.putValue(Parameters.Type.PICTURE_SIZE, PICTURE_SIZE);
parameters.putValue(Parameters.Type.PREVIEW_SIZE, PREVIEW_SIZE);

// When
testee.updateParameters(parameters);

// Then
verify(wrapped).updateParameters(
parametersWithJust(Parameters.Type.PICTURE_SIZE, PICTURE_SIZE)
);
verify(wrapped).updateParameters(
parametersWithJust(Parameters.Type.PREVIEW_SIZE, PREVIEW_SIZE)
);

verifyNoMoreInteractions(wrapped);
}

private Parameters parametersWithJust(Parameters.Type type, Object value) {
Parameters parameters = new Parameters();
parameters.putValue(type, value);

return parameters;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.fotoapparat.hardware.v1.parameters;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.log.Logger;
import io.fotoapparat.parameter.Parameters;

import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class SupressExceptionsParametersOperatorTest {

@Mock
ParametersOperator wrapped;
@Mock
Logger logger;
@Mock
Parameters parameters;

@InjectMocks
SupressExceptionsParametersOperator testee;

@Test
public void updateParameters() throws Exception {
// Given
doThrow(new RuntimeException())
.when(wrapped)
.updateParameters(parameters);

// When
testee.updateParameters(parameters);

// Then
verify(wrapped).updateParameters(parameters);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.fotoapparat.hardware.v1.parameters;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import io.fotoapparat.hardware.operators.ParametersOperator;
import io.fotoapparat.parameter.Parameters;

import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;

@RunWith(MockitoJUnitRunner.class)
public class SwitchOnFailureParametersOperatorTest {

@Mock
ParametersOperator first;
@Mock
ParametersOperator second;
@Mock
Parameters parameters;

SwitchOnFailureParametersOperator testee;

@Before
public void setUp() throws Exception {
testee = new SwitchOnFailureParametersOperator(
first, second
);
}

@Test
public void firstSucceeds() throws Exception {
// When
testee.updateParameters(parameters);

// Then
verify(first).updateParameters(parameters);

verifyZeroInteractions(second);
}

@Test
public void firstFails() throws Exception {
// Given
doThrow(new RuntimeException())
.when(first)
.updateParameters(parameters);

// When
testee.updateParameters(parameters);

// Then
verify(second).updateParameters(parameters);
}

}

0 comments on commit b25fadd

Please sign in to comment.