blob: aa560a94d176f6154c2de73861163afaff9e3a9a [file] [log] [blame]
package com.fairphone.psensor.helpers;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Helper methods to access the proximity sensor.
*/
public class ProximitySensorHelper {
private static final String TAG = ProximitySensorHelper.class.getSimpleName();
/**
* Minimal value to accept as valid from the sensor reading (in sensor units).
*/
public static final int READ_MIN_LIMIT = 0;
/**
* Maximal value to accept as valid from the sensor reading (in sensor units).
*/
public static final int READ_MAX_LIMIT = 255;
/**
* Command to read the sensor value.
*/
private static final String READ_COMMAND = "/system/bin/senread";
/**
* Result prefix returned by the reading command.
*/
private static final String READ_COMMAND_RESULT_PREFIX = "[RESULT]";
/**
* Amount of times to perform a sensor reading.
*/
private static final int READ_N_TIMES = 3;
/**
* Time to wait between two sensor readings (in milliseconds).
*/
private static final int READ_DELAY_MS = 500;
/**
* Empty constructor to avoid instantiation.
*/
private ProximitySensorHelper() {
}
/**
* Determine whether the proximity sensor value is readable or not based on the reading tool availability. <br>
* <br>
* The reading tool is tested to exist and be executable.
*
* @return <code>true</code> if the proximity sensor value is readable, <code>false</code> if not.
*/
public static boolean canReadProximitySensorValue() {
final File tool = new File(READ_COMMAND);
return tool.exists() && tool.canExecute();
}
/**
* Read the proximity sensor value read_times times and return the mean value. <br>
* <br>
* Wait {@link #READ_DELAY_MS} between each read, even if there is only one read planned.
*
* @param min_value The lower threshold (inclusive) of accepted range.
* @param max_value The upper threshold (inclusive) of accepted range.
* @return The mean of all the value read (up to {@link #READ_N_TIMES}) or -1 if no read succeeded.
*/
public static int read(int read_times, int min_value, int max_value) {
int result;
int summed_result = 0;
int nb_result_read = 0;
int final_result = -1;
for (int i = 0; i < read_times; i++) {
result = readProximitySensorValue();
if (min_value <= result && result <= max_value) {
summed_result += result;
nb_result_read++;
} else {
Log.d(TAG, "Ignored value out of accepted range (" + result + " not in [" + min_value + "," + max_value + "])");
}
// wait a bit between two sensor reading
try {
Thread.sleep(READ_DELAY_MS);
} catch (Exception e) {
Log.wtf(TAG, e);
}
}
if (nb_result_read == 0) {
// something went wrong with READ_COMMAND, are we allowed to execute it?
Log.e(TAG, "Could not read sensor value " + read_times + " " + ((read_times == 1) ? "time" : "times"));
} else {
if (nb_result_read < read_times) {
Log.w(TAG, "Read " + nb_result_read + "/" + read_times + " values");
}
final_result = Math.round(summed_result / nb_result_read);
}
return final_result;
}
/**
* Call to read(1, {@link #READ_MIN_LIMIT}, {@link #READ_MAX_LIMIT})
*
* @return The value read or -1 if read failed.
* @see ProximitySensorHelper#read(int, int, int)
*/
public static int read() {
return read(1, READ_MIN_LIMIT, READ_MAX_LIMIT);
}
/**
* Call to read({@link #READ_N_TIMES}, min_value, max_value)
*
* @param min_value The lower threshold (inclusive) of accepted range.
* @param max_value The upper threshold (inclusive) of accepted range.
* @return The mean of all the value read (up to {@link #READ_N_TIMES}) or -1 if no read succeeded.
* @see ProximitySensorHelper#read(int, int, int)
*/
public static int read(int min_value, int max_value) {
return read(READ_N_TIMES, min_value, max_value);
}
/**
* Read the proximity sensor value using an external command ({@link #READ_COMMAND}).
*
* @return the proximity sensor value (>= {@link #READ_MIN_LIMIT and <= {@link #READ_MAX_LIMIT}}) or
* <code>-1</code> if there was an error (parsing the value or using the external command).
*/
private static int readProximitySensorValue() {
int value = -1;
Process process = null;
try {
process = Runtime.getRuntime().exec(new String[]{READ_COMMAND});
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
final String line = reader.readLine();
if (line != null && line.startsWith(READ_COMMAND_RESULT_PREFIX)) {
value = Integer.parseInt(line.replace(READ_COMMAND_RESULT_PREFIX, "").trim());
}
} catch (IOException e) {
Log.wtf(TAG, "Could not execute command `" + READ_COMMAND + "`", e);
} catch (NumberFormatException e) {
Log.wtf(TAG, e);
} finally {
if (process != null) {
process.destroy();
}
}
return value;
}
}