/*
* Copyright (c) 2013 The MITRE Corporation, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this work except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mitre.svmp.client;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import org.mitre.svmp.apprtc.AppRTCClient;
import org.mitre.svmp.common.Constants;
import org.mitre.svmp.common.Utility;
import org.mitre.svmp.performance.PerformanceAdapter;
import org.mitre.svmp.performance.SpanPerformanceData;
import org.mitre.svmp.protocol.SVMPProtocol;
import org.mitre.svmp.protocol.SVMPProtocol.Request;
import org.mitre.svmp.protocol.SVMPProtocol.SensorType;
import org.mitre.svmp.protocol.SVMPProtocol.Request.RequestType;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import org.mitre.svmp.services.SessionService;
public class SensorHandler implements SensorEventListener, Constants {
private static final String TAG = SensorHandler.class.getName();
private SessionService service;
private PerformanceAdapter performanceAdapter;
private SensorManager sm;
private List<Sensor> registeredSensors = new ArrayList<Sensor>(PREFERENCES_SENSORS_KEYS.length);
// track timestamp of the last update of each sensor we are tracking
private long[] lastSensorUpdate = new long[PREFERENCES_SENSORS_KEYS.length + 1];
// minimum allowed time between sensor updates in nanoseconds
private long minimumSensorDelay;
public SensorHandler(SessionService service, PerformanceAdapter performanceAdapter) {
this.service = service;
this.performanceAdapter = performanceAdapter;
this.sm = (SensorManager) service.getSystemService(Context.SENSOR_SERVICE);
// get preferences to determine which sensors we should listen to
this.minimumSensorDelay = Utility.getPrefInt(service,
R.string.preferenceKey_sensors_minimumDelay, R.string.preferenceValue_sensors_minimumDelay);
this.minimumSensorDelay *= 1000; // convert microseconds to nanoseconds
}
public void initSensors() {
Log.d(TAG, "startClient started registering listener");
// get preferences to determine which sensors we should listen to
// loop through preferences...
for( int i = 0; i < PREFERENCES_SENSORS_KEYS.length; i++ ) {
// if this sensor is enabled in the preferences, register a listener for it
if( Utility.getPrefBool(service, PREFERENCES_SENSORS_KEYS[i], PREFERENCES_SENSORS_DEFAULTVALUES[i]) )
initSensor(i+1); // sensors start at 1, not 0
}
}
public void cleanupSensors() {
Log.d(TAG,"cleanupsensors()");
for(Sensor currentSensor : registeredSensors) {
sm.unregisterListener(this,currentSensor);
}
}
private boolean initSensor(int type) {
Sensor s = sm.getDefaultSensor(type);
if (s != null) {
Log.i(TAG, "Registering for sensor: (type " + s.getType() + ") " + s.getVendor() + " " + s.getName());
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_UI);
registeredSensors.add(s);
return true;
} else {
Log.e(TAG, "Failed registering listener for default sensor of type " + type);
return false;
}
}
private long getScaledMinDelay(int index) {
long delay = minimumSensorDelay;
if( SENSOR_MINIMUM_UPDATE_SCALES.length > index && index >= 0 )
delay *= index;
return delay;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
int type = event.sensor.getType();
// make sure the time is past the minimum sensor delay, prevents spammy sensor messages
if (event.timestamp >= lastSensorUpdate[type] + getScaledMinDelay(type-1)) {
lastSensorUpdate[type] = event.timestamp;
// increment the sensor update count for performance measurement
performanceAdapter.incrementSensorUpdates();
// send the sensor request message
service.sendMessage(makeSensorRequest(event));
}
}
private Request makeSensorRequest(SensorEvent event) {
// assemble the message
SVMPProtocol.SensorEvent.Builder e = SVMPProtocol.SensorEvent.newBuilder();
e.setType(SensorType.valueOf(event.sensor.getType()));
e.setAccuracy(event.accuracy);
e.setTimestamp(event.timestamp);
List<Float> vals = new ArrayList<Float>(event.values.length);
for (float v : event.values) vals.add(v);
e.addAllValues(vals);
return Request.newBuilder()
.setType(RequestType.SENSOREVENT)
.addSensor(e) // TODO: batch sensor events
.build();
}
}