/*----------------------------------------------------------------------------+ *| | *| 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(); } }