/*----------------------------------------------------------------------------+
*| |
*| Android's Hooker |
*| |
*+---------------------------------------------------------------------------+
*| Copyright (C) 2011 Georges Bossert and Dimitri Kirchner |
*| This program is free software: you can redistribute it and/or modify |
*| it under the terms of the GNU General Public License as published by |
*| the Free Software Foundation, either version 3 of the License, or |
*| (at your option) any later version. |
*| |
*| 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, see <http://www.gnu.org/licenses/>. |
*+---------------------------------------------------------------------------+
*| @url : http://www.amossys.fr |
*| @contact : android-hooker@amossys.fr |
*| @sponsors : Amossys, http://www.amossys.fr |
*+---------------------------------------------------------------------------+
*/
package com.amossys.hooker;
/**
* @brief Main activity is checking if instrumentation service is running, and is printing
* configuration from it.
* Refer to README file for instructions on installing this application.
*/
import com.amossys.hooker.service.InstrumentationService;
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.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class ApkInstrumenterActivity extends Activity {
public static final int Configuration = 1;
private TextView serviceStarted;
private TextView idXp;
private TextView esState;
private EditText esIP;
private EditText esPort;
private EditText esIndex;
private EditText docType;
private TextView filemode;
private EditText filename;
private final static String TAG = "APKInstrumenter";
private Context context;
private Messenger mService = null;
private boolean mBound;
final Messenger mMessenger = new Messenger(new IncomingHandler());
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "Message has been handled by activity: " + msg.toString());
switch (msg.what) {
case ApkInstrumenterActivity.Configuration:
Log.i(TAG, "Service has responded its configuration");
// Construct Bundle from our attributes
Bundle configuration = msg.getData();
idXp.setText(configuration.getString("idxp"));
if (configuration.getBoolean("fileMode")) {
filemode.setText("ON");
} else {
filemode.setText("OFF");
}
if (configuration.getBoolean("networkMode")) {
esState.setText("ON");
} else {
esState.setText("OFF");
}
esIP.setText(configuration.getString("esIp"));
esPort.setText(Integer.toString(configuration.getInt("esPort")));
// int esNbThread = configuration.getInt("esNbThread");
esIndex.setText(configuration.getString("esIndex"));
docType.setText(configuration.getString("esDoctype"));
filename.setText(configuration.getString("fileName"));
if (checkIfServiceIsRunning()) {
serviceStarted.setText("ON");
} else {
serviceStarted.setText("OFF");
}
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
mBound = true;
try {
Message msg = Message.obtain(null,
InstrumentationService.ConnectToService);
mService.send(msg);
} catch (RemoteException e) {
Log.e(TAG, "Service has crashed", e);
}
Log.i(TAG, "Connected with the service");
}
@Override
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;
mBound = false;
Log.i(TAG, "Activity disconnected from the service");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
// Init attributes
serviceStarted = (TextView) findViewById(R.id.serviceStatus);
idXp = (TextView) findViewById(R.id.idExperiment);
esState = (TextView) findViewById(R.id.esStatus);
esIP = (EditText) findViewById(R.id.esIP);
Log.i(TAG, "1");
esPort = (EditText) findViewById(R.id.esPort);
Log.i(TAG, "2");
esIndex = (EditText) findViewById(R.id.esIndex);
Log.i(TAG, "3");
docType = (EditText) findViewById(R.id.docType);
Log.i(TAG, "4");
filemode = (TextView) findViewById(R.id.filemodeStatus);
Log.i(TAG, "5");
filename = (EditText) findViewById(R.id.filename);
// Disable edittext
esIP.setKeyListener(null);
esPort.setKeyListener(null);
filename.setKeyListener(null);
esIndex.setKeyListener(null);
docType.setKeyListener(null);
filemode.setKeyListener(null);
doBindService();
if (checkIfServiceIsRunning()) {
serviceStarted.setText("ON");
} else {
serviceStarted.setText("OFF");
}
}
private boolean checkIfServiceIsRunning() {
// If the service is running when the activity starts, we want to
// automatically bind to it.
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (InstrumentationService.class.getName().equals(service.service.getClassName())) {
serviceStarted.setText("OFF");
return true;
}
}
return false;
}
/**
* Ask InstrumentationService to send its configuration.
*/
public void askForConfiguration() {
if (!mBound) {
Log.i(TAG, "mBound is null, sendEvent failed");
return;
}
Message msg = Message.obtain(null, InstrumentationService.GetConfiguration);
msg.replyTo = mMessenger;
try {
Log.i(TAG, "Asking configuration if instrumentation service");
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.select_target, menu);
return true;
}
/**
* Build an intent and start the service.
*/
public void doBindService() {
bindService(new Intent(context, InstrumentationService.class), mConnection,
Context.BIND_AUTO_CREATE);
Log.i(TAG, "Application has been bound to service.");
}
/**
* Stops the service. This method is never called since we don't want the
* service to be stopped for now .
*/
void doUnbindService() {
if (mBound) {
// If we have received the service, and hence registered with it, then now
// is the time to
// unregister.
if (mService != null) {
// Detach our existing connection.
Log.i(TAG, "Trying to unbind");
unbindService(mConnection);
mBound = false;
mService = null;
}
Log.i(TAG, "Unbinded from service");
}
}
public void testService(View v) {
askForConfiguration();
}
}