package eu.livegov.mobilesensing.manager; import java.security.acl.LastOwnerException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import eu.livegov.mobilesensing.Constants; import eu.livegov.mobilesensing.sensors.SensorService; import eu.livegov.mobilesensing.sensors.SensorValue; import eu.livegov.mobilesensing.sensors.SensorService.SensorServiceBinder; import eu.livegov.mobilesensing.sensors.SensorValueBatch; import eu.livegov.mobilesensing.sensors.accelerometer.AccelerometerSensorService; import eu.livegov.mobilesensing.sensors.gps.GpsSensorService; import eu.livegov.mobilesensing.sensors.gyroscope.GyroscopeSensorService; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * SensorManagerClass (SM) manages SensorServices * * The SM... * * * ..is a "started" service which runs in the background even when * MainActivity is closed. * * * ...starts and stops SensorServices. They are connected via the * "Bind Service" approach * * * ...communicates with the GUI via Intents * * * ...aggregates data from the Sensors * * * ...writes aggregated data to the file system * * @author hartmann * */ public class SensorManager extends Service implements SensorManagerInterface { // CONSTANTS public static final String LOG_TAG = Constants.LOG_TAG; public static final String ACTION_BIND = "BIND"; public static final String ACTION_UNBIND = "UNBIND"; public static final String ACTION_START_RECORDING = "START_RECORDING"; public static final String ACTION_STOP_RECORDING = "STOP_RECORDING"; public static final String ACTION_STORE_DATA = "WRITE_DATA"; public static final String ACTION_SEND_SENSOR_VALUES = "SEND_VALUES"; public static final String ACTION_STATUS = "STATUS"; public static final String INTENT_SENSOR_VALUES = "eu.livegov.mobilesensor.SENSOR_VALUE_INTENT"; // STATICS public static boolean running = false; /** * List of sensors available in the Framework */ private static List<SensorDescription> availableSensors = new LinkedList<SensorDescription>(); public static Map<String,SensorDescription> getSensorDescription = new HashMap<String,SensorDescription>(); /* * Static Initialization * * Add available sensors to sensor list */ static { // Generate list of available sensors addAvailableSensor(AccelerometerSensorService.class); addAvailableSensor(GpsSensorService.class); addAvailableSensor(GyroscopeSensorService.class); } private static void addAvailableSensor(Class<? extends SensorService> sensorClass){ SensorDescription desc = new SensorDescription(sensorClass); availableSensors.add(desc); getSensorDescription.put(desc.getSensorName(), desc); Log.i(LOG_TAG,"Added sensor "+desc.getSensorName()+" to availableSensors"); } /* * SensorManager Startup */ @Override public IBinder onBind(Intent intent) { // Sensor Manager cannot be bound. return null; } @Override public void onCreate() { super.onCreate(); Log.i(LOG_TAG, "Sensor Manager started"); running = true; } @Override public void onDestroy() { super.onDestroy(); unbindAllSensorServices(); Log.i(LOG_TAG, "Sensor Manager stopped"); running = false; } /** * Intent Handling */ @Override public int onStartCommand(Intent intent, int flags, int startId) { String action = intent.getAction(); if (action == null) { Log.i(LOG_TAG, "Called SensorManager without action"); return super.onStartCommand(intent, flags, startId); } Log.i(LOG_TAG, "Called SensorManager with action " + action); // Handle action requests if (action.equals(ACTION_BIND)) { bindAllSensorSerives(); } else if (action.equals(ACTION_UNBIND)){ unbindAllSensorServices(); } else if (action.equals(ACTION_START_RECORDING)){ startRecording(); } else if (action.equals(ACTION_STOP_RECORDING)) { stopRecording(); } else if (action.equals(ACTION_STATUS)) { statusAll(); } else if (action.equals(ACTION_STORE_DATA)){ storeData(); } else if (action.equals(ACTION_SEND_SENSOR_VALUES)) { getLastValues(); sendLastValues(); } else { Log.e(LOG_TAG,"Unimplemented Action " + action); } return super.onStartCommand(intent, flags, startId); } /* * Manage Sensor Bindings */ private void bindSensorService(SensorDescription desc) { if (desc.isBound()) return; Log.i(LOG_TAG, "Binding sensor " + desc.getSensorName() ); ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder binder) { registerSensorServiceObject(this, name, binder); } @Override public void onServiceDisconnected(ComponentName name) { // SensorService crashed hard String fullName = name.getClassName(); String sensorName = fullName.substring(fullName.lastIndexOf('.') + 1); Log.i(LOG_TAG,"Service crashed" + sensorName); getSensorDescription.get(sensorName).crashed(); } }; Log.i(LOG_TAG,"Binding " + desc.getSensorName() + " with " + serviceConnection); bindService( new Intent(this, desc.getServiceClass()), serviceConnection, BIND_AUTO_CREATE ); } private void registerSensorServiceObject( ServiceConnection serviceConnection, ComponentName name, IBinder iBinder){ SensorServiceBinder binder = (SensorServiceBinder) iBinder; SensorService sensorService = binder.getService(); String sensorName = sensorService.getClass().getSimpleName(); if (!binder.startupSuccess) { Log.i(LOG_TAG,"SensorStartup " + sensorName + " unusccesfull. Unbinding."); unbindService(serviceConnection); return; } // Lookup and Update description update SensorDescription desc = getSensorDescription.get(sensorName); if (desc != null) { desc.setServiceObject(sensorService); desc.setServiceConnection(serviceConnection); Log.i(LOG_TAG,"Sensor " + sensorName + " registered."); } else { Log.i(LOG_TAG,"Sensor " + sensorName + " not found in LookupMap. Unbinding."); unbindService(serviceConnection); } } private void bindAllSensorSerives(){ for (SensorDescription desc : availableSensors){ bindSensorService(desc); } } private void unbindSensorService(SensorDescription desc) { if (desc.isBound()) { Log.i(LOG_TAG,"Unbindung "+desc.getSensorName()); desc.unbind(this); } } private void unbindAllSensorServices(){ for (SensorDescription desc : availableSensors){ unbindSensorService(desc); } } // ////////////// METHODS FOR SENSOR HANDLING /////////////////// @Override public List<String> statusAll() { Log.i(LOG_TAG, "Status All: " + availableSensors.size()); List<String> sensorStatusList = new ArrayList<String>(); for (SensorDescription desc : availableSensors) { Log.i(LOG_TAG, "Service " + desc.getSensorName() + "Status " + desc.getStatus() ); } return sensorStatusList; } @Override public void setConfig(SensorManagerConfig config) { // TODO Auto-generated method stub } @Override public void startRecording() { for (SensorDescription desc : availableSensors) { if (desc.isBound()) { desc.getServiceObject().startRecording(); } } } @Override public void stopRecording() { for (SensorDescription desc : availableSensors) { if (desc.isBound()){ desc.getServiceObject().stopRecording(); } } } @Override public void storeData() { // TODO Auto-generated method stub } /** * Broadcast Last received SensorValues * used for display in GUI */ private void sendLastValues() { Log.i(LOG_TAG,"Broadcasting last values"); String out = ""; for (SensorValue v: getLastValues()){ out += v.toString() + "\n"; } Intent valueIntent = new Intent(INTENT_SENSOR_VALUES); valueIntent.putExtra("Value", out); sendBroadcast(valueIntent); } @Override public List<SensorValue> getLastValues() { LinkedList<SensorValue> Values = new LinkedList<SensorValue>(); for (SensorDescription desc : availableSensors) { if (desc.isRecording()) { Values.add(desc.getServiceObject().getLastValue()); Log.i(LOG_TAG, "lastValue " + desc.getServiceObject().getLastValue().toString()); } } return Values; } public List<SensorValueBatch> pullAllValues() { LinkedList<SensorValueBatch> Batches = new LinkedList<SensorValueBatch>(); for (SensorDescription desc : availableSensors) { if (desc.isRecording()) { SensorValueBatch batch = new SensorValueBatch(); batch.values = (List<SensorValue>) desc.getServiceObject().pullData(); batch.meta = desc.getServiceObject().getMetadata(); } } return Batches; } }