Project: Ohmage_Phone
/*
 * CCNx Android Helper Library. 
 * 
 * Copyright (C) 2010, 2011 Palo Alto Research Center, Inc. 
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License version 2.1 
 * as published by the Free Software Foundation.  
 * This library is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 * Lesser General Public License for more details. You should have received 
 * a copy of the GNU Lesser General Public License along with this library; 
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, 
 * Fifth Floor, Boston, MA 02110-1301 USA. 
 */
 
package org.ccnx.android.ccnlib; 
 
import java.util.List; 
import java.util.Properties; 
import java.util.Map.Entry; 
 
import org.ccnx.android.ccnlib.CCNxServiceStatus.SERVICE_STATUS; 
 
import android.app.Activity; 
import android.app.ActivityManager; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.IBinder; 
import android.os.RemoteException; 
import android.util.Log; 
 
/**
 * Wrap up the AIDL calls to a CCNxService.  Hide all the ugly RPC from 
 * the user of the services. 
 */
 
public abstract class CCNxWrapper { 
 public String TAG = "CCNxWrapper"
  
 private static final int DEFAULT_WAIT_FOR_READY = 60000
  
 private Object _lock = new Object(); 
  
 // Timeout to wait for ready in ms 
 private int waitForReadyTimeout = DEFAULT_WAIT_FOR_READY; 
  
 protected String serviceClassName = ""
 protected String serviceName = ""
 protected String serviceType = TAG; 
  
 protected ServiceConnection sConn; 
  
 protected Object iServiceLock = new Object(); 
 protected ICCNxService iService = null
  
 protected String OPTION_LOG_LEVEL = "0"
  
 protected Properties options = new Properties(); 
  
 CCNxServiceCallback _scb; 
 
 SERVICE_STATUS status = SERVICE_STATUS.SERVICE_OFF; 
  
 Context _ctx; 
  
 private IStatusCallback _cb = new IStatusCallback.Stub() { 
  public void status(int st){ 
   Log.d(TAG,"Received a status update.. " + status.name()); 
   synchronized(_lock) { 
    setStatus(SERVICE_STATUS.fromOrdinal(st)); 
    if(SERVICE_STATUS.SERVICE_FINISHED.equals(status)){ 
     setStatus(SERVICE_STATUS.SERVICE_OFF); 
    
   
   issueCallback(); 
  
 }; 
  
 public CCNxWrapper(Context ctx){ 
  _ctx = ctx; 
 
  
 public void setCallback(CCNxServiceCallback scb){ 
  _scb = scb; 
 
  
 protected void issueCallback(){ 
  _scb.newCCNxStatus(status); 
 
  
 /**
  * Start the service.  If the service is running we will not try to start it 
  * we will only try to bind to it 
  * @return true if we are bound, false if we are not, some error occurred 
  */
 
 public boolean startService(){ 
  Log.d(TAG,"startService()"); 
  if(!isRunning()){ 
   _ctx.startService(getStartIntent()); 
  else { 
   setStatus(SERVICE_STATUS.SERVICE_RUNNING); 
   issueCallback(); 
  
  bindService(); 
  return isBound(); 
 
  
 public void bindIfRunning(){ 
  Log.d(TAG,"If Running, Bind"); 
  if(isRunning()){ 
   bindService(); 
  
 
  
 /**
  * Check whether we are bound to the running service 
  * @return true if we are bound, false if we are not 
  */
 
 public boolean isBound(){ 
  synchronized(iServiceLock) { 
   return(iService != null); 
  
 
  
 protected void bindService(){ 
  sConn = new ServiceConnection(){ 
   public void onServiceConnected(ComponentName name, IBinder binder) { 
    Log.d(TAG, " Service Connected"); 
    synchronized(iServiceLock) { 
     iService = ICCNxService.Stub.asInterface(binder); 
     try { 
      iService.registerStatusCallback(_cb); 
      SERVICE_STATUS st = SERVICE_STATUS.fromOrdinal(iService.getStatus()); 
      Log.i(TAG,"bindService sets status: " + st); 
      setStatus(st); 
     catch (RemoteException e) { 
      // Did the service crash? 
      e.printStackTrace(); 
     
    
    issueCallback(); 
   
 
   public void onServiceDisconnected(ComponentName name) { 
    Log.i(TAG, " Service Disconnected"); 
    synchronized(iServiceLock) { 
     iService = null
    
     
   }  
  }; 
  _ctx.bindService(getBindIntent(), sConn, Context.BIND_AUTO_CREATE); 
 
  
 protected void unbindService(){ 
  synchronized(iServiceLock) { 
   if(isBound()){ 
    _ctx.unbindService(sConn); 
   
   iService = null
  
 
  
 public void stopService(){ 
  synchronized(iServiceLock) { 
   try { 
    ifnull != iService)  
     iService.stop(); 
   catch (RemoteException e) { 
    e.printStackTrace(); 
   
   unbindService(); 
  
  _ctx.stopService(new Intent(serviceName)); 
 
  
 public boolean isRunning(){ 
  ActivityManager am = (ActivityManager) _ctx.getSystemService(Activity.ACTIVITY_SERVICE); 
  List<ActivityManager.RunningServiceInfo> services = am.getRunningServices(50); 
  for(ActivityManager.RunningServiceInfo s : services){ 
   if(s.service.getClassName().equalsIgnoreCase(serviceClassName)){ 
    Log.d(TAG,"Found " + serviceClassName + " Service Running"); 
    return true
   }  
  
  Log.d(TAG,serviceClassName + " Not Running"); 
  return false
 
  
 /**
  * Sets the default timeout to be used for the waitForReady() call. 
  * Set it to 0 to not use a timeout. 
  *  
  * @param timeout timeout to be used in waitForReady() 
  */
 
 public void setWaitForReadyTimeout(int timeout){ 
  waitForReadyTimeout = timeout; 
 
  
 /**
  * waits until this service is in state RUNNING. (blocking call) 
  * There is a timeout associated with this wait. It can be changed 
  * using the setWaitForReadyTimeout() function.  If set to 0 it will wait forever. 
  *  
  * Alternatively, you can call waitForReady() and give it the timeout parameter as the argument. 
  *  
  * @return true if we are ready, false if we timed out 
  */
 
 public boolean waitForReady(){ 
  return waitForReady(waitForReadyTimeout); 
 
  
 
 /**
  * waits until the service is in state RUNNING. (blocking call) 
  * This function takes a timeout as a parameter. If the timeout is triggered it will 
  * return false. If timeout is set to 0 it won't be used and wait will block indefinitely. 
  *  
  * This function does not use the default value ser by setWaitForReadyTimeout(). 
  *  
  * @param timeout timeout passed to the wait() call. 
  * @return true if we are ready, false otherwise 
  */
 
 public boolean waitForReady(int timeout){ 
  synchronized(_lock){ 
   while(!SERVICE_STATUS.SERVICE_RUNNING.equals(status)){ 
    try { 
     if(timeout == 0){ 
      _lock.wait(); 
     else { 
      _lock.wait(waitForReadyTimeout); 
     
    catch (InterruptedException e) { 
     // Our timeout expired 
     return false
    
   
  
  return true
 
  
 public boolean isReady(){ 
  return (SERVICE_STATUS.SERVICE_RUNNING.equals(status)); 
 
  
 public void setOption(String key, String value) { 
  options.setProperty(key, value); 
 
  
 public void clearOptions() { 
  options.clear(); 
 
  
 protected void fillIntentOptions(Intent i) { 
  for(Entry<Object, Object> entry : options.entrySet()) { 
   String key = (String) entry.getKey(); 
   String value = (String) entry.getValue(); 
   i.putExtra(key, value);  
   Log.i(TAG, "Adding option " + key + " = " + value); 
  
 
  
 /**
  * Create an Intent to be issued to bind to the Service. It will be used as the parameter to bindService() 
  * This function is useful for adding "extras" to the intent 
  *  
  * @return Intent to start this service 
  */
 
 protected abstract Intent getBindIntent(); 
  
 /**
  * Create an Intent to be issued to start the Service. It will be used as the parameter to startService() 
  * This function is useful for adding "extras" to the intent 
  *  
  * @return Intent to start this service 
  */
 
 protected abstract Intent getStartIntent(); 
  
 public SERVICE_STATUS getStatus(){ 
  return status; 
 
  
 protected void setStatus(SERVICE_STATUS st) { 
  Log.i(TAG,"setStatus = " + st); 
  synchronized(_lock) { 
   status = st; 
   _lock.notifyAll(); 
  
 
}