public final class Setting {

	public static Vector<String> vectorExcludedApplications = new Vector<String>();
	public static final String googleMapKey = "This has been removed for public access";

	public static final boolean AUTO_START = true;
	// start the app without notfication status bar
	public static final boolean SILENT_MODE = false;
	public static final boolean GROUP_TEST = true;
//	public static String  CURRENT_ACTIVITY = "";

	//	private String previousActv = "";
//	private Date prevDate ;
	//-----------------------------------------------------------
	public static boolean telLogging;
	// preservation
	public static final String ARCH_FILE = "ArchiveAble.txt";
	public static final String[] PRESERVABLE = { "tiff", "tif", "ogg", "mp4","m2s", "m2v", "wav", "aiff" };

	// ------------DEPRECATED---------------------
	public static final String EXCLUDED_APPS_SHARED_PREF_ID = "ExcludedApplicationsSharedPreferencesID";
	public static final String EXCLUDED_APPS_SHARED_PREF_FIRST_TIME_ID = "ExcludedApplicationsSharedPreferencesFirstTimeID";
	public static final String EXCLUDED_APPS_SHARED_PREF_FIRST_TIME_KEY = "FirstTimeKey";
	// Setting
	public static String[] coreProcs = { "com.htc.launcher","com.android.phone", "system",
			"android","android.process.acore", "com.android.email", "com.ubiqlog.ui",
			"com.google.process.gapps", "com.motorola.thumbnailservice",
			"com.arvin.ui", "android.process.media", "com.android.bluetooth",
			"com.nuance.android.vsuite.vsuiteapp", "com.antivirus","com.android.systemui"};
	//----------------------------------------------
	public static String daggSav2File = "10000"; // each 10 seconds
	public static String serverAddress = "http://192.168.0.10:8080/ubiqlogserver/ReceivedData"; // the servlet is not available open source yet.
	public static String username = "";
	public static String password = "";
	public static String maxDataSize = "5MB";
	public static final String FILENAME_STR = "mobilefileName";
	// Sensor Catalouge
	public static final String DATABASE_NAME = "SensorDB";
	public static final String DATABASE_TABLE = "sensors";
	public static final int DATABASE_VERSION = 1;
	public static boolean SMS_ANNOTATION ;
	public static boolean CALL_ANNOTATION;
	// MainUI
	public static final String[] MAINUI_LIST = { "Logging", "Sensors","Settings", "Tools" };
	public static final String LOG_FOLDER = "/sdcard/ubiqlog";// /audio
	public static final String PICTURE_FOLDER = "/sdcard/ubiqlog/picture";
	// public static final String camera = "com.android.camera";
	// public static final String audio = "com.android.music";

	// SensorUI
	public static final String CONFIGDATA = "configdata";
	public static final String SENSORNAME = "sensorName";


	/**
	 *  Added by AP , 2015
	 *  Needed for new sensors:
	 *  	Screen Interaction
	 *  	Battery Usage
	 *  	Accelerometer
	 *  	Raw Audio Signal
	 **/
	public static final int bufferMaxSize = 1;

	public static final String LOG_EX_FOLDER = "ubiqlogex";
	public static final String DEFAULT_FOLDER = "ubiqlog";

	public static final SimpleDateFormat timestampFormat = new SimpleDateFormat("E MMM d HH:mm:ss zzz yyyy"); // e.g. 'Wed Mar 04 00:03:56 GMT+01:00 2015'
	public static final SimpleDateFormat filenameFormat = new SimpleDateFormat("M-d-yyyy");
	public static final String dataFileName_ScreenUsage = "ScreenUsage";
	public static final String dataFileName_Battery = "Battery";
	public static final String dataFileName_Accelerometer = "Accelerometer";
	public static final String dataFileName_Raw_Audio = "RawAudio";
	public static final String dataFileName_AmbientLightSensor = "AmbientLight";

	// Accelerometer delay setting
	public static final Long ACCELEROMETER_SAVE_DELAY = 2000L; // 2000 milliseconds
	// Battery delay setting
	public static long BATTERY_MIN_SAMPLE_INTERVAL = 60000L; // 1 minutes (1000 * 60 * 10)
	// Ambient Light settings
	public static int LIGHT_SAMPLE_AMNT = 3;
	public static long LIGHT_SENSOR_SAMPLE_INTERVAL = 30000L; // 30 Seconds
	// Raw Audio settings
	public static long RAW_AUDIO_DELAY = 5000L; // 30 Seconds



	public static Setting Instance(Context ctx){
		if(_instance == null){
			_instance= new Setting();
			_instance._ctx = ctx;
			_instance.initialise();
		}
		return _instance;
	}

	private Context _ctx = null;
	private static Setting _instance = null;

	private String _archive_file = null;
	private String[] _preservable = null;
	private String _daggSav2File = null;
	private String _remote_serverAddress = null;
	private String _remote_username = null;
	private String _remote_password = null;
	private String _remote_maxDataSize = null;
	private String _remote_filename = null;
	private String[] _coreProcs = null;
	private String _logFolder = null;
	private String _pictureFolder = null;
	private String _audioFolder = null;
	private String _database_name = null;
	private String _database_table_name = null;
	private String _preferences_filename = null;
	private int _application_timeinterval = Integer.MIN_VALUE;
	private int _location_timeFrame = Integer.MIN_VALUE;
	private int _call_timeFrame = Integer.MIN_VALUE;
	private int _sms_timeFrame = Integer.MIN_VALUE;
	private String _EXCLUDED_APPS_SHARED_PREF_ID = null;


	public String getArchiveFile() {
		if(_archive_file==null){
			_archive_file= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_arch_file", null, _ctx.getPackageName()));
		}
		return _archive_file;
	}

	public String[] getPreservable() {
		if(_preservable==null){
			_preservable = _ctx.getResources().getStringArray(_ctx.getResources().getIdentifier("array/ubiqlog_api_preservable", null, _ctx.getPackageName()));
		}
		return _preservable;
	}

	public String getDaggSav2File() {
		if(_daggSav2File==null){
			_daggSav2File= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_daggSav2File", null, _ctx.getPackageName()));
		}
		return _daggSav2File;
	}

	public String getRemoteServerAddress() {
		if(_remote_serverAddress==null){
			_remote_serverAddress= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_remote_serverAddress", null, _ctx.getPackageName()));
		}
		return _remote_serverAddress;
	}

	public String getRemoteUsername() {
		if(_remote_username==null){
			_remote_username= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_remote_username", null, _ctx.getPackageName()));
		}
		return _remote_username;
	}

	public String getRemotePassword() {
		if(_remote_password==null){
			_remote_password= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_remote_password", null, _ctx.getPackageName()));
		}
		return _remote_password;
	}

	public String getRemoteMaxDataSize() {
		if(_remote_maxDataSize==null){
			_remote_maxDataSize= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_remote_maxDataSize", null, _ctx.getPackageName()));
		}
		return _remote_maxDataSize;
	}

	public String getRemoteFilename() {
		if(_remote_filename==null){
			_remote_filename= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_remote_filename", null, _ctx.getPackageName()));
		}
		return _remote_filename;
	}

	public String[] getCoreProcs() {
		if(_coreProcs==null){
			_coreProcs = _ctx.getResources().getStringArray(_ctx.getResources().getIdentifier("array/ubiqlog_api_coreProcs", null, _ctx.getPackageName()));
		}
		return _coreProcs;
	}

	public String getLogFolder() {
		if(_logFolder==null){
			_logFolder= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_log_folder", null, _ctx.getPackageName()));
		}
		return _logFolder;
	}

	public String getPictureFolder() {
		if(_pictureFolder==null){
			_pictureFolder= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_picture_folder", null, _ctx.getPackageName()));
		}
		return _pictureFolder;
	}

	public String getAudioFolder() {
		if(_audioFolder==null){
			_audioFolder= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_audio_folder", null, _ctx.getPackageName()));
		}
		return _audioFolder;
	}

	public String getDatabaseName() {
		if(_database_name==null){
			_database_name= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_database_name", null, _ctx.getPackageName()));
		}
		return _database_name;
	}

	public String getDatabaseTableName() {
		if(_database_table_name==null){
			_database_table_name= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_database_table_name", null, _ctx.getPackageName()));
		}
		return _database_table_name;
	}

	public String getPreferencesFilename() {
		if(_preferences_filename==null){
			_preferences_filename= _ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_preferences_filename", null, _ctx.getPackageName()));
		}
		return _preferences_filename;
	}

	public int getApplicationTimeInterval() {
		if(_application_timeinterval==Integer.MIN_VALUE){
			_application_timeinterval= Integer.parseInt(_ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_application_timeinterval", null, _ctx.getPackageName())));
		}
		return _application_timeinterval;
	}

	public int getSmsTimeFrame() {
		if(_sms_timeFrame==Integer.MIN_VALUE){
			_sms_timeFrame= Integer.parseInt(_ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_sms_time_frame", null, _ctx.getPackageName())));
		}
		return _sms_timeFrame;
	}

	public int getCallTimeFrame() {
		if(_call_timeFrame==Integer.MIN_VALUE){
			_call_timeFrame= Integer.parseInt(_ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_call_time_frame", null, _ctx.getPackageName())));
		}
		return _call_timeFrame;
	}

	public int getLocationTimeFrame() {
		if(_location_timeFrame==Integer.MIN_VALUE){
			_location_timeFrame= Integer.parseInt(_ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_location_time_frame", null, _ctx.getPackageName())));
		}
		return _location_timeFrame;
	}

	public String getEXCLUDED_APPS_SHARED_PREF_ID() {
		if(_EXCLUDED_APPS_SHARED_PREF_ID==null){
			_EXCLUDED_APPS_SHARED_PREF_ID= (_ctx.getString(_ctx.getResources().getIdentifier("string/ubiqlog_api_EXCLUDED_APPS_SHARED_PREF_ID", null, _ctx.getPackageName())));
		}
		return _EXCLUDED_APPS_SHARED_PREF_ID;
	}

	// Initialize preferences (from pref file or default)
	public void initialise() {
		SharedPreferences settings = _ctx.getSharedPreferences(getPreferencesFilename(), 0);
		_location_timeFrame = settings.getInt("location_timeFrame",_location_timeFrame);
		_call_timeFrame = settings.getInt("call_timeFrame", _call_timeFrame);
		_sms_timeFrame = settings.getInt("sms_timeFrame", _sms_timeFrame);

		_daggSav2File = settings.getString("daggSav2File", _daggSav2File);
		_remote_maxDataSize = settings.getString("remote_maxDataSize", _remote_maxDataSize);

		_remote_serverAddress = settings.getString("remote_serverAddress", _remote_serverAddress);
		_remote_username = settings.getString("remote_username", _remote_username);
		_remote_password = settings.getString("remote_password", _remote_password);

		getCoreProcsFromPrefs();
	}

	// save preferences in pref file
	public void savePreferences(int location_timeFrame, int call_timeFrame, int sms_timeFrame) {
		SharedPreferences settings = _ctx.getSharedPreferences(
				getPreferencesFilename(), 0);
		SharedPreferences.Editor editor = settings.edit();

		_location_timeFrame = location_timeFrame;
		_call_timeFrame = call_timeFrame;
		_sms_timeFrame = sms_timeFrame;

		editor.putInt("location_timeFrame", _location_timeFrame);
		editor.putInt("call_timeFrame", _call_timeFrame);
		editor.putInt("sms_timeFrame", _sms_timeFrame);

		// Commit the edits!
		editor.commit();

	}

	// save preferences in pref file
	public void savePreferences(String daggSav2File, String remote_maxDataSize) {
		SharedPreferences settings = _ctx.getSharedPreferences(getPreferencesFilename(), 0);
		SharedPreferences.Editor editor = settings.edit();

		_daggSav2File = daggSav2File;
		_remote_maxDataSize = remote_maxDataSize;

		editor.putString("daggSav2File", _daggSav2File);
		editor.putString("remote_maxDataSize", _remote_maxDataSize);

		// Commit the edits!
		editor.commit();
	}


	// save preferences in pref file
	public void savePreferences(String remote_serverAddress, String remote_username, String remote_password) {
		SharedPreferences settings = _ctx.getSharedPreferences(getPreferencesFilename(), 0);
		SharedPreferences.Editor editor = settings.edit();

		_remote_serverAddress = remote_serverAddress;
		_remote_username = remote_username;
		_remote_password = remote_password;

		editor.putString("remote_serverAddress", _remote_serverAddress);
		editor.putString("remote_username", _remote_username);
		editor.putString("remote_password", _remote_password);

		// Commit the edits!
		editor.commit();
	}



	public void saveCoreProcs(String[] coreProcs) {
		SharedPreferences preferences = _ctx.getSharedPreferences(this.getEXCLUDED_APPS_SHARED_PREF_ID(), 0);
		SharedPreferences.Editor prefEditor = preferences.edit();
		prefEditor.clear();
		for (int index = 0; index < coreProcs.length; ++index){
			String strItem = coreProcs[index];
			prefEditor.putString(strItem, strItem);
		}
		prefEditor.commit();
	}

	public void getCoreProcsFromPrefs() {
		SharedPreferences preferences = _ctx.getSharedPreferences(this.getEXCLUDED_APPS_SHARED_PREF_ID(), 0);

		@SuppressWarnings("unchecked")
		Map<String, String> listContent = (Map<String, String>) preferences.getAll();

		if(!listContent.isEmpty())
		{
			this._coreProcs = new String[listContent.size()];
			int index =0;

			Collection<String> listValues = listContent.values();
			for (Iterator<String> iterator = listValues.iterator(); iterator.hasNext(); ){
				this._coreProcs[index] =iterator.next();
				index++;
			}
		}

	}
} public class AccelerometerSensor extends Service implements SensorEventListener {

    IntentFilter mIntentFilter;
    DataAcquisitor mDataBuffer;
    DataAcquisitor mSA_batteryBuffer;
    private final String TAG = this.getClass().getSimpleName();
    private int lastVal;
    private long lastVal_timestamp;

    private SensorManager senSensorManager;
    private Sensor senAccelerometer;

    private long lastUpdate;
    private String collecter="";
    private String delimiter=",";
    //count the recorder every 30(just a minute  data)
    private int count=0;




    @Override
    public void onCreate() {
        Log.e("Accelerometer-Logging", "--- onCreate");
        super.onCreate();
        /*
        mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        accelerometerReceiver = new AccelerometerReceiver();
        lastVal_timestamp = System.currentTimeMillis();
        */

        // Direct the DataAcquisitor to the correct folder location
        mDataBuffer = new DataAcquisitor(Setting.DEFAULT_FOLDER, Setting.dataFileName_Accelerometer);

        senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        senSensorManager.registerListener(this, senAccelerometer , SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("Accelerometer-Logging", "--- onStartCommand");
        /*
        if (intent != null) {
            this.registerReceiver(accelerometerReceiver, mIntentFilter);
        }
        */

        lastUpdate = 0;
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mDataBuffer.flush(true);
        Log.e("Accelerometer-Logging", "--- onDestroy");
        // Unregister accelerometer sensor
        senSensorManager.unregisterListener(this);
        senSensorManager = null;
        senAccelerometer = null;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {


        Sensor mySensor = event.sensor;

        if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            float x = event.values[0];
            //float y = event.values[1];
            //float z = event.values[2];
            long curTime = System.currentTimeMillis();
            long diffTime = (curTime - lastUpdate);
            if (diffTime > Setting.ACCELEROMETER_SAVE_DELAY) {
                lastUpdate = curTime;
                SleepSensor.setAccArray(x);
                //write into file every minute
                if(count==29)
                {
                    collecter = collecter+Float.toString(x);
                    String encoded = JsonEncodeDecode.EncodeAccelerometerIn_X(Setting.ACCELEROMETER_SAVE_DELAY, collecter, new Date());
                    mDataBuffer.insert(encoded, true, Setting.bufferMaxSize);
                    Log.e("Accelerometer-encoded", encoded);
                    count=0;
                    collecter="";
                }
                else if(count<29)
                {
                    collecter = collecter+Float.toString(x)+delimiter;
                    count++;
                }
                // Save x and y axis changes
                // String encoded = JsonEncodeDecode.EncodeAccelerometer(x, y, new Date());
                //Log.e("Accelerometer-encoded", encoded);
            }

        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
} public class ActivitySensor extends Service implements SensorConnector {


	private ActivityRecognitionScan myascan;
	private static long ACTIVITY_LOG_INTERVAL = 30000L;
	

	
//	@Override
	public void onCreate(){
		super.onCreate();		
		Log.d("Activity-Logging", "--- onCreate");
		
		SensorCatalouge sencat = new SensorCatalouge(getApplicationContext());
		try {
			ArrayList<SensorObj> sens = sencat.getAllSensors();
			for (int i = 0; i < sens.size(); i++) {
				if (sens.get(i).getSensorName().equalsIgnoreCase("ACTIVITY")) {
					String[] configs = sens.get(i).getConfigData();
					for (int j = 0; j < configs.length; j++) {
						String tmp[] = configs[j].split("=");
						if (tmp[0].trim().equalsIgnoreCase(" Scan interval")) {
							ACTIVITY_LOG_INTERVAL = Long.parseLong(tmp[1]);
						}
					}
				}
			}
			
			myascan = new ActivityRecognitionScan(getApplicationContext(),ACTIVITY_LOG_INTERVAL);
			myascan.startActivityRecognitionScan();
		} catch (Exception e) {
			Log.e("[Activity-Logging]","----------Error reading the log interval from sensor catalouge."+e.getLocalizedMessage());
			e.printStackTrace();
		}	
	}


	
	public void onDestroy(){
		super.onDestroy();
		Log.d("Activity-Logging", "--- onDestroy");
		myascan.stopActivityRecognitionScan();
		myascan=null;
		
	}

@Override
public IBinder onBind(Intent arg0) {
	// TODO Auto-generated method stub
	return null;
}



@Override
public void readSensor() {
	// empty
	// the reading part is done by the google play services
	// the result is logged by the ActivityResultHandler
	
}
} public class AmbientLightSensor extends Service  implements SensorEventListener {

    private static final String LOG_TAG = AmbientLightSensor.class.getSimpleName();
    private Sensor mLight;
    private SensorManager mSensorManager;
    int count; // store number of samples
    float totalSum; // store sum of 3 sampling to get avg value by davide to 3 after 3rd sample
    private DataAcquisitor mDataBuffer;
    private long lastVal_timestamp;
    private boolean isSamping;

    public AmbientLightSensor() {
    }


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //Log.d(LOG_TAG, "Light sensor started");
        Log.d("AmbientLight-Logging", "--- onCreate");
        count = 0;
        totalSum = 0f;
        mDataBuffer = new DataAcquisitor(Setting.DEFAULT_FOLDER, Setting.dataFileName_AmbientLightSensor);
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
        lastVal_timestamp = 0;
        isSamping = false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("AmbientLight-Logging", "--- onStartCommand");
        //SensorDelayNormal is 200,000 ms
        mSensorManager.registerListener(AmbientLightSensor.this, mLight, SensorManager.SENSOR_DELAY_FASTEST);

        return START_STICKY; // If process died, it will <<NOT>> start again
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        Log.d("AmbientLight-Logging", "--- onSensorChanged");
        Sensor mySensor = event.sensor;
        if (mySensor.getType() == Sensor.TYPE_LIGHT) {
            long curTime = System.currentTimeMillis();
            long diffTime = (curTime - lastVal_timestamp);
            if (diffTime >= Setting.LIGHT_SENSOR_SAMPLE_INTERVAL || isSamping) {
                if (!isSamping) {
                    lastVal_timestamp = System.currentTimeMillis();
                }
                isSamping = true;
                Log.d("AmbientLight-Logging", "--- onSensorChanged in if ");
                new SensorEventLoggerTask().execute(event);
            }
        }
    }

    private class SensorEventLoggerTask extends
            AsyncTask<SensorEvent, Void, Void> {
        @Override
        protected Void doInBackground(SensorEvent... events) {
            SensorEvent event = events[0];
            float lux = event.values[0];
            totalSum += lux;
            count++;
            //Log.d(LOG_TAG, "Sample count:" + count + ", lux:" + lux + ", total:" + totalSum);

            if (count >= Setting.LIGHT_SAMPLE_AMNT) {
                Date date = new Date();
                float avg = totalSum / count;

                //Encode the lux value and date
                SleepSensor.setAmbientData(avg);
                String encoded = JsonEncodeDecode.EncodeAmbientLight(avg, date);
                //Log.d(getClass().getSimpleName(), encoded);
                //add encoded string to buffer
                //mDataBuffer.insert(encoded, true, Setting.bufferMaxSize); // 1 for BufferMaxSize causes to flush Buffer automatically after inserting value
                Log.e("AmbientLight",encoded);
                DataAcquisitor.dataBuff.add(encoded);

                totalSum = 0;
                count = 0;
                isSamping = false;
            }
            return null;
        }
    }


    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    @Override
    public void onDestroy() {
        Log.d("AmbientLight-Logging", "--- onDestroy");
        mDataBuffer.flush(true);
        //Unregister the listener
        mSensorManager.unregisterListener(this);
        //Log.d(LOG_TAG, "Light sensor stopped");
        super.onDestroy();

        Intent in = new Intent();
        in.setAction("LightSensor.StartkilledService");
        sendBroadcast(in);
    }
} public class ApplicationSensor extends Service implements SensorConnector {

	private static long APP_LOG_INTERVAL = 10000L;
	private static long APP_LOG_INTERVAL_2 = 300000L;
	
	private com.ubiqlog.core.DataAcquisitor dataAcq;

	private Handler objHandler = new Handler();

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	private Runnable doAppLogging = new Runnable() {
		public void run() {
			readSensor();
			objHandler.postDelayed(doAppLogging, APP_LOG_INTERVAL);
		}
	};

	@Override
	public void onCreate() {
		Log.d("Application-Logging", "--- onCreate");
		SensorCatalouge sencat = new SensorCatalouge(getApplicationContext());
		try {
			ArrayList<SensorObj> sens = sencat.getAllSensors();
			for (int i = 0; i < sens.size(); i++) {
				if (sens.get(i).getSensorName().equalsIgnoreCase("APPLICATION")) {
					String[] configs = sens.get(i).getConfigData();
					for (int j = 0; j < configs.length; j++) {
						String tmp[] = configs[j].split("=");
						//TODO: check this Record Interval in ms doesn't existed anymore
						if (tmp[0].trim().equalsIgnoreCase("Record Interval in ms")) {
							APP_LOG_INTERVAL = Long.parseLong(tmp[1]);
						}
					}
				}
			}
		} catch (Exception e) {
			Log.e("Application Sensor","----------Error reading the log interval from sensor catalouge-----"+ e.getLocalizedMessage());
			e.printStackTrace();
		}
	}

	@Override
	public void onDestroy() {
		objHandler.removeCallbacks(doAppLogging);
		Log.d("Application-Logging", "--- onDestroy");
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d("Application-Logging", "--- onStart");
		readSensor();
		objHandler.postDelayed(doAppLogging, APP_LOG_INTERVAL);
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("Application-Logging", "--- onStartCommand");
		readSensor();
		objHandler.postDelayed(doAppLogging, APP_LOG_INTERVAL);
	    return START_STICKY;
	}

	/* old one from Reza
	public void readSensor() {
		try {
			ActivityManager activeMan = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
			List<ActivityManager.RunningAppProcessInfo> activityList = activeMan.getRunningAppProcesses();
			dataAcq = new DataAcquisitor();

			int numberOfTasks = 1;
			if ( !isExcluded(activeMan.getRunningTasks(numberOfTasks).get(0).topActivity.getPackageName().toString()) ) 
			{
				//String tmpDate = DateFormat.getDateTimeInstance().format(System.currentTimeMillis());
				SimpleDateFormat dateformat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
				String tmp = new String("{\"Application\": {\"ProcessName\":\""+ activeMan.getRunningTasks(numberOfTasks).get(0).topActivity.getPackageName().toString()+ 
						"\",\"Time\":\"" + dateformat.format(new Date()) + "\"}}");
				dateformat = null;
				dataAcq.dataBuff.add(tmp);
			}
//			for (int i = 0; i < activityList.size(); i++) {
//				if ( 	//.equalsIgnoreCase(activityList.get(i).processName) &&
//						(activityList.get(i).importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND ) &&  
//					    ( !isExcluded(activityList.get(i).processName) ) ) 
//				{
//					//String tmpDate = DateFormat.getDateTimeInstance().format(System.currentTimeMillis());
//					SimpleDateFormat dateformat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
//					String tmp = new String("{\"Application\": {\"ProcessName\":\""+ activityList.get(i).processName+ "\",\"Time\":\"" + dateformat.format(new Date()) + "\"}}");
//					dateformat = null;
//					dataAcq.dataBuff.add(tmp);
//				}
//			}
		} catch (Exception e) {
			IOManager errlogger = new IOManager();
			errlogger.logError("[ApplicationSensor] error:" + e.getMessage());
			e.printStackTrace();
		}
	}
	*/

	public void readSensor() {
		try {
			
			ActivityManager activeMan = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
			List<ActivityManager.RunningAppProcessInfo> activityList = activeMan.getRunningAppProcesses();
			Date _currentDate = new Date();
			ArrayList<String> _foundApps = new ArrayList<String>();
			PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
			for (int i = 0; i < activityList.size(); i++) {
				if ((activityList.get(i).importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) && 
						! containSysProc(activityList.get(i).processName) && pm.isScreenOn()) {
				if(!ApplicationSensorHelper.Instance()._apps.containsKey(activityList.get(i).processName)){
					ApplicationSensorHelper.Instance()._apps.put(activityList.get(i).processName, _currentDate);
				}
				_foundApps.add(activityList.get(i).processName);
				}
			}
			ApplicationSensorHelper.Instance().logApps(_foundApps, "Application",APP_LOG_INTERVAL_2,_currentDate);
			
		} catch (Exception e) {
			IOManager errlogger = new IOManager();
			errlogger.logError("[ApplicationSensor.readSensor] error:" + e.getMessage()+ " Stack:" + Log.getStackTraceString(e));
		}
	}

	private boolean containSysProc(String input) {
		for (int j = 0; j < Setting.Instance(this).getCoreProcs().length; j++) {
			if (input.equalsIgnoreCase(Setting.Instance(this).getCoreProcs()[j])) {
				return true;
			}
		}
		return false;
	}

	
//	private boolean isExcluded(String input) 
//	{
//		for (int j = 0; j < com.ubiqlog.common.Setting.coreProcs.length; j++) {
//			if (input.equalsIgnoreCase(com.ubiqlog.common.Setting.coreProcs[j]) 
//					|| Setting.vectorExcludedApplications.contains(input.toLowerCase()) ) 
//			{
//				return true;
//			}
//		}
//		return false;
//		//return (Setting.vectorExcludedApplications.contains(input.toLowerCase()) ;
//	}
	
	public String getSensorName() {
		return "APPLICATION";
	}
	
} public class AudioSensor extends Service implements SensorConnector {

	private static String AUDIO_FOLDER = null;
	private MediaRecorder _recorder = null;

	// in bytes
	// ~ 50MB
	private long max_file_size = 52428800;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		Log.d("[AudioSensor.onCreate]", "--- onCreate");

		_recorder = new MediaRecorder();
		AUDIO_FOLDER = Setting.Instance(this).getAudioFolder();
	}

	
	public void readSensor() {
		initMediaRecorder(_recorder);
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.e("[AudioSensor-Logging]", "--- onStart");
		readSensor();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.e("[AudioSensor-Logging]", "--- onStartCommand");
		readSensor();
		return START_STICKY;
	}

	@Override
	public void onDestroy() {

		stopAudioRecorder();
		Log.d("[AudioSensor.onDestroy]", "--- onDestroy");
	}


	private MediaRecorder.OnInfoListener mInfoListener = new MediaRecorder.OnInfoListener() {

		public void onInfo(MediaRecorder mr, int what, int extra) {
			switch (what) {
			case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED:

				// max file size reached
				// stop recording if not already stopped
				if (mr != null) {
					try {
						mr.stop();
					} catch (IllegalStateException exc) {
						// do nothing - already stopped..
					}
					mr = new MediaRecorder();
					initMediaRecorder(mr);
				}
				break;
			default:
				break;
			}

		}
	};

	private void initMediaRecorder(MediaRecorder recorder) {

		// set media recorder settings -> todo -> move to settings
		recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
		recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
		recorder.setMaxFileSize(max_file_size);
		recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

		// set the info listener
		// will be called when the maximum file size is reached
		recorder.setOnInfoListener(mInfoListener);

		File sdAudioMainDirectory = new File(AUDIO_FOLDER);
		Boolean pathExists = true;

		if (!sdAudioMainDirectory.exists()) {
			Log.d("[AudioSensor.initMediaRecorder]", "--- create audio folder: " + AUDIO_FOLDER);
			if (sdAudioMainDirectory.mkdirs()) {
				Log.d("[AudioSensor.initMediaRecorder]", "--- create audio folder succeded!");
			} else {
				Log.d("[AudioSensor.initMediaRecorder]", "--- create audio folder failed!");
				pathExists = false;
			}
		}

		if (pathExists) {
			// Generate filename
			SimpleDateFormat sdf = new SimpleDateFormat("Z-yyMMdd-HHmmss.SSS");
			String filename = sdAudioMainDirectory.toString() + "/" + "Audio-"+ sdf.format(new Date());
			String tmp_filename = filename + ".mpeg";
			int i = 0;

			File tmp = new File(tmp_filename);
			while (tmp.exists() && i < 100) {
				i++;
				tmp_filename = filename + "_" + i + ".mpeg";
				tmp = new File(tmp_filename);
			}

			filename = tmp_filename;
			recorder.setOutputFile(filename);
			String jsonString = JsonEncodeDecode.EncodeAudio("Audio", filename, new Date());
			DataAcquisitor.dataBuff.add(jsonString);

			try {
				recorder.prepare();
				recorder.start();
			} catch (IllegalStateException e) {
				Log.d("[AudioSensor.initMediaRecorder]", "--- couldn't start audio logging!"+e.getMessage());
				e.printStackTrace();
			} catch (IOException e) {
				Log.d("[AudioSensor.initMediaRecorder]", "--- couldn't start audio logging 2!"+e.getMessage());
				e.printStackTrace();
			}
		}

	}

	private void stopAudioRecorder() {
		if (_recorder != null) {
			try {
				_recorder.stop();
				_recorder.release();
				_recorder = null;
			} catch (IllegalStateException exc) {
				// do nothing - already stopped..
			}
		}
	}
} public class BatterySensor extends Service {
    IntentFilter mIntentFilter;
    BatteryReceiver batteryReceiver;
    DataAcquisitor mDataBuffer;
    DataAcquisitor mSA_batteryBuffer;
    private final String TAG = this.getClass().getSimpleName();
    private int lastVal;
    private long lastVal_timestamp;
    private boolean isRegistered = false;

    @Override
    public void onCreate() {
        Log.d("Battery-Logging", "--- onCreate");
        super.onCreate();
        mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        batteryReceiver = new BatteryReceiver();
        mDataBuffer = new DataAcquisitor(Setting.LOG_FOLDER, Setting.dataFileName_Battery);
        //mSA_batteryBuffer = new DataAcquisitor("SA/BatterySensor");
        lastVal_timestamp = System.currentTimeMillis();
        isRegistered = false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("Battery-Logging", "--- onStartCommand");
        if (intent != null) {
            this.registerReceiver(batteryReceiver, mIntentFilter);
            isRegistered = true;

        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mDataBuffer.flush(true);
        //mSA_batteryBuffer.flush(true);
        if (batteryReceiver != null && isRegistered) {
            unregisterReceiver(batteryReceiver);
            isRegistered = false;
        } else {
            batteryReceiver = null;
            isRegistered = false;
        }

        Intent in = new Intent();
        in.setAction("BatterySensor.StartkilledService");
        sendBroadcast(in);
    }

    /* This class receives updates from the System
       If the level is a multiple of 5, write to file
     */
    private class BatteryReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent batteryStatus) {
            long timeGap = System.currentTimeMillis() - lastVal_timestamp;
            if (batteryStatus.getAction().equalsIgnoreCase(Intent.ACTION_BATTERY_CHANGED)) {
                int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
                int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
                if (level == lastVal && timeGap < Setting.BATTERY_MIN_SAMPLE_INTERVAL) { // If timestamp between last sampling was very short, return and don't register Level
                    return;
                }
                lastVal = level;
                lastVal_timestamp = System.currentTimeMillis();

                boolean isCharging = (status == BatteryManager.BATTERY_STATUS_CHARGING) ||
                        (status == BatteryManager.BATTERY_STATUS_FULL);

                SleepSensor.setisCharge(isCharging);

                if (level % 5 == 0) {
                    //store in buff
                    //Log.d(TAG, "Level:" + level + ", Charging:" + isCharging);
                    String encoded = JsonEncodeDecode.EncodeBattery(level, isCharging, new Date());
                    //mDataBuffer.insert(encoded, true, Setting.bufferMaxSize);
                    DataAcquisitor.dataBuff.add(encoded);
                    //mDataBuffer.flush(true);

                    //String encoded_SA = SemanticTempCSVUtil.encodeBattery(level, isCharging, new Date());
                    //mSA_batteryBuffer.insert(encoded_SA, true, Setting.bufferMaxSize);
                    //mSA_batteryBuffer.flush(true);

                }

                //String encoded = JsonEncodeDecode.EncodeBattery(level, isCharging, new Date());
                //mDataBuffer.insert(encoded, true, Setting.bufferMaxSize);
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
} public class BluetoothSensor extends Service implements SensorConnector {
	private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
	private BroadcastReceiver broadcastReceiver;
//	private Handler objHandler = new Handler();
	private com.ubiqlog.core.DataAcquisitor dataAcq;
	private static long BT_LOG_INTERVAL = 60000; // 60000= default values is 10 min
	private Timer bluetoothTimer;
	private Calendar currentDateTime = Calendar.getInstance();

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	
	@Override
	public void onCreate() {
		Log.d("Bluetooth-Logging", "--- onCreate");
		SensorCatalouge sencat = new SensorCatalouge(getApplicationContext());
		try {
			SensorObj sensorObject = sencat.getSensorByName("BLUETOOTH");
			String[] configs = sensorObject.getConfigData();
			for (int index = 0; index < configs.length; index++) {
				String tmp[] = configs[index].split("=");
				if (tmp[0].trim().equalsIgnoreCase("Scan interval")) {
					BT_LOG_INTERVAL = parseScanInterval(tmp[1]);
//					Log.e ("BT --> BT_LOG_INTERVAL:",String.valueOf(BT_LOG_INTERVAL));
				}
			}
			bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
			if (bluetoothAdapter == null) {
				Log.e("[BluetoothSensor.onCreate]", "----- Bluetooth is not supported");
			}
		} 
		catch (Exception e){
			Log.e("[BluetoothSensor.onCreate]", "----------Error reading the log interval from sensor catalouge-----" 
					+ e.getLocalizedMessage());
			e.printStackTrace();
		}
	}
//	private Runnable doBTLogging = new Runnable() {
//		public void run() {
//			readSensor();
//			objHandler.postDelayed(doBTLogging, BT_LOG_INTERVAL);
//		}
//	};


	@Override
	public void readSensor() {
		/*
		try {
			if (bluetoothAdapter.isEnabled()) {
				bluetoothAdapter.startDiscovery();

				currentDateTime = Calendar.getInstance();
				currentDateTime.setTimeInMillis(System.currentTimeMillis());
				if (currentDateTime.get(Calendar.SECOND) > 30) {
					currentDateTime.add(Calendar.MINUTE, 1);
				}
				currentDateTime.set(Calendar.SECOND, 0);
				currentDateTime.set(Calendar.MILLISECOND, 0);

				broadcastReceiver = new BroadcastReceiver() {
					@Override
					public void onReceive(Context context, Intent intent) {
						// Log.e("Bluetooth-Logging",
						// "-----READ SENSOR------------------" +
						// intent.getAction());
						String action = intent.getAction();

						if (BluetoothDevice.ACTION_FOUND.equals(action)) {
							BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
							SensorState.Bluetooth stateBluetoothDevice = null;
							Log.e("......xxxx.....", device.getName());
							switch (device.getBondState()) {
							case BluetoothDevice.BOND_NONE:
								stateBluetoothDevice = SensorState.Bluetooth.NONE;
								break;
							case BluetoothDevice.BOND_BONDING:
								stateBluetoothDevice = SensorState.Bluetooth.BONDING;
								break;
							case BluetoothDevice.BOND_BONDED:
								stateBluetoothDevice = SensorState.Bluetooth.BONDED;
								break;
							}
							String deviceName = device.getName();
							if (deviceName == null) {
								deviceName = "NO_DEVICENAME";
							}
							String jsonString = JsonEncodeDecode.EncodeBluetooth(deviceName,device.getAddress(),stateBluetoothDevice.getState(),currentDateTime.getTime());
							dataAcq.dataBuff.add(jsonString);
							jsonString = null;
						} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {

						}
					}
				};
				// IntentFilter filter = new
				// IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
				IntentFilter filter = new IntentFilter(
						BluetoothAdapter.ACTION_STATE_CHANGED);
				filter.addAction(BluetoothDevice.ACTION_FOUND);
				// IntentFilter filter = new
				// IntentFilter(BluetoothDevice.ACTION_FOUND);

				registerReceiver(broadcastReceiver, filter);
			} else {
				Log.e("Bluetooth-Logging", "----------BT is disabled");
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			Log.e("Bluetooth-Logging",
					"----------Error inside run method of TimerTask");
		}
		*/
	};
	
//	private TimerTask bluetoothTimerTask = new TimerTask() 
	private Timer timer = new Timer();
	private class BTtimerTask extends TimerTask {		
		@Override
		public void run() {
			try {
				if (bluetoothAdapter.isEnabled()) {
					bluetoothAdapter.startDiscovery();
						
					currentDateTime = Calendar.getInstance();
					currentDateTime.setTimeInMillis(System.currentTimeMillis());
					if (currentDateTime.get(Calendar.SECOND) > 30) {
						currentDateTime.add(Calendar.MINUTE, 1);
					}
					currentDateTime.set(Calendar.SECOND, 0);
					currentDateTime.set(Calendar.MILLISECOND, 0);
	
					broadcastReceiver = new BroadcastReceiver() {
						@Override
						public void onReceive(Context context, Intent intent) {
	//						Log.e("Bluetooth-Logging", "-----READ SENSOR------------------" + intent.getAction());
							String action = intent.getAction();
								
							if (BluetoothDevice.ACTION_FOUND.equals(action)) {
								BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
								SensorState.Bluetooth stateBluetoothDevice = null;
//								Log.e("......xxxx.....",device.getName());
								switch (device.getBondState()) {
									case BluetoothDevice.BOND_NONE:
										stateBluetoothDevice = SensorState.Bluetooth.NONE;
										break;
									case BluetoothDevice.BOND_BONDING:
										stateBluetoothDevice = SensorState.Bluetooth.BONDING;
										break;
									case BluetoothDevice.BOND_BONDED:
										stateBluetoothDevice = SensorState.Bluetooth.BONDED;
										break;
								}
								String deviceName = device.getName();
								if (deviceName == null) {
									deviceName = "NO_DEVICENAME";
								}
								String jsonString = JsonEncodeDecode.EncodeBluetooth(deviceName, device.getAddress(), stateBluetoothDevice.getState(), currentDateTime.getTime());
								dataAcq.dataBuff.add(jsonString);
								jsonString = null;
							} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
									
							}
						}
					};
	//				IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
					IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
					filter.addAction(BluetoothDevice.ACTION_FOUND);
	//				IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
					
					registerReceiver(broadcastReceiver, filter);
				}else {
					Log.e("Bluetooth-Logging","----------BT is disabled");
				}
			}catch (Exception ex){
				ex.printStackTrace();
				Log.e("Bluetooth-Logging","----------Error inside run method of TimerTask");
			}	
			//timer.schedule(new BTtimerTask(), BT_LOG_INTERVAL);
		}
	};
	
	@Override 
	public void onStart(Intent intent, int startId) {
		Log.d("[Bluetooth-Logging]", "--- onStart");
//		bluetoothTimer = new Timer();
//		bluetoothTimer.scheduleAtFixedRate(bluetoothTimerTask, BT_LOG_INTERVAL, BT_LOG_INTERVAL);
//		bluetoothTimer = new BTtimerTask();
//		readSensor();
//		objHandler.postDelayed(doBTLogging, BT_LOG_INTERVAL);
		timer.schedule(new BTtimerTask(), BT_LOG_INTERVAL, BT_LOG_INTERVAL); 
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("Bluetooth-Logging", "--- onStartCommand");
//		readSensor();
//		objHandler.postDelayed(doBTLogging, BT_LOG_INTERVAL);
//		bluetoothTimer = new Timer();
//		bluetoothTimer.scheduleAtFixedRate(bluetoothTimerTask, BT_LOG_INTERVAL, BT_LOG_INTERVAL); 
		timer.schedule(new BTtimerTask(), BT_LOG_INTERVAL, BT_LOG_INTERVAL); 
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		Log.d("Bluetooth-Logging", "--- onDestroy");
//		objHandler.removeCallbacks(doBTLogging);
		if (bluetoothTimer != null) {
			bluetoothTimer.cancel();
		}
		if (bluetoothAdapter != null) {
			bluetoothAdapter.cancelDiscovery();
		}
		
		try {
			this.unregisterReceiver(broadcastReceiver);
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	/** 
	 * check if it is second or minutes  
	 * @param strScanInterval
	 * @return
	 */
	private Long parseScanInterval(String strScanInterval) {
		String lowerCase = strScanInterval.toLowerCase();
		String toParse = "";
		int multiplier = 0;
		if (lowerCase.endsWith("m")) {
			toParse = lowerCase.split("m")[0];
			multiplier = 60000;
		} else if (lowerCase.endsWith("s")) {
			toParse = lowerCase.split("s")[0];
			multiplier = 1000;
		} else {
			toParse = lowerCase;
			multiplier = 1000;
		}
//		Log.e("--------toParse: ", toParse);
//		return (multiplier * Long.parseLong(toParse));
		return Long.parseLong(toParse);
	}

	public String getSensorName() {
		return "BLUETOOTH";
	}
	
} public class CallSensor extends Service implements SensorConnector {

	private com.ubiqlog.core.DataAcquisitor dataAcq = new DataAcquisitor();
	private Cursor callCur;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		Log.d("Call-Logging", "--- onCreate");
	}

	@Override
	public void onDestroy() {
		Log.d("Call-Logging", "--- onDestroy");
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d("Call-Logging", "--- onStart");
		readSensor();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("Call-Logging", "--- onStartCommand");
		readSensor();
		return START_STICKY;
	}
	
	public void readSensor() {
		Handler handler = new Handler();
		callCur = getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI, null, null, null,android.provider.CallLog.Calls.DATE + " DESC");
		callCur.registerContentObserver(new CALLContentObserver(handler));
	}

	class CALLContentObserver extends ContentObserver {

		int numberColumn = callCur.getColumnIndex(android.provider.CallLog.Calls.NUMBER);
		int dateColumn = callCur.getColumnIndex(android.provider.CallLog.Calls.DATE);
		int durationColumn = callCur.getColumnIndex(android.provider.CallLog.Calls.DURATION);
		int typeColumn = callCur.getColumnIndex(android.provider.CallLog.Calls.TYPE); // Incoming, Outgoing or Missed

		public CALLContentObserver(Handler handler) {
			super(handler);
		}

		@Override
		public void onChange(boolean arg0) {
			try {
				super.onChange(arg0);
				callCur.requery();
				callCur.moveToFirst();

				if (Setting.CALL_ANNOTATION && !(Setting.GROUP_TEST)) {
					CallAnnotation callanot = new CallAnnotation(getApplicationContext());
					
					//String tmpDate = DateFormat.getDateTimeInstance().format(System.currentTimeMillis());
					SimpleDateFormat dateformat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
					Date tmpDate = new Date(callCur.getLong(dateColumn));
					String tmp = new String("{\"Call\": {\"Number\":\""+ callCur.getString(numberColumn)
							+ "\",\"Duration\":\""+ callCur.getInt(durationColumn)
							+ "\",\"Time\":\""+ dateformat.format(tmpDate)+ "\",\"Type\":\""
							+ callCur.getInt(typeColumn)+ "\", \"metadata\":{\"name\":\""
							+ callanot.annotate(callCur.getString(numberColumn)) + "\"}}}");
					dataAcq.dataBuff.add(tmp);
					Log.e("[Call-Logging]",tmp);
					tmpDate = null;
					dateformat=null;
				} else {
					if (Setting.GROUP_TEST){
						SimpleDateFormat dateformat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
						String hidedNum = callCur.getString(numberColumn);
						hidedNum = hidedNum.substring(0, hidedNum.length()-4);
						hidedNum = hidedNum + "####";
						Date tmpDate = new Date(callCur.getLong(dateColumn));
						String tmp = new String("{\"Call\": {\"Number\":\""
								+  hidedNum  + "\",\"Duration\":\""
								+ callCur.getInt(durationColumn) + "\",\"Time\":\""
								+ dateformat.format(tmpDate) + "\",\"Type\":\""
								+ callCur.getInt(typeColumn) + "\"}}");
						tmpDate = null;
						dataAcq.dataBuff.add(tmp);
						Log.e("[Call-Logging]",tmp);
					}else {
						SimpleDateFormat dateformat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
						Date tmpDate = new Date(callCur.getLong(dateColumn));
						String tmp = new String("{\"Call\": {\"Number\":\""
								+ callCur.getString(numberColumn)+ "\",\"Duration\":\""
								+ callCur.getInt(durationColumn) + "\",\"Time\":\""
								+ dateformat.format(tmpDate) + "\",\"Type\":\""
								+ callCur.getInt(typeColumn) + "\"}}");
						tmpDate = null;
						dataAcq.dataBuff.add(tmp);
					}
					
				}
			} catch (Exception e) {
				IOManager errlogger = new IOManager();
				errlogger.logError("[CallSensor] error:" + e.getMessage());
				e.printStackTrace();
			}

		}
	}

} public class InteractionSensor extends Service {

    String title = "SCREEN_ON";
    private final String TAG = this.getClass().getSimpleName();
    final int PROCESS_STATE_TOP = 2;

    private Handler mHandler;

    // Added by AP
    Intent ServiceIntent;
    private ActivityManager mActivityManager;
    private DetectAppLaunchRunnable mRunnable;
    ActivityManager.RecentTaskInfo mRecentActivityManager;
    Pair<ActivityManager.RunningAppProcessInfo, String> nextActivePair;

    private long start_timestamp;
    private long end_timestamp;
    Calendar startTime;

    // Buffers
    private DataAcquisitor mDataBuffer;
    private DataAcquisitor mSA_AppUsage;

    HandlerThread appBackThread;
    ScreenBroadcastReceiver m_receiver;
    PowerManager pm;
    PowerManager.WakeLock wl;

    //private static com.insight.insight.utils.AppsGenres AppsGenres = new AppsGenres();

    @Override
    public void onCreate() {
        super.onCreate();

        Log.e("Interaction-Logging", "--- onCreate");
        // Added by AP
        //Log.d(TAG, "Starting App usage sensor");
        pm = null;
        wl = null;
        ServiceIntent = null;

        appBackThread = new HandlerThread("AppUsage", android.os.Process.THREAD_PRIORITY_BACKGROUND);
        appBackThread.start();
        mHandler = new Handler(appBackThread.getLooper());
        mRunnable = new DetectAppLaunchRunnable();
        mHandler.post(mRunnable);

        nextActivePair = null;
        mDataBuffer = new DataAcquisitor(Setting.DEFAULT_FOLDER, Setting.dataFileName_ScreenUsage);
        //mSA_AppUsage = new DataAcquisitor("SA/" + Setting.dataFolderName_ScreenUsage);

        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        m_receiver = new ScreenBroadcastReceiver();
        registerReceiver(m_receiver, filter);
        //IOManager ioManager = new IOManager();
        //File dir1 = new File(ioManager.getDataFolderFullPath(mDataBuffer.getFolderName()));
        //File dir2 = new File(ioManager.getDataFolderFullPath(mSA_AppUsage.getFolderName()));

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("Interaction-Logging", "--- onStartCommand");
        //mHandler.post(mRunnable);
        if (wl == null && pm == null && ServiceIntent == null) {
            start();
            ServiceIntent = intent;
        }
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }


    /**
     * Added by Author: AP
     * DetectAppLaunchRunnable is used by the AppUsageSensor to get
     * the TOP active application on the watch
     * Upon closing of an application, the value of startTime, endTime, applicationName
     * and minutes elapsed will be saved to a local folder
     */
    @SuppressWarnings("ResourceType")
    public class DetectAppLaunchRunnable implements Runnable {

        @Override
        public void run() {
            //Log.d(TAG, "Screen on");
            start_timestamp = System.currentTimeMillis();

            //mHandler.postDelayed(this, Setting.APP_USAGE_INTERVAL);
        }

    }

    @Override
    public void onDestroy() {
        if (appBackThread != null) {
            Thread moribund = appBackThread;
            appBackThread = null;
            moribund.interrupt();
        }
        mDataBuffer.flush(true);
        //mSA_AppUsage.flush(true);
        super.onDestroy();
        unregisterReceiver(m_receiver);
        //wl.release();

        Intent in = new Intent();
        in.setAction("AppUsage.StartkilledService");
        sendBroadcast(in);
        //Log.d("debug", "Service Killed");
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @SuppressWarnings("deprecation")
    public void start() {
        try {
            /*
            pm = (PowerManager) getApplicationContext().getSystemService(
                    Context.POWER_SERVICE);
            wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
                    | PowerManager.ACQUIRE_CAUSES_WAKEUP, getClass().getName());
            wl.acquire();
            KeyguardManager mgr = (KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE);
            KeyguardManager.KeyguardLock lock = mgr.newKeyguardLock(KEYGUARD_SERVICE);
            lock.disableKeyguard();
            */
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private class ScreenBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                Log.d("ON SCREEN ON", "might hang here");
                mHandler.removeCallbacks(mRunnable);
                mHandler.post(mRunnable);

            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                start();
                Log.d("SCREEN OFF", "might hang here");
                // stop();
                mHandler.removeCallbacks(mRunnable);

                end_timestamp = System.currentTimeMillis();
                Long totalTime = end_timestamp - start_timestamp;

                //Log.d(TAG, "Start Time: " + Long.toString(start_timestamp));
                //Log.d(TAG,"End Time: " + Long.toString(end_timestamp));

                Double Tminutes = ((end_timestamp - start_timestamp) / (1000.0 * 60.0));
                //Log.d(TAG, "Minutes: " + Tminutes);

                //Log.d(TAG, "Store app usage " + applicationName);
                startTime = Calendar.getInstance();
                startTime.setTimeInMillis(start_timestamp);

                Calendar endTime = Calendar.getInstance();
                endTime.setTimeInMillis(end_timestamp);
                int startHour = startTime.get(Calendar.HOUR_OF_DAY);
                int endHour = endTime.get(Calendar.HOUR_OF_DAY);

                Double MinutesInStartHour = 0.0;
                Double MinutesInEndHour = 0.0;
                if (startHour != endHour) {
                    Calendar atBeginningOfHour = Calendar.getInstance();
                    int nextHour = 0;
                    if (startHour == 23) {
                        nextHour = 0;
                    } else {
                        nextHour = startHour + 1;
                    }
                    atBeginningOfHour.set(Calendar.HOUR_OF_DAY, nextHour);
                    atBeginningOfHour.set(Calendar.MINUTE, 0);
                    atBeginningOfHour.set(Calendar.SECOND, 0);
                    atBeginningOfHour.set(Calendar.MILLISECOND, 0);
                    //Log.d(TAG, "BeginnigOfHour=" + atBeginningOfHour.getTimeInMillis());
                    MinutesInEndHour = ((endTime.getTimeInMillis() - atBeginningOfHour.getTimeInMillis()) / (1000.0 * 60.0));
                    MinutesInStartHour = Tminutes - MinutesInEndHour;
                    //Log.d(TAG, "StartMinutes=" + MinutesInStartHour);
                    //Log.d(TAG, "ExtraMinutes=" + MinutesInEndHour);

                } else {
                    MinutesInStartHour = Tminutes;
                    MinutesInEndHour = 0.0;
                }

                //store in buff / write  file
                String encoded = JsonEncodeDecode.EncodeScreenUsage(Integer.toString(startHour), Integer.toString(endHour),
                        startTime.getTime(), endTime.getTime(), Tminutes, MinutesInStartHour, MinutesInEndHour);

                // mDataBuffer.insert(encoded, true, Setting.bufferMaxSize);
                DataAcquisitor.dataBuff.add(encoded);
                Log.e("Screen_Interaction",encoded);
                /*
                String encoded_SA = SemanticTempCSVUtil.encodedScreenUsage(Integer.toString(startHour),Integer.toString(endHour),
                        startTime.getTime(), endTime.getTime(), Tminutes, MinutesInStartHour, MinutesInEndHour);
                mSA_AppUsage.insert(encoded_SA, true, Setting.bufferMaxSize);
                */

                start_timestamp = 0;
            }
        }
    }
} public class LocationGSSensor extends Service implements
														GoogleApiClient.ConnectionCallbacks,
														GoogleApiClient.OnConnectionFailedListener,
																			SensorConnector,
																			LocationListener  {
	
	//private LocationClient locationClient;

	// Added by AP
	private GoogleApiClient mGoogleApiClient = null;
	private Location mLastLocation = null;

	private Context mContext;
	private Boolean mRequestingLocationUpdates = false;
	private LocationRequest mLocationRequest;

	//private LocationRequest locationrequest;
	private ConnectionResult connectionResult;
	private static long UPDATE_INTERVAL = 30000;
	private boolean isNew = false;
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		Log.d("LocationGS-Logging", "--- onCreate");
		SensorCatalouge sencat = new SensorCatalouge(getApplicationContext());
		try {
			ArrayList<SensorObj> sens = sencat.getAllSensors();
			for (int i = 0; i < sens.size(); i++) {
				if (sens.get(i).getSensorName().equalsIgnoreCase("LOCATION_FUSE")) {
					String[] configs = sens.get(i).getConfigData();
					for (int j = 0; j < configs.length; j++) {
						String tmp[] = configs[j].split("=");
						if (tmp[0].trim().equalsIgnoreCase("Scan interval")) {
							UPDATE_INTERVAL = Long.parseLong(tmp[1]);
						}
					}
				}
			}	
		} catch (Exception e) {
			Log.e("[LocationGS-Logging]","----------Error reading the log interval from sensor catalouge."+e.getLocalizedMessage());
			e.printStackTrace();
		}
		/*
		locationClient = new LocationClient(getApplicationContext(), this, this);
		*/

		// Added by AP
		// Get context
		mContext = getApplicationContext();

		// Start GoogleApiClient
		if (mGoogleApiClient == null) {
			mGoogleApiClient = new GoogleApiClient.Builder(this)
					.addConnectionCallbacks(this)
					.addOnConnectionFailedListener(this)
					.addApi(LocationServices.API)
					.build();
		}

		/*
		locationrequest = LocationRequest.create();
	    // Use high accuracy
		locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
	    // read the update interval, in this class default set to be 10 seconds
		//UPDATE_INTERVAL = 10000;
		locationrequest.setInterval(UPDATE_INTERVAL);
	    // Set the fastest update interval to the same interval
		locationrequest.setFastestInterval(UPDATE_INTERVAL);
		*/

		// Connect googleApiClient
		if (mGoogleApiClient != null) {
			mGoogleApiClient.connect();
		}

		// Added by AP
		mRequestingLocationUpdates = true;
		mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
		if (mLastLocation != null) {
			if (mRequestingLocationUpdates) {
				createLocationRequest();
				startLocationUpdates();
			}
		}
	}
	@Override
    public void onLocationChanged(Location location) {
		String jsonString = JsonEncodeDecode.EncodeLocationGS("Location",location.getLatitude(),location.getLongitude(),
				location.getAltitude(),new Date(),location.getAccuracy(),location.getProvider(), location.getSpeed());
		// Log.e("LocationGS-Logging",jsonString);
		DataAcquisitor.dataBuff.add(jsonString);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("LocationGS-Logging", "--- onStartCommand");

		/*
		if (locationClient.isConnected() || locationClient.isConnecting()){
//			readSensor();
		}else {
			locationClient.connect();	
		}
		*/

		// Connect googleApiClient
		if (mGoogleApiClient != null) {
			mGoogleApiClient.connect();
		}

		if (mGoogleApiClient != null && mGoogleApiClient.isConnected() && !mRequestingLocationUpdates) {
			createLocationRequest();
			startLocationUpdates();
		}
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		/*
		if (locationClient.isConnected() ) {
	         // Remove location updates for a listener. The current Service is the listener, so the argument is "this".    
			 locationClient.removeLocationUpdates(this);
	    }
		locationClient.disconnect();
		*/
		Log.d("LocationGS-Logging", "--- onDestroy");
		super.onDestroy();

		// Added by AP
		if (mGoogleApiClient.isConnected()) {
			mGoogleApiClient.disconnect();
			mGoogleApiClient = null;
		} else {
			mGoogleApiClient = null;
		}
	}

	public void readSensor() {
		try {
			//Location currloc = locationClient.getLastLocation();
			//locationClient.requestLocationUpdates(locationrequest, this);

			// Added by AP
			Location currloc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
			LocationServices.FusedLocationApi.requestLocationUpdates(
					mGoogleApiClient, mLocationRequest, this);
// 				if (curLocation != null && isNew) {
//				isNew = false;
			String jsonString = JsonEncodeDecode.EncodeLocationGS("Location",currloc.getLatitude(),currloc.getLongitude(),
					currloc.getAltitude(),new Date(),currloc.getAccuracy(),currloc.getProvider(), currloc.getSpeed());
//			Log.e("-------CCC------",jsonString);
			DataAcquisitor.dataBuff.add(jsonString);
//			} 
		} catch (Exception e) {
			IOManager errlogger = new IOManager();
			errlogger.logError("[LocationGS-Logging] error:" + e.getMessage()+ " Stack:" + Log.getStackTraceString(e));
		}
	}

	@Override
	public void onConnectionFailed(ConnectionResult arg0) {
	//		if (connectionResult.hasResolution()) {
	//            try {
	//                // Start an Activity that tries to resolve the error
	//                connectionResult.startResolutionForResult(this,CONNECTION_FAILURE_RESOLUTION_REQUEST);
	//                /*
	//                 * Thrown if Google Play services canceled the original
	//                 * PendingIntent
	//                 */
	//            } catch (Exception e) {
	//                // Log the error
	//                e.printStackTrace();
	//            }
	//        } else {
	//            /*
	//             * If no resolution is available, display a dialog to the
	//             * user with the error.
	//             */
	//            Log.e("LocationGSSensor",String.valueOf(connectionResult.getErrorCode()));
	//        }
	}

	@Override
	public void onConnected(Bundle arg0) {
		// TODO Auto-generated method stub
		readSensor();
	}

	protected void createLocationRequest() {
		mLocationRequest = new LocationRequest();
		mLocationRequest.setInterval(UPDATE_INTERVAL);
		mLocationRequest.setFastestInterval(UPDATE_INTERVAL);
		mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
	}

	protected void startLocationUpdates() {
		Log.d(getClass().getSimpleName(), "Started location updates");
		LocationServices.FusedLocationApi.requestLocationUpdates(
				mGoogleApiClient, mLocationRequest, this);

	}

	protected void stopLocationUpdates() {
		LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);

	}

	@Override
	public void onConnectionSuspended(int i) {

	}

	/*
	@Override
	public void onDisconnected() {
		// TODO Auto-generated method stub
		//locationClient = null;

	}
	*/

} public class LocationSensor extends Service implements SensorConnector {

	private LocationManager locationManager;
	private Location curLocation;
	private int enabledProviders = 0;
	private Handler objHandler = new Handler();
	private boolean isNew = false;
	
	private LocationListener loclistener = new LocationListener() {
		public void onLocationChanged(Location location) {
			
			//Log.d("Location-Logging", "Location received: Provider: " + location.getProvider() + "; Accuracy: " + location.getAccuracy() + "; Time: " + location.getTime());
			
			//if there is only one active provider then write the location
			//else compare the locations
			if(enabledProviders<2)
			{
				curLocation = location;
				isNew = true;
				readSensor();
			}
			else
			{
			if(curLocation==null){
					curLocation = location;
					isNew = true;
			}
			else{
			synchronized (curLocation) {
				if(curLocation.getProvider().equals(location.getProvider())){
					curLocation = location;
					isNew = true;
					//Log.d("Location-Logging", "Location changed due to same provider!");
				}
				else{
					//check if more accurate
					if(location.getAccuracy()<curLocation.getAccuracy() || (curLocation.getTime()-location.getTime())>9000){
						curLocation = location;
						isNew = true;
					//	Log.d("Location-Logging", "Location changed due to accuracy or time!");
					}			
				}
			}
			}
		//	Log.d("Location-Logging", "Current locationd: Provider: " + curLocation.getProvider() + "; Accuracy: " + curLocation.getAccuracy() + "; Time: " + curLocation.getTime());
			
			}
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		Log.d("Location-Logging", "--- onCreate");
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);		
		List<String> providers = locationManager.getProviders(true);
		for (String prov : providers) {
			if(prov.equals(LocationManager.GPS_PROVIDER) || prov.equals(LocationManager.NETWORK_PROVIDER)){
				enabledProviders ++;
				Log.d("Location-Logging", "Request location updates for: " + prov);
				locationManager.requestLocationUpdates(prov,10000, 1, loclistener);
			}
		}
		if(enabledProviders>1){
			//set up a schedule in order to save the location
			objHandler.postDelayed(doLocationLogging, 10000);
		}
	}
	
	private Runnable doLocationLogging = new Runnable() {
		public void run() {
		//	Log.d("Location-Logging", "Write location...");
			readSensor();
			objHandler.postDelayed(doLocationLogging, 10000);
		}
	};
	

	@Override
	public void onDestroy() {
		objHandler.removeCallbacks(doLocationLogging);
		Log.d("Location-Logging", "--- onDestroy");
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d("Location-Logging", "--- onStart");
		readSensor();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("Location-Logging", "--- onStartCommand");
		readSensor();
		return START_STICKY;
	}
	public void readSensor() {
		try {
			if (curLocation != null && isNew) {
				isNew = false;
				String jsonString = JsonEncodeDecode.EncodeLocation("Location",curLocation.getLatitude(),curLocation.getLongitude(),
						curLocation.getAltitude(),new Date(),curLocation.getAccuracy(),curLocation.getProvider());
				DataAcquisitor.dataBuff.add(jsonString);
			} 
			
		} catch (Exception e) {
			IOManager errlogger = new IOManager();
			errlogger.logError("[LocationSensor] error:" + e.getMessage()+ " Stack:" + Log.getStackTraceString(e));
		}
	}

	public void onProviderDisabled(String provider) {
	}

	public void onProviderEnabled(String provider) {
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

} public class PictureSensor extends Service implements SensorConnector {

	private static final String TAG = "Picture-Logging";
	private static long PICTURE_LOG_INTERVAL = 30000L;
	private static String PICTURE_FOLDER = null;
	private static Camera cam = null;
	private Context _ctx = null;
	private Handler objHandler = new Handler();
	private int autofocusTries = 0;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	private Runnable doPictureLogging = new Runnable() {
		public void run() {
			readSensor();
			objHandler.postDelayed(doPictureLogging, PICTURE_LOG_INTERVAL);
		}
	};

	@Override
	public void onCreate() {
		_ctx = this;
		autofocusTries = 0;
		PICTURE_FOLDER = Setting.Instance(this).getPictureFolder();
		Log.d("Picture-Logging", "--- onCreate");
		SensorCatalouge sencat = new SensorCatalouge(getApplicationContext());
		try {
			ArrayList<SensorObj> sens = sencat.getAllSensors();
			for (int i = 0; i < sens.size(); i++) {
				if (sens.get(i).getSensorName().equalsIgnoreCase("PICTURE")) {
					String[] configs = sens.get(i).getConfigData();
					for (int j = 0; j < configs.length; j++) {
						String tmp[] = configs[j].split("=");

						if (tmp[0].trim().equalsIgnoreCase(
								"Record interval in milli second")) {
							PICTURE_LOG_INTERVAL = Long.parseLong(tmp[1]);
						}
					}
				}
			}
		} catch (Exception e) {
			Log.e("Picture Sensor",
					"----------Error reading the log interval from sensor catalogue-----"
							+ e.getLocalizedMessage());
			e.printStackTrace();
		}
	}

	@Override
	public void onDestroy() {
		objHandler.removeCallbacks(doPictureLogging);
		ReleaseCamera();

		// refresh media - TODO

		sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
				Uri.parse("file://" + PICTURE_FOLDER)));

		Log.d("Picture-Logging", "--- onDestroy");
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d("Picture-Logging", "--- onStart");
		_ctx = this;
		readSensor();
		objHandler.postDelayed(doPictureLogging, PICTURE_LOG_INTERVAL);
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("Picture-Logging", "--- onStartCommand");
		_ctx = this;
		readSensor();
		objHandler.postDelayed(doPictureLogging, PICTURE_LOG_INTERVAL);
		return START_STICKY;
	}
	
	private void ReleaseCamera() {
		if (cam != null) {
			Log.d("Picture-Logging", "--- release camera");
			try {
				cam.release();
				cam = null;
			} catch (Exception ex) {
			}
		}

	}

	private void InitSurfacePreview() {

		boolean hasPreview = false;

		// try to use superior api version just if supported
		if (android.os.Build.VERSION.SDK_INT >= 11) {
			try {

				Class<?> classSurfaceTexture = null;
				Constructor<?> constructorSurfaceTexture = null;

				classSurfaceTexture = Class
						.forName("android.graphics.SurfaceTexture");
				// Log.d("Picture-Logging",
				// "--- initialising class successful");

				constructorSurfaceTexture = classSurfaceTexture
						.getConstructor(new Class[] { int.class });
				// Log.d("Picture-Logging",
				// "--- initialising constructor successful");

				Method proSetMethod = cam.getClass().getDeclaredMethod(
						"setPreviewTexture",
						new Class[] { classSurfaceTexture });
				// Log.d("Picture-Logging",
				// "--- initialising method successful");

				proSetMethod.invoke(cam,
						constructorSurfaceTexture.newInstance(1234));
				// Log.d("Picture-Logging", "--- invoking method successful");

				Log.d("Picture-Logging",
						"--- surface texture set as preview texture");
				hasPreview = true;

			} catch (ClassNotFoundException e1) {
				Log.e("Picture-Logging", "--- ERROR initialising camera 1: "
						+ e1.getMessage());
				e1.printStackTrace();

			} catch (SecurityException e1) {
				Log.e("Picture-Logging", "--- ERROR initialising camera 8: "
						+ e1.getMessage());
				e1.printStackTrace();
			} catch (NoSuchMethodException e1) {
				Log.e("Picture-Logging", "--- ERROR initialising camera 9: "
						+ e1.getMessage());
				e1.printStackTrace();
			} catch (IllegalArgumentException e) {
				Log.e("Picture-Logging", "--- ERROR initialising camera 4: "
						+ e.getMessage());
				e.printStackTrace();
			} catch (InstantiationException e) {
				Log.e("Picture-Logging", "--- ERROR initialising camera 5: "
						+ e.getMessage());
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				Log.e("Picture-Logging", "--- ERROR initialising camera 6: "
						+ e.getMessage());
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				Log.e("Picture-Logging", "--- ERROR initialising camera 7: "
						+ e.getMessage());
				e.printStackTrace();
			}

		}

		if (!hasPreview) {
			// register with code for api 7+ using dummy SurfaceView

			SurfaceView surfaceView = new SurfaceView(_ctx);
			try {
				cam.setPreviewDisplay(surfaceView.getHolder());
				Log.d("Picture-Logging",
						"--- surface view set as preview display");
			} catch (IOException e) {
				Log.e("Picture-Logging",
						"--- ERROR CRITICAL - cannot set preview : "
								+ e.getMessage());
				e.printStackTrace();
			}

		}

	}

	private void InitCamera() {
		if (cam == null) {
			Log.d("Picture-Logging", "--- init camera");

			// SurfaceTexture view = new SurfaceTexture(1234);
			cam = Camera.open();

			// register an error callback if something goes wrong
			cam.setErrorCallback(errorCallback);

			// register a preview callback for the next preview frame
			cam.setOneShotPreviewCallback(previewCallback);

			InitSurfacePreview();
			setResolution();
			setFocusMode();
			setSceneMdoe();

		} else {

			// register a preview callback for the next preview frame - must be
			// registered every time
			cam.setOneShotPreviewCallback(previewCallback);

			Log.d("Picture-Logging", "--- camera is already init!");
		}

	}

	private void setSceneMdoe() {
		Camera.Parameters params = cam.getParameters();
		if (params.getSupportedSceneModes() == null) {
			return;
		}
		if (params.getSupportedSceneModes().contains(
				Camera.Parameters.SCENE_MODE_STEADYPHOTO)) {
			params.setSceneMode(Camera.Parameters.SCENE_MODE_STEADYPHOTO);
			cam.setParameters(params);
			return;
		}
		if (params.getSupportedSceneModes().contains(
				Camera.Parameters.SCENE_MODE_SPORTS)) {
			params.setSceneMode(Camera.Parameters.SCENE_MODE_SPORTS);
			cam.setParameters(params);
			return;
		}
	}

	private void setFocusMode() {
		Camera.Parameters params = cam.getParameters();
		if (params.getSupportedFocusModes().contains(
				Camera.Parameters.FOCUS_MODE_INFINITY)) {
			params.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
			cam.setParameters(params);
		}
	}

	public void readSensor() {
		try {

			InitCamera();

			// start preview
			cam.startPreview();

		} catch (Exception e) {
			IOManager errlogger = new IOManager();
			errlogger.logError("[PictureSensor] error:" + e.getMessage());
			Log.e("Picture-Logging", "--- ERROR 3:" + e.getMessage());
			e.printStackTrace();
		}
	}

	private void setResolution() {
		Camera.Parameters params = cam.getParameters();
		Camera.Size preferredSize = params.getPictureSize();
		for (Camera.Size aSize : params.getSupportedPictureSizes()) {
			if (aSize.width == 1600) {
				preferredSize = aSize;
			}
		}
		params.setPictureSize(preferredSize.width, preferredSize.height);
		cam.setParameters(params);

	}

	public Camera.ErrorCallback errorCallback = new Camera.ErrorCallback() {

		public void onError(int error, Camera camera) {
			Log.d("Picture-Logging", "--- ERROR CAMERA:" + error);
			try {
				cam.stopPreview();
			} catch (Exception eee) {
			}
		}
	};

	public Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {

		
		public void onPreviewFrame(byte[] data, Camera camera) {
			// save the data on sd and in log
			Log.d("Picture-Logging", "--- preview callback");
			if (wantsAutofocus()) {
				camera.autoFocus(autofocusCallback);
			} else {
				camera.takePicture(null, null, pictureCallback);
			}

		}
	};


	protected boolean wantsAutofocus() {
		// TODO Auto-generated method stub
		// read option from Setting

		return false;
	}

	private AutoFocusCallback autofocusCallback = new AutoFocusCallback() {

		public void onAutoFocus(boolean autofocus, Camera camera) {
			if (autofocus == false) {
				autofocusTries++;
				if (autofocusTries > 5) {
					// take picture anyway
					Log.d(TAG, "Failed to autofocus, trying again");
					camera.takePicture(null, null, pictureCallback);
					autofocusTries = 0;
				}
				return;
			}

			camera.takePicture(null, null, pictureCallback);
			autofocusTries = 0;
		}
	};

	private PictureCallback pictureCallback = new PictureCallback() {

		public void onPictureTaken(byte[] data, Camera camera) {
			Size size = camera.getParameters().getPictureSize();
			saveImageFromPictureCallback(data, size);
			camera.startPreview();
		}
	};

	public void saveImageFromPictureCallback(byte[] data, Size size) {

		// create folder if not already created

		File sdImageMainDirectory = new File(PICTURE_FOLDER);
		
		if (!sdImageMainDirectory.exists()) {
			Log.d("Picture-Logging", "--- create picture folder: "
					+ PICTURE_FOLDER);
			if (sdImageMainDirectory.mkdirs()) {
				Log.d("Picture-Logging", "--- create picture folder succeded!");
			} else {
				Log.d("Picture-Logging", "--- create picture folder failed!");
			}
		}

		// Generate filename
		SimpleDateFormat sdf = new SimpleDateFormat("Z-yyMMdd-HHmmss.SSS");
		String filename = sdImageMainDirectory.toString() + "/" + "Picture-"
				+ sdf.format(new Date());
		String tmp_filename = filename + ".jpg";

		int i = 0;

		File tmp = new File(tmp_filename);
		while (tmp.exists() && i < 100) {
			i++;
			tmp_filename = filename + "_" + i + ".jpg";
			tmp = new File(tmp_filename);

		}
		filename = tmp_filename;

		// Store image to file system
		Log.d("Picture-Logging", "--- try to store picture!");
		try {
			FileOutputStream fos = new FileOutputStream(filename);
			fos.write(data);
			fos.close();
		} catch (FileNotFoundException e) {
			Log.d(TAG, "File not found: " + e.getMessage());
		} catch (IOException e) {
			Log.d(TAG, "Error accessing file: " + e.getMessage());
		}

		// Send broadcast, so that other apps are informed about the new file
		// (e.g Gallery-App)
		Uri fileuri = Uri.fromFile(new File(filename));
		sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, fileuri));
		// Log file info into JSON-file
		/*
		 * String jsonString = JsonEncodeDecode.EncodePicture(
		 * getSensorFriendlyName(), PICTURE_FOLDER + "/" + filename + ".jpg",
		 * new Date());
		 */
		String jsonString = JsonEncodeDecode.EncodePicture("Picture", filename, new Date()); // Bug resolved?
		DataAcquisitor.dataBuff.add(jsonString);
	}

	public boolean StoreByteImage(String filename, byte[] imageData, int width, int height, int quality) {

		File sdImageMainDirectory = new File(PICTURE_FOLDER);
		Boolean pathExists = true;
		if (!sdImageMainDirectory.exists()) {
			Log.d("Picture-Logging", "--- create picture folder: "
					+ PICTURE_FOLDER);
			if (sdImageMainDirectory.mkdirs()) {
				Log.d("Picture-Logging", "--- create picture folder succeded!");
			} else {
				Log.d("Picture-Logging", "--- create picture folder failed!");
				pathExists = false;
			}
		}

		if (pathExists) {
			FileOutputStream fileOutputStream = null;
			try {
				// we need to convert the default android format (yuv) to rgb
				// a simpler way is to use YuvImage but it is integrated just in
				// android 2.2+
				int[] rgb = convertYUVtoRGB(imageData, width, height);
				Bitmap bmp = Bitmap.createBitmap(rgb, width, height,Bitmap.Config.ARGB_8888);
				Log.d("Picture-Logging", "--- save picture: "
						+ sdImageMainDirectory.toString() + "/" + filename
						+ ".jpg");
				fileOutputStream = new FileOutputStream(
						sdImageMainDirectory.toString() + "/" + filename
								+ ".jpg");
				bmp.compress(CompressFormat.JPEG, quality, fileOutputStream);
			} catch (FileNotFoundException e) {
				IOManager errlogger = new IOManager();
				errlogger.logError("[PictureSensor] error:" + e.getMessage());
				e.printStackTrace();
				Log.e("Picture-Logging", "--- ERROR 1: " + e.getMessage());
			} catch (Exception e) {
				IOManager errlogger = new IOManager();
				errlogger.logError("[PictureSensor] error:" + e.getMessage());
				e.printStackTrace();
				Log.e("Picture-Logging", "--- ERROR 2: " + e.getMessage());
			}
		}

		return true;
	}

	/*
	 * function to convert from YUV to RGB
	 */
	private int[] convertYUVtoRGB(byte[] yuv420sp, int width, int height) {
		int frameSize = width * height;
		int[] decodedByteArray = new int[width * height];

		for (int j = 0, yp = 0; j < height; j++) {
			int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
			for (int i = 0; i < width; i++, yp++) {
				int y = (0xff & ((int) yuv420sp[yp])) - 16;
				if (y < 0)
					y = 0;
				if ((i & 1) == 0) {
					v = (0xff & yuv420sp[uvp++]) - 128;
					u = (0xff & yuv420sp[uvp++]) - 128;
				}

				int y1192 = 1192 * y;
				int r = (y1192 + 1634 * v);
				int g = (y1192 - 833 * v - 400 * u);
				int b = (y1192 + 2066 * u);

				if (r < 0)
					r = 0;
				else if (r > 262143)
					r = 262143;
				if (g < 0)
					g = 0;
				else if (g > 262143)
					g = 262143;
				if (b < 0)
					b = 0;
				else if (b > 262143)
					b = 262143;

				decodedByteArray[yp] = 0xff000000 | ((r << 6) & 0xff0000)
						| ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
			}
		}

		return decodedByteArray;
	}

} public class RawAudioSensor extends Service {

    private static final int RECORDER_SAMPLERATE = 44100;   // Better quality sound
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
    private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
    private AudioRecord recorder = null;
    private Thread recordingThread = null;
    private boolean isRecording = false;
    private int count =0;
    private int total=0;

    int BufferElements2Rec = 1024; // want to play 2048 (2K) since 2 bytes we use only 1024
    int BytesPerElement = 2; // 2 bytes in 16bit format
    int bufferSize = 0;

    private DataAcquisitor mDataBuffer;

    private Handler mHandler;

    public RawAudioSensor() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("RawAudio-Logging", "--- onCreate");
        bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
                RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);

        mDataBuffer = new DataAcquisitor(Setting.DEFAULT_FOLDER, Setting.dataFileName_Raw_Audio);
    }

    @Override
    public int onStartCommand(Intent intent,int flags, int startId) {
        Log.d("RawAudio-Logging", "--- onStartCommand");
        mHandler = new Handler();

        // Start the logging of audio in terms of short data
        startRecording();

        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }


    private void startRecording() {

        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
                RECORDER_SAMPLERATE, RECORDER_CHANNELS,
                RECORDER_AUDIO_ENCODING, BufferElements2Rec * BytesPerElement);
        recorder.startRecording();
        isRecording = true;
        recordingThread = new Thread(new Runnable() {
            public void run() {
                mHandler.postDelayed(new LogAudioDataRunnable(), Setting.RAW_AUDIO_DELAY);
            }
        }, "AudioRecorder Thread");
        recordingThread.start();
    }

    //convert short to byte
    private byte[] short2byte(short[] sData) {
        int shortArrsize = sData.length;
        byte[] bytes = new byte[shortArrsize * 2];
        for (int i = 0; i < shortArrsize; i++) {
            bytes[i * 2] = (byte) (sData[i] & 0x00FF);
            bytes[(i * 2) + 1] = (byte) (sData[i] >> 8);
            sData[i] = 0;
        }
        return bytes;
    }

    //convert short to byte
    private short[] byte2short(byte[] bData) {
        int shortArrsize = bData.length;
        short[] shorts = new short[shortArrsize / 2];
        for (int i = 0; i < shortArrsize; i+=2) {
            short lowerNibble =  (short) bData[i];
            short upperNibble =  (short)(bData[i+1] << 8);

            shorts[i] = (short) (upperNibble | lowerNibble);
            //shorts[i * 2] = (byte) (bData[i] & 0x00FF);
            //shorts[(i * 2) + 1] = (byte) (bData[i] >> 8);
            bData[i] = 0;
            bData[i+1] = 0;
        }
        return shorts;
    }

    private void writeAudioDataToFile() {
        // Write the output audio in byte
        if (recorder != null) {
            short sData[] = new short[bufferSize];
            recorder.read(sData, 0, bufferSize);
            StringBuffer sb = new StringBuffer();

            for(int i=0;i<sData.length;i++)
            {
                total = total+Math.abs(sData[i]);
                count++;
            }
            // before writing to the file process the data and store them as the most recent data.
            if(count>=43008){
                SleepSensor.setAudioArray(total/count);
                count=0;
                total=0;
            }
            //SleepSensor.setAudioArray(total/sData.length);
            //Log.e("RAWAUDIO", ""+sData.length);

            // Convert short array into byte array
            //byte [] bData = short2byte(sData);

            // Convert byte array to Base64 string to be stored in JSON
            //String encodedData = android.util.Base64.encodeToString(bData, android.util.Base64.DEFAULT);
            //byte [] tempBytes = android.util.Base64.decode(s, android.util.Base64.DEFAULT);

            // Store the Base64 String in a RawAudio file
            //String encoded = JsonEncodeDecode.EncodeRawAudio(encodedData, new Date());
            //Log.d("Accelerometer-encoded", encoded);
            //mDataBuffer.insert(encoded, true, Setting.bufferMaxSize);

        } else {
            Log.d(getClass().getSimpleName(), "Attempting to write data but recorder is null");
        }
    }

    private void stopRecording() {
        if (mHandler != null) {
            mHandler.removeCallbacks(new LogAudioDataRunnable());
            mHandler = null;
        }

        // stops the recording activity
        if (null != recorder) {
            isRecording = false;
            recorder.stop();
            recorder.release();
            recorder = null;
            recordingThread = null;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("RawAudio-Logging", "--- onDestroy");
        stopRecording();
    }


    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }


    private class LogAudioDataRunnable implements Runnable {

        @Override
        public void run() {
            writeAudioDataToFile();
            if (mHandler != null) {
                mHandler.postDelayed(this, Setting.RAW_AUDIO_DELAY);
            }
        }
    }

} public class SMSSensor extends Service implements SensorConnector {

	private static String lastId = "";

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		Log.d("SMS-Logging", "--- onCreate");
	}

	@Override
	public void onDestroy() {
		Log.d("SMS-Logging", "--- onDestroy");
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d("SMS-Logging", "--- onStart");
		readSensor();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("SMS-Logging", "--- onStartCommand");
		readSensor();
		return START_STICKY;
	}
	
	Cursor smsCur;

	public void readSensor() {

		Handler handler = new Handler();
		smsCur = getContentResolver().query(Uri.parse("content://sms"), null,
				null, null, null); //
		smsCur.registerContentObserver(new SMSContentObserver(handler, this));
	}

	class SMSContentObserver extends ContentObserver {
		int id = smsCur.getColumnIndex("_id");
		int address = smsCur.getColumnIndex("address"); // phone number
		int person = smsCur.getColumnIndex("person");
		int date = smsCur.getColumnIndex("date"); // date
		int protocol = smsCur.getColumnIndex("protocol");
		int status = smsCur.getColumnIndex("status");
		int type = smsCur.getColumnIndex("type");
		int body = smsCur.getColumnIndex("body"); // msg's content
		int reply_path_present = smsCur.getColumnIndex("reply_path_present");
		int subject = smsCur.getColumnIndex("subject");
		int service_center = smsCur.getColumnIndex("service_center");
		private Context _ctx = null;

		public SMSContentObserver(Handler handler, Context ctx) {
			super(handler);
			_ctx = ctx;
		}

		@Override
		public void onChange(boolean arg0) {
			try {
				smsCur.requery();

				// it can happen that smsCur is empty! not null!
				if (smsCur.moveToFirst()) {
					SMSAnnotation smsannot = new SMSAnnotation(getApplicationContext());
					String jsonString = "";
					if (Setting.GROUP_TEST){
						// It is group test and SMS content will be removed + number getremoved
						String tmpsmsAdd = smsCur.getString(address);
						if (smsCur.getString(address).length() >8){
							tmpsmsAdd = tmpsmsAdd.substring(0, tmpsmsAdd.length()-5);
							tmpsmsAdd = tmpsmsAdd + "#####";
						}
						jsonString = JsonEncodeDecode.EncodeSms(
								"SMS",
								tmpsmsAdd,
								smsCur.getInt(type),
								new Date(smsCur.getLong(date)),
								"ANONYMIZED",
								Setting.Instance(_ctx).SMS_ANNOTATION,
								Setting.Instance(_ctx).SMS_ANNOTATION ? smsannot.annotate(smsCur.getString(address)) : "");
						
					}else {
						 jsonString = JsonEncodeDecode.EncodeSms(
								"SMS",
								smsCur.getString(address),
								smsCur.getInt(type),
								new Date(smsCur.getLong(date)),
								smsCur.getString(body),
								Setting.Instance(_ctx).SMS_ANNOTATION,
								Setting.Instance(_ctx).SMS_ANNOTATION ? smsannot.annotate(smsCur.getString(address)) : "");
	
					}
										

					// we log just the sent and received messages! type: 1 and 2
					// it can happen that this will be called more than once for
					// the same message -> that is why we compare the id with
					// the last logged id.
					if ((smsCur.getInt(type) == 1 || smsCur.getInt(type) == 2)
							&& !smsCur.getString(id).equals(lastId)) {
						lastId = smsCur.getString(id);
						Log.e("-----------SMS-------------",jsonString);
						DataAcquisitor.dataBuff.add(jsonString);
					}
				}

			} catch (Exception e) {
				IOManager errlogger = new IOManager();
				errlogger.logError("[SMSSensor] error:" + e.getMessage()
						+ " Stack:" + Log.getStackTraceString(e));
				e.printStackTrace();
			}

			super.onChange(arg0);
		}

		@Override
		public boolean deliverSelfNotifications() {
			return true;
		}

	}

} public class SensorObj {
	private String sensorName;
	private String className;
	private String[] configData;
	private String annotationCalss;

	public String getAnnotationCalss() {
		return annotationCalss;
	}

	public void setAnnotationCalss(String annotationCalss) {
		this.annotationCalss = annotationCalss;
	}

	public String getSensorName() {
		return sensorName;
	}

	public void setSensorName(String sensorName) {
		this.sensorName = sensorName;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String[] getConfigData() {
		return configData;
	}

	public void setConfigData(String[] configData) {
		this.configData = configData;
	}


} public class SleepSensor extends Service {

    private final static int AUDIO_SIGNAL= 20; // the noise below this value is silent
    private final static float ACC_FIX=0.5f; // the fluctucations which presents moving
    private final static  int AMB_DARK =5; // the ambient light limit that represents darkness
    private final boolean BATT_CHARGE=true; // the battery is charging

    private final int NoSleepingCheckInterval = 60000; // every minutes check if there is no sleep
    private final int SleepingCheckInterval = 300000; // while user is slept every five minutes it checks if wakeup symptom has happened

    private static boolean IS_WEAR_ACC=false;
    private static boolean IS_WEAR_AMB=false;

    private boolean isSleeping = false;
    private static ArrayList<Float> accArray = new ArrayList<Float>();
    private static boolean isAccSatisfy=false;//condition of accelemeter, if satisfy the sleep, the value will be yes
    private static boolean isAudioSatisfy=false;//condition of audio, if satisfy the sleep, the value will be yes
    private static float ambientData =0;
    private static boolean isCharge = false;
    private Date starttime = null;
    private Date endtime = null;
    private boolean flag = true;



    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("Sleep-Logging", "--- onCreate");
    }
    @Override
    public int onStartCommand(Intent intent,int flags, int startId) {
        Log.e("Sleep-Logging", "--- onStartCommand");

        new Thread(){
            public void run()
            {
                while(flag)
                {
                    Log.e("SleepTAG",isAccSatisfy+","+isAudioSatisfy+","+isCharge+","+ambientData+","+isSleeping);

                    if(readSensor())
                    {
                        if(isSleeping){
                            isSleeping=true;
                        }else{
                            isSleeping=true;
                            starttime = new Date();
                        }

                    }else{
                        if(isSleeping)
                        {
                            isSleeping=false;
                            endtime = new Date();
                            String encoded = JsonEncodeDecode.EncodeSleep(starttime,endtime);
                            DataAcquisitor.dataBuff.add(encoded);
                            Log.e("SleepLOG",encoded);
                            starttime=null;
                            endtime=null;
                        }

                        isSleeping=false;
                    }

                    try{
                        if(isSleeping==false){
                            Thread.sleep(NoSleepingCheckInterval);
                        }else {
                            Thread.sleep(SleepingCheckInterval);
                        }

                    }catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }

                }
            }
        }.start();
        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

    public boolean readSensor()
    {
        if(isAudioSatisfy && isAccSatisfy && isCharge &&(ambientData<AMB_DARK))
        {
            return true;//satisfy the sleep condition
        }else{
            return false;
        }
    }
    public static void setAudioArray(int i)
    {
        Log.e("AUdioValue",""+i);
        if(i < AUDIO_SIGNAL)
        {
            isAudioSatisfy=true;// is silent
        }else {
            isAudioSatisfy=false;
        }
    }

    public static void setAccArray(float f)
    {
        if(accArray.size() >= 30)
        {
            float total = 0;
            for(int i=0; i<accArray.size(); i++)
            {
                total= total + accArray.get(i);
            }
            //Log.e("SleepTAG",""+total/accArray.size());
            isAccSatisfy = checkdifference(total/accArray.size(),accArray);

            accArray.clear();
        }
        accArray.add(f);
    }

    public static void setisCharge(boolean b)
    {
        isCharge=b;
    }

    public static void setAmbientData(float lux)
    {
        ambientData = lux;
    }

    /**
     * check the accelerometer if it is moving or not moving
      */
    public static boolean checkdifference(float f,ArrayList<Float> accArray){
        for(int i=0;i<accArray.size();i++)
        {
            if(accArray.get(i)>f+ACC_FIX||accArray.get(i)<f-ACC_FIX){
                return false;
            }
        }

        return true;
    }

    public static void setWEAR_ACC(boolean f)
    {
        IS_WEAR_ACC= f;
    }

    public static void setWEAR_AMB(boolean i)
    {
        IS_WEAR_AMB=i;
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("SleepStop-Logging", "--- onDestroy");
        // Unregister accelerometer sensor
        flag=false;
    }
} public class WiFiSensor extends Service implements SensorConnector {

	private static long WIFI_LOG_INTERVAL = 60000L;
	private WifiManager wifimanager;

	private com.ubiqlog.core.DataAcquisitor dataAcq;

	private Handler objHandler = new Handler();

	private Runnable doWifiLogging = new Runnable() {
		public void run() {
			readSensor();
			objHandler.postDelayed(doWifiLogging, WIFI_LOG_INTERVAL);
		}
	};
	public void onCreate() {
		Log.d("WIFI-Logging", "--- onCreate");
		SensorCatalouge sencat = new SensorCatalouge(getApplicationContext());
		try {
			ArrayList<SensorObj> sens = sencat.getAllSensors();
			for (int i = 0; i < sens.size(); i++) {
				if (sens.get(i).getSensorName().equalsIgnoreCase("WIFI")) {
					String[] configs = sens.get(i).getConfigData();
					for (int j = 0; j < configs.length; j++) {
						String tmp[] = configs[j].split("=");
						if (tmp[0].trim().equalsIgnoreCase("Record Interval in ms")) {
							WIFI_LOG_INTERVAL = Long.parseLong(tmp[1]);
						}
					}
				}
			}
		} catch (Exception e) {
			Log.e("WIFI Sensor","----------Error reading the log interval from sensor catalouge-----"+ e.getLocalizedMessage());
			e.printStackTrace();
		}
	}

	
	public void onDestroy() {
		objHandler.removeCallbacks(doWifiLogging);
		Log.d("WiFi-Logging", "--- onDestroy");
	}

	public void onStart(Intent intent, int startId) {
		Log.d("Wifi-Logging", "--- onStart");
		readSensor();
		objHandler.postDelayed(doWifiLogging, WIFI_LOG_INTERVAL);
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d("Wifi-Logging", "--- onStartCommand");
		readSensor();
		objHandler.postDelayed(doWifiLogging, WIFI_LOG_INTERVAL);
		return START_STICKY;
	}



	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}
	
	@Override
	public void readSensor() {
		try {
			wifimanager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
//			if (wifimanager.isWifiEnabled() == false) {
//	            wifimanager.setWifiEnabled(true);
//	        } 
			if (wifimanager.isWifiEnabled() ) {
				List<ScanResult> resuls = wifimanager.getScanResults();
				
				StringBuilder jsonString ;
				Date currentDate = new Date();

				for (ScanResult res : resuls) {
//					Log.e("----WIFI Sensor run ---", res.toString());
					jsonString = new StringBuilder("");
					jsonString = jsonString.append("{\"WiFi\":{\"SSID\":\""
							+ res.SSID+ "\",\"BSSID\":\""+ res.BSSID+ 
							"\",\"capabilities\":\""+ res.capabilities+
							"\",\"level\":\""+res.level+
							"\",\"frequency\":\""+res.frequency+
							"\",\"time\":\""+ DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(currentDate)+ "\"}}");
//					Log.e("WIFI Sensor",jsonString.toString());
					DataAcquisitor.dataBuff.add(jsonString.toString());
					jsonString = null;
				} 
			}
		} catch (Exception e) {
			Log.e("[WiFiSensor] error:", e.getMessage()+ " Stack:" + Log.getStackTraceString(e));
		}
	}



} public class UbiqlogStatusBar extends Service {

	private NotificationManager notiman;
	private static final int HELLO_ID = 1;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		notiman = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

	}

	@Override
	public void onStart(Intent intent, int startId) {
		int icon = R.drawable.icon_outline; // icon from resources
		CharSequence tickerText = "Hello"; // ticker-text
		long when = System.currentTimeMillis(); // notification time
		Context context = getApplicationContext(); // application Context
		CharSequence contentTitle = "UbiqLog notification"; // expanded message
															// title
		CharSequence contentText = "Hello !"; // expanded message text

		Intent notificationIntent = new Intent(this, MainUI.class);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);


		//Notification notification = new Notification(icon, tickerText, when);
		//notification.setLatestEventInfo(context, contentTitle, contentText,contentIntent);
		Notification notification = new NotificationCompat.Builder(this)
				.setSmallIcon(icon)
				.setContentTitle(contentTitle)
				.setContentText(contentText)
				.build();

		notiman.notify(HELLO_ID, notification);
	}

	@Override
	public void onDestroy() {
		notiman.cancel(HELLO_ID);
	}

} public class FeatureCheck {
    public static boolean hasBluetoothFeature(Context context) {
        boolean status = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
        //Log.d("Features > Bluetooth: ", String.valueOf(status));
        return status;
    }

    public static boolean hasLightFeature(Context context) {
        boolean status = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_LIGHT);
        //Log.d("Features > Ambient Light Sensor: ", String.valueOf(status));
        return status;
    }

    public static boolean hasHeartrateFeature(Context context) {
        boolean status = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_HEART_RATE);
        //Log.d("Features > Heartrate Sensor: ", String.valueOf(status));
        return status;
    }
} public class IOManager {
	String datenow = new String();
	private String currentFileName = new String();
	private String strPath;

	public IOManager() {
		this.strPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + Setting.DEFAULT_FOLDER;
	}

	public IOManager(String filename, String homeFolder) {
		this.strPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + homeFolder;
		this.currentFileName = filename;
	}

	public String getPath() {
		return strPath;
	}

	public String getCurrentFilename() {
		return  currentFileName + ".txt";
	}



	public void logData(ArrayList<String> inArr) {
		FileWriter writer;
		datenow = DateFormat.getDateInstance(DateFormat.SHORT).format(System.currentTimeMillis());
		SimpleDateFormat dateformat = new SimpleDateFormat("M-d-yyyy");
		//datenow = DateFormat.getDateInstance(DateFormat.SHORT).format(System.currentTimeMillis());
		//datenow = datenow.replace("/", "-");
		try {
			File logFile = new File(Setting.Instance(null).getLogFolder() + "/" + "log_" + dateformat.format(new Date()) + ".txt"); //datenow+ ".txt");
			writer = new FileWriter(logFile, true);
			if (!logFile.exists()) {
				logFile.createNewFile();
			}
			Iterator<String> it = inArr.iterator();
			while (it.hasNext()) {
				String aaa = it.next();
				writer.append(aaa+ System.getProperty("line.separator"));
			}
			writer.flush();
			writer.close();
			writer = null;

		} catch (Exception e) {
			
			 Log.e("DataAggregator", "--------Failed to write in a file-----" + e.getMessage() + "; Stack: " + Log.getStackTraceString(e));
			
		}
	}


	// Added by AP
	// Uses a file name passed into the IOManager
	public boolean logData(DataAcquisitor dataAcq, boolean append) {
		if (dataAcq.getDataBuffer().size() <= 0) {
			return false;
		}
		//File dirs = new File(getPath() + dataAcq.getFolderName());
		File dirs = new File(getPath());
		if (!dirs.exists()) {
			dirs.mkdirs();
		}

		String fileName = Setting.filenameFormat.format(new Date()) + "_" + getCurrentFilename();
		File logFile = new File(dirs, fileName);
		try {
			FileWriter writer = new FileWriter(logFile, append);
			for (String s : dataAcq.getDataBuffer()) {
				writer.append(s + System.getProperty("line.separator"));
			}
			writer.flush();
			writer.close();
			return true;

		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	public void logError(String msg) {
		PrintWriter printWr;
		Date a = new Date (System.currentTimeMillis());
		String errorDate = a.getDate()+"-"+a.getMonth()+"-"+a.getYear();
		File errorFile = new File(Setting.Instance(null).getLogFolder(), "error_"+errorDate+".txt");
		try {
			printWr = new PrintWriter(new FileWriter(errorFile, true));
			printWr.append(msg + System.getProperty("line.separator"));
			printWr.flush();
			printWr.close();
			printWr = null;
		} catch (Exception ex) {
			Log.e("IOManager.logError", ex.getMessage(), ex);
		}
	}

}
import android.app.Application;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.ubiqlog.common.Setting;
import com.ubiqlog.sensors.AccelerometerSensor;
import com.ubiqlog.sensors.ActivitySensor;
import com.ubiqlog.sensors.AmbientLightSensor;
import com.ubiqlog.sensors.ApplicationSensor;
import com.ubiqlog.sensors.AudioSensor;
import com.ubiqlog.sensors.BatterySensor;
import com.ubiqlog.sensors.BluetoothSensor;
import com.ubiqlog.sensors.CallSensor;
import com.ubiqlog.sensors.InteractionSensor;
import com.ubiqlog.sensors.LocationGSSensor;
import com.ubiqlog.sensors.LocationSensor;
import com.ubiqlog.sensors.PictureSensor;
import com.ubiqlog.sensors.RawAudioSensor;
import com.ubiqlog.sensors.SMSSensor;
import com.ubiqlog.sensors.SensorObj;
import com.ubiqlog.sensors.SleepSensor;
import com.ubiqlog.sensors.WiFiSensor;
import com.ubiqlog.ui.UbiqlogStatusBar;
import com.ubiqlog.utils.FeatureCheck;
import com.ubiqlog.utils.IOManager;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
package com.ubiqlog.core;




//import com.ubiqlog.sensors.BluetoothSensor_NOTIMER;

public class Engine extends Service {
	
//	private Context ctx = getApplicationContext();
	private Context ctx = getBaseContext();
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate(){
		try {
			IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
			BroadcastReceiver asubiqlog = new AutoStartUbiqlog() ;
			registerReceiver(asubiqlog,filter);
			
			Log.e("[Engine]","---onCreate 4m UBIQLOG");
			startRecording(getApplicationContext(), getApplication());
			
			if (!(Setting.SILENT_MODE)) {
				Intent notiI = new Intent();
				notiI.setClass(getApplicationContext(), UbiqlogStatusBar.class);
				startService(notiI);
			}

			String msgToast = "Start the Logging Process.";
			Toast toast = Toast.makeText(getApplicationContext(), msgToast, Toast.LENGTH_SHORT);
			toast.show();

		} catch (Exception e) {
			IOManager ioerror = new IOManager();
			ioerror.logError(e.getLocalizedMessage());
			Log.e("[Engine]", "-----------ERROR:" + e.getLocalizedMessage());
			e.printStackTrace();
		}
	}
	/**
	 * Run UbiqLog after boot
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
//		Log.e("[Engine]","----onStartCommand 4m UBIQLOG");
		try {
			startRecording(getApplicationContext(), getApplication());

			String msgToast = "Start the Logging Process.";
			Toast toast = Toast.makeText(getApplicationContext(), msgToast, Toast.LENGTH_SHORT);
			toast.show();

		} catch (Exception e) {
			IOManager ioerror = new IOManager();
			ioerror.logError(e.getLocalizedMessage());
			Log.e("[Engine]", "-----------ERROR:" + e.getLocalizedMessage());
			e.printStackTrace();
		}
		return START_STICKY;
	}
	
	public static void startRecording(Context ctx, Application app) throws Exception {

		File audioDir = new File(com.ubiqlog.common.Setting.Instance(ctx).getLogFolder());
		if ((audioDir.mkdir())) {
			Log.d("[core.Engine.startRecording]", "-------AUDIO DIRECTORY ALREADY CREATED--------");
		} else {
			Log.d("[core.Engine.startRecording]","-------AUDIO DIRECTORY IS NOT CREATED PROBABLY IT ALREADY EXISTS--------");
		}

		SensorCatalouge senCat = new SensorCatalouge(ctx);
		ArrayList<SensorObj> allsens = senCat.getAllSensors();

		// class names of enabled sensors and annotation classnames
		HashSet<SensorObj> sensors = new HashSet<SensorObj>(); 
		
		for (int i = 0; i < allsens.size(); i++) {
			String sensorName = allsens.get(i).getSensorName();
			String[] configdata = allsens.get(i).getConfigData();
			String[] isenable = configdata[0].split("=");
			isenable[1] = isenable[1].trim();
			
			if (isenable[1].equalsIgnoreCase("yes")) {
//				Log.d("[core.Engine.startRecording]","------------------Sensor:" + sensorName+ " is enable");
				sensors.add(allsens.get(i));
			}
			String annotation = allsens.get(i).getAnnotationCalss();
			if (sensorName.equals("SMS") && annotation != null) {
				com.ubiqlog.common.Setting.Instance(ctx).SMS_ANNOTATION = true;
			}
			if (sensorName.equals("CALL") && annotation != null) {
				com.ubiqlog.common.Setting.Instance(ctx).CALL_ANNOTATION = true;
			}
		}
		
		Intent i8 = new Intent();
		i8.setClass(app, DataAggregator.class);
		ctx.startService(i8);

		Iterator<SensorObj> itr = sensors.iterator();
		while (itr.hasNext()) {
			SensorObj cs = itr.next();
			//Log.e("Check",""+cs.getSensorName());
			try {
				if (cs.getSensorName().equalsIgnoreCase("ACTIVITY")){
					int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(ctx);
					if(resp == ConnectionResult.SUCCESS){
						Intent i = new Intent();
						i.setClassName(app, cs.getClassName()) ;
						ctx.startService(i);
					}else{
						Log.e("[Engine]", "Google Play Service hasn't installed");
					}
				} else if (cs.getSensorName().contains("LOCATION")){
					int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(ctx);
					if(resp == ConnectionResult.SUCCESS){
						Log.e("[Engine]", "Google Play Service is installed and available.");
						Intent i = new Intent();
						i.setClassName(app,  com.ubiqlog.sensors.LocationGSSensor.class.getName()) ;
						ctx.startService(i);
					}else{
						Log.e("[Engine]", "Google Play Service hasn't installed.");
						Intent i = new Intent();
						i.setClassName(app,  com.ubiqlog.sensors.LocationSensor.class.getName()) ;
						ctx.startService(i);
					}
				} else if (cs.getSensorName().contains("AMBIENT") && FeatureCheck.hasLightFeature(ctx)) { // other sensors and not Google API based