content: /* Android IMSI-Catcher Detector | (c) AIMSICD Privacy Project
   * -----------------------------------------------------------
   * LICENSE:  http://git.io/vki47 | TERMS:  http://git.io/vki4o
   * -----------------------------------------------------------
   */
  package zz.aimsicd.lite;
  
  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.util.Log;
  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 java.util.List;
  import java.util.Locale;
  
  import zz.aimsicd.lite.adapters.AIMSICDDbAdapter;
  import zz.aimsicd.lite.constants.DrawerMenu;
  import zz.aimsicd.lite.service.AimsicdService;
  import zz.aimsicd.lite.service.CellTracker;
  import zz.aimsicd.lite.ui.activities.AboutActivity;
  import zz.aimsicd.lite.ui.activities.BaseActivity;
  import zz.aimsicd.lite.ui.activities.DebugLogs;
  import zz.aimsicd.lite.ui.activities.SettingsActivity;
  import zz.aimsicd.lite.ui.drawer.DrawerMenuActivityConfiguration;
  import zz.aimsicd.lite.ui.drawer.NavDrawerItem;
  import zz.aimsicd.lite.ui.fragments.AtCommandFragment;
  import zz.aimsicd.lite.ui.fragments.CellInfoFragment;
  import zz.aimsicd.lite.ui.fragments.DbViewerFragment;
  import zz.aimsicd.lite.ui.fragments.DeviceFragment;
  import zz.aimsicd.lite.ui.fragments.MapFragment;
  import zz.aimsicd.lite.utils.AsyncResponse;
  import zz.aimsicd.lite.utils.Cell;
  import zz.aimsicd.lite.utils.GeoLocation;
  import zz.aimsicd.lite.utils.Helpers;
  import zz.aimsicd.lite.utils.Icon;
  import zz.aimsicd.lite.utils.LocationServices;
  import zz.aimsicd.lite.utils.RequestTask;
  
  public class MainActivity 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;
  
      @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:zz.aimsicd.lite");
                              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(Locale.US);
          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, 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.DATABASE_SETTINGS.BACKUP_DB:
                  new RequestTask(this, RequestTask.BACKUP_DATABASE).execute();
                  break;
          }
  
          if (selectedItem.getId() == DrawerMenu.ID.DATABASE_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.DATABASE_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.APPLICATION.QUIT) {
              try {
                  if (mAimsicdService.isSmsTracking()) {
                      mAimsicdService.stopSmsTracking();
                  }
              } catch (Exception ee) {
                 Log.w(TAG, mTAG + "Exception in smstracking module: " + ee.getMessage());
              }
  
              if (mAimsicdService != null) {
                  mAimsicdService.onDestroy();
              }
              //Close database on Exit
              Log.i(TAG, mTAG + "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 && !networkOperator.isEmpty()) {
                  int mcc = Integer.parseInt(networkOperator.substring(0, 3));
                  cell.setMCC(mcc);
                  int mnc = Integer.parseInt(networkOperator.substring(3));
                  cell.setMNC(mnc);
                 Log.d(TAG, mTAG + "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, mAimsicdService);
              } 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.i(TAG, mTAG + "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, mAimsicdService);
          } 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.i(TAG, mTAG + "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.w(TAG, mTAG + "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(MainActivity.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();
      }
  
      /**
       * Invoked only once during app's lifetime. For successive calls see
       * {@link #onPrepareOptionsMenu(Menu)}. Both used primarily to determine checkboxes for tracking
       * and detection.
       *
       * Because the service may not available on app boot, we default to false until the service
       * boots. Once that occurs, the checkboxes are driven by the service's status.
       *
       * @param menu
       * @return
       */
      @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);
          MenuItem toggleCellTrackingMenuItem = menu.findItem(R.id.toggle_cell_tracking);
  
          // The service may not exist on first app boot. Choose sane defaults
          if (mAimsicdService == null) {
              toggleAttackDetectionMenuItem.setChecked(false);
              toggleCellTrackingMenuItem.setChecked(false);
          } else {
              toggleAttackDetectionMenuItem.setChecked(mAimsicdService.isMonitoringCell());
              toggleCellTrackingMenuItem.setChecked(mAimsicdService.isTrackingCell());
          }
          return true;
      }
  
      /**
       * Display latest cell tracking & attack detection truth when opening menu over & over
       *
       * @param menu
       * @return
       */
      @Override
      public boolean onPrepareOptionsMenu(Menu menu) {
          // Bail early if there's no service to get the facts from
          if (mAimsicdService == null) {
              return super.onPrepareOptionsMenu(menu);
          }
          MenuItem toggleAttackDetectionMenuItem = menu.findItem(R.id.toggle_attack_detection);
          MenuItem toggleCellTrackingMenuItem = menu.findItem(R.id.toggle_cell_tracking);
          toggleAttackDetectionMenuItem.setChecked(mAimsicdService.isMonitoringCell());
          toggleCellTrackingMenuItem.setChecked(mAimsicdService.isTrackingCell());
          return super.onPrepareOptionsMenu(menu);
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          switch (item.getItemId()) {
              case R.id.toggle_attack_detection:
                  monitorCell();
                  item.setChecked(mAimsicdService.isMonitoringCell());
                  break;
              case R.id.toggle_cell_tracking:
                  trackCell();
                  item.setChecked(mAimsicdService.isTrackingCell());
                  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.e(TAG, mTAG + "Error: Stopping SMS detection : " + ee.getMessage());
              }
              // Close database on Exit
              Log.i(TAG, mTAG + "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.i(TAG, mTAG + "SMS Detection Thread Started");
          } else if (!root_sms && mAimsicdService.isSmsTracking()) {
              mAimsicdService.stopSmsTracking();
              Helpers.msgShort(this, "Sms Detection Stopped");
              Log.i(TAG, mTAG + "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());
      }
  
      public void onStop() {
          super.onStop();
          ((AppAIMSICD) getApplication()).detach(this);
      }
  
      @Override
      public void onStart() {
          super.onStart();
          ((AppAIMSICD) getApplication()).attach(this);
      }
  }
  