Android Open Source - HarleyDroid Harley Droid Service






From Project

Back to project page HarleyDroid.

License

The source code is released under:

GNU General Public License

If you think the Android project HarleyDroid listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

//
// HarleyDroid: Harley Davidson J1850 Data Analyser for Android.
///* w  w  w.j  a  va 2  s  .  c o m*/
// Copyright (C) 2010-2012 Stelian Pop <stelian@popies.net>
//
// 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 org.harleydroid;

import java.lang.ref.WeakReference;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class HarleyDroidService extends Service
{
  private static final boolean D = false;
  private static final String TAG = HarleyDroidService.class.getSimpleName();

  private static final int MSG_NONE = 0;
  private static final int MSG_CONNECTED = 1;
  private static final int MSG_DISCONNECTED = 2;
  private static final int MSG_START_POLL = 3;
  private static final int MSG_STARTED_POLL = 4;
  private static final int MSG_START_SEND = 5;
  private static final int MSG_STARTED_SEND = 6;
  private static final int MSG_SET_SEND = 7;
  private static final int MSG_DISCONNECT = 8;

  private static final int STATE_DISCONNECT = 1;
  private static final int STATE_TO_DISCONNECT = 2;
  private static final int STATE_CONNECT = 3;
  private static final int STATE_TO_CONNECT = 4;
  private static final int STATE_POLL = 5;
  private static final int STATE_TO_POLL = 6;
  private static final int STATE_SEND = 7;
  private static final int STATE_TO_SEND = 8;
  private static final int STATE_WAIT_RECONNECT = 9;

  private final IBinder binder = new HarleyDroidServiceBinder();
  private HarleyDroidLogger mLogger = null;
  private HarleyData mHD;
  private int mNotifyId;
  private NotificationCompat.Builder mNotifyBuilder;
  private NotificationManager mNotificationManager;
  private Handler mHandler = null;
  private String mInterfaceType = null;
  private BluetoothDevice mDevice = null;
  private J1850Interface mInterface = null;
  private boolean mLogging = false;
  private boolean mMetric = true;
  private boolean mGPS = true;
  private boolean mLogRaw = false;
  private boolean mLogUnknown = false;
  private boolean mAutoReconnect = false;
  private Thread mReconThread = null;
  private int mReconnectDelay = 0;
  private int mCurrentState = STATE_DISCONNECT;
  private int mWantedState = STATE_DISCONNECT;
  private String mSendType[];
  private String mSendTA[];
  private String mSendSA[];
  private String mSendCommand[];
  private String mSendExpect[];
  private int mSendTimeout[];
  private int mSendDelay;
  protected SharedPreferences mPrefs;
  private Handler mServiceHandler;

  @Override
  public void onCreate() {
    super.onCreate();
    if (D) Log.d(TAG, "onCreate()");

    mPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    mHD = new HarleyData(mPrefs);
    mServiceHandler = new HarleyDroidServiceHandler(this);

    mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    mNotifyId = 1;
    mNotifyBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_stat_notify_harleydroid)
            .setContentTitle(getText(R.string.notification_label))
            .setOngoing(true)
            .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, HarleyDroidDashboard.class), 0));
    notify(R.string.notification_connecting);
    startForeground(mNotifyId, mNotifyBuilder.build());
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if (D) Log.d(TAG, "onDestroy()");
  }

  public void doDestroy() {
    if (D) Log.d(TAG, "doDestroy()");

    doDisconnect();
    mNotificationManager.cancel(mNotifyId);
    mNotificationManager = null;
    mHD.destroy();
    stopSelf();
  }

  @Override
  public IBinder onBind(Intent intent) {
    if (D) Log.d(TAG, "onBind()");

    return binder;
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    if (D) Log.d(TAG, "onStartCommand()");

    return START_STICKY;
  }

  public class HarleyDroidServiceBinder extends Binder {
    HarleyDroidService getService() {
      return HarleyDroidService.this;
    }
  }

  public HarleyData getHarleyData() {
    return mHD;
  }

  public void setHandler(Handler handler) {
    if (D) Log.d(TAG, "setHandler()");

    mHandler = handler;
  }

  public void setLogging(boolean logging, boolean metric, boolean gps, boolean logRaw, boolean logUnknown) {
    mLogging = logging;
    mMetric = metric;
    mGPS = gps;
    mLogRaw = logRaw;
    mLogUnknown = logUnknown;
  }

  public void setAutoReconnect(boolean autoReconnect, int reconnectDelay) {
    mAutoReconnect = autoReconnect;
    mReconnectDelay = reconnectDelay;
  }

  public void setInterfaceType(String interfaceType, BluetoothDevice dev) {
    boolean reconnect = (mInterface != null);

    if (mInterfaceType == null ||
      !mInterfaceType.equals(interfaceType) ||
      (!HarleyDroid.EMULATOR && (mDevice == null ||
                     !mDevice.getAddress().equals(dev.getAddress())))) {

      if (D) Log.d(TAG, "setInterfaceType(" + interfaceType + ")");

      mInterfaceType = interfaceType;
      mDevice = dev;
      if (reconnect)
        doDisconnect();
      if (HarleyDroid.EMULATOR)
        mInterface = new EmulatorInterface(this);
      else {
        if (interfaceType.equals("elm327"))
          mInterface = new ELM327Interface(this, dev);
        else if (interfaceType.equals("hdi"))
          mInterface = new HarleyDroidInterface(this, dev);
      }
      mCurrentState = STATE_DISCONNECT;
      if (reconnect)
        stateMachine();
    }
  }

  public boolean isInitialized() {
    return mInterface != null;
  }

  private void notify(int id) {
    if (mNotificationManager != null) {
      CharSequence text = getText(id);
      mNotifyBuilder.setContentText(text);
      mNotificationManager.notify(mNotifyId, mNotifyBuilder.build());
    }
  }

  private void doDisconnect() {
    if (mReconThread != null)
      mReconThread.interrupt();
    if (mLogger != null) {
      mHD.removeHarleyDataDashboardListener(mLogger);
      mHD.removeHarleyDataDiagnosticsListener(mLogger);
      mHD.removeHarleyDataRawListener(mLogger);
      mLogger.stop();
      mLogger = null;
    }
    if (mInterface != null)
      mInterface.disconnect();
  }

  private void stateMachine() {
    if (D) Log.d(TAG, "stateMachine(): transition from " + mCurrentState + " to " + mWantedState);

    if (mCurrentState == mWantedState)
      return;

    switch (mWantedState) {
    case STATE_CONNECT:
      switch (mCurrentState) {
      case STATE_DISCONNECT:
      case STATE_WAIT_RECONNECT:
        mCurrentState = STATE_TO_CONNECT;
        notify(R.string.notification_connecting);
        mHandler.obtainMessage(HarleyDroid.STATUS_CONNECTING, -1, -1).sendToTarget();
        mInterface.connect(mHD);
        return;
      case STATE_POLL:
      case STATE_SEND:
      case STATE_TO_DISCONNECT:
      case STATE_TO_CONNECT:
      case STATE_TO_POLL:
      case STATE_TO_SEND:
        /* nothing to done, wait for state to settle */
        return;
      }
      break;
    case STATE_DISCONNECT:
      switch (mCurrentState) {
      case STATE_CONNECT:
      case STATE_SEND:
      case STATE_POLL:
      case STATE_WAIT_RECONNECT:
        doDestroy();
        return;
      case STATE_TO_DISCONNECT:
      case STATE_TO_CONNECT:
      case STATE_TO_POLL:
      case STATE_TO_SEND:
        /* nothing to done, wait for state to settle */
        return;
      }
      return;
    case STATE_POLL:
      switch (mCurrentState) {
      case STATE_DISCONNECT:
      case STATE_WAIT_RECONNECT:
        mCurrentState = STATE_TO_CONNECT;
        notify(R.string.notification_connecting);
        mHandler.obtainMessage(HarleyDroid.STATUS_CONNECTING, -1, -1).sendToTarget();
        mInterface.connect(mHD);
        return;
      case STATE_CONNECT:
      case STATE_SEND:
        mCurrentState = STATE_TO_POLL;
        mInterface.startPoll();
        return;
      case STATE_TO_DISCONNECT:
      case STATE_TO_CONNECT:
      case STATE_TO_POLL:
      case STATE_TO_SEND:
        /* nothing to done, wait for state to settle */
        return;
      }
      break;
    case STATE_SEND:
      switch (mCurrentState) {
      case STATE_DISCONNECT:
      case STATE_WAIT_RECONNECT:
        mCurrentState = STATE_TO_CONNECT;
        notify(R.string.notification_connecting);
        mHandler.obtainMessage(HarleyDroid.STATUS_CONNECTING, -1, -1).sendToTarget();
        mInterface.connect(mHD);
        return;
      case STATE_CONNECT:
      case STATE_POLL:
        mCurrentState = STATE_TO_SEND;
        mInterface.startSend(mSendType, mSendTA, mSendSA, mSendCommand, mSendExpect, mSendTimeout, mSendDelay);
        return;
      case STATE_TO_DISCONNECT:
      case STATE_TO_CONNECT:
      case STATE_TO_POLL:
      case STATE_TO_SEND:
        /* nothing to done, wait for state to settle */
        return;
      }
      break;
    case STATE_WAIT_RECONNECT:
      switch (mCurrentState) {
      case STATE_DISCONNECT:
        mCurrentState = STATE_WAIT_RECONNECT;
        return;
      case STATE_CONNECT:
      case STATE_POLL:
      case STATE_TO_DISCONNECT:
      case STATE_TO_CONNECT:
      case STATE_TO_POLL:
      case STATE_TO_SEND:
        /* nothing to done, wait for state to settle */
        return;
      }
      break;
    }
    if (D) Log.d(TAG, "stateMachine(): bad state transition from " + mCurrentState + " to " + mWantedState);
  }

  public void handleMessage(Message msg) {
    if (D) Log.d(TAG, "handleMessage " + msg.what);

    switch (msg.what) {
    case MSG_NONE:
      mReconThread = null;
      mWantedState = msg.arg1;
      break;
    case MSG_CONNECTED:
      mHandler.obtainMessage(HarleyDroid.STATUS_CONNECTED, -1, -1).sendToTarget();
      HarleyDroidService.this.notify(R.string.notification_connected);
      J1850.resetCounters();
      mCurrentState = STATE_CONNECT;
      if (mLogging) {
        mLogger = new HarleyDroidLogger(HarleyDroidService.this, mMetric, mGPS, mLogRaw, mLogUnknown);
        mLogger.start();
        mHD.addHarleyDataDashboardListener(mLogger);
        mHD.addHarleyDataDiagnosticsListener(mLogger);
        mHD.addHarleyDataRawListener(mLogger);
      }
      break;
    case MSG_DISCONNECT:
      mHandler.obtainMessage(HarleyDroid.STATUS_NONE, -1, -1).sendToTarget();
      mWantedState = STATE_DISCONNECT;
      break;
    case MSG_DISCONNECTED:
      mHandler.obtainMessage(msg.arg1, -1, -1).sendToTarget();
      mCurrentState = STATE_DISCONNECT;
      mHD.savePersistentData();
      if (mAutoReconnect) {
        final int lastState = mWantedState;
        HarleyDroidService.this.notify(R.string.notification_autorecon);
        mHandler.obtainMessage(HarleyDroid.STATUS_AUTORECON, -1, -1).sendToTarget();

        doDisconnect();
        mReconThread = new Thread() {
          public void run() {
            setName("HarleyDroidService: reconThread");
            try {
              Thread.sleep(mReconnectDelay * 1000);
              //mServiceHandler.removeCallbacksAndMessages(null);
              mServiceHandler.obtainMessage(MSG_NONE, lastState, -1).sendToTarget();
              // try again to go to mWantedState
            } catch (InterruptedException e) {
            }
          }
        };
        mWantedState = STATE_WAIT_RECONNECT;
        mReconThread.start();
      }
      else {
        doDestroy();
        return;
      }
      break;
    case MSG_START_POLL:
      mWantedState = STATE_POLL;
      break;
    case MSG_STARTED_POLL:
      HarleyDroidService.this.notify(R.string.notification_polling);
      mCurrentState = STATE_POLL;
      break;
    case MSG_START_SEND:
      mWantedState = STATE_SEND;
      mSendType = msg.getData().getStringArray("type");
      mSendTA = msg.getData().getStringArray("ta");
      mSendSA = msg.getData().getStringArray("sa");
      mSendCommand = msg.getData().getStringArray("command");
      mSendExpect = msg.getData().getStringArray("expect");
      mSendTimeout = msg.getData().getIntArray("timeout");
      mSendDelay = msg.getData().getInt("delay");
      break;
    case MSG_STARTED_SEND:
      HarleyDroidService.this.notify(R.string.notification_diagnostics);
      mCurrentState = STATE_SEND;
      break;
    case MSG_SET_SEND:
      mInterface.setSendData(msg.getData().getStringArray("type"),
          msg.getData().getStringArray("ta"),
          msg.getData().getStringArray("sa"),
          msg.getData().getStringArray("command"),
          msg.getData().getStringArray("expect"),
          msg.getData().getIntArray("timeout"),
          msg.getData().getInt("delay"));
    }
    stateMachine();
  }

  public void connected() {
    if (D) Log.d(TAG, "connected()");
    //mServiceHandler.removeCallbacksAndMessages(null);
    mServiceHandler.obtainMessage(MSG_CONNECTED, -1, -1).sendToTarget();
  }

  public void disconnected(int error) {
    if (D) Log.d(TAG, "disconnected()" + mCurrentState + " " + mWantedState);
    //mServiceHandler.removeCallbacksAndMessages(null);
    mServiceHandler.obtainMessage(MSG_DISCONNECTED, error, -1).sendToTarget();
  }

  public void disconnect() {
    if (D) Log.d(TAG, "disconnect()" + mCurrentState + " " + mWantedState);
    //mServiceHandler.removeCallbacksAndMessages(null);
    mServiceHandler.obtainMessage(MSG_DISCONNECT, -1, -1).sendToTarget();
  }

  public void startPoll() {
    if (D) Log.d(TAG, "startPoll()");
    //mServiceHandler.removeCallbacksAndMessages(null);
    mServiceHandler.obtainMessage(MSG_START_POLL, -1, -1).sendToTarget();
  }

  public void startedPoll() {
    if (D) Log.d(TAG, "startedPoll()");
    //mServiceHandler.removeCallbacksAndMessages(null);
    mServiceHandler.obtainMessage(MSG_STARTED_POLL, -1, -1).sendToTarget();
  }

  public void startSend(String type[], String ta[], String sa[], String command[], String expect[], int timeout[], int delay) {
    if (D) Log.d(TAG, "send()");
    Message m = mServiceHandler.obtainMessage(MSG_START_SEND);
    Bundle b = new Bundle();
    b.putStringArray("type", type);
    b.putStringArray("ta", ta);
    b.putStringArray("sa", sa);
    b.putStringArray("command", command);
    b.putStringArray("expect", expect);
    b.putIntArray("timeout", timeout);
    b.putInt("delay", delay);
    m.setData(b);
    //mServiceHandler.removeCallbacksAndMessages(null);
    m.sendToTarget();
  }

  public void startedSend() {
    if (D) Log.d(TAG, "sendDone()");
    //mServiceHandler.removeCallbacksAndMessages(null);
    mServiceHandler.obtainMessage(MSG_STARTED_SEND, -1, -1).sendToTarget();
  }

  public void setSendData(String type[], String ta[], String sa[], String command[], String expect[], int timeout[], int delay) {
    if (D) Log.d(TAG, "setSendData()");
    Message m = mServiceHandler.obtainMessage(MSG_SET_SEND);
    Bundle b = new Bundle();
    b.putStringArray("type", type);
    b.putStringArray("ta", ta);
    b.putStringArray("sa", sa);
    b.putStringArray("command", command);
    b.putStringArray("expect", expect);
    b.putIntArray("timeout", timeout);
    b.putInt("delay", delay);
    m.setData(b);
    //mServiceHandler.removeCallbacksAndMessages(null);
    m.sendToTarget();
  }

  public boolean isPolling() {
    if (D) Log.d(TAG, "isPolling()");

    return (mCurrentState == STATE_POLL);
  }

  public boolean isSending() {
    if (D) Log.d(TAG, "isSending()");

    return (mCurrentState == STATE_SEND);
  }

  static class HarleyDroidServiceHandler extends Handler {
    private final WeakReference<HarleyDroidService> mHarleyDroidService;

      HarleyDroidServiceHandler(HarleyDroidService harleyDroidService) {
          mHarleyDroidService = new WeakReference<HarleyDroidService>(harleyDroidService);
      }

    @Override
    public void handleMessage(Message msg) {
      HarleyDroidService hds = mHarleyDroidService.get();
      if (hds != null)
        hds.handleMessage(msg);
    }
  }
}




Java Source Code List

org.harleydroid.About.java
org.harleydroid.ELM327Interface.java
org.harleydroid.EmulatorInterface.java
org.harleydroid.Eula.java
org.harleydroid.Gauge.java
org.harleydroid.HarleyDataDashboardListener.java
org.harleydroid.HarleyDataDiagnosticsListener.java
org.harleydroid.HarleyDataRawListener.java
org.harleydroid.HarleyData.java
org.harleydroid.HarleyDroidDashboardView.java
org.harleydroid.HarleyDroidDashboard.java
org.harleydroid.HarleyDroidDiagnosticsView.java
org.harleydroid.HarleyDroidDiagnostics.java
org.harleydroid.HarleyDroidGPS.java
org.harleydroid.HarleyDroidInterface.java
org.harleydroid.HarleyDroidLogger.java
org.harleydroid.HarleyDroidService.java
org.harleydroid.HarleyDroidSettings.java
org.harleydroid.HarleyDroid.java
org.harleydroid.J1850Interface.java
org.harleydroid.J1850.java
org.harleydroid.NonBlockingBluetoothSocket.java
org.harleydroid.VINDecoder.java