/* Android IMSI-Catcher Detector | (c) AIMSICD Privacy Project
* -----------------------------------------------------------
* LICENSE: http://git.io/vki47 | TERMS: http://git.io/vki4o
* -----------------------------------------------------------
*/
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.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.v4.widget.SwipeRefreshLayout;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.TableRow;
import com.secupwn.aimsicd.R;
import com.secupwn.aimsicd.service.AimsicdService;
import com.secupwn.aimsicd.service.CellTracker;
import com.secupwn.aimsicd.utils.Cell;
import com.secupwn.aimsicd.utils.Device;
import com.secupwn.aimsicd.utils.Helpers;
import com.secupwn.aimsicd.ui.widget.HighlightTextView;
import com.kaichunlin.transition.animation.AnimationManager;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import io.freefair.android.injection.annotation.Inject;
import io.freefair.android.injection.annotation.InjectView;
import io.freefair.android.injection.annotation.XmlLayout;
import io.freefair.android.injection.app.InjectionFragment;
import io.freefair.android.util.logging.Logger;
@XmlLayout(R.layout.fragment_device)
public class DeviceFragment extends InjectionFragment implements SwipeRefreshLayout.OnRefreshListener {
@Inject
private Logger log;
@Inject
OkHttpClient okHttpClient;
@InjectView(R.id.swipeRefresLayout)
private SwipeRefreshLayout swipeRefreshLayout;
private AimsicdService mAimsicdService;
private boolean mBound;
private Context mContext;
@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 onResume() {
super.onResume();
if (!mBound) {
// Bind to LocalService
Intent intent = new Intent(mContext, AimsicdService.class);
mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
updateUI();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
// Unbind from the service
if (mBound) {
mContext.unbindService(mConnection);
mBound = false;
}
}
/**
* 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;
updateUI();
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
log.error("Service Disconnected");
mBound = false;
}
};
private void updateUI() {
HighlightTextView content;
TableRow tr;
if (mBound) {
final AnimationManager ani = new AnimationManager();
mAimsicdService.getCellTracker().refreshDevice();
Device mDevice = mAimsicdService.getCellTracker().getDevice();
switch (mDevice.getPhoneId()) {
case TelephonyManager.PHONE_TYPE_NONE: // Maybe bad!
case TelephonyManager.PHONE_TYPE_SIP: // Maybe bad!
case TelephonyManager.PHONE_TYPE_GSM: {
content = (HighlightTextView) getView().findViewById(R.id.network_lac);
content.updateText(String.valueOf(mAimsicdService.getCell().getLocationAreaCode()), ani);
tr = (TableRow) getView().findViewById(R.id.gsm_cellid);
tr.setVisibility(View.VISIBLE);
content = (HighlightTextView) getView().findViewById(R.id.network_cellid);
content.updateText(String.valueOf(mAimsicdService.getCell().getCellId()), ani);
break;
}
case TelephonyManager.PHONE_TYPE_CDMA: {
tr = (TableRow) getView().findViewById(R.id.cdma_netid);
tr.setVisibility(View.VISIBLE);
content = (HighlightTextView) getView().findViewById(R.id.network_netid);
content.updateText(String.valueOf(mAimsicdService.getCell().getLocationAreaCode()), ani);
tr = (TableRow) getView().findViewById(R.id.cdma_sysid);
tr.setVisibility(View.VISIBLE);
content = (HighlightTextView) getView().findViewById(R.id.network_sysid);
content.updateText(String.valueOf(mAimsicdService.getCell().getSid()), ani);
tr = (TableRow) getView().findViewById(R.id.cdma_baseid);
tr.setVisibility(View.VISIBLE);
content = (HighlightTextView) getView().findViewById(R.id.network_baseid);
content.updateText(String.valueOf(mAimsicdService.getCell().getCellId()), ani);
break;
}
}
if (mAimsicdService.getCell().getTimingAdvance() != Integer.MAX_VALUE) {
tr = (TableRow) getView().findViewById(R.id.lte_timing_advance);
tr.setVisibility(View.VISIBLE);
content = (HighlightTextView) getView().findViewById(R.id.network_lte_timing_advance);
content.updateText(String.valueOf(mAimsicdService.getCell().getTimingAdvance()), ani);
} else {
tr = (TableRow) getView().findViewById(R.id.lte_timing_advance);
tr.setVisibility(View.GONE);
}
if (mAimsicdService.getCell().getPrimaryScramblingCode() != Integer.MAX_VALUE) {
content = (HighlightTextView) getView().findViewById(R.id.network_psc);
content.updateText(String.valueOf(mAimsicdService.getCell().getPrimaryScramblingCode()), ani);
tr = (TableRow) getView().findViewById(R.id.primary_scrambling_code);
tr.setVisibility(View.VISIBLE);
}
String notAvailable = getString(R.string.n_a);
content = (HighlightTextView) getView().findViewById(R.id.sim_country);
content.updateText(mDevice.getSimCountry().orElse(notAvailable), ani);
content = (HighlightTextView) getView().findViewById(R.id.sim_operator_id);
content.updateText(mDevice.getSimOperator().orElse(notAvailable), ani);
content = (HighlightTextView) getView().findViewById(R.id.sim_operator_name);
content.updateText(mDevice.getSimOperatorName().orElse(notAvailable), ani);
content = (HighlightTextView) getView().findViewById(R.id.sim_imsi);
content.updateText(mDevice.getSimSubs().orElse(notAvailable), ani);
content = (HighlightTextView) getView().findViewById(R.id.sim_serial);
content.updateText(mDevice.getSimSerial().orElse(notAvailable), ani);
content = (HighlightTextView) getView().findViewById(R.id.device_type);
content.updateText(mDevice.getPhoneType(), ani);
content = (HighlightTextView) getView().findViewById(R.id.device_imei);
content.updateText(mDevice.getIMEI(), ani);
content = (HighlightTextView) getView().findViewById(R.id.device_version);
content.updateText(mDevice.getIMEIv(), ani);
content = (HighlightTextView) getView().findViewById(R.id.network_name);
content.updateText(mDevice.getNetworkName(), ani);
content = (HighlightTextView) getView().findViewById(R.id.network_code);
content.updateText(mDevice.getMncMcc(), ani);
content = (HighlightTextView) getView().findViewById(R.id.network_type);
content.updateText(mDevice.getNetworkTypeName(), ani);
content = (HighlightTextView) getView().findViewById(R.id.data_activity);
content.updateText(mDevice.getDataActivityType(), ani);
content = (HighlightTextView) getView().findViewById(R.id.data_status);
content.updateText(mDevice.getDataState(), ani);
content = (HighlightTextView) getView().findViewById(R.id.network_roaming);
content.updateText(String.valueOf(mDevice.isRoaming()), ani);
ani.startAnimation(5000);
}
}
@Override
public void onRefresh() {
if (CellTracker.OCID_API_KEY != null && !CellTracker.OCID_API_KEY.equals("NA")) {
Request request = createOpenCellIdApiCall();
okHttpClient.newCall(request).enqueue(getOpenCellIdResponseCallback());
} else {
Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
public void run() {
Helpers.sendMsg(getActivity(), getString(R.string.no_opencellid_key_detected));
swipeRefreshLayout.setRefreshing(false);
}
});
}
}
@NonNull
private Callback getOpenCellIdResponseCallback() {
return new Callback() {
@Override
public void onFailure(Request request, IOException e) {
Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
public void run() {
refreshFailed();
}
});
}
@Override
public void onResponse(final Response response) throws IOException {
Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
public void run() {
Cell cell = responseToCell(response);
processFinish(cell);
}
});
}
};
}
//TODO: Use Retrofit for this
private Request createOpenCellIdApiCall() {
StringBuilder sb = new StringBuilder();
sb.append("http://www.opencellid.org/cell/get?key=").append(CellTracker.OCID_API_KEY);
if (mAimsicdService.getCell().getMobileCountryCode() != Integer.MAX_VALUE) {
sb.append("&mcc=").append(mAimsicdService.getCell().getMobileCountryCode());
}
if (mAimsicdService.getCell().getMobileNetworkCode() != Integer.MAX_VALUE) {
sb.append("&mnc=").append(mAimsicdService.getCell().getMobileNetworkCode());
}
if (mAimsicdService.getCell().getLocationAreaCode() != Integer.MAX_VALUE) {
sb.append("&lac=").append(mAimsicdService.getCell().getLocationAreaCode());
}
if (mAimsicdService.getCell().getCellId() != Integer.MAX_VALUE) {
sb.append("&cellid=").append(mAimsicdService.getCell().getCellId());
}
sb.append("&format=json");
return new Request.Builder()
.url(sb.toString())
.get()
.build();
}
private Cell responseToCell(Response response) {
try {
JSONObject jsonCell = new JSONObject(response.body().string());
Cell cell = new Cell();
cell.setLat(jsonCell.getDouble("lat"));
cell.setLon(jsonCell.getDouble("lon"));
cell.setMobileCountryCode(jsonCell.getInt("mcc"));
cell.setMobileNetworkCode(jsonCell.getInt("mnc"));
cell.setCellId(jsonCell.getInt("cellid"));
cell.setLocationAreaCode(jsonCell.getInt("lac"));
return cell;
} catch (JSONException | IOException e) {
e.printStackTrace();
}
return null;
}
private void processFinish(Cell cell) {
if (cell != null) {
log.info("processFinish - Cell =" + cell.toString());
if (cell.isValid()) {
mAimsicdService.setCell(cell);
Helpers.msgShort(mContext, getActivity().getString(R.string.refreshed_cell_id_info)); // TODO re-translating other languages
updateUI();
swipeRefreshLayout.setRefreshing(false);
}
}
}
private void refreshFailed() {
Helpers.msgShort(mContext, "Failed to refresh CellId. Check network connection.");
swipeRefreshLayout.setRefreshing(false);
}
}