/** * TorProxy - Anonymous data communication for Android devices * Copyright (C) 2009 Connell Gauld * * Thanks to University of Cambridge, * Alastair Beresford and Andrew Rice * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package uk.ac.cam.cl.dtg.android.tor.TorProxy; import uk.ac.cam.cl.dtg.android.tor.TorProxyLib.ITorProxyControl; import uk.ac.cam.cl.dtg.android.tor.TorProxyLib.TorProxyLib; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; public class TorProxySettings extends Activity implements OnCheckedChangeListener { // Connection to Tor control service private ITorProxyControl mTorProxyControl = null; private final IntentFilter mTorProfileFilter = new IntentFilter( TorProxyLib.PROFILE_CHANGE_INTENT); // UI elements private RadioGroup mProfileRadioGroup = null; // Update thread things private boolean updateDisplay = true; private Updater updater = null; // Standard handler for updating UI in correct thread private final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; /** * Updates the UI every second * * @author cmg47 * */ private class Updater extends Thread { @Override public void run() { try { while (updateDisplay) { Thread.sleep(1000); // 1 second if (handler != null) handler.sendMessage(handler.obtainMessage()); } } catch (InterruptedException e) { // Thread sleep interrupted } } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Deal with the UI setContentView(R.layout.main); mProfileRadioGroup = (RadioGroup) findViewById(R.id.radioGroup); mProfileRadioGroup.setOnCheckedChangeListener(this); } @Override protected void onStart() { super.onStart(); // Start up the Tor control service // Use startService rather than bindService since we want // the service to continue even after the user leaves // this activity. startService(new Intent(this, TorProxyControlService.class)); } @Override protected void onPause() { // Stop the UI update thread updateDisplay = false; updater = null; unregisterReceiver(mTorUpdates); unbindService(svcConn); super.onPause(); } @Override protected void onResume() { super.onResume(); // Bind to the Tor control service bindService(new Intent(this, TorProxyControlService.class), svcConn, 0); registerReceiver(mTorUpdates, mTorProfileFilter); // Start the UI update thread updateDisplay = true; if (updater == null) { updater = new Updater(); updater.setName("UIUpdater"); updater.start(); } } private ServiceConnection svcConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mTorProxyControl = ITorProxyControl.Stub.asInterface(service); updateProfile(); } @Override public void onServiceDisconnected(ComponentName name) { mTorProxyControl = null; updateProfile(); } }; @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem arg0) { switch (arg0.getItemId()) { case R.id.menuAbout: startActivity(new Intent(this, AboutActivity.class)); return true; case R.id.menuSettings: startActivity(new Intent(this, EditPreferences.class)); return true; /*case R.id.menuTesting: startActivity(new Intent(this, UnitTests.class)); return true;*/ } return false; } /** * Set the profile * @param profile */ private void setProfile(final int profile) { new Thread() { @Override public void run() { try { if (mTorProxyControl != null) mTorProxyControl.setProfile(profile); } catch (RemoteException e) { // Oh well } } }.start(); } /** * Get an update of the current profile from the service and update the UI as appropriate */ private void updateProfile() { if (mTorProxyControl != null) { int i; try { i = mTorProxyControl.getProfile(); switch (i) { case TorProxyLib.PROFILE_OFF: mProfileRadioGroup.check(R.id.radioOff); break; case TorProxyLib.PROFILE_ONDEMAND: mProfileRadioGroup.check(R.id.radioOnDemand); break; case TorProxyLib.PROFILE_ON: mProfileRadioGroup.check(R.id.radioAlwaysOn); break; } } catch (RemoteException e) { // Oh well } } } // Broadcast receiver for receiving updates from the control service BroadcastReceiver mTorUpdates = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { updateProfile(); } }; @Override public void onCheckedChanged(RadioGroup group, int checkedId) { int profile = 0; switch (checkedId) { case R.id.radioOff: profile = TorProxyLib.PROFILE_OFF; break; case R.id.radioOnDemand: profile = TorProxyLib.PROFILE_ONDEMAND; break; case R.id.radioAlwaysOn: profile = TorProxyLib.PROFILE_ON; break; } if (mTorProxyControl != null) { setProfile(profile); } } }