/* * Created by Angel Leon (@gubatron), Alden Torres (aldenml) * Copyright (c) 2011-2013, FrostWire(R). All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.bt.download.android.gui.services; import com.bt.download.android.R; import com.bt.download.android.core.ConfigurationManager; import com.bt.download.android.core.Constants; import com.bt.download.android.core.player.CoreMediaPlayer; import com.bt.download.android.gui.Librarian; import com.bt.download.android.gui.PeerManager; import com.bt.download.android.gui.activities.MainActivity; import com.bt.download.android.gui.transfers.TransferManager; import com.frostwire.bittorrent.BTEngine; import com.frostwire.logging.Logger; import com.frostwire.util.ThreadPool; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Binder; import android.os.IBinder; import android.os.Process; import android.util.Log; import java.io.File; import java.util.concurrent.ExecutorService; /** * @author gubatron * @author aldenml * */ public class EngineService extends Service implements IEngineService { private static final Logger LOG = Logger.getLogger(EngineService.class); private static final String TAG = "FW.EngineService"; private final static long[] VENEZUELAN_VIBE = buildVenezuelanVibe(); private final IBinder binder; static final ExecutorService threadPool = ThreadPool.newThreadPool("Engine"); // services in background private final CoreMediaPlayer mediaPlayer; private byte state; private OnSharedPreferenceChangeListener preferenceListener; public EngineService() { binder = new EngineServiceBinder(); mediaPlayer = new ApolloMediaPlayer(this); registerPreferencesChangeListener(); state = STATE_DISCONNECTED; } @Override public IBinder onBind(Intent intent) { return binder; } @Override public int onStartCommand(Intent intent, int flags, int startId) { ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancelAll(); return START_STICKY; } @Override public void onDestroy() { LOG.debug("EngineService onDestroy"); ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).cancelAll(); stopServices(false); mediaPlayer.stop(); mediaPlayer.shutdown(); BTEngine.getInstance().stop(); new Thread("shutdown-halt") { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // ignore } Process.killProcess(Process.myPid()); } }.start(); } @Override public CoreMediaPlayer getMediaPlayer() { return mediaPlayer; } @Override public byte getState() { return state; } @Override public boolean isStarted() { return getState() == STATE_STARTED; } @Override public boolean isStarting() { return getState() == STATE_STARTING; } @Override public boolean isStopped() { return getState() == STATE_STOPPED; } @Override public boolean isStopping() { return getState() == STATE_STOPPING; } @Override public boolean isDisconnected() { return getState() == STATE_DISCONNECTED; } @Override public synchronized void startServices() { // hard check for TOS // if (!ConfigurationManager.instance().getBoolean(Constants.PREF_KEY_GUI_TOS_ACCEPTED)) { // return; // } if (!Librarian.instance().isExternalStorageMounted()) { return; } if (isStarted() || isStarting()) { return; } state = STATE_STARTING; Librarian.instance().invalidateCountCache(); //TransferManager.instance().loadTorrents(); BTEngine.getInstance().resume(); PeerManager.instance().clear(); if (ConfigurationManager.instance().getBoolean(Constants.PREF_KEY_NETWORK_USE_UPNP)) { PeerManager.instance().start(); } state = STATE_STARTED; Log.v(TAG, "Engine started"); } @Override public synchronized void stopServices(boolean disconnected) { if (isStopped() || isStopping() || isDisconnected()) { return; } state = STATE_STOPPING; BTEngine.getInstance().pause(); PeerManager.instance().clear(); try { PeerManager.instance().stop(); } catch (Throwable e) { LOG.error("Error stopping peer manager", e); } state = disconnected ? STATE_DISCONNECTED : STATE_STOPPED; Log.v(TAG, "Engine stopped, state: " + state); } @Override public ExecutorService getThreadPool() { return threadPool; } @Override public void notifyDownloadFinished(String displayName, File file) { try { Context context = getApplicationContext(); Intent i = new Intent(context, MainActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); i.putExtra(Constants.EXTRA_DOWNLOAD_COMPLETE_NOTIFICATION, true); i.putExtra(Constants.EXTRA_DOWNLOAD_COMPLETE_PATH, file.getAbsolutePath()); PendingIntent pi = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = new Notification(R.drawable.frostwire_notification, getString(R.string.download_finished), System.currentTimeMillis()); notification.vibrate = ConfigurationManager.instance().vibrateOnFinishedDownload() ? VENEZUELAN_VIBE : null; notification.number = TransferManager.instance().getDownloadsToReview(); notification.flags |= Notification.FLAG_AUTO_CANCEL; notification.setLatestEventInfo(context, getString(R.string.download_finished), displayName, pi); manager.notify(Constants.NOTIFICATION_DOWNLOAD_TRANSFER_FINISHED, notification); } catch (Throwable e) { Log.e(TAG, "Error creating notification for download finished", e); } } @Override public void shutdown() { stopForeground(true); stopSelf(); } private void registerPreferencesChangeListener() { preferenceListener = new OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(Constants.PREF_KEY_GUI_NICKNAME)) { PeerManager.instance().clear(); } } }; ConfigurationManager.instance().registerOnPreferenceChange(preferenceListener); } private static long[] buildVenezuelanVibe() { long shortVibration = 80; long mediumVibration = 100; long shortPause = 100; long mediumPause = 150; long longPause = 180; return new long[] { 0, shortVibration, longPause, shortVibration, shortPause, shortVibration, shortPause, shortVibration, mediumPause, mediumVibration }; } public class EngineServiceBinder extends Binder { public EngineService getService() { return EngineService.this; } } }