blob: aa560a94d176f6154c2de73861163afaff9e3a9a [file] [log] [blame]
Borjan Tchakaloff4497b4e2016-08-29 19:42:38 +02001package com.fairphone.psensor.helpers;
2
3import android.util.Log;
4
5import java.io.BufferedReader;
6import java.io.File;
7import java.io.IOException;
8import java.io.InputStreamReader;
9
10/**
11 * Helper methods to access the proximity sensor.
12 */
13public class ProximitySensorHelper {
14 private static final String TAG = ProximitySensorHelper.class.getSimpleName();
15
16 /**
17 * Minimal value to accept as valid from the sensor reading (in sensor units).
18 */
19 public static final int READ_MIN_LIMIT = 0;
20 /**
21 * Maximal value to accept as valid from the sensor reading (in sensor units).
22 */
23 public static final int READ_MAX_LIMIT = 255;
24
25 /**
26 * Command to read the sensor value.
27 */
28 private static final String READ_COMMAND = "/system/bin/senread";
29 /**
30 * Result prefix returned by the reading command.
31 */
32 private static final String READ_COMMAND_RESULT_PREFIX = "[RESULT]";
33
34 /**
35 * Amount of times to perform a sensor reading.
36 */
37 private static final int READ_N_TIMES = 3;
38 /**
39 * Time to wait between two sensor readings (in milliseconds).
40 */
41 private static final int READ_DELAY_MS = 500;
42
43 /**
44 * Empty constructor to avoid instantiation.
45 */
46 private ProximitySensorHelper() {
47 }
48
49 /**
50 * Determine whether the proximity sensor value is readable or not based on the reading tool availability. <br>
51 * <br>
52 * The reading tool is tested to exist and be executable.
53 *
54 * @return <code>true</code> if the proximity sensor value is readable, <code>false</code> if not.
55 */
56 public static boolean canReadProximitySensorValue() {
57 final File tool = new File(READ_COMMAND);
58
59 return tool.exists() && tool.canExecute();
60 }
61
62 /**
63 * Read the proximity sensor value read_times times and return the mean value. <br>
64 * <br>
65 * Wait {@link #READ_DELAY_MS} between each read, even if there is only one read planned.
66 *
67 * @param min_value The lower threshold (inclusive) of accepted range.
68 * @param max_value The upper threshold (inclusive) of accepted range.
69 * @return The mean of all the value read (up to {@link #READ_N_TIMES}) or -1 if no read succeeded.
70 */
71 public static int read(int read_times, int min_value, int max_value) {
72 int result;
73 int summed_result = 0;
74 int nb_result_read = 0;
75 int final_result = -1;
76
77 for (int i = 0; i < read_times; i++) {
78 result = readProximitySensorValue();
79
80 if (min_value <= result && result <= max_value) {
81 summed_result += result;
82 nb_result_read++;
83 } else {
84 Log.d(TAG, "Ignored value out of accepted range (" + result + " not in [" + min_value + "," + max_value + "])");
85 }
86
87 // wait a bit between two sensor reading
88 try {
89 Thread.sleep(READ_DELAY_MS);
90 } catch (Exception e) {
91 Log.wtf(TAG, e);
92 }
93 }
94
95 if (nb_result_read == 0) {
96 // something went wrong with READ_COMMAND, are we allowed to execute it?
97 Log.e(TAG, "Could not read sensor value " + read_times + " " + ((read_times == 1) ? "time" : "times"));
98 } else {
99 if (nb_result_read < read_times) {
100 Log.w(TAG, "Read " + nb_result_read + "/" + read_times + " values");
101 }
102
103 final_result = Math.round(summed_result / nb_result_read);
104 }
105
106 return final_result;
107 }
108
109 /**
110 * Call to read(1, {@link #READ_MIN_LIMIT}, {@link #READ_MAX_LIMIT})
111 *
112 * @return The value read or -1 if read failed.
113 * @see ProximitySensorHelper#read(int, int, int)
114 */
115 public static int read() {
116 return read(1, READ_MIN_LIMIT, READ_MAX_LIMIT);
117 }
118
119 /**
120 * Call to read({@link #READ_N_TIMES}, min_value, max_value)
121 *
122 * @param min_value The lower threshold (inclusive) of accepted range.
123 * @param max_value The upper threshold (inclusive) of accepted range.
124 * @return The mean of all the value read (up to {@link #READ_N_TIMES}) or -1 if no read succeeded.
125 * @see ProximitySensorHelper#read(int, int, int)
126 */
127 public static int read(int min_value, int max_value) {
128 return read(READ_N_TIMES, min_value, max_value);
129 }
130
131 /**
132 * Read the proximity sensor value using an external command ({@link #READ_COMMAND}).
133 *
134 * @return the proximity sensor value (>= {@link #READ_MIN_LIMIT and <= {@link #READ_MAX_LIMIT}}) or
135 * <code>-1</code> if there was an error (parsing the value or using the external command).
136 */
137 private static int readProximitySensorValue() {
138 int value = -1;
139 Process process = null;
140
141 try {
142 process = Runtime.getRuntime().exec(new String[]{READ_COMMAND});
143 final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
144 final String line = reader.readLine();
145
146 if (line != null && line.startsWith(READ_COMMAND_RESULT_PREFIX)) {
147 value = Integer.parseInt(line.replace(READ_COMMAND_RESULT_PREFIX, "").trim());
148 }
149 } catch (IOException e) {
150 Log.wtf(TAG, "Could not execute command `" + READ_COMMAND + "`", e);
151 } catch (NumberFormatException e) {
152 Log.wtf(TAG, e);
153 } finally {
154 if (process != null) {
155 process.destroy();
156 }
157 }
158
159 return value;
160 }
161}