package nl.sense_os.service.commonsense;
import nl.sense_os.service.constants.SenseDataTypes;
import nl.sense_os.service.constants.SensePrefs;
import nl.sense_os.service.constants.SensePrefs.Main;
import nl.sense_os.service.constants.SensePrefs.Main.Ambience;
import nl.sense_os.service.constants.SensePrefs.Main.Motion;
import nl.sense_os.service.constants.SensorData.SensorDescriptions;
import nl.sense_os.service.constants.SensorData.SensorNames;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.nfc.NfcManager;
import android.os.Build;
import android.telephony.TelephonyManager;
/**
* Class that verifies that all the phone's sensors are known at CommonSense.
*
* @author Steven Mulder <steven@sense-os.nl>
*
* @see DefaultSensorRegistrationService
*/
public class DefaultSensorRegistrator extends SensorRegistrator {
public DefaultSensorRegistrator(Context context) {
super(context);
}
// private static final String TAG = "Sensor Registration";
/**
* Checks the IDs for light, camera light, noise, pressure sensors.
*
* @param deviceUuid
* @param deviceType
*
* @return true if all sensor IDs are found or created
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private boolean checkAmbienceSensors(String deviceType, String deviceUuid) {
// preallocate objects
SensorManager sm = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
Sensor sensor;
boolean success = true;
// match light sensor
sensor = sm.getDefaultSensor(Sensor.TYPE_LIGHT);
if (null != sensor) {
success &= checkSensor(SensorNames.LIGHT, SensorNames.LIGHT, SenseDataTypes.JSON,
sensor.getName(), "{\"lux\":0}", deviceType, deviceUuid);
} else {
// Log.v(TAG, "No light sensor present!");
}
// match camera light sensor (only for Android < 4.0)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// multiple camera support starting from Android 2.3
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD) {
for (int camera_id = 0; camera_id < Camera.getNumberOfCameras(); ++camera_id) {
success &= checkSensor(SensorNames.CAMERA_LIGHT, "Camera Light",
SenseDataTypes.JSON, "camera " + camera_id + " average luminance",
"{\"lux\":0}", deviceType, deviceUuid);
}
}
}
// match noise sensor
success &= checkSensor(SensorNames.NOISE, "noise", SenseDataTypes.FLOAT, SensorNames.NOISE,
"0.0", deviceType, deviceUuid);
// match noise sensor (burst-mode)
SharedPreferences mainPrefs = getContext().getSharedPreferences(SensePrefs.MAIN_PREFS,
Context.MODE_PRIVATE);
if (mainPrefs.getBoolean(Ambience.BURSTMODE, false)) {
success &= checkSensor(SensorNames.NOISE_BURST, "noise (burst-mode)", SenseDataTypes.JSON, "noise (dB)",
"{\"interval:\":0,\"data\":[2.23, 19.45, 20.2]}", deviceType, deviceUuid);
}
// match auto calibrated noise sensor
success &= checkSensor(SensorNames.NOISE, "noise", SenseDataTypes.FLOAT,
SensorDescriptions.AUTO_CALIBRATED, "0.0", deviceType, deviceUuid);
// match noise spectrum
success &= checkSensor(
SensorNames.AUDIO_SPECTRUM,
"audio spectrum",
SenseDataTypes.JSON,
"audio spectrum (dB)",
"{\"bandwidth\":10, \"spectrum\":[40, 50, 40 , 20, 40, 60, 43, 12, 34, 56]}",
deviceType, deviceUuid);
// match pressure sensor
sensor = sm.getDefaultSensor(Sensor.TYPE_PRESSURE);
if (null != sensor) {
success &= checkSensor(SensorNames.PRESSURE, SensorNames.PRESSURE,
SenseDataTypes.FLOAT, sensor.getName(), "1.0", deviceType, deviceUuid);
} else {
// Log.v(TAG, "No pressure sensor present!");
}
// match Magnetic Field sensor
sensor = sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
if (null != sensor) {
success &= checkSensor(SensorNames.MAGNETIC_FIELD, SensorNames.MAGNETIC_FIELD,
SenseDataTypes.JSON, sensor.getName(), "{\"x\":0, \"y\":0, \"z\":0}",
deviceType, deviceUuid);
} else {
// Log.v(TAG, "No magnetic field sensor present!");
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
sensor = sm.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
if (null != sensor) {
success &= checkSensor(SensorNames.AMBIENT_TEMPERATURE, "ambient temperature",
SenseDataTypes.FLOAT, sensor.getName(), "1.0", deviceType, deviceUuid);
} else {
// Log.v(TAG, "No ambient temperature sensor present!");
}
sensor = sm.getDefaultSensor(Sensor.TYPE_RELATIVE_HUMIDITY);
if (null != sensor) {
success &= checkSensor(SensorNames.RELATIVE_HUMIDITY, "relative humidity",
SenseDataTypes.FLOAT, sensor.getName(), "1.0", deviceType, deviceUuid);
} else {
// Log.v(TAG, "No relative humidity sensor present!");
}
}
// match loudness sensor
success &= checkSensor(SensorNames.LOUDNESS, SensorNames.LOUDNESS, SenseDataTypes.FLOAT,
SensorNames.LOUDNESS, "0.0", deviceType, deviceUuid);
return success;
}
private boolean checkDebugSensors(String deviceType, String deviceUuid) {
boolean success = true;
// match myrianode sensor
SharedPreferences mainPrefs = getContext().getSharedPreferences(SensePrefs.MAIN_PREFS,
Context.MODE_PRIVATE);
if (mainPrefs.getBoolean(Main.Advanced.LOCATION_FEEDBACK, false)) {
success &= checkSensor(SensorNames.ATTACHED_TO_MYRIANODE,
SensorNames.ATTACHED_TO_MYRIANODE, SenseDataTypes.STRING, "Sense Logger",
"string", deviceType, deviceUuid);
}
return success;
}
/**
* Checks the IDs for Bluetooth and Wi-Fi scan sensors.
*
* @param deviceUuid
* @param deviceType
*
* @return true if all sensor IDs are found or created
*/
@TargetApi(10)
private boolean checkDeviceScanSensors(String deviceType, String deviceUuid) {
// preallocate objects
boolean success = true;
// match Bluetooth scan
success &= checkSensor(SensorNames.BLUETOOTH_DISCOVERY, "bluetooth scan",
SenseDataTypes.JSON, SensorNames.BLUETOOTH_DISCOVERY,
"{\"name\":\"string\",\"address\":\"string\",\"rssi\":0}", deviceType, deviceUuid);
// match Bluetooth neighbours count
success &= checkSensor(SensorNames.BLUETOOTH_NEIGHBOURS_COUNT,
"bluetooth neighbours count", SenseDataTypes.INT,
SensorNames.BLUETOOTH_NEIGHBOURS_COUNT, "0", deviceType, deviceUuid);
// match Wi-Fi scan
success &= checkSensor(
SensorNames.WIFI_SCAN,
"wi-fi scan",
SenseDataTypes.JSON,
SensorNames.WIFI_SCAN,
"{\"ssid\":\"string\",\"bssid\":\"string\",\"frequency\":0,\"rssi\":0,\"capabilities\":\"string\"}",
deviceType, deviceUuid);
// match NFC scan
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) {
NfcManager nm = (NfcManager) getContext().getSystemService(Context.NFC_SERVICE);
if (null != nm.getDefaultAdapter()) {
success &= checkSensor(SensorNames.NFC_SCAN, "nfc scan", SenseDataTypes.JSON,
SensorNames.NFC_SCAN,
"{\"id\":\"string\",\"technology\":\"string\",\"message\":\"string\"}",
deviceType, deviceUuid);
}
}
return success;
}
/**
* Checks the ID for the location sensor
*
* @param deviceUuid
* @param deviceType
*
* @return true if the sensor ID is found or created
*/
private boolean checkLocationSensors(String deviceType, String deviceUuid) {
boolean succes = true;
// match location sensor
succes &= checkSensor(
SensorNames.LOCATION,
SensorNames.LOCATION,
SenseDataTypes.JSON,
SensorNames.LOCATION,
"{\"longitude\":1.0,\"laitude\":1.0,\"altitude\":1.0,\"accuracy\":1.0,\"speed\":1.0,\"bearing\":1.0,\"provider\":\"provider\"}",
deviceType, deviceUuid);
// traveled distance sensor
succes &= checkSensor(SensorNames.TRAVELED_DISTANCE_1H, SensorNames.TRAVELED_DISTANCE_1H,
SenseDataTypes.FLOAT, SensorNames.TRAVELED_DISTANCE_1H, "0.0", deviceType,
deviceUuid);
return succes;
}
/**
* Checks the IDs for the accelerometer, orientation, fall detector, motion energy sensors.
*
* @param deviceUuid
* @param deviceType
*
* @return true if the sensor ID is found or created
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@SuppressWarnings("deprecation")
// TODO: replace orientation sensor with modern version
private boolean checkMotionSensors(String deviceType, String deviceUuid) {
// preallocate objects
SensorManager sm = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
Sensor sensor;
boolean success = true;
SharedPreferences mainPrefs = getContext().getSharedPreferences(SensePrefs.MAIN_PREFS,
Context.MODE_PRIVATE);
sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (null != sensor) {
// match accelerometer
if (mainPrefs.getBoolean(Motion.ACCELEROMETER, true)) {
success &= checkSensor(SensorNames.ACCELEROMETER, "acceleration",
SenseDataTypes.JSON, sensor.getName(),
"{\"x-axis\":1.0,\"y-axis\":1.0,\"z-axis\":1.0}", deviceType, deviceUuid);
}
if (mainPrefs.getBoolean(Motion.EPIMODE, false)) {
success &= checkSensor(SensorNames.ACCELEROMETER_EPI, "acceleration (epi-mode)",
SenseDataTypes.JSON, sensor.getName(), "{\"interval\":0,\"data\":[]}",
deviceType, deviceUuid);
}
if (mainPrefs.getBoolean(Motion.BURSTMODE, false)) {
success &= checkSensor(SensorNames.ACCELEROMETER_BURST,
"acceleration (burst-mode)", SenseDataTypes.JSON, sensor.getName(),
"{\"interval\":0,\"data\":[]}", deviceType, deviceUuid);
}
// match motion energy
if (mainPrefs.getBoolean(Main.Motion.MOTION_ENERGY, false)) {
success &= checkSensor(SensorNames.MOTION_ENERGY, SensorNames.MOTION_ENERGY,
SenseDataTypes.FLOAT, SensorNames.MOTION_ENERGY, "1.0", deviceType,
deviceUuid);
}
// match fall detector
if (mainPrefs.getBoolean(Main.Motion.FALL_DETECT, false)) {
success &= checkSensor(SensorNames.FALL_DETECTOR, "fall", SenseDataTypes.BOOL,
"human fall", "true", deviceType, deviceUuid);
}
// match fall detector
if (mainPrefs.getBoolean(Main.Motion.FALL_DETECT_DEMO, false)) {
success &= checkSensor(SensorNames.FALL_DETECTOR, "fall (demo)",
SenseDataTypes.BOOL, "demo fall", "true", deviceType, deviceUuid);
}
// match linear acceleration
if (mainPrefs.getBoolean(Motion.LINEAR_ACCELERATION, true)) {
//check if actual linear accelerometer exists,
//if not we set burst-mode only
String processed ="";
if (null != sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)) {
success &= checkSensor(SensorNames.LIN_ACCELERATION,
SensorNames.LIN_ACCELERATION, SenseDataTypes.JSON, sensor.getName(),
"{\"x-axis\":1.0,\"y-axis\":1.0,\"z-axis\":1.0}", deviceType,
deviceUuid);
}else {
processed = "processed ";
}
if (mainPrefs.getBoolean(Motion.BURSTMODE, false)) {
success &= checkSensor(SensorNames.LINEAR_BURST,
"linear acceleration " + processed + "(burst-mode)", SenseDataTypes.JSON,
sensor.getName(), "{\"interval\":0,\"data\":[]}", deviceType,
deviceUuid);
}
}
} else {
// Log.v(TAG, "No accelerometer present!");
}
// match orientation
if (mainPrefs.getBoolean(Motion.ORIENTATION, true)) {
sensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (null != sensor) {
success &= checkSensor(SensorNames.ORIENT, SensorNames.ORIENT, SenseDataTypes.JSON,
sensor.getName(), "{\"azimuth\":1.0,\"pitch\":1.0,\"roll\":1.0}",
deviceType, deviceUuid);
} else {
// Log.v(TAG, "No orientation sensor present!");
}
}
// match gyroscope
if (mainPrefs.getBoolean(Motion.GYROSCOPE, true)) {
sensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (null != sensor) {
success &= checkSensor(SensorNames.GYRO, "rotation rate", SenseDataTypes.JSON,
sensor.getName(),
"{\"azimuth rate\":1.0,\"pitch rate\":1.0,\"roll rate\":1.0}", deviceType,
deviceUuid);
if (mainPrefs.getBoolean(Motion.BURSTMODE, false)) {
success &= checkSensor(SensorNames.GYRO_BURST, "rotation rate (burst-mode)",
SenseDataTypes.JSON, sensor.getName(), "{\"interval\":0,\"data\":[]}",
deviceType, deviceUuid);
}
} else {
// Log.v(TAG, "No gyroscope present!");
}
}
return success;
}
/**
* Checks IDs for the battery, screen activity, proximity, cal state, connection type, service
* state, signal strength sensors.
*
* @param deviceUuid
* @param deviceType
*
* @return true if all of the sensor IDs were found or created
*/
private boolean checkPhoneStateSensors(String deviceType, String deviceUuid) {
// preallocate objects
SensorManager sm = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
Sensor sensor;
boolean success = true;
// match battery sensor
success &= checkSensor(SensorNames.BATTERY_SENSOR, "battery state", SenseDataTypes.JSON,
SensorNames.BATTERY_SENSOR, "{\"status\":\"string\",\"level\":\"string\"}",
deviceType, deviceUuid);
// match screen activity
success &= checkSensor(SensorNames.SCREEN_ACTIVITY, SensorNames.SCREEN_ACTIVITY,
SenseDataTypes.JSON, SensorNames.SCREEN_ACTIVITY, "{\"screen\":\"string\"}",
deviceType, deviceUuid);
// match proximity
sensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (null != sensor) {
success &= checkSensor(SensorNames.PROXIMITY, SensorNames.PROXIMITY,
SenseDataTypes.FLOAT, sensor.getName(), "0.0", deviceType, deviceUuid);
} else {
// Log.v(TAG, "No proximity sensor present!");
}
TelephonyManager tm = (TelephonyManager) getContext()
.getSystemService(Context.TELEPHONY_SERVICE);
if (null != tm.getDeviceId()) {
// match call state
success &= checkSensor(SensorNames.CALL_STATE, SensorNames.CALL_STATE,
SenseDataTypes.JSON, SensorNames.CALL_STATE,
"{\"state\":\"string\",\"incomingNumber\":\"string\"}", deviceType, deviceUuid);
// match service state
success &= checkSensor(SensorNames.SERVICE_STATE, SensorNames.SERVICE_STATE,
SenseDataTypes.JSON, SensorNames.SERVICE_STATE,
"{\"state\":\"string\",\"phone number\":\"string\",\"manualSet\":true}",
deviceType, deviceUuid);
// match signal strength
success &= checkSensor(SensorNames.SIGNAL_STRENGTH, SensorNames.SIGNAL_STRENGTH,
SenseDataTypes.JSON, SensorNames.SIGNAL_STRENGTH,
"{\"GSM signal strength\":1,\"GSM bit error rate\":1}", deviceType, deviceUuid);
} else {
// Log.v(TAG, "No telephony present");
}
// match connection type
success &= checkSensor(SensorNames.CONN_TYPE, "network type", SenseDataTypes.STRING,
SensorNames.CONN_TYPE, "string", deviceType, deviceUuid);
// match ip address
success &= checkSensor(SensorNames.IP_ADDRESS, SensorNames.IP_ADDRESS,
SenseDataTypes.STRING, SensorNames.IP_ADDRESS, "string", deviceType, deviceUuid);
// match messages waiting sensor
success &= checkSensor(SensorNames.UNREAD_MSG, "message waiting", SenseDataTypes.BOOL,
SensorNames.UNREAD_MSG, "true", deviceType, deviceUuid);
// match data connection
success &= checkSensor(SensorNames.DATA_CONN, SensorNames.DATA_CONN, SenseDataTypes.STRING,
SensorNames.DATA_CONN, "string", deviceType, deviceUuid);
// match data connection
success &= checkSensor(SensorNames.DATA_CONN, SensorNames.DATA_CONN, SenseDataTypes.STRING,
SensorNames.DATA_CONN, "string", deviceType, deviceUuid);
// match installed apps sensor
success &= checkSensor(SensorNames.APP_INSTALLED, "installed apps", SenseDataTypes.JSON,
SensorNames.APP_INSTALLED, "{\"installed\":[]}", deviceType, deviceUuid);
// TODO figure out a better way to send an array of objects
// match foreground app sensor
success &= checkSensor(SensorNames.APP_FOREGROUND, "foreground app", SenseDataTypes.JSON,
SensorNames.APP_FOREGROUND, "{\"label\":\"Sense app\",\"process\":\"nl.sense_os.app\",\"activity\":\"SenseMainActivity\"}", deviceType, deviceUuid);
return success;
}
@Override
public boolean verifySensorIds(String deviceType, String deviceUuid) {
boolean success = checkAmbienceSensors(deviceType, deviceUuid);
success &= checkDeviceScanSensors(deviceType, deviceUuid);
success &= checkLocationSensors(deviceType, deviceUuid);
success &= checkMotionSensors(deviceType, deviceUuid);
success &= checkPhoneStateSensors(deviceType, deviceUuid);
success &= checkDebugSensors(deviceType, deviceUuid);
return success;
}
}