/* Android IMSI-Catcher Detector | (c) AIMSICD Privacy Project * ----------------------------------------------------------- * LICENSE: http://git.io/vki47 | TERMS: http://git.io/vki4o * ----------------------------------------------------------- */ /* This was introduced by Aussie in the Pull Request Commit: * https://github.com/xLaMbChOpSx/Android-IMSI-Catcher-Detector/commit/6d8719ab356a3ecbd0b526a9ded0cabb17ab2021 * * Where he writes: * "" * Advanced Cell Fragment added to display the Neighboring Cell information in two ways: Firstly * through telephony manager methods which does not work on Samsung Devices, a fallback is available * through the methods developed by Alexey and will display if these are successful. * Ciphering Indicator also uses Alexey's methods and will display on Samsung devices. * "" */ package com.secupwn.aimsicd.ui.fragments; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.support.v4.widget.SwipeRefreshLayout; import android.text.TextUtils; import android.view.View; import android.widget.ListView; import android.widget.TableRow; import android.widget.TextView; import com.secupwn.aimsicd.R; import com.secupwn.aimsicd.adapters.BaseInflaterAdapter; import com.secupwn.aimsicd.adapters.CardItemData; import com.secupwn.aimsicd.adapters.CellCardInflater; import com.secupwn.aimsicd.rilexecutor.RilExecutor; import com.secupwn.aimsicd.service.AimsicdService; import com.secupwn.aimsicd.service.CellTracker; import com.secupwn.aimsicd.utils.Cell; import com.secupwn.aimsicd.utils.Helpers; import java.util.List; import java.util.concurrent.TimeUnit; import io.freefair.android.injection.annotation.InjectView; import io.freefair.android.injection.annotation.XmlLayout; import io.freefair.android.injection.app.InjectionFragment; /** * Description: This class updates the CellInfo fragment. This is also known as * the Neighboring Cells info, which is using the MultiRilClient to * show neighboring cells on the older Samsung Galaxy S2/3 series. * It's refresh rate is controlled in the settings by: * * arrays.xml: * pref_refresh_entries (the names) * pref_refresh_values (the values in seconds) * * * Dependencies: Seem that this is intimately connected to: CellTracker.java service... * * * TODO: 1) Use an IF check, in order not to run the MultiRilClient on non supported devices * as this will cause excessive logcat spam. * TODO: 2) Might wanna make the refresh rate lower/higher depending on support * */ @XmlLayout(R.layout.fragment_cell_info) public class CellInfoFragment extends InjectionFragment implements SwipeRefreshLayout.OnRefreshListener { public static final int STOCK_REQUEST = 1; public static final int SAMSUNG_MULTIRIL_REQUEST = 2; private AimsicdService mAimsicdService; private RilExecutor rilExecutor; private boolean mBound; private Context mContext; private final Handler timerHandler = new Handler(); private List<Cell> neighboringCells; @InjectView(R.id.list_view) private ListView lv; @InjectView(R.id.neighboring_cells) private TextView mNeighboringCells; @InjectView(R.id.neighboring_number) private TextView mNeighboringTotal; @InjectView(R.id.neighboring_total) private TableRow mNeighboringTotalView; @InjectView(R.id.ciphering_indicator_title) private TextView mCipheringIndicatorLabel; @InjectView(R.id.ciphering_indicator) private TextView mCipheringIndicator; @InjectView(R.id.swipeRefreshLayout) private SwipeRefreshLayout swipeRefreshLayout; private final Runnable timerRunnable = new Runnable() { @Override public void run() { updateUI(); timerHandler.postDelayed(this, CellTracker.REFRESH_RATE); } }; @Override public void onPause() { super.onPause(); timerHandler.removeCallbacks(timerRunnable); } @Override public void onResume() { super.onResume(); if (!mBound) { // Bind to LocalService Intent intent = new Intent(mContext, AimsicdService.class); mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } // Refresh display if preference (pref_refresh_values) is not set to manual (0) // For automatic it is "1" and defined in: // CellTracker.java :: onSharedPreferenceChanged() if (CellTracker.REFRESH_RATE != 0) { timerHandler.postDelayed(timerRunnable, 0); Helpers.msgShort(mContext, mContext.getString(R.string.refreshing_every) + " " + TimeUnit.MILLISECONDS.toSeconds(CellTracker.REFRESH_RATE) + " " + mContext.getString(R.string.seconds)); } } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mContext = getActivity().getBaseContext(); // Bind to LocalService Intent intent = new Intent(mContext, AimsicdService.class); mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); swipeRefreshLayout.setOnRefreshListener(this); } @Override public void onDestroy() { super.onDestroy(); // Unbind from the service if (mBound) { mContext.unbindService(mConnection); mBound = false; } timerHandler.removeCallbacks(timerRunnable); } /** * 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(); rilExecutor = mAimsicdService.getRilExecutor(); mBound = true; updateUI(); } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; @Override public void onRefresh() { updateUI(); swipeRefreshLayout.setRefreshing(false); } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { updateUI(); } } private void updateUI() { if (mBound && rilExecutor.mMultiRilCompatible) { new CellAsyncTask().execute(SAMSUNG_MULTIRIL_REQUEST); } else { new CellAsyncTask().execute(STOCK_REQUEST); } } void updateCipheringIndicator() { final List<String> list = rilExecutor.getCipheringInfo(); getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (list != null) { mCipheringIndicatorLabel.setVisibility(View.VISIBLE); mCipheringIndicator.setVisibility(View.VISIBLE); mCipheringIndicator.setText(TextUtils.join("\n", list)); } } }); } boolean getStockNeighboringCells() { if (mBound) { neighboringCells = mAimsicdService.getCellTracker().updateNeighboringCells(); return neighboringCells.size() > 0; } return false; } void updateStockNeighboringCells() { mNeighboringTotal.setText(String.valueOf(neighboringCells.size())); if (neighboringCells.size() != 0) { BaseInflaterAdapter<CardItemData> adapter = new BaseInflaterAdapter<>(new CellCardInflater()); int i = 1; int total = neighboringCells.size(); for (Cell cell : neighboringCells) { CardItemData data = new CardItemData(cell, i++ + " / " + total); adapter.addItem(data, false); } lv.setAdapter(adapter); mNeighboringCells.setVisibility(View.GONE); mNeighboringTotalView.setVisibility(View.VISIBLE); } } void updateNeighboringCells() { final List<String> list = rilExecutor.getNeighbors(); getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (list != null) { mNeighboringCells.setText(TextUtils.join("\n", list)); mNeighboringCells.setVisibility(View.VISIBLE); mNeighboringTotalView.setVisibility(View.GONE); } } }); } void getSamSungMultiRil() { if (mBound && rilExecutor.mMultiRilCompatible) { new CellAsyncTask().execute(SAMSUNG_MULTIRIL_REQUEST); } } private class CellAsyncTask extends AsyncTask<Integer, Void, Boolean> { @Override protected Boolean doInBackground(Integer... type) { switch (type[0]) { case STOCK_REQUEST: return getStockNeighboringCells(); case SAMSUNG_MULTIRIL_REQUEST: if (mBound) { updateNeighboringCells(); updateCipheringIndicator(); } break; } return false; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); if (result) { updateStockNeighboringCells(); } else { getSamSungMultiRil(); } } } }