package de.tu.darmstadt.seemoo.ansian.control.threads; import android.app.Notification; import android.app.Service; import android.content.ActivityNotFoundException; import android.content.Intent; import android.net.Uri; import android.os.IBinder; import android.util.Log; import android.view.WindowManager; import android.widget.Toast; import de.greenrobot.event.EventBus; import de.greenrobot.event.Subscribe; import de.tu.darmstadt.seemoo.ansian.MainActivity; import de.tu.darmstadt.seemoo.ansian.control.SourceControl; import de.tu.darmstadt.seemoo.ansian.control.StateHandler; import de.tu.darmstadt.seemoo.ansian.control.events.ChangeChannelWidthEvent; import de.tu.darmstadt.seemoo.ansian.model.demodulation.Demodulation.DemoType; import de.tu.darmstadt.seemoo.ansian.model.preferences.MiscPreferences; import de.tu.darmstadt.seemoo.ansian.model.preferences.Preferences; import de.tu.darmstadt.seemoo.ansian.model.sources.IQSourceInterface; import de.tu.darmstadt.seemoo.ansian.model.sources.IQSourceInterface.SourceType; /** * This Service enables demodulating, recording and general data collection * while running in the background. * * @author Markus Grau and Steffen Kreis * */ public class AnsianService extends Service { private static MainActivity activity; private MiscPreferences preferences; private SourceControl sourceControl; private static final String LOGTAG = "ThreadHandler"; private Alarm alarm; public AnsianService() { activity = MainActivity.instance; preferences = Preferences.MISC_PREFERENCE; sourceControl = SourceControl.getInstance(); alarm = new Alarm(activity); EventBus.getDefault().register(this); } public Scheduler scheduler; public Demodulator demodulator; private FFTCalcThread fftCalc; public Scheduler getScheduler() { return scheduler; } @Override public void onCreate() { super.onCreate(); } /** * Will start AnSiAn. This includes creating a source (if null), open a * source (if not open), starting the scheduler (which starts the source) * and starting the processing loop. * * @param recording * @param demodulation * @return */ public boolean startService(DemoType demodulation) { alarm.start(); if (SourceControl.getSource() == null) { if (!SourceControl.getInstance().createSource()) return false; } SourceControl.getInstance().changeSource(); // check if the source is open. if not, open it! if (!sourceControl.isOpen()) { if (!sourceControl.openSource()) { Toast.makeText(activity, "Source not available (" + SourceControl.getSource().getName() + ")", Toast.LENGTH_LONG).show(); // StateHandler.stop(); return false; } return false; // we have to wait for the source to become ready... // onIQSourceReady() will call startAnalyzer() again... } else { if (!StateHandler.isStopped()) Log.d(LOGTAG, "" + getSource()); // Create a new instance of Scheduler and Processing Loop: scheduler = new Scheduler(getSource()); Log.d(LOGTAG, "" + scheduler); scheduler.start(); fftCalc = new FFTCalcThread(); fftCalc.start(); // Start the demodulator thread: demodulator = new Demodulator(scheduler.getDemodQueue(), getSource().getPacketSize(), demodulation); demodulator.start(); // Prevent the screen from turning off: activity.runOnUiThread(new Runnable() { @Override public void run() { activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }); } return true; } private IQSourceInterface getSource() { return SourceControl.getSource(); } public void setDemodulationMode(DemoType demod) { if (demodulator != null) demodulator.setDemodulationMode(demod); } /** * Will stop AnSiAn. This includes shutting down the scheduler (which turns * off the source), the processing loop and the demodulator if running. */ public void stopService() { alarm.stop(); // Stop the Scheduler if running: if (scheduler != null) { scheduler.stopScheduler(); } // Stop the Demodulator if running: if (demodulator != null) demodulator.stopDemodulator(); if (fftCalc != null) fftCalc.stopFFTCalcThread(); // Stop the scanner if running: // allow screen to turn off again: activity.runOnUiThread(new Runnable() { @Override public void run() { activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }); } @Override public void onDestroy() { EventBus.getDefault().unregister(this); // stop Service Toast.makeText(this, "service should be stopped", Toast.LENGTH_SHORT).show(); Log.d("test", "serviceOnDestroy was called"); stopService(); // close source if (getSource() != null && getSource().isOpen()) getSource().close(); // shut down RTL2832U driver if running IQSourceInterface source = getSource(); if (!StateHandler.isStopped() && source != null && source.getType() == SourceType.RTLSDR_SOURCE && preferences.isExternalSource()) { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("iqsrc://-x")); // -x is invalid. will // cause the driver // to shut down (if // running) startActivity(intent); } catch (ActivityNotFoundException e) { Log.e(LOGTAG, "onDestroy: RTL2832U is not installed"); } } super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { stopService(); stopSelf(); return super.onUnbind(intent); } @Subscribe public void onEvent(ChangeChannelWidthEvent event) { if (demodulator != null) { demodulator.setChannelWidth(event.getChannelWidth()); } } /* (non-Javadoc) * @see android.app.Service#onBind(android.content.Intent) */ @Override public IBinder onBind(Intent intent) { return null; } }