Android Open Source - commotion-android Mesh Service






From Project

Back to project page commotion-android.

License

The source code is released under:

GNU General Public License

If you think the Android project commotion-android 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

/*
 *  This file is part of Commotion Mesh Tether
 *  Copyright (C) 2010 by Szymon Jakubczak
 */*www . j a va 2  s  .com*/
 *  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 net.commotionwireless.meshtether;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Map;
import java.util.Properties;

import net.commotionwireless.meshtether.Util.MACAddress;
import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;

import net.commotionwireless.shell.*;

/**
 * Manages the running process, client list, and log
 */
public class MeshService extends android.app.Service {
  final static String TAG = "MeshService";
  // messages from the process
  final static int MSG_OUTPUT     = 1;
  final static int MSG_ERROR      = 2;
  // messages from self
  final static int MSG_EXCEPTION  = 3;
  final static int MSG_NETSCHANGE = 4;
  // requests from activities
  final static int MSG_START      = 5;
  final static int MSG_STOP       = 6;
  final static int MSG_ASSOC      = 7;
  final static int MSG_STATS      = 8;
  final static int MSG_STOP_OLSRD_OUTPUT = 10;
  // messages for the ProgressDialog
  final static int MSG_SHOW_PROGRESSDIALOG = 11;
  final static int MSG_HIDE_PROGRESSDIALOG = 12;
  // app states
  public final static int STATE_STOPPED  = 0;
  public final static int STATE_STARTING = 1;
  public final static int STATE_RUNNING  = 2; // process said OK

  // private state
  private int state = STATE_STOPPED;
  private WifiManager.WifiLock wifiLock;

  private String activeSSID = "";
  private String activeBSSID = "";
  private String activeIP = "";
  private String activeNetmask = "";
  private String activeIpGeneration = "";
  private String activeDNS = "";
  private String activeOlsrdConf = "";
  
  private Shell mShell;
  private ShellProcess WifiShellProcess;

  private PowerManager.WakeLock wakeLock;
  private BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      mHandler.sendEmptyMessage(MSG_NETSCHANGE);
    }
  };

  // public state
  public final Util.StyledStringBuilder log = new Util.StyledStringBuilder();

  final static int COLOR_ERROR    = 0xffff2222;
  final static int COLOR_LOG      = 0xff888888;//android.R.color.primary_text_dark;
  final static int COLOR_TIME     = 0xffffffff;

  public static class ClientData {
    final String remoteIP;
    final float linkQuality;
    final float neighborLinkQuality;
    final int linkCost;
    final int validityTime;
    boolean hasRouteToOther;
    boolean hasDefaultRoute;
    ClientData(String ip, float lq, float nlq, int lc, int vt) {
      remoteIP = ip;
      linkQuality = lq;
      neighborLinkQuality = nlq;
      linkCost = lc;
      validityTime = vt;
      hasRouteToOther = false;
      hasDefaultRoute = false;
    }
    @Override
    public String toString() { return remoteIP + " " + linkQuality + " " + neighborLinkQuality; }
    public String toNiceString() { return remoteIP; }
  }
  public final ArrayList<ClientData> clients = new ArrayList<ClientData>();
  public final Util.TrafficStats stats = new Util.TrafficStats();

  // WARNING: this is not entirely safe
  public static MeshService singleton = null;

  // cached for convenience
  private String if_lan = "";
  private Util.MACAddress if_mac = null;
  private MeshTetherApp app;
  private WifiManager wifiManager;
  private int currentNetId = -1;
  private ConnectivityManager connManager;
  private boolean filteringEnabled = false;
  private Method mStartForeground = null;

  /** public service interface */
  public void startRequest() {
    mHandler.sendEmptyMessage(MSG_START);
  }

  public void assocRequest() {
    mHandler.sendEmptyMessage(MSG_ASSOC);
  }

  public void stopRequest() {
    mHandler.sendEmptyMessage(MSG_STOP);
  }

  public void statsRequest(long delay) {
    Message msg = mHandler.obtainMessage(MSG_STATS);
    mHandler.sendMessageDelayed(msg, delay);
  }

  public int getState() {
    return state;
  }

  public boolean hasFiltering() {
    return filteringEnabled;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    singleton = this;
    
    mShell = Shell.getInstance();

    wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    try {
      mStartForeground = getClass().getMethod("startForeground", new Class[] {
          int.class, Notification.class});
    } catch (NoSuchMethodException e) {
      mStartForeground = null;
    }

    state = STATE_STOPPED;
    filteringEnabled = false;

    app = (MeshTetherApp)getApplication();
    app.serviceStarted(this);

    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MeshService");
    wakeLock.acquire();

    wifiLock = wifiManager.createWifiLock (WifiManager.WIFI_MODE_FULL, "MeshService");
    // WifiManager.WIFI_MODE_FULL_HIGH_PERF is only available at API level 12

    IntentFilter filter = new IntentFilter();
    filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    registerReceiver(connectivityReceiver, filter);

  }

  @Override
  public void onDestroy() {
    if (state != STATE_STOPPED)
      Log.e(TAG, "service destroyed while running!");
    // ensure we clean up
    stopProcess();
    state = STATE_STOPPED;
    app.processStopped();
    wakeLock.release();

    mShell.stopShell();
    
    try {
      unregisterReceiver(connectivityReceiver);
    } catch (Exception e) {
      // ignore
    }

    singleton = null;
    super.onDestroy();
  }

  private static String getWifiStateString(int state) {
    switch (state) {
    case WifiManager.WIFI_STATE_ENABLED:
      return "WIFI_STATE_ENABLED";
    case WifiManager.WIFI_STATE_ENABLING:
      return "WIFI_STATE_ENABLING";
    case WifiManager.WIFI_STATE_DISABLED:
      return "WIFI_STATE_DISABLED";
    case WifiManager.WIFI_STATE_DISABLING:
      return "WIFI_STATE_DISABLING";
    case WifiManager.WIFI_STATE_UNKNOWN:
      return "WIFI_STATE_UNKNOWN";
    default:
      return "(none)";
    }
  }

  // our handler
  private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) { handle(msg); }
  };
  private ShellProcess mDelRouteProcess;

  private void handle(Message msg) {
    switch (msg.what) {
    case MSG_SHOW_PROGRESSDIALOG:
      Log.i(TAG, "handle MSG_SHOW_PROGRESSDIALOG");
      app.showProgressMessage((String)msg.obj);
      break;
    case MSG_HIDE_PROGRESSDIALOG:
      Log.i(TAG, "handle MSG_HIDE_PROGRESSDIALOG");
      app.hideProgressDialog();
      break;
    case MSG_EXCEPTION:
      Log.i(TAG, "handle MSG_EXCEPTION");
      if (state == STATE_STOPPED) return;
      Throwable thr = (Throwable)msg.obj;
      log(true, getString(R.string.exception) + " " + thr.getMessage());
      Log.e(TAG, "Exception " + thr.getMessage() + " " + Log.getStackTraceString(thr));
      stopProcess();
      mShell.stopShell();
      state = STATE_STOPPED;
      break;
    case MSG_ERROR:
      Log.i(TAG, "handle MSG_ERROR");
      if (state == STATE_STOPPED) return;
      if (WifiShellProcess == null) return; // don't kill it again...
      if (msg.obj != null) {
        String line = (String)msg.obj;
        log(true, line); // just dump it and ignore it
      } else {
        // no message, means process died
        log(true, getString(R.string.unexpected));
        stopProcess();
        mShell.stopShell();

        if ((state == STATE_STARTING)) {
          String err = log.toString();
          if (isRootError(err)) {
            app.failed(MeshTetherApp.ERROR_ROOT);
          } else if (isSupplicantError(err)) {
            app.failed(MeshTetherApp.ERROR_SUPPLICANT);
          } else {
            app.failed(MeshTetherApp.ERROR_OTHER);
          }
        } else {
          app.failed(MeshTetherApp.ERROR_OTHER);
        }
        state = STATE_STOPPED;
      }
      break;
    case MSG_OUTPUT:
      Log.i(TAG, "handle MSG_OUTPUT");
      if (state == STATE_STOPPED) return;
      if (WifiShellProcess == null) return; // cut the gibberish
      String line = (String)msg.obj;
      if (line == null) {
        // ignore it, wait for MSG_ERROR(null)
        break;
      }
      if (line.startsWith("WIFI: OK")) {
        // WIFI: OK <IFNAME> <MAC>
        String[] parts = line.split(" +");
        if_lan = parts[2];
        if_mac = Util.MACAddress.parse(parts[3]);
        if (state == STATE_STARTING) {
          state = STATE_RUNNING;
          log(false, getString(R.string.running));
          clients.clear();
          stats.init(Util.fetchTrafficData(if_lan));
          //app.foundIfLan(if_lan); // this will allow 3G <-> 4G with simple restart
          app.processStarted();
          mHandler.sendEmptyMessage(MSG_ASSOC);
          mHandler.sendEmptyMessage(MSG_HIDE_PROGRESSDIALOG);
        }
      } else {
        log(false, line);
      }
      break;
    case MSG_START:
      Log.i(TAG, "handle MSG_START");

      if (state != STATE_STOPPED) return;
      log.clear();

      if ( !setMeshProfile())
        break;
      log(false, getString(R.string.starting) + " " + activeSSID);

      // TODO make this only overwrite on upgrade to new version
      log(false, getString(R.string.unpacking));
      if (!NativeHelper.unzipAssets(this) || !NativeHelper.installBusyboxSymlinks()) {
        log(true, getString(R.string.unpackerr));
        state = STATE_STOPPED;
        break;
      }

      if ( !wifiManager.isWifiEnabled()) {
        log(false, getString(R.string.enablingwifi));
        wifiManager.setWifiEnabled(true); // this will send MSG_NETSCHANGE
      }
      if (wifiManager.getConnectionInfo().getIpAddress() != 0) // if connected, disconnect
        wifiManager.disconnect(); // this will send MSG_NETSCHANGE

      mShell.setForkCommand(NativeHelper.SU_C_FORK, buildEnvFromPrefs());
      mShell.startShell();
      Shell.waitForShellToStart(mShell);
      
      state = STATE_STARTING;
      // FALL THROUGH!
    case MSG_NETSCHANGE:
      Log.i(TAG, "handle MSG_NETSCHANGE");
      int wifiState = wifiManager.getWifiState();
      String wifiStateString = getWifiStateString(wifiState);
      if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
        // wifi is good (or lost), we can start now...
        if ((state == STATE_STARTING) && (WifiShellProcess == null)) {
          if (app.findIfWan()) {
            // TODO if WAN found with checkUplink(), then setup Hna4 routing
            log(false, "Found active WAN interface");
          } else {
            ///log(true, getString(R.string.wanerr));
            //state = STATE_STOPPED;
            //break;
            log(false, "No active WAN interface found");
          }

          log(false, "Enabling wifi for " + activeSSID);
          WifiConfiguration wc = new WifiConfiguration();
          wc.priority = 100000;
          wc.hiddenSSID = true; // Android won't see Adhoc SSIDs
          wc.status = WifiConfiguration.Status.ENABLED;
          wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
          wc.SSID = activeSSID;
          wc.BSSID = activeBSSID;
          currentNetId = wifiManager.addNetwork(wc);
          if(currentNetId < 0) {
            System.out.println("Unable to add network configuration for " + activeSSID);
            return;
          }
          wifiManager.enableNetwork(currentNetId, true);

          // set up the static IP settings
          // TODO read and store the current settings so they can be restored on stop
          log(false, "Setting up IP config");
          final ContentResolver cr = getContentResolver();
          Settings.System.putInt(cr, Settings.System.WIFI_USE_STATIC_IP, 1);
          Settings.System.putString(cr, Settings.System.WIFI_STATIC_IP, activeIP);
          Settings.System.putString(cr, Settings.System.WIFI_STATIC_NETMASK, activeNetmask);
          Settings.System.putString(cr, Settings.System.WIFI_STATIC_GATEWAY, activeIP);
          Settings.System.putString(cr, Settings.System.WIFI_STATIC_DNS1, activeDNS);

          // meshing works very poorly with wifi sleep enabled
          // TODO check if this sticks after the app quits, if so
          // save the current value and restore it on stopping
          Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY,
              Settings.System.WIFI_SLEEP_POLICY_NEVER);

          if (!startProcess()) {
            log(true, getString(R.string.starterr));
            state = STATE_STOPPED;
            break;
          }
        } // if not checkUpLink then we simply wait...
      } else { // not WIFI_STATE_ENABLED
        app.updateToast("WIFI: " + wifiStateString, false); log(false, "WIFI: " + wifiStateString);
        switch (state) {
        case STATE_RUNNING:
          app.updateToast("STATE_RUNNING", true); log(false, "STATE_RUNNING");
          stopProcess(); // this tears down everything
          mShell.stopShell();
          state = STATE_STARTING;
          break;
        case STATE_STARTING:
          app.updateToast("STATE_STARTING", false); log(false, "STATE_STARTING");
          break;
        case STATE_STOPPED:
          app.updateToast("STATE_STOPPED", false); log(false, "STATE_STOPPED");
          break;
        default:
          app.updateToast("Something went wrong...", false);   log(false, "Something went wrong...");
        }
      }
      break;
    case MSG_STOP:
      Log.i(TAG, "handle MSG_STOP");
      if (state == STATE_STOPPED) return;
      stopProcess();
      mShell.stopShell();
      wifiManager.disableNetwork(currentNetId);
      wifiManager.removeNetwork(currentNetId);
      final ContentResolver cr = getContentResolver();
      Settings.System.putInt(cr, Settings.System.WIFI_USE_STATIC_IP, 0);
      log(false, getString(R.string.stopped));
      state = STATE_STOPPED;
      break;
    case MSG_ASSOC:
      Log.i(TAG, "handle MSG_ASSOC");
      if (state != STATE_RUNNING) return;
      if (tellProcess("WLAN")) {
        app.updateToast(getString(R.string.beaconing), true);
      }
      if (clients.isEmpty() && app.prefs.getBoolean("lan_autoassoc", false)) {
        mHandler.removeMessages(MSG_ASSOC);
        // rebeacon, in 5 seconds
        mHandler.sendEmptyMessageDelayed(MSG_ASSOC, 5000);
      }
      break;
    case MSG_STATS:
      //Log.i(TAG, "handle MSG_STATS");
      mHandler.removeMessages(MSG_STATS);
      if (state != STATE_RUNNING || if_lan.length() == 0) return;
      stats.update(Util.fetchTrafficData(if_lan));
      break;
    }
    app.updateStatus();
    if (state == STATE_STOPPED) {
      app.processStopped();
      app.hideProgressDialog();
    }
  }

  protected void log(boolean error, String msg) {
    android.text.format.Time time = new android.text.format.Time();
    time.setToNow();
    Log.i(TAG, "log: " + msg);
    log.append(COLOR_TIME, time.format("%H:%M:%S\t"))
    .append(error ? COLOR_ERROR : COLOR_LOG, msg)
    .append("\n");
    Message message = mHandler.obtainMessage();
    message.what = MSG_SHOW_PROGRESSDIALOG;
    message.obj = msg;
    mHandler.sendMessage(message);
  }

  /** Worker Threads */
  private class OutputMonitor implements Runnable {
    private final java.io.BufferedReader br;
    private final int msg;
    public OutputMonitor(int t, java.io.InputStream is) {
      br = Util.toReader(is);
      msg = t;
    }
    @Override
    public void run() {
      try{
        String line;
        do {
          line = br.readLine();
          mHandler.obtainMessage(msg, line).sendToTarget(); // NOTE: the last null is also sent!
        } while(line != null);
      } catch (Exception e) {
        mHandler.obtainMessage(MSG_EXCEPTION, e).sendToTarget();
      }
    }
  }
  
  private boolean checkUplink() {
    if (app.prefs.getBoolean("wan_nowait", false)) {
      return true;
    }
    NetworkInfo mobileInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    NetworkInfo wimaxInfo = connManager.getNetworkInfo(6);
    return (mobileInfo.isConnected() || ((wimaxInfo != null) && wimaxInfo.isConnected()));
  }

  private String getPrefValue(String pref) {

    // initialize default values if not done this in the past
    PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

    final int[] ids = SettingsActivity.prefids;
    for (int i = 0; i < ids.length; ++i) {
      String k = getString(ids[i]);
      String v = prefs.getString(k, null);
      if (k.equalsIgnoreCase(pref))
        return v;
    }
    return null;
  }
  /** Prepare env vars for ./wifi from preferences */
  protected String[] buildEnvFromPrefs() {
    ArrayList<String> envlist = new ArrayList<String>();

    // get the existing environment first, since many programs like 'su' require 
    // env vars like LD_LIBRARY_PATH to be set
    Map<String, String> env = System.getenv();
    for (String envName : env.keySet()) {
      if (envName.equals("LD_LIBRARY_PATH")) {
        // set LD_LIBRARY_PATH to load olsrd plugins
        envlist.add(envName + "=" + NativeHelper.app_bin.getAbsolutePath() + ":" + env.get(envName));          
      } else {
        envlist.add(envName + "=" + env.get(envName));
      }
    }

    // initialize default values if not done this in the past
    PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

    final int[] ids = SettingsActivity.prefids;
    for (int i = 0; i < ids.length; ++i) {
      String k = getString(ids[i]);
      String v = prefs.getString(k, null);
      if (v != null && v.length() != 0) {
        // TODO some chars need to be escaped, but this seems to add "" to the ESSID name
        //          if (ids[i] == R.string.lan_essid) {
        //            v = '"'+v+'"';
        //          }
        // Special handling for Mesh Prefix 
        if (k.equalsIgnoreCase(getString(R.string.adhoc_ip)))
        {
          if (v.matches("^[0-9]{1,3}$"))
          {
            // Convert the Mesh Prefix into a Mesh IP.
            WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
            if (wifiManager != null)
            {
              WifiInfo wifiInfo = wifiManager.getConnectionInfo();
              if (wifiInfo != null)
              {
                Log.d(TAG, "Mac addr: " + wifiInfo.getMacAddress());
                MACAddress macAddress = MACAddress.parse(wifiInfo.getMacAddress());
                v += "." + macAddress.getOctet(4) + "." + macAddress.getOctet(5) + "." + macAddress.getOctet(6);
              }
            }
          }
        }
        envlist.add("brncl_" + k + "=" + v);
      }
    }
    // not included in prefids are checkboxes
    final int[] checks = SettingsActivity.checks;
    for (int i = 0; i < checks.length; ++i) {
      String k = getString(checks[i]);
      if (prefs.getBoolean(k, false))
        envlist.add("brncl_" + k + "=1");
    }
    envlist.add("brncl_path=" + NativeHelper.app_bin.getAbsolutePath());
    envlist.add("olsrd_conf_path=" + activeOlsrdConf);
    
    String[] ret = envlist.toArray(new String[0]);
    for (String s : ret) {
      Log.i(TAG, "env var: " + s);
    }
    return ret;
  }

  private String formatSSID(String ssid) {
    if (ssid == null)
      return null;
    return "\"".concat(ssid).concat("\"");
  }

  private String generateIP(String base, String netmask) {
    String[] netmaskBytes = netmask.split("[.]+");
    String[] baseBytes = base.split("[.]+");
    // start at byte 1 since a completely random IP would be stupid
    String ret = baseBytes[0];
    for (int i=1; i<baseBytes.length; i++) {
      // if the netmask byte doesn't exist or is zero, generate that byte
      ret += ".";
      if (baseBytes[i].equals("0") && (i >= netmaskBytes.length || netmaskBytes[i].equals("0")))
        ret += String.valueOf((int)(Math.random() * 254));
      else
        ret += Byte.parseByte(baseBytes[i]);
    }
    return ret;
  }

  private boolean setMeshProfile() {
    activeOlsrdConf = new File(NativeHelper.app_bin, "olsrd.conf").getAbsolutePath();
    if (app.activeProfile.equals(getString(R.string.defaultprofile))) {
      activeSSID = formatSSID(getPrefValue(getString(R.string.lan_essid)));
      activeBSSID = getPrefValue(getString(R.string.lan_bssid));
      activeIP = getPrefValue(getString(R.string.adhoc_ip));
      activeNetmask = getPrefValue(getString(R.string.adhoc_netmask));
      activeDNS = getPrefValue(getString(R.string.adhoc_dns_server));
    } else {
      // TODO
      Properties prop = new Properties();
      String propFilename = app.profileProperties.get(app.activeProfile);
      String confFilename = propFilename.replace(".properties", ".conf");
      if (new File(confFilename).exists())
        activeOlsrdConf = confFilename;
      try {
        prop.load(new FileInputStream(propFilename));
      } catch (Exception e) {
        e.printStackTrace();
        app.updateToast(getString(R.string.profile_load_error) + " " + propFilename, false);
        return false;
      }
      activeSSID = formatSSID(prop.getProperty("ssid"));
      activeBSSID = prop.getProperty("bssid");
      activeNetmask = prop.getProperty("netmask");
      activeIpGeneration = prop.getProperty("ipgenerate");
      if (activeIpGeneration != null && 
          (activeIpGeneration.equals("true") || activeIpGeneration.equals("1"))) {
        activeIP = generateIP(prop.getProperty("ip"), activeNetmask);
        activeIpGeneration = "true";
      } else {
        activeIP = prop.getProperty("ip");
        activeIpGeneration = "false";
      }
      activeDNS = prop.getProperty("dns");
    }
    return true;
  }

  String[] getActiveMeshProfile() {
     String[] ret = { activeSSID, activeBSSID, activeIP, activeNetmask, activeIpGeneration, activeDNS, activeOlsrdConf };
     return ret;
  }

  private boolean startProcess() {
    // calling 'su -c' from Java doesn't work so we use a helper script

    log(false, "Aquiring wifi lock");
    wifiLock.acquire();
    app.showProgressMessage(R.string.startingolsrd);
    try {
      mDelRouteProcess = new ShellProcess("MSG_STOP_OLSRD_OUTPUT", NativeHelper.DEL_ROUTE, mShell);
      mDelRouteProcess.setHandler(mHandler, MSG_STOP_OLSRD_OUTPUT);
      mDelRouteProcess.runAsynchronous();
      
      //DelRouteProcess = new MeshTetherProcess(NativeHelper.DEL_ROUTE, env, NativeHelper.app_bin);
      //DelRouteProcess.runUntilExit(mHandler, MSG_STOP_OLSRD_OUTPUT, MSG_STOP_OLSRD_OUTPUT);
      
      WifiShellProcess = new ShellProcess("MSG_OUTPUT", NativeHelper.SU_C, mShell);
      WifiShellProcess.setHandler(mHandler, MSG_OUTPUT);
      WifiShellProcess.runAsynchronous();
      
      //WifiProcess = new MeshTetherProcess(NativeHelper.SU_C, env, NativeHelper.app_bin);
      //WifiProcess.run(mHandler, MSG_OUTPUT, MSG_ERROR);
    } catch (Exception e) {
      log(true, String.format(getString(R.string.execerr), NativeHelper.SU_C));
      Log.e(TAG, "start failed " + e.toString());
      return false;
    }
    return true;
  }

  private void stopProcess() {
    /*
     * TODO: UN copy and paste!!
     */
    if (state != STATE_STOPPED) {
      app.showProgressMessage(R.string.servicestopping);
      ShellProcess StopOlsrProcess = null;
      
      StopOlsrProcess = new ShellProcess("MSG_STOP_OLSRD_OUTPUT", NativeHelper.STOP_OLSRD, mShell);
      StopOlsrProcess.setHandler(mHandler, MSG_STOP_OLSRD_OUTPUT);
      if (!StopOlsrProcess.runSynchronous()) {
        Log.w(TAG, "Could not StopOlsrProcess");
      }
      if (WifiShellProcess != null) {
        // first, just close the stream
        if (state != STATE_STOPPED) {
          try {
            WifiShellProcess.stop();
          } catch (Exception e) {
            Log.w(TAG, "Exception while closing WifiShellProcess: " + e.toString());
          }
        }
        WifiShellProcess = null;
      }
      log(false, "Disconnecting from " + activeSSID);
      wifiManager.disconnect();
      log(false, "Releasing wifi lock");
      wifiLock.release();
      clients.clear();
      app.linksActivity.update();
      app.hideProgressDialog();
    }
  }


  private boolean tellProcess(String msg) {
    if (WifiShellProcess != null) {
      try {
        WifiShellProcess.sendInput(msg);
        return true;
      } catch (Exception e) {
        Log.w(TAG, "tellProcess(): " + e.toString());
      }
    }
    return false;
  }

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

  /**
   * This is a wrapper around the new startForeground method, using the older
   * APIs if it is not available.
   */
  public void startForegroundCompat(int id, Notification notification) {
    // If we have the new startForeground API, then use it.
    if (mStartForeground != null) {
      try {
        mStartForeground.invoke(this, new Object[] {Integer.valueOf(id), notification});
      } catch (InvocationTargetException e) {
        Log.w(TAG, "Unable to invoke startForeground", e);
      } catch (IllegalAccessException e) {
        Log.w(TAG, "Unable to invoke startForeground", e);
      }
      return;
    }
    // Fall back on the old API.
    //setForeground(true);
  }

  public static boolean isSupplicantError(String msg) {
    return msg.contains("supplicant");
  }

  public static boolean isRootError(String msg) {
    return msg.contains("ermission") || msg.contains("su: not found");
  }

}




Java Source Code List

net.commotionwireless.meshtether.IPPreference.java
net.commotionwireless.meshtether.InfoActivity.java
net.commotionwireless.meshtether.LinksActivity.java
net.commotionwireless.meshtether.MACPreference.java
net.commotionwireless.meshtether.MeshIPPreference.java
net.commotionwireless.meshtether.MeshService.java
net.commotionwireless.meshtether.MeshTetherApp.java
net.commotionwireless.meshtether.NativeHelper.java
net.commotionwireless.meshtether.SettingsActivity.java
net.commotionwireless.meshtether.StatusActivity.java
net.commotionwireless.meshtether.ToggleReceiver.java
net.commotionwireless.meshtether.Util.java