ConnectionManagerService.java :  » UnTagged » androboinc » sk » boinc » androboinc » service » Android Open Source

Android Open Source » UnTagged » androboinc 
androboinc » sk » boinc » androboinc » service » ConnectionManagerService.java
/* 
 * AndroBOINC - BOINC Manager for Android
 * Copyright (C) 2010, Pavol Michalec
 * 
 * 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 sk.boinc.androboinc.service;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import sk.boinc.androboinc.bridge.ClientBridge;
import sk.boinc.androboinc.bridge.ClientBridgeCallback;
import sk.boinc.androboinc.clientconnection.ClientReplyReceiver;
import sk.boinc.androboinc.clientconnection.ClientRequestHandler;
import sk.boinc.androboinc.clientconnection.NoConnectivityException;
import sk.boinc.androboinc.debug.Logging;
import sk.boinc.androboinc.util.ClientId;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;


public class ConnectionManagerService extends Service implements ClientRequestHandler, ClientBridgeCallback, ConnectivityListener {
  private static final String TAG = "ConnectionManagerService";

  private static final int TERMINATE_GRACE_PERIOD_CONN = 45;
  private static final int TERMINATE_GRACE_PERIOD_IDLE = 3;

  public class LocalBinder extends Binder {
    public ConnectionManagerService getService() {
      return ConnectionManagerService.this;
    }
  }

  private final IBinder mBinder = new LocalBinder();
  private final Handler mHandler = new Handler();
  private Runnable mTerminateRunnable = null;

  private ConnectivityStatus mConnectivityStatus = null;
  private ClientBridge mClientBridge = null;
  private Set<ClientBridge> mDyingBridges = new HashSet<ClientBridge>();
  private Set<ClientReplyReceiver> mObservers = new HashSet<ClientReplyReceiver>();
  private NetworkStatisticsHandler mNetStats = null;


  @Override
  public IBinder onBind(Intent intent) {
    if (Logging.DEBUG) Log.d(TAG, "onBind()");
    // Just make sure the service is running:
    startService(new Intent(this, ConnectionManagerService.class));
    return mBinder;
  }

  @Override
  public void onRebind(Intent intent) {
    if (mTerminateRunnable != null) {
      // There is Runnable to stop the service
      // We cancel that request now
      mHandler.removeCallbacks(mTerminateRunnable);
      mTerminateRunnable = null;
      if (Logging.DEBUG) Log.d(TAG, "onRebind() - canceled stopping of the service");
    }
    else {
      // This is not expected
      if (Logging.ERROR) Log.e(TAG, "onRebind() - mTerminateRunnable empty");
      // We just make sure the service is running
      // If service is still running, it's kept running anyway
      startService(new Intent(this, ConnectionManagerService.class));
    }
  }

  @Override
  public boolean onUnbind(Intent intent) {
    // The observers should be empty at this time (all are unbound from us)
    if (!mObservers.isEmpty()) {
      if (Logging.WARNING) Log.w(TAG, "onUnbind(), but mObservers is not empty");
      mObservers.clear();
    }
    // Create runnable which will stop service after grace period
    mTerminateRunnable = new Runnable() {
      @Override
      public void run() {
        // We remove reference to self
        mTerminateRunnable = null;
        // Disconnect client if still connected
        if (mClientBridge != null) {
          // Still connected to some client - disconnect it now
          disconnect();
        }
        // Stop service
        stopSelf();
        if (Logging.DEBUG) Log.d(TAG, "Stopped service");
      }
    };
    // Post the runnable to self - delayed by grace period
    long gracePeriod;
    if (mClientBridge != null) {
      gracePeriod = TERMINATE_GRACE_PERIOD_CONN * 1000;
    }
    else {
      gracePeriod = TERMINATE_GRACE_PERIOD_IDLE * 1000;
    }
    mHandler.postDelayed(mTerminateRunnable, gracePeriod);
    if (Logging.DEBUG) Log.d(TAG, "onUnbind() - Started grace period to terminate self");
    return true;
  }

  @Override
  public void onCreate() {
    if (Logging.DEBUG) Log.d(TAG, "onCreate()");
    // Add connectivity monitoring (to be notified when connection is down)
    mConnectivityStatus = new ConnectivityStatus(this, this);
    // Create network statistics handler
    mNetStats = new NetworkStatisticsHandler(this);
  }

  @Override
  public void onDestroy() {
    if (Logging.DEBUG) Log.d(TAG, "onDestroy()");
    // Clean-up connectivity monitoring
    mConnectivityStatus.cleanup();
    mConnectivityStatus = null;
    // Clean-up network statistics handler
    mNetStats.cleanup();
    mNetStats = null;
  }

  @Override
  public void onConnectivityLost() {
    if (mClientBridge != null) {
      // We are interested in this event only when connected
      if (Logging.DEBUG) Log.d(TAG, "onConnectivityLost() while connected to host " + mClientBridge.getClientId().getNickname());
      // TODO Handle connectivity loss
    }
  }

  @Override
  public void onConnectivityRestored(int connectivityType) {
    if (mClientBridge != null) {
      // We are interested in this event only when connected
      if (Logging.DEBUG) Log.d(TAG, "onConnectivityRestored() while connected to host " + mClientBridge.getClientId().getNickname() + ", connectivity type: " + connectivityType);
      // TODO Handle connectivity restoration
    }
  }

  @Override
  public void onConnectivityChangedType(int connectivityType) {
    if (mClientBridge != null) {
      // We are interested in this event only when connected
      if (Logging.DEBUG) Log.d(TAG, "onConnectivityChangedType() while connected to host " + mClientBridge.getClientId().getNickname() + ", new connectivity type: " + connectivityType);
      // TODO Handle connectivity type change
    }
  }

  @Override
  public void bridgeDisconnected(ClientBridge clientBridge) {
    // The bridge got disconnected (explicit disconnect, connect unsuccessful, abnormal close etc)
    if (mClientBridge == clientBridge) {
      // The currently connected bridge was disconnected.
      // This is unsolicited disconnect
      if (Logging.INFO) Log.i(TAG, "Unsolicited disconnect of ClientBridge");
      mClientBridge = null;
    }
    else {
      if (mDyingBridges.contains(clientBridge)) {
        // This is the bridge disconnected by us
        if (Logging.DEBUG) Log.d(TAG, "ClientBridge finished disconnect");
        mDyingBridges.remove(clientBridge);
      }
      else {
        // This is not expected
        if (Logging.WARNING) Log.w(TAG, "Unknown ClientBridge disconnected");
      }
    }
  }

  /**
   * Locally stores reference to the service user.
   * <p>
   * If bridge is connected, the reference is passed to bridge as well.
   * <br>
   * If bridge is not connected, the stored reference will be used later at connection time
   * and it will be passed to bridge then.
   * @param observer - user of the service
   */
  @Override
  public void registerStatusObserver(ClientReplyReceiver observer) {
    mObservers.add(observer);
    if (mClientBridge != null) {
      mClientBridge.registerStatusObserver(observer);
    }
    if (Logging.DEBUG) Log.d(TAG, "Attached new observer: " + observer.toString());
  }

  /**
   * Deletes locally stored reference to service user.
   * <p>
   * If bridge is connected, the reference is also passed to bridge, so it can be deleted there as well.
   * @param observer - user of the service
   */
  @Override
  public void unregisterStatusObserver(ClientReplyReceiver observer) {
    mObservers.remove(observer);
    if (mClientBridge != null) {
      mClientBridge.unregisterStatusObserver(observer);
    }
    if (Logging.DEBUG) Log.d(TAG, "Detached observer: " + observer.toString());
  }

  @Override
  public void connect(ClientId host, boolean retrieveInitialData) throws NoConnectivityException {
    if (Logging.DEBUG) Log.d(TAG, "connect() to host " + host.getNickname());
    if (mClientBridge != null) {
      // Connected to some client - disconnect it first
      disconnect();
    }
    if (mConnectivityStatus.isConnected()) {
      // Create new bridge first
      mClientBridge = new ClientBridge(this, mNetStats);
      // Propagate all current observers to bridge, so they will be informed about status
      Iterator<ClientReplyReceiver> it = mObservers.iterator();
      while (it.hasNext()) {
        ClientReplyReceiver observer = it.next();
        mClientBridge.registerStatusObserver(observer);
      }
      // Finally, initiate connection to remote client
      mClientBridge.connect(host, retrieveInitialData);
    }
    else {
      throw new NoConnectivityException();
    }
  }

  @Override
  public void disconnect() {
    if (mClientBridge != null) {
      if (Logging.DEBUG) Log.d(TAG, "disconnect() - started towards " + mClientBridge.getClientId().getNickname());
      mDyingBridges.add(mClientBridge);
      mClientBridge.disconnect();
      mClientBridge = null;
    }
    else {
      if (Logging.DEBUG) Log.d(TAG, "disconnect() - not connected already ");
    }
  }

  @Override
  public ClientId getClientId() {
    if (mClientBridge != null) {
      return mClientBridge.getClientId();
    }
    else {
      return null;
    }
  }

  @Override
  public void updateClientMode(ClientReplyReceiver callback) {
    if (mClientBridge != null) {
      mClientBridge.updateClientMode(callback);
    }
  }

  @Override
  public void updateHostInfo(ClientReplyReceiver callback) {
    if (mClientBridge != null) {
      mClientBridge.updateHostInfo(callback);
    }
  }

  @Override
  public void updateProjects(ClientReplyReceiver callback) {
    if (mClientBridge != null) {
      mClientBridge.updateProjects(callback);
    }
  }

  @Override
  public void updateTasks(ClientReplyReceiver callback) {
    if (mClientBridge != null) {
      mClientBridge.updateTasks(callback);
    }
  }

  @Override
  public void updateTransfers(ClientReplyReceiver callback) {
    if (mClientBridge != null) {
      mClientBridge.updateTransfers(callback);
    }
  }

  @Override
  public void updateMessages(ClientReplyReceiver callback) {
    if (mClientBridge != null) {
      mClientBridge.updateMessages(callback);
    }
  }

  @Override
  public void cancelScheduledUpdates(ClientReplyReceiver callback) {
    if (mClientBridge != null) {
      mClientBridge.cancelScheduledUpdates(callback);
    }
  }

  @Override
  public void runBenchmarks() {
    if (mClientBridge != null) {
      mClientBridge.runBenchmarks();
    }
  }

  @Override
  public void setRunMode(ClientReplyReceiver callback, int mode) {
    if (mClientBridge != null) {
      mClientBridge.setRunMode(callback, mode);
    }
  }

  @Override
  public void setNetworkMode(ClientReplyReceiver callback, int mode) {
    if (mClientBridge != null) {
      mClientBridge.setNetworkMode(callback, mode);
    }
  }

  @Override
  public void shutdownCore() {
    if (mClientBridge != null) {
      mClientBridge.shutdownCore();
    }
  }

  @Override
  public void doNetworkCommunication() {
    if (mClientBridge != null) {
      mClientBridge.doNetworkCommunication();
    }
  }

  @Override
  public void projectOperation(ClientReplyReceiver callback, int operation, String projectUrl) {
    if (mClientBridge != null) {
      mClientBridge.projectOperation(callback, operation, projectUrl);
    }
  }

  @Override
  public void taskOperation(ClientReplyReceiver callback, int operation, String projectUrl, String taskName) {
    if (mClientBridge != null) {
      mClientBridge.taskOperation(callback, operation, projectUrl, taskName);
    }
  }

  @Override
  public void transferOperation(ClientReplyReceiver callback, int operation, String projectUrl, String fileName) {
    if (mClientBridge != null) {
      mClientBridge.transferOperation(callback, operation, projectUrl, fileName);
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.