com.SecUpwN.AIMSICD.AIMSICD.java Source code

Java tutorial

Introduction

Here is the source code for com.SecUpwN.AIMSICD.AIMSICD.java

Source

/* Android IMSI-Catcher Detector | (c) AIMSICD Privacy Project
 * -----------------------------------------------------------
 * LICENSE:  http://git.io/vki47 | TERMS:  http://git.io/vki4o
 * -----------------------------------------------------------
 */
package com.SecUpwN.AIMSICD;

import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import com.SecUpwN.AIMSICD.activities.AboutActivity;
import com.SecUpwN.AIMSICD.activities.BaseActivity;
import com.SecUpwN.AIMSICD.activities.DebugLogs;
import com.SecUpwN.AIMSICD.fragments.MapFragment;
import com.SecUpwN.AIMSICD.activities.SettingsActivity;
import com.SecUpwN.AIMSICD.adapters.AIMSICDDbAdapter;
import com.SecUpwN.AIMSICD.constants.DrawerMenu;
import com.SecUpwN.AIMSICD.drawer.DrawerMenuActivityConfiguration;
import com.SecUpwN.AIMSICD.drawer.NavDrawerItem;
import com.SecUpwN.AIMSICD.fragments.AtCommandFragment;
import com.SecUpwN.AIMSICD.fragments.CellInfoFragment;
import com.SecUpwN.AIMSICD.fragments.DbViewerFragment;
import com.SecUpwN.AIMSICD.fragments.DeviceFragment;
import com.SecUpwN.AIMSICD.service.AimsicdService;
import com.SecUpwN.AIMSICD.service.CellTracker;
import com.SecUpwN.AIMSICD.utils.AsyncResponse;
import com.SecUpwN.AIMSICD.utils.Cell;
import com.SecUpwN.AIMSICD.utils.GeoLocation;
import com.SecUpwN.AIMSICD.utils.Helpers;
import com.SecUpwN.AIMSICD.utils.Icon;
import com.SecUpwN.AIMSICD.utils.LocationServices;
import com.SecUpwN.AIMSICD.utils.RequestTask;
import com.SecUpwN.AIMSICD.utils.StackOverflowXmlParser;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.List;

import io.freefair.android.injection.annotation.Inject;

public class AIMSICD extends BaseActivity implements AsyncResponse {

    private boolean mBound;
    private SharedPreferences prefs;
    private SharedPreferences.OnSharedPreferenceChangeListener prefListener;
    private Editor prefsEditor;
    private String mDisclaimerAccepted;
    private AimsicdService mAimsicdService;

    private DrawerLayout mDrawerLayout;
    private ActionBar mActionBar;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;
    private CharSequence mDrawerTitle;
    private CharSequence mTitle;

    private DeviceFragment deviceFragment;
    private CellInfoFragment cellInfoFragment;
    private AtCommandFragment atCommandFragment;
    private DbViewerFragment dbViewerFragment;
    private MapFragment mapFragment;

    private long mLastPress = 0; // Back press to exit timer

    private DrawerMenuActivityConfiguration mNavConf;

    @Inject
    OkHttpClient okHttpClient;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        deviceFragment = new DeviceFragment();
        cellInfoFragment = new CellInfoFragment();
        atCommandFragment = new AtCommandFragment();
        dbViewerFragment = new DbViewerFragment();
        mapFragment = new MapFragment();

        mNavConf = new DrawerMenuActivityConfiguration.Builder(this).build();

        mDrawerLayout = (DrawerLayout) findViewById(mNavConf.getDrawerLayoutId());
        mDrawerList = (ListView) findViewById(mNavConf.getLeftDrawerId());
        mActionBar = getSupportActionBar();
        mTitle = getTitle();
        mDrawerTitle = getTitle();

        mDrawerList.setAdapter(mNavConf.getBaseAdapter());

        mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
                mDrawerLayout, /* DrawerLayout object */
                R.string.drawer_open, /* "open drawer" description */
                R.string.drawer_close /* "close drawer" description */
        ) {
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
                mActionBar.setTitle(mTitle);
                invalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                mActionBar.setTitle(mDrawerTitle);
                invalidateOptionsMenu();
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        mActionBar.setDisplayHomeAsUpEnabled(true);
        mActionBar.setHomeButtonEnabled(true);

        prefs = getSharedPreferences(AimsicdService.SHARED_PREFERENCES_BASENAME, 0);

        /* Pref listener to enable sms detection on pref change   */
        prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
            public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
                if (key.equals(getString(R.string.adv_user_root_pref_key))) {
                    SmsDetection();
                }

            }
        };
        prefs.registerOnSharedPreferenceChangeListener(prefListener);

        mDisclaimerAccepted = getResources().getString(R.string.disclaimer_accepted);

        if (!prefs.getBoolean(mDisclaimerAccepted, false)) {
            final AlertDialog.Builder disclaimer = new AlertDialog.Builder(this).setTitle(R.string.disclaimer_title)
                    .setMessage(R.string.disclaimer)
                    .setPositiveButton(R.string.text_agree, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            prefsEditor = prefs.edit();
                            prefsEditor.putBoolean(mDisclaimerAccepted, true);
                            prefsEditor.apply();
                            startService();
                        }
                    }).setNegativeButton(R.string.text_disagree, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            prefsEditor = prefs.edit();
                            prefsEditor.putBoolean(mDisclaimerAccepted, false);
                            prefsEditor.apply();
                            Uri packageUri = Uri.parse("package:com.SecUpwN.AIMSICD");
                            Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageUri);
                            startActivity(uninstallIntent);
                            finish();
                            if (mAimsicdService != null) {
                                mAimsicdService.onDestroy();
                            }
                        }
                    });

            AlertDialog disclaimerAlert = disclaimer.create();
            disclaimerAlert.show();
        } else {
            startService();
        }
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        final String iconType = prefs.getString(getString(R.string.pref_ui_icons_key), "SENSE").toUpperCase();
        mActionBar.setIcon(Icon.getIcon(Icon.Type.valueOf(iconType), ((AppAIMSICD) getApplication()).getStatus()));
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }

        final String PERSIST_SERVICE = getString(R.string.pref_persistservice_key);
        boolean persistService = prefs.getBoolean(PERSIST_SERVICE, false);
        if (!persistService) {
            stopService(new Intent(this, AimsicdService.class));
        }
    }

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            mDrawerLayout.closeDrawer(mDrawerList);
            selectDrawerItem(position);
        }
    }

    void selectDrawerItem(int position) {
        NavDrawerItem selectedItem = mNavConf.getNavItems().get(position);
        String title = selectedItem.getLabel();

        switch (selectedItem.getId()) {
        case DrawerMenu.ID.MAIN.PHONE_SIM_DETAILS:
            openFragment(deviceFragment);
            title = getString(R.string.app_name_short);
            break;
        case DrawerMenu.ID.MAIN.CURRENT_TREAT_LEVEL:
            openFragment(cellInfoFragment);
            title = getString(R.string.app_name_short);
            break;
        case DrawerMenu.ID.MAIN.AT_COMMAND_INTERFACE:
            openFragment(atCommandFragment);
            title = getString(R.string.app_name_short);
            break;
        case DrawerMenu.ID.MAIN.DB_VIEWER:
            openFragment(dbViewerFragment);
            title = getString(R.string.app_name_short);
            break;
        case DrawerMenu.ID.APPLICATION.UPLOAD_LOCAL_BTS_DATA:
            // Request uploading here?
            new RequestTask(this, com.SecUpwN.AIMSICD.utils.RequestTask.DBE_UPLOAD_REQUEST).execute("");
            // no string needed for csv based upload
            break;
        case DrawerMenu.ID.MAIN.ANTENNA_MAP_VIEW:
            openFragment(mapFragment);
            title = getString(R.string.app_name_short);
            break;
        case DrawerMenu.ID.SETTINGS.BACKUP_DB:
            new RequestTask(this, RequestTask.BACKUP_DATABASE).execute();
            break;
        }

        if (selectedItem.getId() == DrawerMenu.ID.SETTINGS.RESTORE_DB) {
            if (CellTracker.LAST_DB_BACKUP_VERSION < AIMSICDDbAdapter.DATABASE_VERSION) {
                Helpers.msgLong(this, getString(R.string.unable_to_restore_backup_from_previous_database_version));
            } else {
                new RequestTask(this, RequestTask.RESTORE_DATABASE).execute();
            }
        } else if (selectedItem.getId() == DrawerMenu.ID.SETTINGS.RESET_DB) {
            // WARNING! This deletes the entire database, thus any subsequent DB access will FC app.
            //          Therefore we need to either restart app or run AIMSICDDbAdapter, to rebuild DB.
            //          See: https://github.com/SecUpwN/Android-IMSI-Catcher-Detector/issues/581 and Helpers.java
            Helpers.askAndDeleteDb(this);

        } else if (selectedItem.getId() == DrawerMenu.ID.APPLICATION.DOWNLOAD_LOCAL_BTS_DATA) {
            downloadBtsDataIfApiKeyAvailable();
        } else if (selectedItem.getId() == DrawerMenu.ID.MAIN.ALL_CURRENT_CELL_DETAILS) {
            if (CellTracker.OCID_API_KEY != null && !CellTracker.OCID_API_KEY.equals("NA")) {

                //TODO: Use Retrofit for that
                StringBuilder sb = new StringBuilder();
                sb.append("http://www.opencellid.org/cell/get?key=").append(CellTracker.OCID_API_KEY);

                if (mAimsicdService.getCell().getMCC() != Integer.MAX_VALUE) {
                    sb.append("&mcc=").append(mAimsicdService.getCell().getMCC());
                }

                if (mAimsicdService.getCell().getMNC() != Integer.MAX_VALUE) {
                    sb.append("&mnc=").append(mAimsicdService.getCell().getMNC());
                }

                if (mAimsicdService.getCell().getLAC() != Integer.MAX_VALUE) {
                    sb.append("&lac=").append(mAimsicdService.getCell().getLAC());
                }

                if (mAimsicdService.getCell().getCID() != Integer.MAX_VALUE) {
                    sb.append("&cellid=").append(mAimsicdService.getCell().getCID());
                }

                sb.append("&format=xml");

                Request request = new Request.Builder().url(sb.toString()).get().build();

                okHttpClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Request request, IOException e) {

                    }

                    @Override
                    public void onResponse(Response response) throws IOException {
                        try {
                            List<Cell> cellList = new StackOverflowXmlParser().parse(response.body().byteStream());
                            AIMSICD.this.processFinish(cellList);
                        } catch (XmlPullParserException e) {
                            e.printStackTrace();
                        }
                    }
                });
            } else {
                Helpers.sendMsg(this, getString(R.string.no_opencellid_key_detected));
            }
        } else if (selectedItem.getId() == DrawerMenu.ID.APPLICATION.QUIT) {
            try {
                if (mAimsicdService.isSmsTracking()) {
                    mAimsicdService.stopSmsTracking();
                }
            } catch (Exception ee) {
                log.warn("Exception in smstracking module: " + ee.getMessage());
            }

            if (mAimsicdService != null) {
                mAimsicdService.onDestroy();
            }
            //Close database on Exit
            log.info("Closing db from DrawerMenu.ID.APPLICATION.QUIT");
            new AIMSICDDbAdapter(getApplicationContext()).close();
            finish();
        }

        mDrawerList.setItemChecked(position, true);

        if (selectedItem.updateActionBarTitle()) {
            setTitle(title);
        }

        if (this.mDrawerLayout.isDrawerOpen(this.mDrawerList)) {
            mDrawerLayout.closeDrawer(mDrawerList);
        }
    }

    private void openFragment(Fragment fragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        transaction.replace(R.id.content_frame, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }

    private void downloadBtsDataIfApiKeyAvailable() {
        if (CellTracker.OCID_API_KEY != null && !CellTracker.OCID_API_KEY.equals("NA")) {

            Cell cell = new Cell();
            TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            String networkOperator = tm.getNetworkOperator();

            if (networkOperator != null) {
                int mcc = Integer.parseInt(networkOperator.substring(0, 3));
                cell.setMCC(Integer.parseInt(networkOperator.substring(0, 3)));
                int mnc = Integer.parseInt(networkOperator.substring(3));
                cell.setMNC(Integer.parseInt(networkOperator.substring(3, 5)));
                log.debug("CELL:: mcc=" + mcc + " mnc=" + mnc);
            }

            GeoLocation loc = mAimsicdService.lastKnownLocation();
            if (loc != null) {
                Helpers.msgLong(this, getString(R.string.contacting_opencellid_for_data));

                cell.setLon(loc.getLongitudeInDegrees());
                cell.setLat(loc.getLatitudeInDegrees());
                Helpers.getOpenCellData(this, cell, RequestTask.DBE_DOWNLOAD_REQUEST);
            } else {
                Helpers.msgShort(this, getString(R.string.waiting_for_location));

                // This uses the LocationServices to get CID/LAC/MNC/MCC to be used
                // for grabbing the BTS data from OCID, via their API.
                // CID Location Async Output Delegate Interface Implementation
                LocationServices.LocationAsync locationAsync = new LocationServices.LocationAsync();
                locationAsync.delegate = this;
                locationAsync.execute(mAimsicdService.getCell().getCID(), mAimsicdService.getCell().getLAC(),
                        mAimsicdService.getCell().getMNC(), mAimsicdService.getCell().getMCC());
            }
        } else {
            Helpers.sendMsg(this, getString(R.string.no_opencellid_key_detected));
        }
    }

    @Override
    public void processFinish(float[] location) {
        log.info("processFinish - location[0]=" + location[0] + " location[1]=" + location[1]);

        if (Float.floatToRawIntBits(location[0]) == 0 && Float.floatToRawIntBits(location[1]) != 0) {
            Helpers.msgLong(this, getString(R.string.contacting_opencellid_for_data));
            Helpers.getOpenCellData(this, mAimsicdService.getCell(), RequestTask.DBE_DOWNLOAD_REQUEST);
        } else {
            Helpers.msgLong(this, getString(R.string.unable_to_determine_last_location));
        }
    }

    @Override
    public void processFinish(List<Cell> cells) {
        if (cells != null) {
            if (!cells.isEmpty()) {
                for (Cell cell : cells) {
                    log.info("processFinish - Cell =" + cell.toString());
                    if (cell.isValid()) {
                        mAimsicdService.setCell(cell);
                        Intent intent = new Intent(AimsicdService.UPDATE_DISPLAY);
                        intent.putExtra("update", true);
                        sendBroadcast(intent);
                    }
                }
            }
        }
    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        mActionBar.setTitle(mTitle);
    }

    /**
     * Service Connection to bind the activity to the service
     */
    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            mAimsicdService = ((AimsicdService.AimscidBinder) service).getService();
            mBound = true;

            // Check if tracking cell details check location services are still enabled
            if (mAimsicdService.isTrackingCell()) {
                mAimsicdService.checkLocationServices();
            }

            if (!mAimsicdService.isSmsTracking()
                    && prefs.getBoolean(getString(R.string.adv_user_root_pref_key), false)) {
                /*Auto Start sms detection here if:
                *    isSmsTracking = false <---- not running
                *    root sms enabled = true
                *
                * */
                SmsDetection();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            log.warn("Service disconnected");
            mBound = false;
        }
    };

    private void startService() {
        // don't start service if disclaimer is not accepted
        if (!prefs.getBoolean(mDisclaimerAccepted, false)) {
            return;
        }

        if (!mBound) {
            // Bind to LocalService
            Intent intent = new Intent(AIMSICD.this, AimsicdService.class);
            //Start Service before binding to keep it resident when activity is destroyed
            startService(intent);
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

            openFragment(deviceFragment);
        }
    }

    /**
     * Triggered when GUI is opened
     */
    @Override
    public void onResume() {
        super.onResume();
        invalidateOptionsMenu();
        startService();
    }

    /**
     * Triggered when GUI is closed/put to background
     */
    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);

        MenuItem toggleAttackDetectionMenuItem = menu.findItem(R.id.toggle_attack_detection);
        toggleAttackDetectionMenuItem.setChecked(true);
        MenuItem toggleCellTrackingMenuItem = menu.findItem(R.id.toggle_cell_tracking);
        toggleCellTrackingMenuItem.setChecked(true);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.toggle_attack_detection:
            item.setChecked(!item.isChecked());
            monitorCell();
            break;
        case R.id.toggle_cell_tracking:
            item.setChecked(!item.isChecked());
            trackCell();
            break;
        case R.id.settings:
            Intent settingsIntent = new Intent(this, SettingsActivity.class);
            startActivity(settingsIntent);
            break;
        case R.id.about:
            Intent aboutIntent = new Intent(this, AboutActivity.class);
            startActivity(aboutIntent);
            break;
        case R.id.debugging:
            Intent i = new Intent(this, DebugLogs.class);
            startActivity(i);
            break;
        }

        return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
    }

    /**
     * Exit application if Back button is pressed twice
     */
    @Override
    public void onBackPressed() {
        Toast onBackPressedToast = Toast.makeText(this, R.string.press_once_again_to_exit, Toast.LENGTH_SHORT);
        long currentTime = System.currentTimeMillis();
        if (currentTime - mLastPress > 5000) {
            onBackPressedToast.show();
            mLastPress = currentTime;
        } else {
            onBackPressedToast.cancel();
            super.onBackPressed();
            try {
                if (mAimsicdService.isSmsTracking()) {
                    mAimsicdService.stopSmsTracking();
                }
            } catch (Exception ee) {
                log.error("Error: Stopping SMS detection : " + ee.getMessage());
            }
            // Close database on Exit
            log.info("Closing db from onBackPressed()");
            new AIMSICDDbAdapter(getApplicationContext()).close();
            finish();
        }
    }

    private void SmsDetection() {
        boolean root_sms = prefs.getBoolean(getString(R.string.adv_user_root_pref_key), false); // default is false

        if (root_sms && !mAimsicdService.isSmsTracking()) {
            mAimsicdService.startSmsTracking();
            Helpers.msgShort(this, "SMS Detection Started");
            log.info("SMS Detection Thread Started");
        } else if (!root_sms && mAimsicdService.isSmsTracking()) {
            mAimsicdService.stopSmsTracking();
            Helpers.msgShort(this, "Sms Detection Stopped");
            log.info("SMS Detection Thread Stopped");
        }
    }

    /**
     * Cell Information Tracking - Enable/Disable
     */
    private void trackCell() {
        mAimsicdService.setCellTracking(mAimsicdService.isTrackingCell());
    }

    /**
     * Cell Information Monitoring - Enable/Disable
     */
    private void monitorCell() {
        mAimsicdService.setCellMonitoring(!mAimsicdService.isMonitoringCell());
    }

    /**
     * FemtoCell Detection (CDMA Phones ONLY) - Enable/Disable
     */
    private void trackFemtocell() {
        mAimsicdService.setTrackingFemtocell(!mAimsicdService.isTrackingFemtocell());
    }

    public void onStop() {
        super.onStop();
        ((AppAIMSICD) getApplication()).detach(this);
    }

    @Override
    public void onStart() {
        super.onStart();
        ((AppAIMSICD) getApplication()).attach(this);
    }
}