package de.tudarmstadt.informatik.hostage.ui;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
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.content.SharedPreferences;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.LocalBroadcastManager;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.widget.ViewAnimator;
import de.tudarmstadt.informatik.hostage.Hostage;
import de.tudarmstadt.informatik.hostage.Hostage.LocalBinder;
import de.tudarmstadt.informatik.hostage.R;
import de.tudarmstadt.informatik.hostage.persistence.HostageDBOpenHelper;
/**
* MainActivity is the central activity for the GUI of the application.
* MainActivity is launched when the application is first started. It shows the
* user:
* - information about the network
* - light indicators for recorded attacks on each protocol
* - amount of attacks on each protocols
* The user can start and stop services.
*
* @author Mihai Plasoianu
* @author Lars Pandikow
* @author Wulf Pfeiffer
*/
public class MainActivity extends FragmentActivity {
/**
* Integer representing a grey light.
*/
public static final int LIGHT_GREY = 0x01;
/**
* Integer representing a green light.
*/
public static final int LIGHT_GREEN = 0x02;
/**
* Integer representing a red light.
*/
public static final int LIGHT_RED = 0x03;
/**
* Integer representing a yellow light.
*/
public static final int LIGHT_YELLOW = 0x04;
private SharedPreferences connectionInfo;
private Hostage mService;
private boolean serviceBound;
// variables for the swipe animation
private ViewAnimator viewAnimator;
private GestureDetector gestureDetector;
private Animation animFlipInLR;
private Animation animFlipOutLR;
private Animation animFlipInRL;
private Animation animFlipOutRL;
private ListView listView;
private ListViewAdapter adapter;
/**
* Connection to bind the background service
*
* @see Hostage
*/
private ServiceConnection mConnection = new ServiceConnection() {
/**
* After the service is bound, check which has been clicked and start
* it.
*
* @see android.content.ServiceConnection#onServiceConnected(android.content.ComponentName)
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ((LocalBinder) service).getService();
serviceBound = true;
updateUI();
}
/**
* After the service is unbound, delete reference.
*
* @see android.content.ServiceConnection#onServiceDisconnected(android.content.ComponentName)
*/
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
serviceBound = false;
}
};
/**
* Receiver for custom broadcast.
*
* @see #BROADCAST
*/
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Update user interface.
updateUI();
updateConnectionInfText();
}
};
SimpleOnGestureListener simpleOnGestureListener = new SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float sensitvity = 50;
if ((e1.getX() - e2.getX()) > sensitvity) {
swipeRightToLeft();
} else if ((e2.getX() - e1.getX()) > sensitvity) {
swipeLeftToRight();
}
return true;
}
};
/**
* Called when User presses on/off button.
*
* @param view
*/
public void buttonOnOffClick(View view) {
if (((ToggleButton) view).isChecked()) {
if (isParanoid()) {
String[] protocols = getResources().getStringArray(R.array.protocols);
for (String protocol : protocols) {
mService.startListener(protocol);
}
} else {
if (mService.isRunning("SMB")) {
mService.stopListener("SMB");
} else {
mService.startListener("SMB");
}
}
} else {
mService.stopListeners();
stopAndUnbind();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.action_settings:
startActivity(new Intent(this, SettingsActivity.class));
break;
case R.id.action_about:
startActivity(new Intent(this, AboutActivity.class));
break;
default:
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
/**
* Starts the ViewLog activity, when the Button is pressed.
*
* @see ViewLog
* @param view
* View elements which triggers the method call.
*/
public void showLog(View view) {
// startActivity(new Intent(this, ViewLog.class));
}
public void startPlayGround(View view) {
startActivity(new Intent(this, PlayGroundActivity.class));
}
/**
* Binds service to Activity
*
* @see Hostage
*/
private void bindService() {
bindService(getServiceIntent(), mConnection, BIND_AUTO_CREATE);
}
/**
* Returns an intent to start HoneyService.
*
* @return An Intent to start HoneyService
*/
private Intent getServiceIntent() {
return new Intent(this, Hostage.class);
}
/**
* Initializes the ListView. Creating its contents dynamic from protocol
* res/values/protocols.xml
*/
private void initListView() {
ArrayList> data = new ArrayList>();
for (String protocol : getResources().getStringArray(R.array.protocols)) {
HashMap d = new HashMap();
d.put("light", String.valueOf(R.drawable.light_grey));
d.put("protocol", protocol);
d.put("connections", "-");
data.add(d);
}
listView = (ListView) findViewById(R.id.listViewProtocols);
adapter = new ListViewAdapter(getLayoutInflater(), data);
listView.setAdapter(adapter);
listView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
String protocolName = (String) ((HashMap, ?>) adapter.getItem(position)).get("protocol");
if (mService.isRunning(protocolName)) {
mService.stopListener(protocolName);
} else {
mService.startListener(protocolName);
}
}
});
}
/**
* Initializes variables for screen animation
*/
private void initViewAnimator() {
viewAnimator = (ViewAnimator) findViewById(R.id.viewAnimator);
gestureDetector = new GestureDetector(this, simpleOnGestureListener);
animFlipInLR = AnimationUtils.loadAnimation(this, R.anim.in_left_to_right);
animFlipOutLR = AnimationUtils.loadAnimation(this, R.anim.out_left_to_right);
animFlipInRL = AnimationUtils.loadAnimation(this, R.anim.in_right_to_left);
animFlipOutRL = AnimationUtils.loadAnimation(this, R.anim.out_right_to_left);
}
/**
* Checks if user selected paranoid mode.
*
* @return True when paranoid mode is selected, else returns false.
*/
private boolean isParanoid() {
return ((CheckBox) findViewById(R.id.checkBoxParanoid)).isChecked();
}
/**
* Checks if a {@link Hostage} instance is running.
*
* @return True if {@link Hostage} is running, else false.
*/
private boolean isServiceBound() {
return serviceBound;
}
/**
* Checks if a {@link Hostage} instance is running.
*
* @return True if {@link Hostage} is running, else false.
*/
private boolean isServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (service.service.getClassName().equals(Hostage.class.getName())) {
return true;
}
}
return false;
}
/**
* Register broadcast receiver for custom broadcast.
*
* @see #BROADCAST
*/
private void registerReceiver() {
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(getString(R.string.broadcast)));
}
/**
* If mobile phone is connected to a wireless network starts the background
* service ands binds itself to it. Else notifies the user that service
* could not be started.
*/
private void startAndBind() {
startService(getServiceIntent());
bindService();
}
/**
* Stops service and unbinds it.
*
* @see Hostage
*/
private void stopAndUnbind() {
unbindService();
stopService(getServiceIntent());
}
/**
* Called when a swipe to the Right is registered.
*/
private void swipeLeftToRight() {
if (viewAnimator.getDisplayedChild() == 1) {
viewAnimator.setInAnimation(animFlipInLR);
viewAnimator.setOutAnimation(animFlipOutLR);
viewAnimator.setDisplayedChild(0);
}
}
/**
* Called when a swipe to the Left is registered.
*/
private void swipeRightToLeft() {
if (viewAnimator.getDisplayedChild() == 0) {
viewAnimator.setInAnimation(animFlipInRL);
viewAnimator.setOutAnimation(animFlipOutRL);
viewAnimator.setDisplayedChild(1);
}
}
/**
* Unbinds service.
*
* @see Hostage
*/
private void unbindService() {
unbindService(mConnection);
}
/**
* Unregisters broadcast receiver for custom broadcast.
*
* @see #BROADCAST
*/
private void unregisterReceiver() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
}
/**
* Gets Information about connection state and updates the GUI.
*/
private void updateConnectionInfText() {
TextView ssidView = (TextView) findViewById(R.id.textViewSSIDValue);
TextView bssidView = (TextView) findViewById(R.id.textViewBSSIDValue);
TextView internalIPView = (TextView) findViewById(R.id.textViewInternalIPValue);
TextView externalIPView = (TextView) findViewById(R.id.textViewExternalIPValue);
// externalIPView.setText("Loading...");
// Get connection information
String ssid = connectionInfo.getString(getString(R.string.connection_info_ssid), null);
String bssid = connectionInfo.getString(getString(R.string.connection_info_bssid), null);
String internalIP = connectionInfo.getString(getString(R.string.connection_info_internal_ip), null);
String externalIP = connectionInfo.getString(getString(R.string.connection_info_external_ip), null);
// Set text fields
if (ssid != null)
ssidView.setText(ssid);
else
ssidView.setText("-");
if (bssid != null)
bssidView.setText(bssid);
else
bssidView.setText("-");
if (internalIP != null)
internalIPView.setText(internalIP);
else
internalIPView.setText("-");
if (externalIP != null)
externalIPView.setText(externalIP);
else
externalIPView.setText("-");
}
/**
* Sets the connections count for a given protocol.
*
* @param connections
* New value for recorded connections.
* @param protocolName
* Name of the protocol which should be updated.
*/
private void updateProtocolConnections(int connections, String protocolName) {
for (int i = 0; i < adapter.getCount(); ++i) {
HashMap d = (HashMap) adapter.getItem(i);
if (d.get("protocol").equals(protocolName)) {
d.put("connections", String.valueOf(connections));
}
}
adapter.notifyDataSetChanged();
}
/**
* Sets the light indicator for a given protocol.
*
* @param light
* Integer code to set the light color.
* @param protocolName
* Name of the protocol which should be updated.
*/
private void updateProtocolLight(int light, String protocolName) {
for (int i = 0; i < adapter.getCount(); ++i) {
HashMap d = (HashMap) adapter.getItem(i);
if (d.get("protocol").equals(protocolName)) {
switch (light) {
case LIGHT_GREY:
d.put("light", String.valueOf(R.drawable.light_grey));
d.put("connections", "-");
break;
case LIGHT_GREEN:
d.put("light", String.valueOf(R.drawable.light_green));
break;
case LIGHT_RED:
d.put("light", String.valueOf(R.drawable.light_red));
break;
case LIGHT_YELLOW:
d.put("light", String.valueOf(R.drawable.light_yellow));
break;
}
}
}
adapter.notifyDataSetChanged();
}
/**
* Sets the big light indicator.
*
* @param light
* Integer code to set the light color.
* @see #LIGHT_GREY
* @see #LIGHT_GREEN
* @see #LIGHT_RED
* @see #LIGHT_YELLOW
*/
private void updateStatusLight(int light) {
switch (light) {
case LIGHT_GREY:
((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_grey_large);
break;
case LIGHT_GREEN:
((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_green_large);
break;
case LIGHT_RED:
((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_red_large);
break;
case LIGHT_YELLOW:
((ImageView) findViewById(R.id.imageViewLight)).setImageResource(R.drawable.light_yellow_large);
break;
}
}
/* ############# Help functions for animation ################## */
/**
* Updates Information shown by the GUI.
*/
private void updateUI() {
boolean activeListeners = false;
boolean activeHandlers = false;
boolean yellowLight = false;
// Check for all protocols if listeners are active and attacks have been
// recorded
// Update protocol lights and connection information.
for (String protocol : getResources().getStringArray(R.array.protocols)) {
if (isServiceBound()) {
// Check if protocol is active
if (mService.isRunning(protocol)) {
activeListeners = true;
int handlerCount = mService.getNumberOfActiveConnections(protocol);
// Check if attacks have been recorded in this session.
if (handlerCount > 0) {
activeHandlers = true;
updateProtocolLight(LIGHT_RED, protocol);
updateProtocolConnections(handlerCount, protocol);
} else {
// Check if the bssid of the wireless network has
// already
// been recorded as infected.
HostageDBOpenHelper dbh = new HostageDBOpenHelper(this);
if (dbh.bssidSeen(protocol, connectionInfo.getString(getString(R.string.connection_info_bssid), null))) {
updateProtocolLight(LIGHT_YELLOW, protocol);
yellowLight = true;
} else {
updateProtocolLight(LIGHT_GREEN, protocol);
}
updateProtocolConnections(0, protocol);
}
} else {
updateProtocolLight(LIGHT_GREY, protocol);
}
} else {
updateProtocolLight(LIGHT_GREY, protocol);
}
}
// Update the big attack indicator.
if (activeListeners) {
if (activeHandlers) {
updateStatusLight(LIGHT_RED);
} else {
if (yellowLight) {
updateStatusLight(LIGHT_YELLOW);
} else {
updateStatusLight(LIGHT_GREEN);
}
}
((ToggleButton) findViewById(R.id.toggleButtonOnOff)).setChecked(true);
findViewById(R.id.checkBoxParanoid).setEnabled(false);
} else {
updateStatusLight(LIGHT_GREY);
((ToggleButton) findViewById(R.id.toggleButtonOnOff)).setChecked(false);
findViewById(R.id.checkBoxParanoid).setEnabled(true);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
connectionInfo = getSharedPreferences(getString(R.string.connection_info), Context.MODE_PRIVATE);
// Create dynamic view elements
initViewAnimator();
initListView();
// Initialize Class variables
startAndBind();
}
@Override
protected void onDestroy() {
// Unbind running service
if (!mService.hasRunningListeners()) {
stopAndUnbind();
}
super.onDestroy();
}
@Override
protected void onStart() {
super.onStart();
// Register Broadcast Receiver
registerReceiver();
// Bind service if running, else check for connection change and delete
// sessionData
if (isServiceRunning()) {
bindService(getServiceIntent(), mConnection, BIND_AUTO_CREATE);
}
// Update UI
updateConnectionInfText();
}
@Override
protected void onStop() {
// Unregister Broadcast Receiver
unregisterReceiver();
super.onStop();
}
}