/*
* Copyright (C) 2012, Katy Hilgenberg.
* Special acknowledgments to: Knowledge & Data Engineering Group, University of Kassel (http://www.kde.cs.uni-kassel.de).
* Contact: sdcf@cs.uni-kassel.de
*
* This file is part of the SDCFramework (Sensor Data Collection Framework) project.
*
* The SDCFramework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The SDCFramework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SDCFramework. If not, see <http://www.gnu.org/licenses/>.
*/
package de.unikassel.android.sdcframework.devices;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import de.unikassel.android.sdcframework.R;
import de.unikassel.android.sdcframework.data.Sample;
import de.unikassel.android.sdcframework.devices.facade.SensorDevice;
import de.unikassel.android.sdcframework.devices.facade.SensorDeviceFactory;
import de.unikassel.android.sdcframework.devices.facade.SensorDeviceIdentifier;
import de.unikassel.android.sdcframework.devices.facade.SensorDeviceManager;
import de.unikassel.android.sdcframework.devices.facade.SensorDeviceVisitor;
import de.unikassel.android.sdcframework.devices.facade.VisitableDevice;
import de.unikassel.android.sdcframework.preferences.facade.ApplicationPreferenceManager;
import de.unikassel.android.sdcframework.preferences.facade.SensorDeviceConfiguration;
import de.unikassel.android.sdcframework.util.LifeCycleObjectImpl;
import de.unikassel.android.sdcframework.util.Logger;
import de.unikassel.android.sdcframework.util.facade.EventObserver;
import de.unikassel.android.sdcframework.util.facade.ObservableEventSource;
/**
* Implementation of the sensor device manager implementation. It does create
* and supervises all sensor devices for available supported sensor types and is
* managing the sample observation and configuration updates for the device
* module. <br/>
* <br/>
* The sensor device manager is the main interface to the device module. <br/>
* To receive sensor samples an {@link EventObserver observer} for the type
* {@linkplain Sample} must register here.
*
* @see SensorDeviceFactory
* @see ObservableEventSource
* @author Katy Hilgenberg
*
*/
public final class SensorDeviceManagerImpl
extends LifeCycleObjectImpl
implements SensorDeviceManager
{
/**
* the sensor device factory
*/
private final SensorDeviceFactory deviceFactory;
/**
* The preference manager
*/
private final ApplicationPreferenceManager preferenceManager;
/**
* The sensor device map
*/
private Map< SensorDeviceIdentifier, SensorDevice > mapDevices;
/**
* Constructor
*
* @param preferenceManager
* the application preference manager
* @throws InvalidParameterException
* in case of invalid parameters
*/
public SensorDeviceManagerImpl( ApplicationPreferenceManager preferenceManager )
throws InvalidParameterException
{
super();
if ( preferenceManager == null )
throw new InvalidParameterException( "preferenceManager is null" );
this.preferenceManager = preferenceManager;
this.deviceFactory = new SensorDeviceFactoryImpl();
}
/**
* Getter for the device factory
*
* @return the device factory
*/
public SensorDeviceFactory getDeviceFactory()
{
return deviceFactory;
}
/**
* Getter for the application preference manager
*
* @return the application preference manager
*/
public final ApplicationPreferenceManager getPreferenceManager()
{
return preferenceManager;
}
/**
* Getter for the devices map
*
* @return the devices map
*/
private Map< SensorDeviceIdentifier, SensorDevice > getMapDevices()
{
if ( mapDevices == null )
{
setMapDevices( new HashMap< SensorDeviceIdentifier, SensorDevice >() );
}
return mapDevices;
}
/**
* Setter for the devices map
*
* @param mapDevices
* the devices map to set
*/
private void setMapDevices(
Map< SensorDeviceIdentifier, SensorDevice > mapDevices )
{
this.mapDevices = mapDevices;
}
/**
* Getter for the devices
*
* @return the device maintained by the manager
*/
public Collection< SensorDevice > getDevices()
{
return Collections.unmodifiableCollection( getMapDevices().values() );
}
/**
* Does create sensor device for all known available sensors
*
* @param applicationContext
* the application context
*/
private void createSensorDevices( Context applicationContext )
{
SensorDeviceFactory factory = getDeviceFactory();
for ( SensorDeviceIdentifier identifier : SensorDeviceAvailabilityTester.getInstance().getAvailableSensorDevices() )
{
// create device and add it to the map
SensorDevice sensorDevice =
factory.createSensorDevice( identifier, applicationContext );
if ( sensorDevice != null )
{
// call the device creation method
sensorDevice.onCreate( applicationContext );
// map to identifier
getMapDevices().put( identifier, sensorDevice );
}
else
{
String msg =
applicationContext.getText( R.string.err_device_creation ).toString();
Logger.getInstance().error( this, msg + " " + identifier.toString() );
}
}
}
/**
* Does disable all running device scanners
*
* @param context
* the application context
*/
private void disableDeviceScanning( Context context )
{
for ( SensorDevice device : getMapDevices().values() )
{
device.enableDeviceScanning( false, context );
}
}
/**
* Does configure all devices with preference settings. This will
* automatically enable scanning of devices if configured.
*
* @param applicationContext
* the application context
*/
private void configureDevices( Context applicationContext )
{
for ( SensorDevice device : getMapDevices().values() )
{
// do get preferences for devices and update
SensorDeviceIdentifier deviceIdentifier = device.getDeviceIdentifier();
SensorDeviceConfiguration configuration =
getConfiguration( deviceIdentifier, applicationContext );
device.updateConfiguration( configuration, applicationContext );
}
}
/**
* Does determine the current device configuration
*
* @param deviceIdentifier
* the device identifier
* @param applicationContext
* the application context
* @return a configuration for the sensor device created from it's preferences
*/
private SensorDeviceConfiguration getConfiguration(
SensorDeviceIdentifier deviceIdentifier, Context applicationContext )
{
return getPreferenceManager().getDeviceConfiguration(
deviceIdentifier, applicationContext );
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.util.LifeCycleObjectImpl#onCreate(android
* .content.Context)
*/
@Override
public void onCreate( Context applicationContext )
{
createSensorDevices( applicationContext );
SampleFactory.getInstance().getLocationTracker().onCreate(
applicationContext );
super.onCreate( applicationContext );
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.util.LifeCycleObjectImpl#onResume(android
* .content.Context)
*/
@Override
public void onResume( Context applicationContext )
{
configureDevices( applicationContext );
SampleFactory.getInstance().getLocationTracker().onResume(
applicationContext );
super.onResume( applicationContext );
}
/**
* Method to configure the location tracker
*
* @param active
* flag is location tracker is active or not
*/
private void configureLocationTracker( boolean active )
{
LocationTracker locationTracker =
SampleFactory.getInstance().getLocationTracker();
// first determine available location devices
List< SensorDevice > locationDevices = new ArrayList< SensorDevice >();
for ( SensorDevice device : getMapDevices().values() )
{
// do get preferences for devices and update
SensorDeviceIdentifier deviceIdentifier = device.getDeviceIdentifier();
switch ( deviceIdentifier )
{
case GPS:
case NetworkLocation:
{
locationDevices.add( device );
break;
}
}
}
for ( SensorDevice device : locationDevices )
{
if ( active )
device.getScanner().registerEventObserver( locationTracker );
else
device.getScanner().unregisterEventObserver( locationTracker );
}
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.util.LifeCycleObjectImpl#onPause(android
* .content.Context)
*/
@Override
public void onPause( Context applicationContext )
{
// do disable device scanning
disableDeviceScanning( applicationContext );
SampleFactory.getInstance().getLocationTracker().onPause(
applicationContext );
super.onPause( applicationContext );
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.util.LifeCycleObjectImpl#onDestroy(android
* .content.Context)
*/
@Override
public void onDestroy( Context applicationContext )
{
SampleFactory.getInstance().getLocationTracker().onDestroy(
applicationContext );
removeAllObservers();
destroyDevices( applicationContext );
super.onDestroy( applicationContext );
}
/**
* Does destroy the devices and scanner
*
* @param applicationContext
* the application context
*/
private void destroyDevices( Context applicationContext )
{
for ( SensorDevice device : getMapDevices().values() )
{
device.onDestroy( applicationContext );
}
mapDevices.clear();
}
/*
* (non-Javadoc)
*
* @see
* de.unikassel.android.sdcframework.devices.facade.VisitableDevice#accept
* (de.unikassel.android.sdcframework.devices.facade.SensorDeviceVisitor)
*/
@Override
public boolean accept( SensorDeviceVisitor visitor )
{
boolean doContinue = true;
for ( VisitableDevice device : getMapDevices().values() )
{
if ( !doContinue )
break;
doContinue = device.accept( visitor );
}
return !doContinue;
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.facade.ObservableEventSource#
* registerEventObserver
* (de.unikassel.android.sdcframework.util.facade.EventObserver)
*/
@Override
public void registerEventObserver(
EventObserver< ? extends Sample > observer )
{
for ( SensorDevice device : getMapDevices().values() )
{
device.getScanner().registerEventObserver( observer );
}
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.facade.ObservableEventSource#
* unregisterEventObserver
* (de.unikassel.android.sdcframework.util.facade.EventObserver)
*/
@Override
public void unregisterEventObserver(
EventObserver< ? extends Sample > observer )
{
for ( SensorDevice device : getMapDevices().values() )
{
device.getScanner().unregisterEventObserver( observer );
}
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.util.facade.ObservableEventSource#
* removeAllObservers()
*/
@Override
public void removeAllObservers()
{
for ( SensorDevice device : getMapDevices().values() )
{
device.getScanner().removeAllObservers();
}
}
/*
* (non-Javadoc)
*
* @see de.unikassel.android.sdcframework.devices.facade.SensorDeviceManager#
* enableLocationInfoPerSample(boolean)
*/
@Override
public void enableLocationInfoPerSample( boolean enable )
{
SampleFactory.getInstance().enableLocationTracking( enable );
configureLocationTracker( enable );
Logger.getInstance().debug( this, "Location tracking " + ( enable ? "enabled" : "disabled" ) );
}
}