package ru.dtlbox.custom;
import info.guardianproject.onionkit.ui.OrbotHelper;
import info.guardianproject.otr.app.im.app.AccountActivity;
import org.torproject.android.service.ITorService;
import org.torproject.android.service.TorServiceConstants;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class CustomOrbotHelper extends OrbotHelper {
protected final static String LOG_TAG = "CustomOrbotHelper";
public final static String INTENT_TOR_SERVICE = "ru.dtlbox.TOR_SERVICE";
public final static String TOR_CUSTOM_SERVICE_NAME = "CustomOrbotHelper";
private ITorService mService = null;
private static Context mContext = null;
//get instance of CustomOrbotHelper
public static CustomOrbotHelper getInstance(){
if (mContext != null)
return SingletonHolder.instance;
else
return null;
}
private static class SingletonHolder{
public static CustomOrbotHelper instance = new CustomOrbotHelper(mContext);
}
//for nobody can use constructor directly
private CustomOrbotHelper(Context context) {
super(context);
}
/**
* set static context for orbot helper creation
* this function provide to pass context into super class
* in super class it was used for detecting orbot application
*/
public static void setContext(Context context){
mContext = context;
}
public void torServiceStartAsync(final Activity activity){
(new Thread(new Runnable() {
@Override
public void run() {
torServiceStart(activity);
}
})).start();
}
//try to start tor service
public void torServiceStart(final Activity activity) {
Log.d(LOG_TAG, "tor service start");
try {
if (isOrbotInstalled()) {
Log.i(LOG_TAG, "orbotinstalled.Trying to start custom tor service");
if (!isOrbotRunning()) {
Intent intent = new Intent(URI_ORBOT);
intent.setAction(ACTION_START_TOR);
activity.startActivityForResult(intent, 1);
} else
Log.i(LOG_TAG, "orbot already running");
} else {
Log.i(LOG_TAG, "orbot is not installed.Trying to start custom tor service");
// if (!isServiceRunning(TOR_CUSTOM_SERVICE_NAME))
// activity.startService(new Intent(INTENT_TOR_SERVICE));
// else
// Log.i(LOG_TAG, "custom tor service already running");
if (mService == null)
bindService();
else
try {
startTor();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "error during start orbot");
e.printStackTrace();
}
}
//check is any tor service running
public boolean isTorServiceRunning(){
if(isOrbotInstalled())
return super.isOrbotRunning();
else
return isServiceRunning(TOR_CUSTOM_SERVICE_NAME);
}
//check is custom service running
private Boolean isServiceRunning(String serviceName) {
ActivityManager activityManager = (ActivityManager) mContext
.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo runningServiceInfo : activityManager
.getRunningServices(Integer.MAX_VALUE)) {
if (serviceName.equals(runningServiceInfo.service.getClassName())) {
return true;
}
}
return false;
}
/**
* Class for interacting with the main interface of the service.
*/
// this is the connection that gets called back when a successfull bind occurs
// we should use this to activity monitor unbind so that we don't have to call
// bindService() a million times
public ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
Log.i(LOG_TAG, "onServiceConnected");
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
mService = ITorService.Stub.asInterface(service);
Log.i(LOG_TAG, "on service connected");
// if(!((CustomTorService) mService).isStarted())
// mContext.startService(new Intent(INTENT_TOR_SERVICE));
try {
startTor();
} catch (RemoteException e) {
// In this case the service has crashed before we could even
// do anything with it; we can count on soon being
// disconnected (and then reconnected if it can be restarted)
// so there is no need to do anything here.
Log.d(LOG_TAG, "error registering callback to service", e);
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
}
};
public void startTor() throws RemoteException {
// this is a bit of a strange/old/borrowed code/design i used to change the service state
// not sure it really makes sense when what we want to say is just "startTor"
mService.setProfile(TorServiceConstants.PROFILE_ON); //this means turn on
}
//this is where we bind!
private void bindService() {
Log.i(LOG_TAG, "bind service");
//since its auto create, we prob don't ever need to call startService
//also we should again be consistent with using either iTorService.class.getName()
//or the variable constant
mContext.bindService(new Intent(INTENT_TOR_SERVICE),
mConnection, Context.BIND_AUTO_CREATE);
}
}