cleaned up notification support and added Share service

This commit is contained in:
n8fr8 2013-02-12 14:29:41 +07:00
parent 25a895a608
commit c5627f4f9a
1 changed files with 200 additions and 84 deletions

View File

@ -30,6 +30,8 @@ import org.torproject.android.R;
import org.torproject.android.TorConstants; import org.torproject.android.TorConstants;
import org.torproject.android.Utils; import org.torproject.android.Utils;
import org.torproject.android.settings.AppManager; import org.torproject.android.settings.AppManager;
import org.torproject.android.share.ShareItem;
import org.torproject.android.share.ShareService;
import android.app.Application; import android.app.Application;
import android.app.Notification; import android.app.Notification;
@ -43,12 +45,14 @@ import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteCallbackList; import android.os.RemoteCallbackList;
import android.os.RemoteException; import android.os.RemoteException;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
public class TorService extends Service implements TorServiceConstants, TorConstants, Runnable, EventHandler public class TorService extends Service implements TorServiceConstants, TorConstants, Runnable, EventHandler
{ {
@ -74,6 +78,11 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private ArrayList<String> configBuffer = null; private ArrayList<String> configBuffer = null;
private ArrayList<String> resetBuffer = null; private ArrayList<String> resetBuffer = null;
//Orbot file sharing service
private ShareService mShareServe = null; //if hidden services activated
private String mShareServeHost = null;
private int mShareServePort = -1;
// private String appHome; // private String appHome;
private File appBinHome; private File appBinHome;
@ -87,6 +96,9 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private long mTotalTrafficWritten = 0; private long mTotalTrafficWritten = 0;
private long mTotalTrafficRead = 0; private long mTotalTrafficRead = 0;
private boolean mConnectivity = true;
private NotificationManager mNotificationManager = null;
public void logMessage(String msg) public void logMessage(String msg)
{ {
@ -123,6 +135,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
initControlConnection(); initControlConnection();
updateTorConfiguration();
currentStatus = STATUS_ON; currentStatus = STATUS_ON;
return true; return true;
@ -178,18 +192,16 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private void clearNotifications () private void clearNotifications ()
{ {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll(); mNotificationManager.cancelAll();
} }
private void showToolbarNotification (String notifyMsg, int notifyId, int icon, int flags) private void showToolbarNotification (String notifyMsg, int notifyId, int icon, int flags)
{ {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence tickerText = notifyMsg; CharSequence tickerText = notifyMsg;
long when = System.currentTimeMillis(); long when = System.currentTimeMillis();
@ -208,7 +220,6 @@ public class TorService extends Service implements TorServiceConstants, TorConst
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotificationManager.notify(notifyId, notification); mNotificationManager.notify(notifyId, notification);
@ -236,6 +247,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
initTorPaths(); initTorPaths();
IntentFilter mNetworkStateFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mNetworkStateReceiver , mNetworkStateFilter);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
new Thread () new Thread ()
{ {
@ -282,8 +299,6 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{ {
initTor(); initTor();
isRunning = true; isRunning = true;
IntentFilter mNetworkStateFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mNetworkStateReceiver , mNetworkStateFilter);
} }
catch (Exception e) catch (Exception e)
{ {
@ -311,6 +326,20 @@ public class TorService extends Service implements TorServiceConstants, TorConst
// Unregister all callbacks. // Unregister all callbacks.
mCallbacks.kill(); mCallbacks.kill();
}
private void stopShareService ()
{
try
{
if (mShareServe != null)
mShareServe.stopService();
}
catch (Exception e)
{
Log.e(TAG, "error stopping share service",e);
}
} }
private void stopTor () private void stopTor ()
@ -332,10 +361,13 @@ public class TorService extends Service implements TorServiceConstants, TorConst
clearNotifications(); clearNotifications();
sendCallbackStatusMessage(getString(R.string.status_disabled));
if (hasRoot) if (hasRoot)
disableTransparentProxy(); disableTransparentProxy();
stopShareService();
sendCallbackStatusMessage(getString(R.string.status_disabled));
} }
catch (Exception e) catch (Exception e)
{ {
@ -371,7 +403,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private void getHiddenServiceHostname () private String getHiddenServiceHostname ()
{ {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
@ -385,17 +417,18 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (file.exists()) if (file.exists())
{ {
try { try {
String onionHostname = Utils.readString(new FileInputStream(file)); String onionHostname = Utils.readString(new FileInputStream(file)).trim();
showToolbarNotification(getString(R.string.hidden_service_on) + ' ' + onionHostname, HS_NOTIFY_ID, R.drawable.ic_stat_tor, Notification.FLAG_ONGOING_EVENT); showToolbarNotification(getString(R.string.hidden_service_on) + ' ' + onionHostname, HS_NOTIFY_ID, R.drawable.ic_stat_tor, Notification.FLAG_ONGOING_EVENT);
Editor pEdit = prefs.edit(); Editor pEdit = prefs.edit();
pEdit.putString("pref_hs_hostname",onionHostname); pEdit.putString("pref_hs_hostname",onionHostname);
pEdit.commit(); pEdit.commit();
return onionHostname;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
logException("unable to read onion hostname file",e); logException("unable to read onion hostname file",e);
showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr, -1); showToolbarNotification(getString(R.string.unable_to_read_hidden_service_name), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr, -1);
return; return null;
} }
} }
else else
@ -406,7 +439,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
} }
} }
return; return null;
} }
@ -538,12 +571,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if ((!(fileTor.exists() && filePrivoxy.exists())) || forceInstall) if ((!(fileTor.exists() && filePrivoxy.exists())) || forceInstall)
{ {
if (currentStatus != STATUS_OFF) stopTor();
stopTor();
TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome); TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome);
boolean success = installer.installFromRaw(); boolean success = installer.installFromRaw();
if (success) if (success)
{ {
@ -569,6 +602,14 @@ public class TorService extends Service implements TorServiceConstants, TorConst
} }
setBinaryPerms();
return true;
}
private void setBinaryPerms () throws Exception
{
StringBuilder log = new StringBuilder (); StringBuilder log = new StringBuilder ();
logNotice("(re)Setting permission on Tor binary"); logNotice("(re)Setting permission on Tor binary");
@ -583,7 +624,6 @@ public class TorService extends Service implements TorServiceConstants, TorConst
String[] cmd3 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + fileObfsProxy.getAbsolutePath()}; String[] cmd3 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + fileObfsProxy.getAbsolutePath()};
TorServiceUtils.doShellCommand(cmd3, log, false, true); TorServiceUtils.doShellCommand(cmd3, log, false, true);
return true;
} }
public void initTor () throws Exception public void initTor () throws Exception
@ -608,13 +648,16 @@ public class TorService extends Service implements TorServiceConstants, TorConst
try { try {
setBinaryPerms();
runTorShellCmd(); runTorShellCmd();
runPrivoxyShellCmd(); runPrivoxyShellCmd();
if (hasRoot && enableTransparentProxy) if (hasRoot && enableTransparentProxy)
enableTransparentProxy(transProxyAll, transProxyTethering); enableTransparentProxy(transProxyAll, transProxyTethering);
new Thread (new TotalUpdaterRunnable()).start(); //new Thread (new TotalUpdaterRunnable()).start();
} catch (Exception e) { } catch (Exception e) {
logException("Unable to start Tor: " + e.getMessage(),e); logException("Unable to start Tor: " + e.getMessage(),e);
@ -877,7 +920,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
sendCallbackStatusMessage(getString(R.string.tor_process_waiting)); sendCallbackStatusMessage(getString(R.string.tor_process_waiting));
Thread.sleep(1000); Thread.sleep(3000);
} }
} }
@ -991,27 +1034,32 @@ public class TorService extends Service implements TorServiceConstants, TorConst
} }
} }
private void startNotification (String message)
private void startNotification ()
{ {
Notification notice = new Notification(R.drawable.ic_stat_tor, getString(R.string.status_activated), System.currentTimeMillis()); Notification notice = new Notification(R.drawable.ic_stat_tor, getString(R.string.status_activated), System.currentTimeMillis());
//This constructor is deprecated. Use Notification.Builder instead
//Notification notice = new Notification(R.drawable.iocipher, "Active: " + mIpAddress, System.currentTimeMillis());
Intent intent = new Intent(TorService.this, Orbot.class); Intent intent = new Intent(TorService.this, Orbot.class);
PendingIntent pendIntent = PendingIntent.getActivity(TorService.this, 0, intent, 0); PendingIntent pendIntent = PendingIntent.getActivity(TorService.this, 0, intent, 0);
//This method is deprecated. Use Notification.Builder instead. //This method is deprecated. Use Notification.Builder instead.
notice.setLatestEventInfo(TorService.this,getString(R.string.app_name), getString(R.string.status_activated), pendIntent); notice.setLatestEventInfo(TorService.this,getString(R.string.app_name), message, pendIntent);
notice.flags |= Notification.FLAG_NO_CLEAR; if (prefPersistNotifications)
notice.flags |= Notification.FLAG_ONGOING_EVENT; {
notice.flags |= Notification.FLAG_NO_CLEAR;
notice.flags |= Notification.FLAG_ONGOING_EVENT;
startForeground(NOTIFY_ID,notice); startForeground(NOTIFY_ID,notice);
}
else
{
mNotificationManager.notify(NOTIFY_ID,notice);
}
} }
@ -1025,17 +1073,13 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{ {
currentStatus = STATUS_ON; currentStatus = STATUS_ON;
if (prefPersistNotifications) startNotification(getString(R.string.status_activated));
{
startNotification();
}
else
{
showToolbarNotification (getString(R.string.status_activated),NOTIFY_ID,R.drawable.ic_stat_tor, Notification.FLAG_ONGOING_EVENT);
}
getHiddenServiceHostname ();
//we load this here from the file directory based on data
//written by Tor binary
mShareServeHost = getHiddenServiceHostname ();
} }
@ -1090,23 +1134,43 @@ public class TorService extends Service implements TorServiceConstants, TorConst
public void bandwidthUsed(long read, long written) { public void bandwidthUsed(long read, long written) {
/*if (ENABLE_DEBUG_LOG) //too much debugging data NF 2012/10
{
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Bandwidth used: "); sb.append("Bandwidth: ");
sb.append(read/1000); sb.append(formatCount(read));
sb.append("kb read / "); sb.append(" down / ");
sb.append(written/1000); sb.append(formatCount(written));
sb.append("kb written"); sb.append(" up");
logNotice(sb.toString()); if (mConnectivity && prefPersistNotifications)
}*/ startNotification(sb.toString());
mTotalTrafficWritten += read;
mTotalTrafficRead += written;
/*
try
{
mTotalTrafficWritten = Long.parseLong(conn.getInfo("traffic/written"));
mTotalTrafficRead = Long.parseLong(conn.getInfo("traffic/read"));
}
catch (IOException ioe){}
*/
sendCallbackStatusMessage(written, read, mTotalTrafficWritten, mTotalTrafficRead); sendCallbackStatusMessage(written, read, mTotalTrafficWritten, mTotalTrafficRead);
} }
private String formatCount(long count) {
// Converts the supplied argument into a string.
// Under 2Mb, returns "xxx.xKb"
// Over 2Mb, returns "xxx.xxMb"
if (count < 1e6)
return ((float)((int)(count*10/1024))/10 + "kbps");
return ((float)((int)(count*100/1024/1024))/100 + "mbps");
//return count+" kB";
}
/*
class TotalUpdaterRunnable implements Runnable class TotalUpdaterRunnable implements Runnable
{ {
@ -1137,7 +1201,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
} }
} }
} }*/
public void circuitStatus(String status, String circID, String path) { public void circuitStatus(String status, String circID, String path) {
@ -1269,18 +1333,10 @@ public class TorService extends Service implements TorServiceConstants, TorConst
try { try {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(TorService.this);
ENABLE_DEBUG_LOG = prefs.getBoolean("pref_enable_logging",false);
Log.i(TAG,"debug logging:" + ENABLE_DEBUG_LOG);
prefPersistNotifications = prefs.getBoolean(TorConstants.PREF_PERSIST_NOTIFICATIONS, true);
updateTorConfiguration(); updateTorConfiguration();
} catch (RemoteException e) { } catch (RemoteException e) {
logException ("error applying prefs",e); logException ("error applying prefs",e);
} }
@ -1401,6 +1457,11 @@ public class TorService extends Service implements TorServiceConstants, TorConst
return false; return false;
} }
public String addOnionShare (Uri data, String contentType)
{
return addOnionShareImpl (data, contentType);
}
}; };
private ArrayList<String> callbackBuffer = new ArrayList<String>(); private ArrayList<String> callbackBuffer = new ArrayList<String>();
@ -1442,6 +1503,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (mCallbacks == null) if (mCallbacks == null)
return; return;
// Broadcast to all clients the new value. // Broadcast to all clients the new value.
final int N = mCallbacks.beginBroadcast(); final int N = mCallbacks.beginBroadcast();
@ -1518,23 +1580,30 @@ public class TorService extends Service implements TorServiceConstants, TorConst
private final BroadcastReceiver mNetworkStateReceiver = new BroadcastReceiver() { private final BroadcastReceiver mNetworkStateReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
try {
mBinder.updateConfiguration("DisableNetwork", noConnectivity ? "1" : "0", false);
mBinder.saveConfiguration();
if (noConnectivity) mConnectivity = !intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
{
logNotice("No network connectivity. Putting Tor to sleep...");
}
else
{
logNotice("Network connectivity is good. Waking Tor up...");
if (currentStatus == STATUS_ON)
{
try {
mBinder.updateConfiguration("DisableNetwork", mConnectivity ? "0" : "1", false);
mBinder.saveConfiguration();
if (!mConnectivity)
{
logNotice("No network connectivity. Putting Tor to sleep...");
startNotification(getString(R.string.no_internet_connection_tor));
}
else
{
logNotice("Network connectivity is good. Waking Tor up...");
startNotification(getString(R.string.status_activated));
}
} catch (RemoteException e) {
logException ("error applying prefs",e);
} }
} catch (RemoteException e) { }
logException ("error applying prefs",e);
}
} }
}; };
@ -1543,6 +1612,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefPersistNotifications = prefs.getBoolean(TorConstants.PREF_PERSIST_NOTIFICATIONS, true);
ENABLE_DEBUG_LOG = prefs.getBoolean("pref_enable_logging",false); ENABLE_DEBUG_LOG = prefs.getBoolean("pref_enable_logging",false);
Log.i(TAG,"debug logging:" + ENABLE_DEBUG_LOG); Log.i(TAG,"debug logging:" + ENABLE_DEBUG_LOG);
@ -1713,17 +1784,39 @@ public class TorService extends Service implements TorServiceConstants, TorConst
StringTokenizer st = new StringTokenizer (hsPorts,","); StringTokenizer st = new StringTokenizer (hsPorts,",");
String hsPortConfig = null; String hsPortConfig = null;
int hsPort = -1;
while (st.hasMoreTokens()) while (st.hasMoreTokens())
{ {
hsPortConfig = st.nextToken(); try
if (hsPortConfig.indexOf(":")==-1) //setup the port to localhost if not specifed
{ {
hsPortConfig = hsPortConfig + " 127.0.0.1:" + hsPortConfig; hsPortConfig = st.nextToken();
}
mBinder.updateConfiguration("HiddenServicePort",hsPortConfig, false); if (hsPortConfig.indexOf(":")==-1) //setup the port to localhost if not specifed
{
hsPortConfig = hsPortConfig + " 127.0.0.1:" + hsPortConfig;
}
mBinder.updateConfiguration("HiddenServicePort",hsPortConfig, false);
hsPort = Integer.parseInt(hsPortConfig.split(" ")[0]);
//start this for the first port specified
if (mShareServe == null)
{
//we load this here from the file directory based on data
//written by Tor binary
mShareServeHost = getHiddenServiceHostname ();
mShareServePort = hsPort;
mShareServe = new ShareService(10, this);
mShareServe.startService(hsPort);
}
} catch (NumberFormatException e) {
Log.e(this.TAG,"error parsing hsport",e);
} catch (Exception e) {
Log.e(this.TAG,"error starting share server",e);
}
} }
@ -1739,6 +1832,29 @@ public class TorService extends Service implements TorServiceConstants, TorConst
return true; return true;
} }
public String addOnionShareImpl (Uri data, String contentType)
{
try
{
ShareItem si = new ShareItem();
si.mUriData = data;
si.mContentType = contentType;
String guid = mShareServe.addShare(si);
String shareUrl = "http://" + mShareServeHost + ':' + mShareServePort + '/' + guid;
return shareUrl;
}
catch (Exception e)
{
Log.e(TAG,"unable to handle share",e);
}
return null;
}
//using Google DNS for now as the public DNS server //using Google DNS for now as the public DNS server
private String writeDNSFile () throws IOException private String writeDNSFile () throws IOException
{ {