From d6161fb4b41cb7c50b59b686e46dadf9428c94ed Mon Sep 17 00:00:00 2001 From: xLaMbChOpSx Date: Thu, 3 Apr 2014 18:52:46 +1100 Subject: [PATCH 1/3] Remove RootTools & Further testing for OemRilRequestStrings Removed RootTools and a method that invoked su rights which were left over from testing microcom applet. Further modifications in an attempt to receive a response from the Strings Ril method. --- libs/RootTools.jar | Bin 82333 -> 0 bytes res/values/strings.xml | 2 +- src/com/SecUpwN/AIMSICD/AIMSICD.java | 2 +- src/com/SecUpwN/AIMSICD/ATRilHook.java | 56 +++++++++++++++++++------ src/com/SecUpwN/AIMSICD/Utils.java | 19 --------- 5 files changed, 45 insertions(+), 34 deletions(-) delete mode 100644 libs/RootTools.jar diff --git a/libs/RootTools.jar b/libs/RootTools.jar deleted file mode 100644 index d04a24c5b651551b42aaee9f9f05caa3244d979c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82333 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 RIL OEM Hook Test Choose a RIL OEM Hook API to test: - API 1 (datalen=0) + CRSM - RilStrings API 2 (datalen=1) API 3 (datalen=6) API 4 Type command : diff --git a/src/com/SecUpwN/AIMSICD/AIMSICD.java b/src/com/SecUpwN/AIMSICD/AIMSICD.java index a8ab8c1ae..1643d32a8 100755 --- a/src/com/SecUpwN/AIMSICD/AIMSICD.java +++ b/src/com/SecUpwN/AIMSICD/AIMSICD.java @@ -35,7 +35,7 @@ public void onCreate(Bundle savedInstanceState) { Device.InitDevice(mContext); // Check required utilities are available - Utils.CheckUtils(mContext); + //Utils.CheckUtils(); outputView = (TextView) findViewById(R.id.view); outputView.setHorizontalFadingEdgeEnabled(false); diff --git a/src/com/SecUpwN/AIMSICD/ATRilHook.java b/src/com/SecUpwN/AIMSICD/ATRilHook.java index 3839a42a0..e04ae9202 100644 --- a/src/com/SecUpwN/AIMSICD/ATRilHook.java +++ b/src/com/SecUpwN/AIMSICD/ATRilHook.java @@ -23,6 +23,7 @@ import com.android.internal.telephony.PhoneFactory; import java.lang.reflect.Method; +import java.util.Arrays; public class ATRilHook extends Activity { @@ -30,6 +31,7 @@ public class ATRilHook extends Activity { private RadioButton mRadioButtonAPI1 = null; private RadioGroup mRadioGroupAPI = null; private EditText mRespText = null; + private EditText mInput = null; private ListView mListView; private String[] mDisplay; private Phone mPhone = null; @@ -39,6 +41,8 @@ public class ATRilHook extends Activity { private int mCurrentSvcMode = OemCommands.OEM_SM_TYPE_TEST_MANUAL; private int mCurrentModeType = OemCommands.OEM_SM_TYPE_SUB_ENTER; + private static final int EVENT_OEM_RIL_MESSAGE = 13; + private static final int EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE = 1300; private static final int EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE = 1400; private static final int EVENT_UNSOL_RIL_OEM_HOOK_RAW = 500; @@ -65,13 +69,14 @@ public void onCreate(Bundle icicle) { mPhone = PhoneFactory.getDefaultPhone(); mOemCommands = OemCommands.getInstance(sContext); + mInput = (EditText) findViewById(R.id.edit_cmdstr); mRespText = (EditText) findViewById(R.id.edit_cmdstr); mRespText.setOnKeyListener(new OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { // If the event is a key down event on the "enter" button if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { // Perform action on key press - Toast.makeText(sContext, mRespText.getText(), Toast.LENGTH_SHORT).show(); + Helpers.msgShort(sContext, mRespText.getText().toString()); return true; } return false; @@ -109,10 +114,9 @@ public void execRIL(View view) { Message msg; switch (idButtonChecked) { case R.id.radio_api1: - oemhook = new byte[1]; - oemhook[0] = (byte) 0xAA; - sendRequest(oemhook, EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE); - mRespText.setText(""); + mPhone.invokeOemRilRequestStrings(new String[] { "AT+CRSM=176,28589,0,0,3\0" }, + mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE)); + mRespText.setText("---Wait response---"); break; case R.id.radio_api2: oemhook = new byte[2]; @@ -135,11 +139,8 @@ public void execRIL(View view) { mRespText.setText(""); break; case R.id.radio_api4: - String[] oemhookstring = {"UNIAT", - ((EditText) findViewById(R.id.edit_cmdstr)).getText().toString() + "\r" }; - msg = mHandler.obtainMessage(EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE); - mPhone.invokeOemRilRequestStrings(oemhookstring, msg); - mRespText = (EditText) findViewById(R.id.edit_response); + mPhone.invokeOemRilRequestStrings(new String[] { mInput.getText().toString() + '\0' }, + mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE)); mRespText.setText("---Wait response---"); break; case R.id.radio_api5: @@ -214,6 +215,7 @@ private void logRilOemHookResponseString(AsyncResult ar) { String[] aos = (String[]) ar.result; mListView.setAdapter(new ArrayAdapter(ATRilHook.this, R.layout.list_item, aos)); + mRespText.setText(aos[0]); } private void log(String msg) { @@ -348,10 +350,38 @@ public void handleMessage(Message msg) { //result = (AsyncResult) msg.obj; //logRilOemHookResponse(result); break; - case EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE: - log("EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE"); + case EVENT_OEM_RIL_MESSAGE: + log("EVENT_OEM_RIL_MESSAGE"); result = (AsyncResult) msg.obj; - logRilOemHookResponseString(result); + //logRilOemHookResponseString(result); + + if (result.exception != null) { + Log.e(LOG_TAG, "", result.exception); + return; + } + if (result.result == null) { + Log.v(LOG_TAG, "No need to refresh."); + return; + } + String[] aos = (String[]) result.result; + + if (aos.length == 0) { + Log.v(LOG_TAG, "Length = 0"); + return; + } + + if (mDisplay == null || mDisplay.length != aos.length) { + Log.v(LOG_TAG, "New array = " + aos.length); + mDisplay = new String[aos.length]; + } + + for (int i = 0; i < aos.length; i++) { + StringBuilder strb = new StringBuilder(); + strb.append(aos[i]); + mDisplay[i] = strb.toString(); + } + mListView.setAdapter(new ArrayAdapter(ATRilHook.this, R.layout.list_item, mDisplay)); + break; } } diff --git a/src/com/SecUpwN/AIMSICD/Utils.java b/src/com/SecUpwN/AIMSICD/Utils.java index d8d83f34a..5a455b424 100644 --- a/src/com/SecUpwN/AIMSICD/Utils.java +++ b/src/com/SecUpwN/AIMSICD/Utils.java @@ -3,7 +3,6 @@ import android.content.Context; import android.util.Log; import com.SecUpwN.AIMSICD.cmdprocessor.CMDProcessor; -import com.stericson.RootTools.RootTools; import java.io.*; import java.util.ArrayList; @@ -13,24 +12,6 @@ public class Utils { private static String TAG = "AIMSICD_Utils"; - public static void CheckUtils(Context ctx) { - final String mChmod; - final Context mInstance = ctx; - - // Check chmod utils - if (RootTools.checkUtil("chmod")) - mChmod = "chmod"; - else { - if (RootTools.checkUtil("busybox") && RootTools.hasUtil("chmod", "busybox")) - mChmod = "busybox chmod"; - else if (RootTools.checkUtil("toolbox") && RootTools.hasUtil("chmod", "toolbox")) - mChmod = "toolbox chmod"; - else - mChmod = ""; - } - - } - // Copy assets to local private static boolean CopyAssetsToLocal(Context ctx, String mSourceName, String mDstName) { String mBasePath = GetBasePath(ctx); From ecb5f309a96c955fd3ae9a18d8d2ebac4662f9f9 Mon Sep 17 00:00:00 2001 From: xLaMbChOpSx Date: Sun, 6 Apr 2014 17:48:50 +1000 Subject: [PATCH 2/3] Actionbar & Device Class rewrite Actionbar menu has been applied removing the old menu style and adding a more up to date solution that can be easily extended and modified, resources added from the Android provided Actionbar icon sets for graphical representation of the tracking of cell, signal and location. Device class was rewritten as a non-static class which resulted in a number of changes being made to other classes to take this into account, this should have really been the way I initially wrote this class but oh well it is better now :) Screenshot of the Action bar changes can be found here: http://i57.tinypic.com/i2lw60.png --- AndroidManifest.xml | 2 + ...id-support-v7-appcompat.jar.REMOVED.git-id | 1 + res/drawable-hdpi/ic_action_computer.png | Bin 0 -> 288 bytes res/drawable-hdpi/ic_action_import_export.png | Bin 0 -> 457 bytes .../ic_action_location_found.png | Bin 0 -> 638 bytes res/drawable-hdpi/ic_action_location_off.png | Bin 0 -> 639 bytes res/drawable-hdpi/ic_action_map.png | Bin 0 -> 802 bytes res/drawable-hdpi/ic_action_network_cell.png | Bin 0 -> 278 bytes .../ic_action_network_cell_not_tracked.png | Bin 0 -> 789 bytes res/drawable-hdpi/ic_action_remove.png | Bin 0 -> 353 bytes res/drawable-hdpi/track_cell.png | Bin 0 -> 4731 bytes res/drawable-hdpi/untrack_cell.png | Bin 0 -> 4934 bytes res/menu/main_menu.xml | 32 ++++ res/values/strings.xml | 12 ++ src/com/SecUpwN/AIMSICD/AIMSICD.java | 150 ++++++++++-------- src/com/SecUpwN/AIMSICD/ATRilHook.java | 25 +-- src/com/SecUpwN/AIMSICD/Device.java | 133 ++++++++-------- src/com/SecUpwN/AIMSICD/MapViewer.java | 9 +- 18 files changed, 211 insertions(+), 153 deletions(-) create mode 100644 libs/android-support-v7-appcompat.jar.REMOVED.git-id create mode 100644 res/drawable-hdpi/ic_action_computer.png create mode 100644 res/drawable-hdpi/ic_action_import_export.png create mode 100644 res/drawable-hdpi/ic_action_location_found.png create mode 100644 res/drawable-hdpi/ic_action_location_off.png create mode 100644 res/drawable-hdpi/ic_action_map.png create mode 100644 res/drawable-hdpi/ic_action_network_cell.png create mode 100644 res/drawable-hdpi/ic_action_network_cell_not_tracked.png create mode 100644 res/drawable-hdpi/ic_action_remove.png create mode 100644 res/drawable-hdpi/track_cell.png create mode 100644 res/drawable-hdpi/untrack_cell.png create mode 100644 res/menu/main_menu.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a9e08558d..8f63d63da 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -40,11 +40,13 @@ diff --git a/libs/android-support-v7-appcompat.jar.REMOVED.git-id b/libs/android-support-v7-appcompat.jar.REMOVED.git-id new file mode 100644 index 000000000..398da5100 --- /dev/null +++ b/libs/android-support-v7-appcompat.jar.REMOVED.git-id @@ -0,0 +1 @@ +045c79330c542825344ce10ab654ba0b0fcc2a0a \ No newline at end of file diff --git a/res/drawable-hdpi/ic_action_computer.png b/res/drawable-hdpi/ic_action_computer.png new file mode 100644 index 0000000000000000000000000000000000000000..e63bd835d3da990c7ef900c1eb8edfdc4cca0e1c GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1Ghdf;zLn>~)nSPMB*?`B@@X;;C6AU^R_%39gk}_ZuE}6N> zLHq>+&xC&-JPsTJ6YfpciJx@C-cMz>22e8tLs6n(_ulWlcf8APYtHw)Hv8t55@%7# z2bQF86=c-N59)h!Ndy=?O)Zk+clHZNlH_C3GU-58hz8W>m<7#J-*U$(M+ zHMqXAVNz+)yM{S;WU^;By0w=UEsS2nzwb``4Bjgr%T_YkMY_9fc7G+$aXE0Z=70TQ gdywsOrtfE9X5ibSbk15Nkr5=~>FVdQ&MBb@0Q1Ufn*aa+ literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_action_import_export.png b/res/drawable-hdpi/ic_action_import_export.png new file mode 100644 index 0000000000000000000000000000000000000000..18c0fe7d63774763dd23a014a5bafb6aa2798b95 GIT binary patch literal 457 zcmV;)0XF`LP)L<49_M` zTZp}W_|W8mn8Qvt=e_{@KKas&+H7345D^@v+y~N{mFNnxOJDYZzrlL}16zkY+MO%ablgb15WwU^v5*K50U|&IhyW2_ zXeTZj*10J_$C*avfUi)x2dv4`wYhRGVaMXHUx4qt>keJBw&aaj2t=+#s703x`W&6G zP=m{U6?a73HCtg?z!=5;%Y2BtSjWmL#5vKeZr@v7MnUj`qR!uxH_Cn<-`08!J00FK z6GpOhrUeB2`zbe-C$%9Wvi0XiAP{(hrvL*0bYz4`Hhrth00000NkvXXu0mjf#6iL8 literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_action_location_found.png b/res/drawable-hdpi/ic_action_location_found.png new file mode 100644 index 0000000000000000000000000000000000000000..4748e9016541f3bea4390d244691291d8237f851 GIT binary patch literal 638 zcmV-^0)hRBP)s?JgKqcTp>z z(vLYXJ{^PSbC55T3}e4{p5PokKfkx}DN&w|y^c8MZ7MaK*f`ArWSb96Mn#ExW{jfG z1jIB(C2Ik5DrQcGw5t;PRl-ivLKYJyIWUI2!6##k5Aa`xV@w=K`w_dW#9P7~XU6!X z#~O+01g=#YI_x@tETfB5-Vru^k>DH(z2;KFXp$4q3NH-LCpYA8Vw^&aIS@#?SV=FW zcfan4Zz;GrweF+f6ljQEx{70TC1kRD^z&E9f+n+KuKmNc(?_HEdXZAx0GuFXPJT5jtsq$}tGyGn}UhFvb0PIY1EvgZI6n}#bk*d9on;93g3 zW+S<^Nt0L?o7gNip!C?&i2}!R;rXjb&c2zOd^;_!19*omNhl4v(2&q6hu)9Jyi(r$ z{5bhb{bN6?%;I6IU;qFB07*qoM6N<$g3uWk2LJ#7 literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_action_location_off.png b/res/drawable-hdpi/ic_action_location_off.png new file mode 100644 index 0000000000000000000000000000000000000000..7eb4136759c29bcff2f896d0f9d08de1e628f5de GIT binary patch literal 639 zcmV-_0)YLAP)dSHCn@hFm~%Fs2&Z006&*$15&c5(TW(nnpsK6BzM6m;nGjMbDGu%DVunG*K%? z=|>-EpANzE7tjyX40FHnI>A2F|MJ)1Q#N@z^f;|^-sYs55nI>bm!LOF8;j#oI^B@b zoNZ(=W0I2qB*BGRS05$9uM;ajVwVxPnooPvmyx z#f%$)?-~B9u&pjM=Bf>&wMii=4JwJ}@!L^1LI8iP>0fDcS*?Z0`=xPL1P}oD$N*<7 zw~gSLlvGE-IJ{=6O#K#h%+RHt7mNrRg4fA{FXjTHJFjy3O)I{VCKM;+e8AR3(5G z;#ufVW8Q6_+PIf?tngY3|6jV45?Ef-xVu>ubE7Y(TkivShRtci>3g7I)SUM{9}jt? z?3|9HKh)3rT4fR!TQygU%8&y~t-{6CqU(iDi`3aQyT4xl&*uRfQZUBx;>C-X3Cgzs Z0|3uI9;JeGDXjni002ovPDHLkV1i`07lr@; literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_action_map.png b/res/drawable-hdpi/ic_action_map.png new file mode 100644 index 0000000000000000000000000000000000000000..370cf5c38f3efec6d186a1e65ee9b23efbf0c1cb GIT binary patch literal 802 zcmV+-1Ks?IP)|3eB;0~7!SPyjh)Rx^smmSjcNVBlsnV2tHk-QM2Geu_G7 zPY(bO0Cx^xAii8KmkE80JK}fQ>-Bbj0FVu7q#Xgk#FzffP^bbSyE0$XDu&boAdaoC z$$QGtSrY(lIg!AL7(eZ4p$<4VqK`8jpM6lsx8q#lW)KQtXPlb?6hF78<5HZH?BE0d zE4IJ{>n5v1*M9J8Xz-PN74j!Zbqr9lWf-c>>+WMxA;G(x#wR(ISvsG>k(fa50pt); zg~aM-iZU$#qA)~bBo+Yk2+k+I0q7zSt2`v9Cjeq9c>F(wlCVMRK%^ww79$cR+z`19 z4o{%ZQQ|uToiZP-%fR4xX+am&gwqKe9b&E}pN9a(aD3cq1fb7vO(%qtqbfzA-=knT zz^OnZcdVFW%Sg#OzeL1OzLJHV2&C5|D5W87p*lN~KqwuyAEQSju2Dxq56h>Ej}eyQ{zP-{b{`mPkL z+yH2XYyL!^K3>{t=4PnIZ=#b_Zq8eWy%a?r{*}%4(03&^@pl8oG07^^^g+x-k+uNH z(XiP^GY#FMHUZ2ldUG{l53T^XAn*l1`{5q|!avt3h-I6>G=(g$*#r2YP*tKz$!Ap~ z08*W2C)Ews8h{#(mk!CdQ(6ZBzR(paA2OPFa9$KAu^8`ydYTA(10Y9$SK`9uMsRrP z&>W_^2-(PJEQPv=0va00m5)ly9GbfSI3D9kM&^S;OxmP}a6Gr@pX>qf#tl2H5VmN# z)$Cg);4u(@VH+wG(u$^!Vd?;+Hl1d`q)zLeMGZ9C--)+1H}!_*6kXq28JkBk-L}Vz g?gxN-2k;}n0Dm9>SJ?%Fr~m)}07*qoM6N<$f=nP{CIA2c literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_action_network_cell.png b/res/drawable-hdpi/ic_action_network_cell.png new file mode 100644 index 0000000000000000000000000000000000000000..194247d905bd6acc9f23c562b22cdc976bf02128 GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GJ3L(+Ln>~)nR$`d!9c`SbU#}HZ}x_^T%82I>=H(11Gl~Z z%rxbDpFOBF01~OpFSV zuo$~K=>iGFg~aFr!K8~im1rp%C}3PPls~WcxIjV(Wq_1C!u_V3d(Low@7?b^7dYdh zy~Vuf&^`ur6QpUuH;p%dKCbw;7Sq*mPT-1s>^u7wR3nsX+IBa z+<6hPzUHQj3oB77GH;P20C2Hj)`+x7AfsO~yS#7jFWAz=0Pr{Qv}$KD|JnMsbQx0a zxyUK%eNwb3eHUJ*+V^ z695nq7pO?e3kYB*m%HJo=eg*vrJFh`~V zZ)>#I>`UZrYvSDPC+)JZwHTfnUf#c-?S32-9#@0;?$K;H4|AL=WUFVvu|05>rJvH5 zJt`ijiD=o@00062lBMz;!19Sw=qyVCD1h@0aH13{XFQ%(jFv4Pl?N1n0yxhx%FNwI z#N#LtW$Zo&0svwqYCd&^6o3Ly017|>*nNEqiY TshCS900000NkvXXu0mjfBim98 literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/ic_action_remove.png b/res/drawable-hdpi/ic_action_remove.png new file mode 100644 index 0000000000000000000000000000000000000000..e206f296c2535b11a2243ae93a31b2957f42ab7d GIT binary patch literal 353 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 literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/untrack_cell.png b/res/drawable-hdpi/untrack_cell.png new file mode 100644 index 0000000000000000000000000000000000000000..c23a9d6138683831e30d73a3a53c63f25d1ebb4d GIT binary patch literal 4934 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 + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 2b7b459b9..a88970508 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -30,6 +30,18 @@ # EVO-0 # EVO-A + + Track Cell Details + Untrack Cell Details + Track Location + Untrack Location + Track Signal + Untrack Signal + Show Map + Export Database tables + AT Command Injection + + RIL OEM Hook Test Choose a RIL OEM Hook API to test: diff --git a/src/com/SecUpwN/AIMSICD/AIMSICD.java b/src/com/SecUpwN/AIMSICD/AIMSICD.java index 1643d32a8..dc96e36db 100755 --- a/src/com/SecUpwN/AIMSICD/AIMSICD.java +++ b/src/com/SecUpwN/AIMSICD/AIMSICD.java @@ -8,20 +8,25 @@ import android.util.Log; import android.view.KeyEvent; import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.webkit.WebView; import android.widget.TextView; +import android.os.Build; public class AIMSICD extends Activity { private final String TAG = "AIMSICD"; + private Device mDevice; + private TextView outputView; private WebView webview; private boolean isAbout; private final Context mContext = this; + private Menu mMenu; /** * Called when the activity is first created. @@ -31,110 +36,121 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); - //Initialise device details - Device.InitDevice(mContext); - - // Check required utilities are available - //Utils.CheckUtils(); + mDevice = new Device(mContext); outputView = (TextView) findViewById(R.id.view); outputView.setHorizontalFadingEdgeEnabled(false); outputView.setText("Information:\n\n"); - if (Device.getPhoneID() == TelephonyManager.PHONE_TYPE_GSM) { - outputView.append("SIM country: " + Device.getSimCountry(false) + "\n"); - outputView.append("SIM Op ID: " + Device.getSimOperator(false) + "\n"); - outputView.append("SIM Op Name: " + Device.getSimOperatorName(false) + "\n"); - outputView.append("SIM IMSI: " + Device.getSimSubs(false) + "\n"); - outputView.append("SIM serial: " + Device.getSimSerial(false) + "\n\n"); + if (mDevice.getPhoneID() == TelephonyManager.PHONE_TYPE_GSM) { + outputView.append("SIM country: " + mDevice.getSimCountry(false) + "\n"); + outputView.append("SIM Op ID: " + mDevice.getSimOperator(false) + "\n"); + outputView.append("SIM Op Name: " + mDevice.getSimOperatorName(false) + "\n"); + outputView.append("SIM IMSI: " + mDevice.getSimSubs(false) + "\n"); + outputView.append("SIM serial: " + mDevice.getSimSerial(false) + "\n\n"); } - int netID = Device.getNetID(true); - outputView.append("Device type: " + Device.getPhoneType(false) + "\n"); - outputView.append("Device IMEI: " + Device.getIMEI(false) + "\n"); - outputView.append("Device version: " + Device.getIMEIv(false) + "\n"); - outputView.append("Device num: " + Device.getPhoneNumber(false) + "\n\n"); - outputView.append("Network name: " + Device.getNetworkName(false) + "\n"); - outputView.append("Network code: " + Device.getSmmcMcc(false) + "\n"); - outputView.append("Network type: " + Device.getNetworkTypeName() + "\n"); - outputView.append("Network LAC: " + Device.getsLAC(false) + "\n"); - outputView.append("Network CellID: " + Device.getsCellId(false) + "\n\n"); + int netID = mDevice.getNetID(true); + outputView.append("Device type: " + mDevice.getPhoneType(false) + "\n"); + outputView.append("Device IMEI: " + mDevice.getIMEI(false) + "\n"); + outputView.append("Device version: " + mDevice.getIMEIv(false) + "\n"); + outputView.append("Device num: " + mDevice.getPhoneNumber(false) + "\n\n"); + outputView.append("Network name: " + mDevice.getNetworkName(false) + "\n"); + outputView.append("Network code: " + mDevice.getSmmcMcc(false) + "\n"); + outputView.append("Network type: " + mDevice.getNetworkTypeName() + "\n"); + outputView.append("Network LAC: " + mDevice.getsLAC(false) + "\n"); + outputView.append("Network CellID: " + mDevice.getsCellId(false) + "\n\n"); - outputView.append("Data activity: " + Device.getActivityDesc(netID) + "\n"); - outputView.append("Data status: " + Device.getStateDesc(netID) + "\n"); + outputView.append("Data activity: " + mDevice.getActivityDesc(netID) + "\n"); + outputView.append("Data status: " + mDevice.getStateDesc(netID) + "\n"); outputView.append("--------------------------------\n"); outputView.append("[LAC,CID]|DAct|DStat|Net|Sig|Lat|Lng\n"); Log.i(TAG, "**** AIMSICD ****"); - Log.i(TAG, "Device type : " + Device.getPhoneType(false)); - Log.i(TAG, "Device imei : " + Device.getIMEI(false)); - Log.i(TAG, "Device version: " + Device.getIMEIv(false)); - Log.i(TAG, "Device num : " + Device.getPhoneNumber(false)); - Log.i(TAG, "Network type : " + Device.getNetworkTypeName()); - Log.i(TAG, "Network CellID: " + Device.getsCellId(false)); - Log.i(TAG, "Network LAC : " + Device.getsLAC(false)); - Log.i(TAG, "Network code : " + Device.getSmmcMcc(false)); - Log.i(TAG, "Network name : " + Device.getNetworkName(false)); + Log.i(TAG, "Device type : " + mDevice.getPhoneType(false)); + Log.i(TAG, "Device imei : " + mDevice.getIMEI(false)); + Log.i(TAG, "Device version: " + mDevice.getIMEIv(false)); + Log.i(TAG, "Device num : " + mDevice.getPhoneNumber(false)); + Log.i(TAG, "Network type : " + mDevice.getNetworkTypeName()); + Log.i(TAG, "Network CellID: " + mDevice.getsCellId(false)); + Log.i(TAG, "Network LAC : " + mDevice.getsLAC(false)); + Log.i(TAG, "Network code : " + mDevice.getSmmcMcc(false)); + Log.i(TAG, "Network name : " + mDevice.getNetworkName(false)); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu items for use in the action bar + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_menu, menu); + mMenu = menu; + return super.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(Menu menu) { - menu.clear(); - if (Device.isTrackingCell()) { - menu.add(1, 0, 0, "Untrack Cell"); + MenuItem mTrackCell = menu.findItem(R.id.track_cell); + MenuItem mTrackSignal = menu.findItem(R.id.track_signal); + MenuItem mTrackLocation = menu.findItem(R.id.track_location); + + if (mDevice.isTrackingCell()) { + mTrackCell.setTitle(getResources().getString(R.string.track_cell)); + mTrackCell.setIcon(getResources().getDrawable(R.drawable.track_cell)); } else { - menu.add(1, 0, 0, "Track Cell"); + mTrackCell.setTitle(getResources().getString(R.string.untrack_cell)); + mTrackCell.setIcon(getResources().getDrawable(R.drawable.untrack_cell)); } - if (Device.isTrackingSignal()) { - menu.add(1, 1, 0, "Untrack Signal"); + if (mDevice.isTrackingSignal()) { + mTrackSignal.setTitle(getResources().getString(R.string.track_signal)); + mTrackSignal.setIcon(getResources().getDrawable(R.drawable.ic_action_network_cell)); } else { - menu.add(1, 1, 0, "Track Signal"); + mTrackSignal.setTitle(getResources().getString(R.string.untrack_signal)); + mTrackSignal.setIcon(getResources().getDrawable(R.drawable.ic_action_network_cell_not_tracked)); } - if (Device.isTrackingLocation()) { - menu.add(1, 2, 0, "Untrack Location"); + if (mDevice.isTrackingLocation()) { + mTrackLocation.setTitle(getResources().getString(R.string.track_location)); + mTrackLocation.setIcon(getResources().getDrawable(R.drawable.ic_action_location_found)); } else { - menu.add(1, 2, 0, "Track Location"); + mTrackLocation.setTitle(getResources().getString(R.string.untrack_location)); + mTrackLocation.setIcon(getResources().getDrawable(R.drawable.ic_action_location_off)); } - menu.add(0, 4, 4, "Show Map"); - - menu.add(0, 6, 6, "Quit"); - menu.add(0, 7, 7, "Export Database Tables"); - menu.add(0, 8, 8, "AT OEM RIL Hook Test"); - menu.setGroupCheckable(1, true, false); - return super.onCreateOptionsMenu(menu); + return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle item selection switch (item.getItemId()) { - case 0: - Device.trackcell(); + case R.id.track_cell: + mDevice.trackcell(); + if (Build.VERSION.SDK_INT > 11) + onPrepareOptionsMenu(mMenu); return true; - case 1: - Device.tracksignal(); + case R.id.track_signal: + mDevice.tracksignal(); + if (Build.VERSION.SDK_INT > 11) + onPrepareOptionsMenu(mMenu); return true; - case 2: - Device.tracklocation(mContext); + case R.id.track_location: + mDevice.tracklocation(mContext); + if (Build.VERSION.SDK_INT > 11) + onPrepareOptionsMenu(mMenu); return true; - case 4: + case R.id.show_map: showmap(); return true; - case 5: - about(); - return true; - case 6: - finish(); - return true; - case 7: - Device.exportDB(); + case R.id.export_database: + mDevice.exportDB(); return true; - case 8: + case R.id.at_injector: Intent intent = new Intent(this, ATRilHook.class); startActivity(intent); return true; + case R.id.app_exit: + finish(); + return true; default: return super.onOptionsItemSelected(item); } @@ -171,4 +187,8 @@ protected final void showmap() { startActivity(myIntent); } + public Device getDevice() { + return mDevice; + } + } diff --git a/src/com/SecUpwN/AIMSICD/ATRilHook.java b/src/com/SecUpwN/AIMSICD/ATRilHook.java index e04ae9202..24f81cb5c 100644 --- a/src/com/SecUpwN/AIMSICD/ATRilHook.java +++ b/src/com/SecUpwN/AIMSICD/ATRilHook.java @@ -42,6 +42,7 @@ public class ATRilHook extends Activity { private int mCurrentModeType = OemCommands.OEM_SM_TYPE_SUB_ENTER; private static final int EVENT_OEM_RIL_MESSAGE = 13; + private static final int RIL_REQUEST_OEM_HOOK_STRINGS = 60; private static final int EVENT_RIL_OEM_HOOK_CMDRAW_COMPLETE = 1300; private static final int EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE = 1400; @@ -114,8 +115,8 @@ public void execRIL(View view) { Message msg; switch (idButtonChecked) { case R.id.radio_api1: - mPhone.invokeOemRilRequestStrings(new String[] { "AT+CRSM=176,28589,0,0,3\0" }, - mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE)); + mPhone.invokeOemRilRequestStrings(new String[] { "AT+CRSM=176,28589,0,0,3\r\0" }, + mHandler.obtainMessage(EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE)); mRespText.setText("---Wait response---"); break; case R.id.radio_api2: @@ -139,8 +140,8 @@ public void execRIL(View view) { mRespText.setText(""); break; case R.id.radio_api4: - mPhone.invokeOemRilRequestStrings(new String[] { mInput.getText().toString() + '\0' }, - mHandler.obtainMessage(EVENT_OEM_RIL_MESSAGE)); + mPhone.invokeOemRilRequestStrings(new String[] { mInput.getText().toString() + '\r' + '\0' }, + mHandler.obtainMessage(EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE)); mRespText.setText("---Wait response---"); break; case R.id.radio_api5: @@ -350,8 +351,8 @@ public void handleMessage(Message msg) { //result = (AsyncResult) msg.obj; //logRilOemHookResponse(result); break; - case EVENT_OEM_RIL_MESSAGE: - log("EVENT_OEM_RIL_MESSAGE"); + case EVENT_RIL_OEM_HOOK_CMDSTR_COMPLETE: + log("RIL_REQUEST_OEM_HOOK_STRINGS"); result = (AsyncResult) msg.obj; //logRilOemHookResponseString(result); @@ -370,17 +371,7 @@ public void handleMessage(Message msg) { return; } - if (mDisplay == null || mDisplay.length != aos.length) { - Log.v(LOG_TAG, "New array = " + aos.length); - mDisplay = new String[aos.length]; - } - - for (int i = 0; i < aos.length; i++) { - StringBuilder strb = new StringBuilder(); - strb.append(aos[i]); - mDisplay[i] = strb.toString(); - } - mListView.setAdapter(new ArrayAdapter(ATRilHook.this, R.layout.list_item, mDisplay)); + mListView.setAdapter(new ArrayAdapter(ATRilHook.this, R.layout.list_item, aos)); break; } diff --git a/src/com/SecUpwN/AIMSICD/Device.java b/src/com/SecUpwN/AIMSICD/Device.java index 4dab2f06c..4db5de388 100644 --- a/src/com/SecUpwN/AIMSICD/Device.java +++ b/src/com/SecUpwN/AIMSICD/Device.java @@ -1,5 +1,6 @@ package com.SecUpwN.AIMSICD; +import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.database.Cursor; @@ -27,46 +28,44 @@ public class Device { - private static String TAG = "AIMSICD_Device"; - - public static String LOCATION_TABLE = "locationinfo"; - public static String CELL_TABLE = "cellinfo"; - public static String SIGNAL_TABLE = "signalinfo"; - public static String DB_NAME = "myCellInfo"; - - private static PhoneStateListener sSignalListenerStrength; - private static PhoneStateListener sSignalListenerLocation; - private static LocationManager lm; - private static LocationListener sLocationListener; - public static SQLiteDatabase sDB; - private static SQLiteHelper dbHelper; - - private static int sPhoneID; - private static int sSignalInfo; - private static int sNetID; - private static int sLacID; - private static int sCellID; - private static double sLongitude; - private static double sLatitude; - private static String sNetType = "", sCellInfo = "", sDataState = ""; - private static String sKML = "", sPhoneNum = "", sCellType = "", sLac = ""; - private static String sNetName = "", sMmcmcc = "", sSimCountry = "", sPhoneType = ""; - private static String sIMEI = "", sIMEIV = "", sSimOperator = "", sSimOperatorName = ""; - private static String sSimSerial = "", sSimSubs = "", sDataActivityType = ""; - - private static boolean TrackingCell; - private static boolean TrackingSignal; - private static boolean TrackingLocation; - - private static ArrayList alPosition; - - private static TelephonyManager tm; - - - - public static void InitDevice(Context mContext) { + private String TAG = "AIMSICD_Device"; + + public String LOCATION_TABLE = "locationinfo"; + public String CELL_TABLE = "cellinfo"; + public String SIGNAL_TABLE = "signalinfo"; + public String DB_NAME = "myCellInfo"; + + private PhoneStateListener sSignalListenerStrength; + private PhoneStateListener sSignalListenerLocation; + private LocationManager lm; + private LocationListener sLocationListener; + public SQLiteDatabase sDB; + private SQLiteHelper dbHelper; + + private int sPhoneID; + private int sSignalInfo; + private int sNetID; + private int sLacID; + private int sCellID; + private double sLongitude; + private double sLatitude; + private String sNetType = "", sCellInfo = "", sDataState = ""; + private String sKML = "", sPhoneNum = "", sCellType = "", sLac = ""; + private String sNetName = "", sMmcmcc = "", sSimCountry = "", sPhoneType = ""; + private String sIMEI = "", sIMEIV = "", sSimOperator = "", sSimOperatorName = ""; + private String sSimSerial = "", sSimSubs = "", sDataActivityType = ""; + + private boolean TrackingCell; + private boolean TrackingSignal; + private boolean TrackingLocation; + + private ArrayList alPosition; + + private TelephonyManager tm; + + Device(Context context) { //TelephonyManager provides system details - tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); //Phone type and associated details sIMEI = tm.getDeviceId(); @@ -105,7 +104,7 @@ public static void InitDevice(Context mContext) { sDataState = getStateDesc(sDataActivity); //Create DB Instance - dbHelper = new SQLiteHelper(mContext); + dbHelper = new SQLiteHelper(context); sDB = dbHelper.getWritableDatabase(); sSignalListenerLocation = new PhoneStateListener() { @@ -212,49 +211,49 @@ public void onSignalStrengthsChanged(SignalStrength signalStrength) { } - public static int getPhoneID() { + public int getPhoneID() { if (sPhoneID <= 0 || sPhoneID > 6) sPhoneID = tm.getPhoneType(); return sPhoneID; } - public static String getSimCountry(boolean force) { + public String getSimCountry(boolean force) { if (sSimCountry.isEmpty() || force) sSimCountry = tm.getSimCountryIso(); return sSimCountry; } - public static String getSimOperator(boolean force) { + public String getSimOperator(boolean force) { if (sSimOperator.isEmpty() || force) sSimOperator = tm.getSimOperator(); return sSimOperator; } - public static String getSimOperatorName(boolean force) { + public String getSimOperatorName(boolean force) { if (sSimOperatorName.isEmpty() || force) sSimOperatorName = tm.getSimOperatorName(); return sSimOperatorName; } - public static String getSimSubs(boolean force) { + public String getSimSubs(boolean force) { if (sSimSubs.isEmpty() || force) sSimSubs = tm.getSubscriberId(); return sSimSubs; } - public static String getSimSerial(boolean force) { + public String getSimSerial(boolean force) { if (sSimSerial.isEmpty() || force) sSimSerial = tm.getSimSerialNumber(); return sSimSerial; } - public static String getPhoneType(boolean force) { + public String getPhoneType(boolean force) { if (sPhoneType.isEmpty()|| force) { if (getPhoneID() == TelephonyManager.PHONE_TYPE_GSM) sPhoneType = "GSM"; @@ -267,47 +266,47 @@ else if (getPhoneID() == TelephonyManager.PHONE_TYPE_CDMA) return sPhoneType; } - public static String getIMEI(boolean force) { + public String getIMEI(boolean force) { if (sIMEI.isEmpty() || force) sIMEI = tm.getDeviceId(); return sIMEI; } - public static String getIMEIv(boolean force) { + public String getIMEIv(boolean force) { if (sIMEIV.isEmpty() || force) sIMEIV = tm.getDeviceSoftwareVersion(); return sIMEIV; } - public static String getPhoneNumber(boolean force) { + public String getPhoneNumber(boolean force) { if (sPhoneNum.isEmpty() || force) sPhoneNum = tm.getLine1Number(); return sPhoneNum; } - public static String getNetworkName(boolean force) { + public String getNetworkName(boolean force) { if (sNetName.isEmpty() || force) sNetName = tm.getNetworkOperatorName(); return sNetName; } - public static String getSmmcMcc(boolean force) { + public String getSmmcMcc(boolean force) { if (sMmcmcc.isEmpty() || force) sMmcmcc = tm.getNetworkOperator(); return sMmcmcc; } - public static String getNetworkTypeName() { + public String getNetworkTypeName() { return tm.getNetworkTypeName(); } - public static int getNetID (boolean force) { + public int getNetID (boolean force) { if (sNetID < 0 || force) { sNetID = tm.getNetworkType(); } @@ -315,7 +314,7 @@ public static int getNetID (boolean force) { return sNetID; } - public static String getsLAC(boolean force) { + public String getsLAC(boolean force) { if (sLac.isEmpty() || force) { GsmCellLocation gsmCellLocation = (GsmCellLocation) tm.getCellLocation(); if (gsmCellLocation != null) { @@ -326,7 +325,7 @@ public static String getsLAC(boolean force) { return sLac; } - public static String getsCellId(boolean force) { + public String getsCellId(boolean force) { if (sCellType.isEmpty() || force) { GsmCellLocation gsmCellLocation = (GsmCellLocation) tm.getCellLocation(); if (gsmCellLocation != null) { @@ -337,7 +336,7 @@ public static String getsCellId(boolean force) { return sCellType; } - public static String getActivityDesc(int dataID) { + public String getActivityDesc(int dataID) { sDataActivityType = "undef"; switch (dataID) { case TelephonyManager.DATA_ACTIVITY_NONE: @@ -359,7 +358,7 @@ public static String getActivityDesc(int dataID) { return sDataActivityType; } - public static String getStateDesc(int dataID) { + public String getStateDesc(int dataID) { sDataState = "undef"; switch (dataID) { case TelephonyManager.DATA_DISCONNECTED: @@ -379,19 +378,19 @@ public static String getStateDesc(int dataID) { return sDataState; } - public static Boolean isTrackingSignal() { + public Boolean isTrackingSignal() { return TrackingSignal; } - public static Boolean isTrackingCell() { + public Boolean isTrackingCell() { return TrackingCell; } - public static Boolean isTrackingLocation() { + public Boolean isTrackingLocation() { return TrackingLocation; } - public static void tracksignal() { + public void tracksignal() { if (TrackingSignal) { tm.listen(sSignalListenerStrength, PhoneStateListener.LISTEN_NONE); TrackingSignal = false; @@ -402,7 +401,7 @@ public static void tracksignal() { } } - public static void trackcell() { + public void trackcell() { if (TrackingCell) { tm.listen(sSignalListenerLocation, PhoneStateListener.LISTEN_NONE); TrackingCell = false; @@ -413,7 +412,7 @@ public static void trackcell() { } } - public static void tracklocation(Context ctx) { + public void tracklocation(Context ctx) { if (TrackingLocation) { lm.removeUpdates(sLocationListener); TrackingLocation = false; @@ -448,7 +447,7 @@ public static void tracklocation(Context ctx) { } } - private static class MyLocationListener implements LocationListener { + private class MyLocationListener implements LocationListener { @Override public void onLocationChanged(Location loc) { if (loc != null) { @@ -478,7 +477,7 @@ public void onStatusChanged(String provider, int status, } } - public static void exportDB () { + public void exportDB () { try { dbHelper.export(LOCATION_TABLE); dbHelper.export(CELL_TABLE); @@ -491,7 +490,7 @@ public static void exportDB () { /** * SQLiteHelper class for the Location, Cell and Signal Strength Databases */ - public static class SQLiteHelper extends SQLiteOpenHelper { + public class SQLiteHelper extends SQLiteOpenHelper { public static final String COLUMN_ID = "_id"; private static final int DATABASE_VERSION = 1; diff --git a/src/com/SecUpwN/AIMSICD/MapViewer.java b/src/com/SecUpwN/AIMSICD/MapViewer.java index 72d96c0ab..d807e4790 100755 --- a/src/com/SecUpwN/AIMSICD/MapViewer.java +++ b/src/com/SecUpwN/AIMSICD/MapViewer.java @@ -16,11 +16,12 @@ import java.util.List; - public class MapViewer extends MapActivity { private final String TAG = "AIMSICD_MapViewer"; public MapView mapView; + private AIMSICD mAimsicd = new AIMSICD(); + private Device mDevice = mAimsicd.getDevice(); private MapController mapc; private final int SIGNAL_SIZE_RATIO = 15; @@ -117,8 +118,8 @@ private void loadentries() { GeoPoint p = null; mapc = mapView.getController(); int color = 0x000000; - Cursor c = Device.sDB.rawQuery("SELECT Net, Lat, Lng, Signal FROM " - + Device.LOCATION_TABLE, null); + Cursor c = mDevice.sDB.rawQuery("SELECT Net, Lat, Lng, Signal FROM " + + mDevice.LOCATION_TABLE, null); if (c.getCount()>0) { if (c.moveToFirst()) { List listOfOverlays = mapView.getOverlays(); @@ -193,7 +194,7 @@ private final void quit() { } private final void erasedb() { - Device.sDB.delete(Device.LOCATION_TABLE, null, null); + mDevice.sDB.delete(mDevice.LOCATION_TABLE, null, null); } } From b2c3648ab4186ded855cddbb72e53a2aa10d5e62 Mon Sep 17 00:00:00 2001 From: xLaMbChOpSx Date: Sun, 6 Apr 2014 20:04:07 +1000 Subject: [PATCH 3/3] Persistant Notification & GPLv3 License Headers Added Persistant Notification which at present just displays the Phone Type (GSM/CDMA), but this will eventually provide the immediate and visual notification of the phone status regarding encryption/ciphering status and possibly Femtocell connections. Added dialog to prompt to enable Location Services if Location Tracking is enabled but Location is not, settings fragment will be displayed to enable location services. Cleaned up a little but of the code from my previous commit, coffee helps sharpen the mind a little of this Windows developer and Android/Java moments of enlightenment can occur :) Added GPLv3 license headers to class files. --- AndroidManifest.xml | 8 +- res/drawable-hdpi/ic_action_location_off.png | Bin 639 -> 1170 bytes res/layout/main.xml | 2 +- res/values/strings.xml | 23 +- src/com/SecUpwN/AIMSICD/AIMSICD.java | 179 ++++-- src/com/SecUpwN/AIMSICD/AIMSICDDbAdapter.java | 287 +++++++++ src/com/SecUpwN/AIMSICD/ATRilHook.java | 21 +- src/com/SecUpwN/AIMSICD/Device.java | 593 ++++++------------ src/com/SecUpwN/AIMSICD/MapViewer.java | 31 +- src/com/SecUpwN/AIMSICD/OemCommands.java | 17 + src/com/SecUpwN/AIMSICD/Utils.java | 17 + .../AbstractAsyncSuCMDProcessor.java | 1 - 12 files changed, 711 insertions(+), 468 deletions(-) create mode 100644 src/com/SecUpwN/AIMSICD/AIMSICDDbAdapter.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8f63d63da..582550e3e 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -42,13 +42,19 @@ android:label="@string/app_name" android:parentActivityName=".AIMSICD" android:exported="true"> + + diff --git a/res/drawable-hdpi/ic_action_location_off.png b/res/drawable-hdpi/ic_action_location_off.png index 7eb4136759c29bcff2f896d0f9d08de1e628f5de..90f845d0c46a7e7800ed5b7ed02cf32db71f24ac 100644 GIT binary patch delta 1149 zcmV-@1cLkj1d<7mB!32COGiWi{{a60|De66lK=n!32;bRa{vGf6951U69E94oEQKA z00(qQO+^RZ1O^EmBWBSE0ssI6A4x<(RA}DqSYK#cbrk;2FE_bOFsrm_SlV@2bqhXp z^C6nS5G=xc&`jDFB?Vto_BN?b1Z6D>Ds5rxMN%Jy6n$Bl(SMhLZXg>I^WuEEL%Y}QV9-@vKKi^IPXq~UVc(uMz zG0Z>iB&bg4f}VZB*L?>7x}awX1k*!m{dMma%s z=4Fxu06Gh1ACd1+%+LAO03sS|nF?8fT&AI^pa@Kx z%v_Uo)MOndGY3Ur`Z5hoIfHEgVE{>WwT{GJA*t=dQ=dnmzvE}Z3Q5wRANUghmVaI7 z_cI{^eSiE%yew|vpZDKJv8`%>80_qe_JqQx1VE->h=Z|3>hDfbe|Jh8j4hgiApq(L zg-;E3_C?!`16us#NagRJu8-Aj-ThK@_)Grh`d{BaKUo2Q((swrq`-Ib;YvKTuV?J( zmkw9(*@caAzt@>M%$x;K22doT+btn+>CI1$$$zEgn*-l|ylR7m6Cd@8pnf3!&4*Xk zIdm968o(%k*amx+0ptM`h^X3B71|7#c?iH6McV&V8Gzv!ns6C2Nko^nEdXYoP*2`M z0YILJjCG`S)H#QUCLTF?m^shPzo;vxa=+2Jy=sm%KmVu?KVjQ^V!PMzob%1x)Dgr` zOMf|_)aHUBW6{kbFmn<>27vQ0mjKKWQPE{iPRVW+z#CrFNq7u6ZBvp-mxGK0$hjOI z>RwKbabnVDKhm4=LXBe7rX06j4xedYjf^u0wN}BgM{@&EDq|I?{2FP~C^Bk}9oCvL zFN)^n4OkmiU35OP3I1jrZ^2L;fENd=d4Jf@dius1`Rx^Ma}3KzF|$2It7{cUZJm_K zwc5*XAQtIWy%sRm3=+2;)=Qxohxt0;RpPdQSt6RijA@dUV?D56xNz$FI}5g5?jS4?RG3S zL^RW25OZp*TYCPlNbYzu_t@KM&viicumxKxZKurND5QZv$Ge9x`9Uu#202m+{AQ_+olnl@T$N*U&{7(lc1C#-p0T>`X zOLx-MI#V8YDd3Y%An@b6hd-Yk1YW#&@iIwyJRT8frqty;3x9`WFF`l19rZN!NRQrt zg@fE*W9n?!w*x%xphXylUpD6pErC|~9)s>dSHCn@hFm~%Fs2&Z006&*$15&c5(TW( znnpsK6BzM6m;nGjMbDGu%DVunG*K%?=|>-EpANzE7tjyX40FHnI>A2F|MJ)1Q#N@z z^f;|^-sYs55r13P;Fq8`N*jygQaas`(VT5$F=LXG03^YMT2~(>!mkr6KVp{=xSCQ2 z!IKvw19*yFQjmv*f1S_}VQx|9-FUema{ zSrv1mFJGry?*n*-&1u8wd!S*|ocBE+4|$~QoQ|VE)X)1`WfB)#HCKzukONDt!o}61 z>xE8>)Y&z=zh3{(=K&j1FvjuX#fz5-%C`Um0M9=jrGj)RtpET307*qoM6N<$g6OIj A4*&oF diff --git a/res/layout/main.xml b/res/layout/main.xml index 89aa6d97b..9ede7a131 100755 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -9,7 +9,7 @@ android:id="@+id/view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/hello" + android:text="@string/app_name" android:typeface="monospace" android:textColor="#00FF00"/> diff --git a/res/values/strings.xml b/res/values/strings.xml index a88970508..d952c6dba 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,25 +1,16 @@ - no content - Android IMSI-Catcher Detector + + AIMSICD + Android IMSI Catcher Detector Signal strength Quit OK Cancel Device Information - OEM RIL Hook - Busybox was not detected on your device, would you like to install it now? - Busybox install failed, please confirm your phone has been rooted and su - binary installed. - - The Microcom applet was not detected on your device, would you like to install it - now? - - The ATinout applet was not detected on your device, would you like to install it - now? - + # GPRS # EDGE # UMTS @@ -40,9 +31,13 @@ Show Map Export Database tables AT Command Injection + Press again to exit + + Location Services Disabled + Would you like to enable Location Services to track GPS Data? - + RIL OEM Hook Test Choose a RIL OEM Hook API to test: CRSM - RilStrings diff --git a/src/com/SecUpwN/AIMSICD/AIMSICD.java b/src/com/SecUpwN/AIMSICD/AIMSICD.java index dc96e36db..616df568a 100755 --- a/src/com/SecUpwN/AIMSICD/AIMSICD.java +++ b/src/com/SecUpwN/AIMSICD/AIMSICD.java @@ -1,33 +1,52 @@ +/* Android IMSI Catcher Detector + * Copyright (C) 2014 + * + * 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 may obtain a copy of the License at + * https://github.com/SecUpwN/Android-IMSI-Catcher-Detector/blob/master/LICENSE + */ + package com.SecUpwN.AIMSICD; import android.app.Activity; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; +import android.support.v4.app.NotificationCompat; import android.telephony.TelephonyManager; import android.util.Log; -import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.webkit.WebView; import android.widget.TextView; -import android.os.Build; +import android.widget.Toast; public class AIMSICD extends Activity { private final String TAG = "AIMSICD"; private Device mDevice; - - private TextView outputView; - - private WebView webview; - - private boolean isAbout; private final Context mContext = this; private Menu mMenu; + //Back press to exit timer + private long mLastPress = 0; + + //Notification ID + private int mID = 1; + /** * Called when the activity is first created. */ @@ -36,9 +55,9 @@ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); - mDevice = new Device(mContext); + mDevice = new Device(mContext, this); - outputView = (TextView) findViewById(R.id.view); + TextView outputView = (TextView) findViewById(R.id.view); outputView.setHorizontalFadingEdgeEnabled(false); outputView.setText("Information:\n\n"); @@ -59,8 +78,8 @@ public void onCreate(Bundle savedInstanceState) { outputView.append("Network name: " + mDevice.getNetworkName(false) + "\n"); outputView.append("Network code: " + mDevice.getSmmcMcc(false) + "\n"); outputView.append("Network type: " + mDevice.getNetworkTypeName() + "\n"); - outputView.append("Network LAC: " + mDevice.getsLAC(false) + "\n"); - outputView.append("Network CellID: " + mDevice.getsCellId(false) + "\n\n"); + outputView.append("Network LAC: " + mDevice.getLAC(false) + "\n"); + outputView.append("Network CellID: " + mDevice.getCellId(false) + "\n\n"); outputView.append("Data activity: " + mDevice.getActivityDesc(netID) + "\n"); outputView.append("Data status: " + mDevice.getStateDesc(netID) + "\n"); @@ -69,14 +88,16 @@ public void onCreate(Bundle savedInstanceState) { outputView.append("[LAC,CID]|DAct|DStat|Net|Sig|Lat|Lng\n"); Log.i(TAG, "**** AIMSICD ****"); Log.i(TAG, "Device type : " + mDevice.getPhoneType(false)); - Log.i(TAG, "Device imei : " + mDevice.getIMEI(false)); + Log.i(TAG, "Device IMEI : " + mDevice.getIMEI(false)); Log.i(TAG, "Device version: " + mDevice.getIMEIv(false)); Log.i(TAG, "Device num : " + mDevice.getPhoneNumber(false)); Log.i(TAG, "Network type : " + mDevice.getNetworkTypeName()); - Log.i(TAG, "Network CellID: " + mDevice.getsCellId(false)); - Log.i(TAG, "Network LAC : " + mDevice.getsLAC(false)); + Log.i(TAG, "Network CellID: " + mDevice.getCellId(false)); + Log.i(TAG, "Network LAC : " + mDevice.getLAC(false)); Log.i(TAG, "Network code : " + mDevice.getSmmcMcc(false)); Log.i(TAG, "Network name : " + mDevice.getNetworkName(false)); + + setNotification(); } @Override @@ -95,26 +116,26 @@ public boolean onPrepareOptionsMenu(Menu menu) { MenuItem mTrackLocation = menu.findItem(R.id.track_location); if (mDevice.isTrackingCell()) { - mTrackCell.setTitle(getResources().getString(R.string.track_cell)); - mTrackCell.setIcon(getResources().getDrawable(R.drawable.track_cell)); + mTrackCell.setTitle(R.string.track_cell); + mTrackCell.setIcon(R.drawable.track_cell); } else { - mTrackCell.setTitle(getResources().getString(R.string.untrack_cell)); - mTrackCell.setIcon(getResources().getDrawable(R.drawable.untrack_cell)); + mTrackCell.setTitle(R.string.untrack_cell); + mTrackCell.setIcon(R.drawable.untrack_cell); } if (mDevice.isTrackingSignal()) { - mTrackSignal.setTitle(getResources().getString(R.string.track_signal)); - mTrackSignal.setIcon(getResources().getDrawable(R.drawable.ic_action_network_cell)); + mTrackSignal.setTitle(R.string.track_signal); + mTrackSignal.setIcon(R.drawable.ic_action_network_cell); } else { - mTrackSignal.setTitle(getResources().getString(R.string.untrack_signal)); - mTrackSignal.setIcon(getResources().getDrawable(R.drawable.ic_action_network_cell_not_tracked)); + mTrackSignal.setTitle(R.string.untrack_signal); + mTrackSignal.setIcon(R.drawable.ic_action_network_cell_not_tracked); } if (mDevice.isTrackingLocation()) { - mTrackLocation.setTitle(getResources().getString(R.string.track_location)); - mTrackLocation.setIcon(getResources().getDrawable(R.drawable.ic_action_location_found)); + mTrackLocation.setTitle(R.string.track_location); + mTrackLocation.setIcon(R.drawable.ic_action_location_found); } else { - mTrackLocation.setTitle(getResources().getString(R.string.untrack_location)); - mTrackLocation.setIcon(getResources().getDrawable(R.drawable.ic_action_location_off)); + mTrackLocation.setTitle(R.string.untrack_location); + mTrackLocation.setIcon(R.drawable.ic_action_location_off); } return super.onPrepareOptionsMenu(menu); } @@ -125,24 +146,27 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.track_cell: mDevice.trackcell(); - if (Build.VERSION.SDK_INT > 11) + if (Build.VERSION.SDK_INT > 11) { onPrepareOptionsMenu(mMenu); + } return true; case R.id.track_signal: mDevice.tracksignal(); - if (Build.VERSION.SDK_INT > 11) + if (Build.VERSION.SDK_INT > 11) { onPrepareOptionsMenu(mMenu); + } return true; case R.id.track_location: - mDevice.tracklocation(mContext); - if (Build.VERSION.SDK_INT > 11) + mDevice.tracklocation(); + if (Build.VERSION.SDK_INT > 11) { onPrepareOptionsMenu(mMenu); + } return true; case R.id.show_map: showmap(); return true; case R.id.export_database: - mDevice.exportDB(); + mDevice.getDbHelper().exportDB(); return true; case R.id.at_injector: Intent intent = new Intent(this, ATRilHook.class); @@ -156,39 +180,88 @@ public boolean onOptionsItemSelected(MenuItem item) { } } - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - return false; + /** + * Exit application if back 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(); + finish(); } - return false; } - protected final void about() { - if (isAbout) { - Log.i(TAG, "Call bring outputview (LOG) to front"); - webview.bringChildToFront(outputView); - outputView.bringToFront(); - isAbout = false; + @Override + public void onDestroy() { + cancelNotification(); + super.onDestroy(); + } - } else { - if (webview != null) { - webview.bringToFront(); - } else { - webview = new WebView(this); - webview.loadUrl("http://secupwn.github.io/Android-IMSI-Catcher-Detector/"); - setContentView(webview); - } - isAbout = true; + /** + * Set or modify the Notification + */ + private void setNotification() { + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(mContext) + .setSmallIcon(R.drawable.iconbn) + .setContentTitle(mContext.getResources().getString(R.string.app_name)) + .setContentText("Phone Type " + mDevice.getPhoneType(false)) + .setOngoing(true) + .setAutoCancel(false); + + Intent notificationIntent = new Intent(this, AIMSICD.class); + PendingIntent contentIntent = PendingIntent.getActivity( + this, 0, notificationIntent, 0); + + mBuilder.setContentIntent(contentIntent); + NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + mNotificationManager.notify(mID, mBuilder.build()); + } + + private void cancelNotification() { + NotificationManager notificationManager = (NotificationManager) getSystemService( + NOTIFICATION_SERVICE); + if (notificationManager != null) { + notificationManager.cancel(mID); } } - protected final void showmap() { + /** + * Show the Map Viewer Activity + */ + private final void showmap() { Intent myIntent = new Intent(this, MapViewer.class); startActivity(myIntent); } + /** + * Returns the device instance + */ public Device getDevice() { return mDevice; } + /** + * Receives a response from Location Services Settings if the user agreed to enable them. + * If activity returns that the user made a valid selection then enable Location Tracking + */ + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // Check which request we're responding to + if (requestCode == mDevice.START_LOCATION_SERVICES) { + // Make sure the request was successful + if (resultCode == Activity.RESULT_OK) { + // Location Services were enabled attempt to enable Location Tracking + mDevice.tracklocation(); + } + } + } + } diff --git a/src/com/SecUpwN/AIMSICD/AIMSICDDbAdapter.java b/src/com/SecUpwN/AIMSICD/AIMSICDDbAdapter.java new file mode 100644 index 000000000..4a3c2c2c3 --- /dev/null +++ b/src/com/SecUpwN/AIMSICD/AIMSICDDbAdapter.java @@ -0,0 +1,287 @@ +package com.SecUpwN.AIMSICD; + +import android.content.Context; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.os.Environment; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +public class AIMSICDDbAdapter { + + private final String TAG = "AISMICD_DbAdaptor"; + + private DbHelper mDbHelper; + private SQLiteDatabase mDb; + private static final int DATABASE_VERSION = 1; + public static final String COLUMN_ID = "_id"; + public String LOCATION_TABLE = "locationinfo"; + public String CELL_TABLE = "cellinfo"; + public String SIGNAL_TABLE = "signalinfo"; + public String DB_NAME = "myCellInfo"; + private final Context mContext; + + public AIMSICDDbAdapter(Context context) { + this.mContext = context; + } + + public AIMSICDDbAdapter open() throws SQLException { + mDbHelper = new DbHelper(mContext); + mDb = mDbHelper.getWritableDatabase(); + return this; + } + + public void close() { + mDbHelper.close(); + } + + /** + * Location Tracking Database + */ + private final String LOC_DATABASE_CREATE = "create table " + + LOCATION_TABLE + " (" + COLUMN_ID + + " integer primary key autoincrement, Lac INTEGER, CellID INTEGER, " + + "Net VARCHAR, Lat VARCHAR, Lng VARCHAR, Signal INTEGER, Connection VARCHAR, " + + "Timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp);"; + + /** + * Cell Information Tracking Database + */ + private final String CELL_DATABASE_CREATE = "create table " + + CELL_TABLE + " (" + COLUMN_ID + + " integer primary key autoincrement, Lac INTEGER, CellID INTEGER, " + + "Net VARCHAR, Lat VARCHAR, Lng VARCHAR, Signal INTEGER, Connection VARCHAR, " + + "Country VARCHAR, Operator VARCHAR, OperatorName VARCHAR, " + + "Timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp);"; + + /** + * Signal Strength Tracking Database + */ + private final String SIG_DATABASE_CREATE = "create table " + + SIGNAL_TABLE + " (" + COLUMN_ID + + " integer primary key autoincrement, Lac INTEGER, CellID INTEGER, " + + "Net VARCHAR, Lat VARCHAR, Lng VARCHAR, Signal INTEGER, Connection VARCHAR, " + + "Timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp);"; + + /** + * Inserts Cell Details into Database + */ + public void insertCell( int lac, int cellID, + int netType, double latitude, double longitude, + int signalInfo, String cellInfo, String simCountry, + String simOperator, String simOperatorName) { + + mDb.execSQL("INSERT INTO " + CELL_TABLE + + " (Lac , CellID, Net, Lat, Lng, Signal, Connection," + + "Country, Operator, OperatorName)" + + " VALUES(" + lac + "," + cellID + "," + netType + "," + + latitude + "," + longitude + "," + signalInfo + ",\"" + + cellInfo + "\", \"" + simCountry + "\"," + simOperator + ",\"" + + simOperatorName + "\");"); + } + + /** + * Inserts Location Details into Database + */ + public void insertLocation(int lac, int cellID, + int netType, double latitude, double longitude, + int signalInfo, String cellInfo) { + + mDb.execSQL("INSERT INTO " + LOCATION_TABLE + + " (Lac , CellID, Net, Lat, Lng, Signal, Connection)" + + " VALUES(" + lac + "," + cellID + "," + netType + "," + + latitude + "," + longitude + "," + signalInfo + ",\"" + + cellInfo + "\");"); + } + + /** + * Inserts Signal Strength Details into Database + */ + public void insertSignal(int lac, int cellID, + int netType, double latitude, double longitude, + int signalInfo, String cellInfo) { + + mDb.execSQL("INSERT INTO " + SIGNAL_TABLE + + " (Lac , CellID, Net, Lat, Lng, Signal, Connection)" + + " VALUES(" + lac + "," + cellID + "," + netType + "," + + latitude + "," + longitude + "," + signalInfo + ",\"" + + cellInfo + "\");"); + } + + /** + * Returns Signal Strength database contents + */ + public Cursor getSignalData() { + return mDb.rawQuery("SELECT Net, Lat, Lng, Signal FROM " + + SIGNAL_TABLE, null); + } + + public void eraseLocationData() { + mDb.delete(LOCATION_TABLE, null, null); + } + + + /** + * Checks to see if Cell already exists in database + */ + public boolean cellExists(int cellID) { + Cursor cursor = mDb.rawQuery("SELECT * FROM " + CELL_TABLE + " WHERE CellID = " + + cellID, null); + + return cursor.getCount()>0; + } + + public void exportDB () { + try { + export(LOCATION_TABLE); + export(CELL_TABLE); + export(SIGNAL_TABLE); + } catch (IOException ioe) { + Log.e (TAG, "exportDB() " + ioe.getMessage()); + } + } + + public void export(String tableName) throws IOException { + Log.i(TAG, "exporting database - " + DB_NAME); + + XmlBuilder xmlBuilder = new XmlBuilder(); + xmlBuilder.start(DB_NAME); + Log.d(TAG, "table name " + tableName); + + exportTable(tableName, xmlBuilder); + String xmlString = xmlBuilder.end(); + writeToFile(xmlString, "aimsicd-" + tableName + ".xml"); + + Log.i(TAG, "exporting database complete"); + } + + private void exportTable(final String tableName, XmlBuilder xmlBuilder) throws IOException { + Log.d(TAG, "exporting table - " + tableName); + xmlBuilder.openTable(tableName); + String sql = "select * from " + tableName; + Cursor c = mDb.rawQuery(sql, new String[0]); + if (c.moveToFirst()) { + int cols = c.getColumnCount(); + do { + xmlBuilder.openRow(); + for (int i = 0; i < cols; i++) { + xmlBuilder.addColumn(c.getColumnName(i), c.getString(i)); + } + xmlBuilder.closeRow(); + } while (c.moveToNext()); + } + c.close(); + xmlBuilder.closeTable(); + } + + private void writeToFile(String xmlString, String exportFileName) throws IOException { + File dir = new File(Environment.getExternalStorageDirectory() + "/AIMSICD/"); + if (!dir.exists()) { + dir.mkdirs(); + } + File file = new File(dir, exportFileName); + file.createNewFile(); + + ByteBuffer buff = ByteBuffer.wrap(xmlString.getBytes()); + FileChannel channel = new FileOutputStream(file).getChannel(); + try { + channel.write(buff); + } finally { + if (channel != null) + channel.close(); + } + } + + /** + * DbHelper class for the SQLite Database functions + */ + public class DbHelper extends SQLiteOpenHelper { + + DbHelper(Context context) { + super(context, DB_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase database) { + database.execSQL(LOC_DATABASE_CREATE); + database.execSQL(CELL_DATABASE_CREATE); + database.execSQL(SIG_DATABASE_CREATE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.w(TAG, + "Upgrading database from version " + oldVersion + " to " + + newVersion + ", which will destroy all old data" + ); + db.execSQL("DROP TABLE IF EXISTS " + LOCATION_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + CELL_TABLE); + db.execSQL("DROP TABLE IF EXISTS " + SIGNAL_TABLE); + onCreate(db); + } + + } + + /** + * XmlBuilder is used to write XML tags (open and close, and a few attributes) + * to a StringBuilder. Here we have nothing to do with IO or SQL, just a fancy StringBuilder. + * + * @author ccollins + * + */ + private static class XmlBuilder { + private static final String OPEN_XML_STANZA = ""; + private static final String CLOSE_WITH_TICK = "'>"; + private static final String DB_OPEN = " 6) - sPhoneID = tm.getPhoneType(); + if (mPhoneID <= 0 || mPhoneID > 6) + mPhoneID = tm.getPhoneType(); - return sPhoneID; + return mPhoneID; } public String getSimCountry(boolean force) { - if (sSimCountry.isEmpty() || force) - sSimCountry = tm.getSimCountryIso(); + if (mSimCountry.isEmpty() || force) + mSimCountry = tm.getSimCountryIso(); - return sSimCountry; + return mSimCountry; } public String getSimOperator(boolean force) { - if (sSimOperator.isEmpty() || force) - sSimOperator = tm.getSimOperator(); + if (mSimOperator.isEmpty() || force) + mSimOperator = tm.getSimOperator(); - return sSimOperator; + return mSimOperator; } public String getSimOperatorName(boolean force) { - if (sSimOperatorName.isEmpty() || force) - sSimOperatorName = tm.getSimOperatorName(); + if (mSimOperatorName.isEmpty() || force) + mSimOperatorName = tm.getSimOperatorName(); - return sSimOperatorName; + return mSimOperatorName; } public String getSimSubs(boolean force) { - if (sSimSubs.isEmpty() || force) - sSimSubs = tm.getSubscriberId(); + if (mSimSubs.isEmpty() || force) + mSimSubs = tm.getSubscriberId(); - return sSimSubs; + return mSimSubs; } public String getSimSerial(boolean force) { - if (sSimSerial.isEmpty() || force) - sSimSerial = tm.getSimSerialNumber(); + if (mSimSerial.isEmpty() || force) + mSimSerial = tm.getSimSerialNumber(); - return sSimSerial; + return mSimSerial; } public String getPhoneType(boolean force) { - if (sPhoneType.isEmpty()|| force) { + if (mPhoneType.isEmpty()|| force) { if (getPhoneID() == TelephonyManager.PHONE_TYPE_GSM) - sPhoneType = "GSM"; + mPhoneType = "GSM"; else if (getPhoneID() == TelephonyManager.PHONE_TYPE_CDMA) - sPhoneType = "CDMA"; + mPhoneType = "CDMA"; else - sPhoneType = "Unknown"; + mPhoneType = "Unknown"; } - return sPhoneType; + return mPhoneType; } public String getIMEI(boolean force) { - if (sIMEI.isEmpty() || force) - sIMEI = tm.getDeviceId(); + if (mIMEI.isEmpty() || force) + mIMEI = tm.getDeviceId(); - return sIMEI; + return mIMEI; } public String getIMEIv(boolean force) { - if (sIMEIV.isEmpty() || force) - sIMEIV = tm.getDeviceSoftwareVersion(); + if (mIMEIV.isEmpty() || force) + mIMEIV = tm.getDeviceSoftwareVersion(); - return sIMEIV; + return mIMEIV; } public String getPhoneNumber(boolean force) { - if (sPhoneNum.isEmpty() || force) - sPhoneNum = tm.getLine1Number(); + if (mPhoneNum.isEmpty() || force) + mPhoneNum = tm.getLine1Number(); - return sPhoneNum; + return mPhoneNum; } public String getNetworkName(boolean force) { - if (sNetName.isEmpty() || force) - sNetName = tm.getNetworkOperatorName(); + if (mNetName.isEmpty() || force) + mNetName = tm.getNetworkOperatorName(); - return sNetName; + return mNetName; } public String getSmmcMcc(boolean force) { - if (sMmcmcc.isEmpty() || force) - sMmcmcc = tm.getNetworkOperator(); + if (mMmcmcc.isEmpty() || force) + mMmcmcc = tm.getNetworkOperator(); - return sMmcmcc; + return mMmcmcc; } public String getNetworkTypeName() { @@ -307,75 +318,79 @@ public String getNetworkTypeName() { } public int getNetID (boolean force) { - if (sNetID < 0 || force) { - sNetID = tm.getNetworkType(); + if (mNetID < 0 || force) { + mNetID = tm.getNetworkType(); } - return sNetID; + return mNetID; } - public String getsLAC(boolean force) { - if (sLac.isEmpty() || force) { + public String getLAC(boolean force) { + if (mLac.isEmpty() || force) { GsmCellLocation gsmCellLocation = (GsmCellLocation) tm.getCellLocation(); if (gsmCellLocation != null) { - sLac = "" + gsmCellLocation.getLac(); + mLac = "" + gsmCellLocation.getLac(); } } - return sLac; + return mLac; } - public String getsCellId(boolean force) { - if (sCellType.isEmpty() || force) { + public String getCellId(boolean force) { + if (mCellType.isEmpty() || force) { GsmCellLocation gsmCellLocation = (GsmCellLocation) tm.getCellLocation(); if (gsmCellLocation != null) { - sCellType = "" + gsmCellLocation.getCid(); + mCellType = "" + gsmCellLocation.getCid(); } } - return sCellType; + return mCellType; } public String getActivityDesc(int dataID) { - sDataActivityType = "undef"; + mDataActivityType = "undef"; switch (dataID) { case TelephonyManager.DATA_ACTIVITY_NONE: - sDataActivityType = "None"; + mDataActivityType = "None"; break; case TelephonyManager.DATA_ACTIVITY_IN: - sDataActivityType = "In"; + mDataActivityType = "In"; break; case TelephonyManager.DATA_ACTIVITY_OUT: - sDataActivityType = "Out"; + mDataActivityType = "Out"; break; case TelephonyManager.DATA_ACTIVITY_INOUT: - sDataActivityType = "In-Out"; + mDataActivityType = "In-Out"; break; case TelephonyManager.DATA_ACTIVITY_DORMANT: - sDataActivityType = "Dormant"; + mDataActivityType = "Dormant"; break; } - return sDataActivityType; + return mDataActivityType; } public String getStateDesc(int dataID) { - sDataState = "undef"; + mDataState = "undef"; switch (dataID) { case TelephonyManager.DATA_DISCONNECTED: - sDataActivityType = "Disconnected"; + mDataActivityType = "Disconnected"; break; case TelephonyManager.DATA_CONNECTING: - sDataActivityType = "Connecting"; + mDataActivityType = "Connecting"; break; case TelephonyManager.DATA_CONNECTED: - sDataActivityType = "Connected"; + mDataActivityType = "Connected"; break; case TelephonyManager.DATA_SUSPENDED: - sDataActivityType = "Suspended"; + mDataActivityType = "Suspended"; break; } - return sDataState; + return mDataState; + } + + public AIMSICDDbAdapter getDbHelper() { + return dbHelper; } public Boolean isTrackingSignal() { @@ -392,55 +407,70 @@ public Boolean isTrackingLocation() { public void tracksignal() { if (TrackingSignal) { - tm.listen(sSignalListenerStrength, PhoneStateListener.LISTEN_NONE); + tm.listen(mSignalListenerStrength, PhoneStateListener.LISTEN_NONE); + Helpers.msgShort(mContext, "Stopped tracking signal strength"); TrackingSignal = false; - sSignalInfo = 0; + mSignalInfo = 0; } else { - tm.listen(sSignalListenerStrength, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); + tm.listen(mSignalListenerStrength, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); + Helpers.msgShort(mContext, "Tracking signal strength"); TrackingSignal = true; } } public void trackcell() { if (TrackingCell) { - tm.listen(sSignalListenerLocation, PhoneStateListener.LISTEN_NONE); + tm.listen(mSignalListenerLocation, PhoneStateListener.LISTEN_NONE); + Helpers.msgShort(mContext, "Stopped tracking cell information"); TrackingCell = false; - sCellInfo = "[0,0]|nn|nn|"; + mCellInfo = "[0,0]|nn|nn|"; } else { - tm.listen(sSignalListenerLocation, PhoneStateListener.LISTEN_CELL_LOCATION); + tm.listen(mSignalListenerLocation, PhoneStateListener.LISTEN_CELL_LOCATION); + Helpers.msgShort(mContext, "Tracking cell information"); TrackingCell = true; } } - public void tracklocation(Context ctx) { + public void tracklocation() { if (TrackingLocation) { - lm.removeUpdates(sLocationListener); + lm.removeUpdates(mLocationListener); + Helpers.msgShort(mContext, "Stopped tracking location"); TrackingLocation = false; - sLongitude = 0.0; - sLatitude = 0.0; + mLongitude = 0.0; + mLatitude = 0.0; } else { if (lm != null) { Log.i(TAG, "LocationManager already existed"); - lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, sLocationListener); + lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener); + Helpers.msgShort(mContext, "Tracking location"); TrackingLocation = true; } else { Log.i(TAG, "LocationManager did not existed"); - lm = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE); + lm = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); if (lm != null) { if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Log.i(TAG, "LocationManager created"); - sLocationListener = new MyLocationListener(); - lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, sLocationListener); + mLocationListener = new MyLocationListener(); + lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener); + Helpers.msgShort(mContext, "Tracking location"); TrackingLocation = true; } else { - // GPS No es permet - Log.i(TAG, "GPS not allowed"); - AlertDialog.Builder msg = new AlertDialog.Builder(ctx); - msg.setMessage("GPS is not enabled!. You won�t be able to use GPS data until you enable it"); - AlertDialog alert = msg.create(); - alert.setTitle("Error:"); - alert.show(); - lm = null; + final AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setMessage(R.string.location_error_message) + .setTitle(R.string.location_error_title); + builder.setPositiveButton(R.string.text_ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + //Display Location Services Menu Fragment + Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); + mActivity.startActivityForResult(intent, START_LOCATION_SERVICES); + } + }); + builder.setNegativeButton(R.string.text_cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + builder.create().show(); } } } @@ -451,12 +481,12 @@ private class MyLocationListener implements LocationListener { @Override public void onLocationChanged(Location loc) { if (loc != null) { - sLongitude = loc.getLongitude(); - sLatitude = loc.getLatitude(); + mLongitude = loc.getLongitude(); + mLatitude = loc.getLatitude(); } if (TrackingLocation) { - dbHelper.insertLocation(sDB, sLacID, sCellID, sNetID, sLatitude, sLongitude, - sSignalInfo, sCellInfo); + dbHelper.insertLocation(mLacID, mCellID, mNetID, mLatitude, mLongitude, + mSignalInfo, mCellInfo); } } @@ -477,215 +507,4 @@ public void onStatusChanged(String provider, int status, } } - public void exportDB () { - try { - dbHelper.export(LOCATION_TABLE); - dbHelper.export(CELL_TABLE); - dbHelper.export(SIGNAL_TABLE); - } catch (IOException ioe) { - Log.e (TAG, "exportDB() " + ioe.getMessage()); - } - } - - /** - * SQLiteHelper class for the Location, Cell and Signal Strength Databases - */ - public class SQLiteHelper extends SQLiteOpenHelper { - - public static final String COLUMN_ID = "_id"; - private static final int DATABASE_VERSION = 1; - - // Database creation statements - private final String LOC_DATABASE_CREATE = "create table " + - LOCATION_TABLE + " (" + COLUMN_ID + - " integer primary key autoincrement, Lac INTEGER, CellID INTEGER, " + - "Net VARCHAR, Lat VARCHAR, Lng VARCHAR, Signal INTEGER, Connection VARCHAR, " + - "Timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp);"; - - private final String CELL_DATABASE_CREATE = "create table " + - CELL_TABLE + " (" + COLUMN_ID + - " integer primary key autoincrement, Lac INTEGER, CellID INTEGER, " + - "Net VARCHAR, Lat VARCHAR, Lng VARCHAR, Signal INTEGER, Connection VARCHAR, " + - "Country VARCHAR, Operator VARCHAR, OperatorName VARCHAR, " + - "Timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp);"; - - private final String SIG_DATABASE_CREATE = "create table " + - SIGNAL_TABLE + " (" + COLUMN_ID + - " integer primary key autoincrement, Lac INTEGER, CellID INTEGER, " + - "Net VARCHAR, Lat VARCHAR, Lng VARCHAR, Signal INTEGER, Connection VARCHAR, " + - "Timestamp TIMESTAMP NOT NULL DEFAULT current_timestamp);"; - - public SQLiteHelper(Context context) { - super(context, DB_NAME, null, DATABASE_VERSION); - } - - public void insertCell(SQLiteDatabase db, int lac, int cellID, - int netType, double latitude, double longitude, - int signalInfo, String cellInfo, String simCountry, - String simOperator, String simOperatorName) { - - db.execSQL("INSERT INTO " + CELL_TABLE + - " (Lac , CellID, Net, Lat, Lng, Signal, Connection," + - "Country, Operator, OperatorName)" + - " VALUES(" + lac + "," + cellID + "," + netType + "," - + latitude + "," + longitude + "," + signalInfo + ",\"" - + cellInfo + "\", \"" + simCountry + "\"," + simOperator + ",\"" - + simOperatorName + "\");"); - } - - public void insertLocation(SQLiteDatabase db, int lac, int cellID, - int netType, double latitude, double longitude, - int signalInfo, String cellInfo) { - - db.execSQL("INSERT INTO " + LOCATION_TABLE + - " (Lac , CellID, Net, Lat, Lng, Signal, Connection)" + - " VALUES(" + lac + "," + cellID + "," + netType + "," - + latitude + "," + longitude + "," + signalInfo + ",\"" - + cellInfo + "\");"); - } - - public void insertSignal(SQLiteDatabase db, int lac, int cellID, - int netType, double latitude, double longitude, - int signalInfo, String cellInfo) { - - db.execSQL("INSERT INTO " + SIGNAL_TABLE + - " (Lac , CellID, Net, Lat, Lng, Signal, Connection)" + - " VALUES(" + lac + "," + cellID + "," + netType + "," - + latitude + "," + longitude + "," + signalInfo + ",\"" - + cellInfo + "\");"); - } - - public boolean cellExists(int cellID) { - Cursor cursor = sDB.rawQuery("SELECT * FROM " + CELL_TABLE + " WHERE CellID = " + - cellID, null); - - return cursor.getCount()>0; - } - - @Override - public void onCreate(SQLiteDatabase database) { - database.execSQL(LOC_DATABASE_CREATE); - database.execSQL(CELL_DATABASE_CREATE); - database.execSQL(SIG_DATABASE_CREATE); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(SQLiteHelper.class.getName(), - "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - db.execSQL("DROP TABLE IF EXISTS " + LOCATION_TABLE); - db.execSQL("DROP TABLE IF EXISTS " + CELL_TABLE); - db.execSQL("DROP TABLE IF EXISTS " + SIGNAL_TABLE); - onCreate(db); - } - - public void export(String tableName) throws IOException { - Log.i(TAG, "exporting database - " + DB_NAME); - - XmlBuilder xmlBuilder = new XmlBuilder(); - xmlBuilder.start(DB_NAME); - Log.d(TAG, "table name " + tableName); - - exportTable(tableName, xmlBuilder); - String xmlString = xmlBuilder.end(); - writeToFile(xmlString, "aimsicd-" + tableName + ".xml"); - - Log.i(TAG, "exporting database complete"); - } - - private void exportTable(final String tableName, XmlBuilder xmlBuilder) throws IOException { - Log.d(TAG, "exporting table - " + tableName); - xmlBuilder.openTable(tableName); - String sql = "select * from " + tableName; - Cursor c = sDB.rawQuery(sql, new String[0]); - if (c.moveToFirst()) { - int cols = c.getColumnCount(); - do { - xmlBuilder.openRow(); - for (int i = 0; i < cols; i++) { - xmlBuilder.addColumn(c.getColumnName(i), c.getString(i)); - } - xmlBuilder.closeRow(); - } while (c.moveToNext()); - } - c.close(); - xmlBuilder.closeTable(); - } - - private void writeToFile(String xmlString, String exportFileName) throws IOException { - File dir = new File(Environment.getExternalStorageDirectory() + "/AIMSICD/"); - if (!dir.exists()) { - dir.mkdirs(); - } - File file = new File(dir, exportFileName); - file.createNewFile(); - - ByteBuffer buff = ByteBuffer.wrap(xmlString.getBytes()); - FileChannel channel = new FileOutputStream(file).getChannel(); - try { - channel.write(buff); - } finally { - if (channel != null) - channel.close(); - } - } - } - - /** - * XmlBuilder is used to write XML tags (open and close, and a few attributes) - * to a StringBuilder. Here we have nothing to do with IO or SQL, just a fancy StringBuilder. - * - * @author ccollins - * - */ - private static class XmlBuilder { - private static final String OPEN_XML_STANZA = ""; - private static final String CLOSE_WITH_TICK = "'>"; - private static final String DB_OPEN = "0) { if (c.moveToFirst()) { List listOfOverlays = mapView.getOverlays(); @@ -173,7 +188,7 @@ private void loadentries() { color = 0xF0F8FF; break; } - Log.i(TAG, " ==> Poin:" + p.toString() + " radius: " + radius + " color: " + color + " signal:" + signal); + Log.i(TAG, " ==> Point:" + p.toString() + " radius: " + radius + " color: " + color + " signal:" + signal); listOfOverlays.add(new MapOverlay(p, radius, color)); } @@ -194,7 +209,7 @@ private final void quit() { } private final void erasedb() { - mDevice.sDB.delete(mDevice.LOCATION_TABLE, null, null); + mDbHelper.eraseLocationData(); } } diff --git a/src/com/SecUpwN/AIMSICD/OemCommands.java b/src/com/SecUpwN/AIMSICD/OemCommands.java index 1c9406caf..fb8ea0862 100644 --- a/src/com/SecUpwN/AIMSICD/OemCommands.java +++ b/src/com/SecUpwN/AIMSICD/OemCommands.java @@ -1,3 +1,20 @@ +/* Android IMSI Catcher Detector + * Copyright (C) 2014 + * + * 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 may obtain a copy of the License at + * https://github.com/SecUpwN/Android-IMSI-Catcher-Detector/blob/master/LICENSE + */ + package com.SecUpwN.AIMSICD; import android.content.Context; diff --git a/src/com/SecUpwN/AIMSICD/Utils.java b/src/com/SecUpwN/AIMSICD/Utils.java index 5a455b424..768fce6b6 100644 --- a/src/com/SecUpwN/AIMSICD/Utils.java +++ b/src/com/SecUpwN/AIMSICD/Utils.java @@ -1,3 +1,20 @@ +/* Android IMSI Catcher Detector + * Copyright (C) 2014 + * + * 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 may obtain a copy of the License at + * https://github.com/SecUpwN/Android-IMSI-Catcher-Detector/blob/master/LICENSE + */ + package com.SecUpwN.AIMSICD; import android.content.Context; diff --git a/src/com/SecUpwN/AIMSICD/cmdprocessor/AbstractAsyncSuCMDProcessor.java b/src/com/SecUpwN/AIMSICD/cmdprocessor/AbstractAsyncSuCMDProcessor.java index 0eb83c9f5..d34bc2d95 100644 --- a/src/com/SecUpwN/AIMSICD/cmdprocessor/AbstractAsyncSuCMDProcessor.java +++ b/src/com/SecUpwN/AIMSICD/cmdprocessor/AbstractAsyncSuCMDProcessor.java @@ -23,7 +23,6 @@ import android.os.AsyncTask; - /** * An abstract implentation of AsyncTask *