Android Open Source - interdroid-swan Evaluation Engine Service






From Project

Back to project page interdroid-swan.

License

The source code is released under:

Copyright (c) 2008-2011 Vrije Universiteit, The Netherlands All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the follo...

If you think the Android project interdroid-swan 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

package interdroid.swan.engine;
/*  w  w w  .  j ava2s.c  o  m*/
import interdroid.swan.ExpressionManager;
import interdroid.swan.R;
import interdroid.swan.SensorConfigurationException;
import interdroid.swan.SwanException;
import interdroid.swan.crossdevice.Converter;
import interdroid.swan.crossdevice.Pusher;
import interdroid.swan.sensors.SensorInterface;
import interdroid.swan.swansong.Expression;
import interdroid.swan.swansong.ExpressionFactory;
import interdroid.swan.swansong.Result;
import interdroid.swan.swansong.ValueExpression;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.PriorityQueue;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

public class EvaluationEngineService extends Service {

  private static final String TAG = "EvaluationEngine";

  private static final String DATABASE_NAME = "swan";
  private static final String TABLE = "expressions";
  private static final int DATABASE_VERSION = 1;
  private static final int NOTIFICATION_ID = 1;

  public static final String ACTION_REGISTER_REMOTE = "interdroid.swan.register_remote";
  public static final String ACTION_UNREGISTER_REMOTE = "interdroid.swan.unregister_remote";
  public static final String ACTION_NEW_RESULT_REMOTE = "interdroid.swan.new_result_remote";

  public static final String UPDATE_EXPRESSIONS = "interdroid.swan.UPDATE_EXPRESSIONS";
  public static final String UPDATE_SENSORS = "interdroid.swan.UPDATE_SENSORS";

  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  PriorityQueue<QueuedExpression> mEvaluationQueue = new PriorityQueue<QueuedExpression>();

  /** The context expressions, mapped by id. */
  private final HashMap<String, QueuedExpression> mRegisteredExpressions = new HashMap<String, QueuedExpression>() {
    /**
     *
     */
    private static final long serialVersionUID = -658408645837738007L;

    @Override
    public QueuedExpression remove(final Object id) {
      removeFromDb((String) id);
      return super.remove(id);
    }

    @Override
    public QueuedExpression put(final String key,
        final QueuedExpression value) {
      storeToDb(value);
      return super.put(key, value);
    }

  };

  Thread mEvaluationThread = new Thread() {
    public void run() {
      while (!interrupted()) {
        QueuedExpression head = mEvaluationQueue.peek();
        if (head == null) {
          Log.d(TAG, "Nothing to evaluate!");
          synchronized (mEvaluationThread) {
            try {
              mEvaluationThread.wait();
            } catch (InterruptedException e) {
              continue;
            }
          }
        } else {
          long deferUntil = head.getDeferUntil();
          if (deferUntil <= System.currentTimeMillis()) {
            // evaluate now
            try {
              // evaluation delay is the time in ms between when
              // the expression should be evaluated (as indicated
              // by deferuntil) and when it is really evaluated.
              // Normally the evaluation delay is neglectable, but
              // when the load is high, this can become
              // significant.
              long evaluationDelay;
              if (deferUntil != 0) {
                evaluationDelay = System.currentTimeMillis()
                    - deferUntil;
                // code below for debugging purposes
                if (evaluationDelay > 3600000) {
                  throw new RuntimeException(
                      "Weird evaluation delay: "
                          + evaluationDelay + ", "
                          + deferUntil);
                }
              } else {
                evaluationDelay = 0;
              }

              long start = System.currentTimeMillis();

              Result result = mEvaluationManager.evaluate(
                  head.getId(), head.getExpression(),
                  System.currentTimeMillis());

              long end = System.currentTimeMillis();

              // update with statistics: evaluationTime and evaluationDelay
              head.evaluated((end - start), evaluationDelay);

              if (head.update(result)) {
                Log.d(TAG, "Result: " + result);
                sendUpdate(head, result);
              }
              // re add the expression to the queue
              synchronized (mEvaluationThread) {
                mEvaluationQueue.remove(head);
                mEvaluationQueue.add(head);
              }
            } catch (SwanException e) {
              Log.d(TAG, "Failed to evaluate", e);
            }
          } else {
            synchronized (mEvaluationThread) {
              try {
                long waitTime = Math.max(
                    1,
                    head.getDeferUntil()
                        - System.currentTimeMillis());
                // Log.d(TAG, "Waiting for " + waitTime +
                // " ms.");
                mEvaluationThread.wait(waitTime);
                // Log.d(TAG, "Done waiting for " + waitTime
                // + " ms.");
              } catch (InterruptedException e) {
                continue;
              }
            }
          }
        }
      }
    }
  };

  NotificationManager mNotificationManager;
  Notification mNotification;
  EvaluationManager mEvaluationManager;

  /**
   * @return all expressions saved in the database.
   */
  private void restoreAfterBoot() {
    SQLiteDatabase db = openDb();

    try {
      Cursor c = db.query(TABLE, new String[] { "expression_id",
          "expression", "on_true", "on_false", "on_undefined",
          "on_new_values" }, null, null, null, null, null);
      if (c != null) {
        try {
          if (c.getCount() > 0) {
            while (c.moveToNext()) {
              try {
                String expressionId = c.getString(0);
                Expression expression = ExpressionFactory
                    .parse(c.getString(1));
                Intent onTrue = null;
                if (c.getString(2) != null) {
                  onTrue = Intent.parseUri(c.getString(2), 0);
                }
                Intent onFalse = null;
                if (c.getString(3) != null) {
                  onFalse = Intent
                      .parseUri(c.getString(3), 0);
                }
                Intent onUndefined = null;
                if (c.getString(4) != null) {
                  onUndefined = Intent.parseUri(
                      c.getString(4), 0);
                }
                Intent onNewValues = null;
                if (c.getString(5) != null) {
                  onNewValues = Intent.parseUri(
                      c.getString(5), 0);
                }

                doRegister(expressionId, expression, onTrue,
                    onFalse, onUndefined, onNewValues);
              } catch (Exception e) {
                Log.e(TAG, "Error while restoring after boot.",
                    e);
              }
            }
          }
        } finally {
          try {
            c.close();
          } catch (Exception e) {
            Log.w(TAG, "Got exception closing cursor.", e);
          }
        }
      }
    } finally {
      closeDb(db);
    }
    if (mRegisteredExpressions.size() == 0) {
      // that means, we tried to restore, but there is nothing active
      Log.d(TAG, "nothing to restore, shutting down...");
      stopSelf();
    }
  }

  /**
   * Delete's an expression from the database.
   * 
   * @param key
   *            The id for the expression.
   * @param type
   *            The type being removed.
   */
  private void removeFromDb(final String id) {
    SQLiteDatabase db = openDb();
    try {
      db.execSQL("DELETE FROM " + TABLE + " WHERE expression_id = ?",
          new String[] { id });
    } finally {
      closeDb(db);
    }
  }

  /**
   * Closes the expression database.
   */
  private void closeDb(final SQLiteDatabase db) {
    if (db != null) {
      db.close();
    }
  }

  /**
   * @return an open database for expressions.
   */
  private synchronized SQLiteDatabase openDb() {
    File dbDir = getDir("databases", Context.MODE_PRIVATE);
    Log.d(TAG, "Created db dir: " + dbDir);
    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(new File(dbDir,
        DATABASE_NAME), null);
    Log.d(TAG, "Got database version: " + db.getVersion());
    if (db.getVersion() < DATABASE_VERSION) {
      Log.d(TAG, "Creating table: " + TABLE);
      db.execSQL("DROP TABLE IF EXISTS " + TABLE);
      db.execSQL("CREATE TABLE "
          + TABLE
          + " (_id integer primary key autoincrement, expression_id string, expression string, on_true string, on_false string, on_undefined string, on_new_values string)");
      db.setVersion(DATABASE_VERSION);
    }
    return db;
  }

  /**
   * Stores an expression to the database.
   * 
   * @param key
   *            the key for the expression
   * @param value
   *            the expression
   * @param type
   *            the type being stored
   */
  private void storeToDb(final QueuedExpression queued) {
    SQLiteDatabase db = openDb();
    try {
      // Make sure it doesn't exist first in case we are reloading it.
      db.delete(TABLE, "expression_id=?", new String[] { queued.getId() });
      ContentValues values = new ContentValues();
      values.put("expression_id", queued.getId());
      values.put("expression", queued.getExpression().toParseString());
      if (queued.getOnTrue() != null) {
        values.put("on_true", queued.getOnTrue().toUri(0));
      }
      if (queued.getOnFalse() != null) {
        values.put("on_false", queued.getOnFalse().toUri(0));
      }
      if (queued.getOnUndefined() != null) {
        values.put("on_undefined", queued.getOnUndefined().toUri(0));
      }
      if (queued.getOnNewValues() != null) {
        values.put("on_new_values", queued.getOnNewValues().toUri(0));
      }
      db.insert(TABLE, "expression_id", values);
    } finally {
      closeDb(db);
    }
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    // we can get several actions here, both from the API and from the
    // Sensors as well as from the Boot event
    if (intent == null) {
      Log.d(TAG,
          "huh? intent is null! This should never happen!! We will try to restore...");
      restoreAfterBoot();
      return START_STICKY;
    }
    String action = intent.getAction();
    if (ExpressionManager.ACTION_REGISTER.equals(action)) {
      String id = intent.getStringExtra("expressionId");
      try {
        Expression expression = ExpressionFactory.parse(intent
            .getStringExtra("expression"));

        Intent onTrue = intent.getParcelableExtra("onTrue");
        Intent onFalse = intent.getParcelableExtra("onFalse");
        Intent onUndefined = intent.getParcelableExtra("onUndefined");
        Intent onNewValues = intent.getParcelableExtra("onNewValues");
        doRegister(id, expression, onTrue, onFalse, onUndefined,
            onNewValues);
      } catch (Throwable t) {
        Log.d(TAG,
            "Failed to register expression: "
                + intent.getStringExtra("expression"), t);
      }
    } else if (ExpressionManager.ACTION_UNREGISTER.equals(action)) {
      String id = intent.getStringExtra("expressionId");
      doUnregister(id);
    } else if (ACTION_REGISTER_REMOTE.equals(action)) {
      Log.d(TAG, "Got remote registration");
      Bundle extras = intent.getExtras();
      String regId = extras.getString("source");
      String expId = extras.getString("id");
      String expressionString = extras.getString("data");
      try {
        Expression expression = ExpressionFactory
            .parse(expressionString);
        doRegister(regId + Expression.SEPARATOR + expId, expression,
            null, null, null, null);
      } catch (Throwable t) {
        Log.d(TAG, "Failed to register remote expression: "
            + expressionString, t);
      }
    } else if (ACTION_UNREGISTER_REMOTE.equals(action)) {
      Bundle extras = intent.getExtras();
      String regId = extras.getString("source");
      String expId = extras.getString("id");
      doUnregister(regId + Expression.SEPARATOR + expId);
    } else if (ACTION_NEW_RESULT_REMOTE.equals(action)) {
      Bundle extras = intent.getExtras();
      String id = extras.getString("id");
      Result result = null;
      try {
        result = (Result) Converter.stringToObject(extras
            .getString("data"));
      } catch (Exception e) {
        // should not happen
        throw new RuntimeException("Should not happen. Please debug!");
      }
      mEvaluationManager.newRemoteResult(id, result);
      doNotify(new String[] { id });
      return START_STICKY;
    } else if (SensorInterface.ACTION_NOTIFY.equals(action)) {
      String[] ids = intent.getStringArrayExtra("expressionIds");
      doNotify(ids);
      return START_STICKY;
    } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
      restoreAfterBoot();
    } else if (UPDATE_EXPRESSIONS.equals(action)) {
      // Use local broadcast manager because broadcast
      // needs only be send to this local app not other applications on
      // android
      LocalBroadcastManager.getInstance(this).sendBroadcast(
          getRegisteredExpressions());
      return START_STICKY;
    } else if (UPDATE_SENSORS.equals(action)) {
      LocalBroadcastManager.getInstance(this).sendBroadcast(
          getActiveSensors());
      return START_STICKY;
    }
    // after we handled the intent, we should update the notification and
    // the mode (foreground/background)
    if (mRegisteredExpressions.size() > 0) {
      updateNotification();
      startForeground(NOTIFICATION_ID, mNotification);
    } else {
      stopForeground(true);
    }
    return START_STICKY;
  }

  private Intent getActiveSensors() {
    Intent intent = new Intent(UPDATE_SENSORS);
    intent.putExtra("sensors", mEvaluationManager.activeSensorsAsBundle());
    return intent;
  }

  private void doRegister(final String id, final Expression expression,
      final Intent onTrue, final Intent onFalse,
      final Intent onUndefined, Intent onNewValues) {
    // handle registration
    Log.d(TAG, "registring id: " + id + ", expression: " + expression);
    if (mRegisteredExpressions.containsKey(id)) {
      // FAIL!
      Log.d(TAG, "failed to register, already contains id!");
      return;
    }
    try {
      mEvaluationManager.initialize(id, expression);
    } catch (SensorConfigurationException e) {
      // FAIL!
      e.printStackTrace();
      return;
    } catch (SensorSetupFailedException e) {
      // FAIL!
      e.printStackTrace();
      return;
    }
    synchronized (mEvaluationThread) {
      // add this expression to our registered expression, the queue and
      // notify the evaluation thread
      QueuedExpression queued = new QueuedExpression(id, expression,
          onTrue, onFalse, onUndefined, onNewValues);
      mRegisteredExpressions.put(id, queued);
      mEvaluationQueue.add(queued);
      mEvaluationThread.notify();
      LocalBroadcastManager.getInstance(this).sendBroadcast(
          getRegisteredExpressions());
    }

  }

  private Intent getRegisteredExpressions() {
    Intent intent = new Intent(UPDATE_EXPRESSIONS);
    Bundle[] expressions = new Bundle[mRegisteredExpressions.size()];
    int i = 0;
    for (String key : mRegisteredExpressions.keySet()) {
      expressions[i] = mRegisteredExpressions.get(key).toBundle();
      i++;
    }
    intent.putExtra("expressions", expressions);
    return intent;
  }

  private void doUnregister(final String id) {
    QueuedExpression expression = mRegisteredExpressions.get(id);
    if (expression == null) {
      // FAIL!
      Log.d(TAG, "Got spurious unregister for id: " + id);
      return;
    }
    // first stop evaluating
    synchronized (mEvaluationThread) {
      mRegisteredExpressions.remove(id);
      mEvaluationQueue.remove(expression);
      // do we really need to notify the evaluation thread here?
      mEvaluationThread.notify();
      LocalBroadcastManager.getInstance(this).sendBroadcast(
          getRegisteredExpressions());
    }
    // then stop sensing
    mEvaluationManager.stop(id, expression.getExpression());
  }

  // what we get back here are leaf ids of expressions.
  private void doNotify(String[] ids) {
    if (ids == null) {
      return;
    }
    for (String id : ids) {
      String rootId = getRootId(id);
      QueuedExpression queued = mRegisteredExpressions.get(rootId);
      if (queued == null) {
        // TODO: maybe broadcast a message to inform sensors to stop
        // producing values for the id
        Log.d(TAG, "Got notify, but no expression registered with id: "
            + rootId + " (original id: " + id
            + "), should we kill the sensor?");
        continue;
      }
      // Log.d(TAG, "Got notification for: " + queued);
      if (queued.getExpression() instanceof ValueExpression
          || !queued.isDeferUntilGuaranteed()) {
        // evaluate now!
        synchronized (mEvaluationThread) {
          // get it out the queue, update defer until, and put it
          // back, then notify the evaluation thread.
          mEvaluationQueue.remove(queued);
          mEvaluationManager.clearCacheFor(id);
          mEvaluationQueue.add(queued);
          mEvaluationThread.notifyAll();
        }
      }
    }
  }

  /*
   * (non-Javadoc)
   * 
   * @see android.app.Service#onCreate()
   */
  @SuppressWarnings("deprecation")
  @Override
  public final void onCreate() {
    super.onCreate();
    // construct the sensor manager
    mEvaluationManager = new EvaluationManager(this);
    // kick off the evaluation thread
    mEvaluationThread.start();
    // init the notification stuff
    mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    mNotification = new Notification(R.drawable.ic_stat_swan,
        "Swan active", System.currentTimeMillis());
    mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
    mNotification.flags |= Notification.FLAG_NO_CLEAR;
  }

  @Override
  public void onDestroy() {
    mEvaluationManager.destroyAll();
    mEvaluationThread.interrupt();
    super.onDestroy();
  }

  /**
   * Update notification.
   */
  @SuppressWarnings("deprecation")
  private void updateNotification() {
    Intent notificationIntent = new Intent(this,
        ExpressionViewerActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
        notificationIntent, 0);
    boolean hasRemote = false;
    for (String id : mRegisteredExpressions.keySet()) {
      if (id.contains(Expression.SEPARATOR)) {
        hasRemote = true;
        break;
      }
    }
    mNotification.icon = hasRemote ? R.drawable.ic_stat_swan_warning
        : R.drawable.ic_stat_swan;
    mNotification.setLatestEventInfo(this, "Swan",
        "number of expressions: " + mRegisteredExpressions.size(),
        contentIntent);
    mNotificationManager.notify(NOTIFICATION_ID, mNotification);
  }

  private void sendUpdate(QueuedExpression queued, Result result) {
    // we know it has changed
    if (queued.getId().contains(Expression.SEPARATOR)) {
      sendUpdateToRemote(queued.getId().split(Expression.SEPARATOR)[0],
          queued.getId().split(Expression.SEPARATOR)[1], result);
      return;
    }
    Intent update = queued.getIntent(result);
    if (update == null) {
      Log.d(TAG, "State change, but no update intent defined");
      return;
    }
    if (queued.getExpression() instanceof ValueExpression) {
      if (result.getValues() == null) {
        Log.d(TAG, "Update canceled, no values");
        return;
      }
      update.putExtra(ExpressionManager.EXTRA_NEW_VALUES,
          result.getValues());
    } else {
      update.putExtra(ExpressionManager.EXTRA_NEW_TRISTATE, result
          .getTriState().name());
      update.putExtra(ExpressionManager.EXTRA_NEW_TRISTATE_TIMESTAMP,
          result.getTimestamp());
    }
    try {
      String intentType = update
          .getStringExtra(ExpressionManager.EXTRA_INTENT_TYPE);
      if (intentType == null
          || intentType
              .equals(ExpressionManager.INTENT_TYPE_BROADCAST)) {
        sendBroadcast(update);
      } else if (intentType
          .equals(ExpressionManager.INTENT_TYPE_ACTIVITY)) {
        update.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(update);
      } else if (intentType.equals(ExpressionManager.INTENT_TYPE_SERVICE)) {
        startService(update);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private void sendUpdateToRemote(final String registrationId,
      final String expressionId, final Result result) {
    // pusher is async
    try {
      Pusher.push(registrationId, expressionId, ACTION_NEW_RESULT_REMOTE,
          Converter.objectToString(result));
    } catch (IOException e) {
      Log.d(TAG, "Exception in converting result to string", e);
    }
  }

  // helper function to strip the suffixes for an expression generated by the
  // evaluation engine and retrieve the original user id (the root id)
  private String getRootId(String id) {
    for (String suffix : Expression.RESERVED_SUFFIXES) {
      if (id.endsWith(suffix)) {
        return getRootId(id.substring(0, id.length() - suffix.length()));
      }
    }
    return id;
  }

}




Java Source Code List

interdroid.swan.ExpressionListener.java
interdroid.swan.ExpressionManager.java
interdroid.swan.SensorConfigurationException.java
interdroid.swan.SensorInfo.java
interdroid.swan.SwanException.java
interdroid.swan.TriStateExpressionListener.java
interdroid.swan.ValueExpressionListener.java
interdroid.swan.crossdevice.Converter.java
interdroid.swan.crossdevice.CrossDeviceReceiver.java
interdroid.swan.crossdevice.Pusher.java
interdroid.swan.crossdevice.Registry.java
interdroid.swan.crossdevice.SwanGCMConstants.java
interdroid.swan.crossdevice.SwanLakeActivity.java
interdroid.swan.engine.EvaluationEngineReceiver.java
interdroid.swan.engine.EvaluationEngineService.java
interdroid.swan.engine.EvaluationManager.java
interdroid.swan.engine.ExpressionViewerActivity.java
interdroid.swan.engine.QueuedExpression.java
interdroid.swan.engine.SensorSetupFailedException.java
interdroid.swan.engine.SensorViewerActivity.java
interdroid.swan.engine.TextProgressBar.java
interdroid.swan.sensors.AbstractConfigurationActivity.java
interdroid.swan.sensors.AbstractCuckooSensor.java
interdroid.swan.sensors.AbstractMemorySensor.java
interdroid.swan.sensors.AbstractSensorBase.java
interdroid.swan.sensors.AbstractVdbSensor.java
interdroid.swan.sensors.MonitorThread.java
interdroid.swan.sensors.SensorInterface.java
interdroid.swan.sensors.TimeSensor.java
interdroid.swan.sensors.impl.BatterySensor.java
interdroid.swan.sensors.impl.BluetoothSensor.java
interdroid.swan.sensors.impl.CalendarSensor.java
interdroid.swan.sensors.impl.CallSensor.java
interdroid.swan.sensors.impl.GyroscopeSensor.java
interdroid.swan.sensors.impl.IntentSensor.java
interdroid.swan.sensors.impl.LightSensor.java
interdroid.swan.sensors.impl.LocationSensor.java
interdroid.swan.sensors.impl.LogCatSensor.java
interdroid.swan.sensors.impl.MagnetometerSensor.java
interdroid.swan.sensors.impl.MovementSensor.java
interdroid.swan.sensors.impl.PolarHeartRate.java
interdroid.swan.sensors.impl.PressureSensor.java
interdroid.swan.sensors.impl.ProximitySensor.java
interdroid.swan.sensors.impl.ScreenSensor.java
interdroid.swan.sensors.impl.SignalStrengthSensor.java
interdroid.swan.sensors.impl.SmartLocationSensor.java
interdroid.swan.sensors.impl.SoundSensor.java
interdroid.swan.sensors.impl.TemperatureSensor.java
interdroid.swan.sensors.impl.TwitterSensor.java
interdroid.swan.sensors.impl.WifiSensor.java
interdroid.swan.sensors.impl.package-info.java
interdroid.swan.swansong.BinaryLogicOperator.java
interdroid.swan.swansong.ComparatorResult.java
interdroid.swan.swansong.Comparator.java
interdroid.swan.swansong.ComparisonExpression.java
interdroid.swan.swansong.ConstantValueExpression.java
interdroid.swan.swansong.ExpressionFactory.java
interdroid.swan.swansong.ExpressionParseException.java
interdroid.swan.swansong.Expression.java
interdroid.swan.swansong.HistoryReductionMode.java
interdroid.swan.swansong.LogicExpression.java
interdroid.swan.swansong.LogicOperator.java
interdroid.swan.swansong.MathOperator.java
interdroid.swan.swansong.MathValueExpression.java
interdroid.swan.swansong.ParseableEnum.java
interdroid.swan.swansong.Parseable.java
interdroid.swan.swansong.Result.java
interdroid.swan.swansong.SensorValueExpression.java
interdroid.swan.swansong.TimestampedValue.java
interdroid.swan.swansong.TriStateExpression.java
interdroid.swan.swansong.TriState.java
interdroid.swan.swansong.UnaryLogicOperator.java
interdroid.swan.swansong.ValueExpression.java
interdroid.swan.ui.EnterConstantDialog.java
interdroid.swan.ui.ExpressionBuilderActivity.java
interdroid.swan.ui.LaunchService.java
interdroid.swan.ui.MergeExpressionDialog.java
interdroid.swan.ui.NewExpressionDialog.java
interdroid.swan.ui.NewMathExpressionDialog.java
interdroid.swan.ui.SelectComparatorDialog.java
interdroid.swan.ui.SelectExpressionDialog.java
interdroid.swan.ui.SelectOperatorDialog.java
interdroid.swan.ui.SelectSensorDialog.java
interdroid.swan.ui.SelectTypedValueDialog.java
interdroid.swan.ui.package-info.java
interdroid.swan.util.SeekBarPreference.java
interdroid.swan.util.TimePreference.java