January 7, 2012

android usb reverse tethering via code

welcome again !

the problem of day is:
when i enable usb reverse tethering adb doesn't not respond anymore, via usb.

so, to have all working (reverse tethering, adb, etc) we need many operations:
1) enable reverse tethering via settings
2) change adb prop to enable tcp
3) start a dhcp request on usb0
4) disable wifi
5) other annoying stuffs?

(and reverse, of course :/)

so, it's time to find an -ultimate- solution.

1) with LLAMA (don't u know LLAMA? know it ! https://market.android.com/details?id=com.kebab.Llama ) i can start a "enable reverse tethering and so others stuff" when i plug the cable (and when certain others conditions are verified - for example: i was in wifi, so i want again connectivity).

2) with irssi connectbot (https://play.google.com/store/apps/details?id=org.woltage.irssiconnectbot) i can start some script which call dhcpd and change adb prop (just a "adb_tcp" script to enable adb over tcp, and "adb_usb" to rechange over usb)

download https://raw.github.com/k0smik0/burt/master/scripts/adb_tcp
#!/system/bin/sh

setprop service.adb.tcp.port 5555
stop adbd
start adbd
and download https://raw.github.com/k0smik0/burt/master/scripts/adb_usb
#!/system/bin/sh

setprop service.adb.tcp.port -1
stop adbd
start adbd


and "netcfg usb0 dhcp" to start a dhcp request (plz attention you need ROOTED phone in order to execute this last one - in general, a rooted phone is needed for all the tricks, actually...)

3) last thing (but it's the worst problem) is to enable usb tethering, and i don't want to check via settings, so it's time to code some lines.

the idea beyond is just simple:
send a broadcast message and a receiver intercepts it and enables/disables usb tethering.
Below, the receiver:
/**
 * GPL Copyleft 2012 Massimiliano Leone - maximilianus@gmail.com .
 */
package net.iubris.burt;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class UsbReverseTetheringIncomingReceiver extends BroadcastReceiver {

  protected static final String ACTION_START = "net.iubris.burt.START";
  protected static final String ACTION_STOP = "net.iubris.burt.STOP";
 
  @Override
  public void onReceive(Context context, Intent intent) {
    final String action = intent.getAction();  
    final Object obj = context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (action.equals(ACTION_START)) {
      actOnTether(obj, "tether");
    } else if (action.equals(ACTION_STOP)) {
      actOnTether(obj, "untether");
    }
  }
    
  private final void actOnTether(Object obj, String act) {
    for (Method m : obj.getClass().getDeclaredMethods()) {
      if (m.getName().equals(act)) {
 try {
   m.invoke(obj, "usb0");
 } catch (IllegalArgumentException e) {
   e.printStackTrace();
 } catch (IllegalAccessException e) {
   e.printStackTrace();
 } catch (InvocationTargetException e) {
   e.printStackTrace();
 }
      }
    }
  } 
}
and the relative AndroidManifest.xml with receiver declaration, permissions, etc.
<manifest android:versioncode="1" android:versionname="1.0" package="net.iubris.burt" xmlns:android="http://schemas.android.com/apk/res/android">

  <uses-sdk android:minsdkversion="8">
    
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">
  <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE">

  <application android:debuggable="false" android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:label="@string/app_name" android:name=".UsbReverseTetheringActivity">
      <intent-filter>
 <action android:name="android.intent.action.MAIN">
   <category android:name="android.intent.category.LAUNCHER"/>
 </action>
      </intent-filter>
    </activity>
    <receiver android:enabled="true" android:name=".UsbReverseTetheringIncomingReceiver">
      <intent-filter>
 <action android:name="net.iubris.burt.START"/>
 <action android:name="net.iubris.burt.STOP"/>
      </intent-filter>
    </receiver>
  </application>
</manifest>
ok, there is also an activity, with 2 buttons start/stop.. but just for a visual sample:
actually, into code, the buttons send broadcast "net.iubris.burt.START" and "net.iubris.burt.STOP"

so, in terminal (irssi connectbot? another else?) the commands are just:

am broadcast -a "net.iubris.burt.START" # to enable
am broadcast -a "net.iubris.burt.STOP" # to disable

and obviously via adb: "adb shell am broadcast etc."

4) finally, a summa cum laude of all these pieces :
--- open irssi connectbot ---
- create a "local" connection called "start usb reverse tethering" (or as u prefer)
- edit its "post-login automation" with these lines (careful to return or use && !)
am broadcast -a net.iubris.burt.START
su -c "netcfg usb0 dhcp"
su -c "adb_tcp"
adb_tcp (from 1, above) is just a script, so u can replace last line with:
su -c "setprop service.adb.tcp.port 5555 && stop adbd && start adbd"
in some terminals (due to kernel/rom version) this last ones is not needed, because adb over usb is working also with usb reverse tethering


--- open Llama ---
- create new event and call "start usb reverse tethering" (or as u want)
- add condition "charging status" as "charging from usb" and other conditions u want it matches (i.e. i have "wifi network connected" = "on" so this switch from wifi to usb r.t. does its jobs because phone is really in a state which we can call "connected")
- add actions: "toggle wifi" as "wifi off" and "run app shortcut" as [irssiconnectbot action], that is the irssiconnectbot local connection u specified above, "start usb reverse tethering" (or name you used for)


5) and to restore ?
--- for irssi-connectbot, a new local connection called "stop usb reverse tethering", where "post-login automation" is:
am broadcast -a net.iubris.burt.STOP
su -c "adb_usb"
as for "adb_tcp", the "adb_usb" is just these commands:
su -c "setprop service.adb.tcp.port -1 && stop adbd && start adbd"

--- and in LLama, an event for "stop usb reverse tethering" can be something like where match condition "charging status" = "using battery" and action "run app shortcut" is irssi-connectbot "stop usb reverse tethering"



finally, the "burt" receiver project on github burt and the builder apk burt.apk



credits to:
http://tjandroid.blogspot.com/2010/12/enabledisable-usb-tethering.html
http://www.apad.tv/apadforum/showthread.php?1280-Solved-system-bin-sh-am-not-found-and-system-bin-sh-pm-not-found