diff --git a/AIMSICD/TikTok-SIM-Privacy.md b/AIMSICD/TikTok-SIM-Privacy.md new file mode 100644 index 000000000..82b5ad5eb --- /dev/null +++ b/AIMSICD/TikTok-SIM-Privacy.md @@ -0,0 +1,45 @@ +## TikTok SIM/Telephony Privacy (Non‑root) + +This guide explains practical steps to prevent apps (e.g., TikTok) from learning SIM/phone identifiers on Android devices without root. + +### 1) Deny phone/SIM permissions +- Settings → Apps → TikTok → Permissions → Phone → Deny. Also deny SMS/Call log if present. +- Force stop TikTok, then Clear storage. + +### 2) Stronger enforcement with ADB (no root) +```bash +# Replace PKG with the exact package of TikTok (e.g., com.zhiliaoapp.musically or com.ss.android.ugc.trill) +PKG=com.zhiliaoapp.musically + +# Revoke telephony-related dangerous permissions +adb shell pm revoke $PKG android.permission.READ_PHONE_STATE +adb shell pm revoke $PKG android.permission.READ_PHONE_NUMBERS +adb shell pm revoke $PKG android.permission.READ_SMS +adb shell pm revoke $PKG android.permission.READ_CALL_LOG + +# Clamp app-ops (Android 10+) +adb shell cmd appops set $PKG READ_DEVICE_IDENTIFIERS ignore +adb shell cmd appops set $PKG READ_PHONE_STATE ignore +adb shell cmd appops set $PKG READ_PHONE_NUMBERS ignore +adb shell cmd appops set $PKG READ_SMS ignore +adb shell cmd appops set $PKG READ_CALL_LOG ignore + +# Reset the app +adb shell am force-stop $PKG +adb shell pm clear $PKG +``` + +### 3) Use a secondary Android user without telephony +- Settings → System → Multiple users → Add user. +- Do not enable “Phone calls & SMS for this user.” +- Switch, install TikTok, use Wi‑Fi. + +### 4) Temporarily disable the SIM subscription +- Settings → Network & Internet → SIMs → toggle OFF the problematic SIM. +- Keep Wi‑Fi ON. Force stop + Clear storage for TikTok before testing. + +### Notes +- Intercepting app traffic is not feasible non‑root due to TLS pinning. +- Use the new “Privacy Advisor” (App → Menu → Privacy Advisor) to see which installed apps request telephony permissions and copy ready‑made ADB commands. + + diff --git a/AIMSICD/src/main/AndroidManifest.xml b/AIMSICD/src/main/AndroidManifest.xml index 983b980d2..91d27ad02 100644 --- a/AIMSICD/src/main/AndroidManifest.xml +++ b/AIMSICD/src/main/AndroidManifest.xml @@ -104,6 +104,16 @@ + + + + + + adapter; + private final List items = new ArrayList<>(); + + private static final Set TELEPHONY_PERMS = new HashSet<>(Arrays.asList( + android.Manifest.permission.READ_PHONE_STATE, + android.Manifest.permission.READ_PHONE_NUMBERS, + android.Manifest.permission.READ_SMS, + android.Manifest.permission.READ_CALL_LOG + )); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_privacy_advisor); + + listView = (ListView) findViewById(R.id.privacy_list); + progressBar = (ProgressBar) findViewById(R.id.privacy_progress); + emptyView = (TextView) findViewById(R.id.privacy_empty); + + adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_2, android.R.id.text1, items) { + @Override + public View getView(int position, View convertView, android.view.ViewGroup parent) { + View v = super.getView(position, convertView, parent); + TextView t1 = (TextView) v.findViewById(android.R.id.text1); + TextView t2 = (TextView) v.findViewById(android.R.id.text2); + AppPerms ap = getItem(position); + if (ap != null) { + t1.setText(ap.label + " (" + ap.packageName + ")"); + t2.setText(getString(R.string.privacy_perms_count, ap.relevantGrantedCount, ap.relevantRequestedCount)); + } + return v; + } + }; + listView.setAdapter(adapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + AppPerms ap = adapter.getItem(position); + if (ap != null) { + showDetailsDialog(ap); + } + } + }); + + loadData(); + } + + private void loadData() { + progressBar.setVisibility(View.VISIBLE); + emptyView.setVisibility(View.GONE); + listView.setVisibility(View.GONE); + + new Thread(new Runnable() { + @Override + public void run() { + final List result = scanInstalled(); + runOnUiThread(new Runnable() { + @Override + public void run() { + items.clear(); + items.addAll(result); + adapter.notifyDataSetChanged(); + + progressBar.setVisibility(View.GONE); + if (items.isEmpty()) { + emptyView.setVisibility(View.VISIBLE); + listView.setVisibility(View.GONE); + } else { + listView.setVisibility(View.VISIBLE); + emptyView.setVisibility(View.GONE); + } + } + }); + } + }).start(); + } + + private List scanInstalled() { + PackageManager pm = getPackageManager(); + List pkgs = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS); + List result = new ArrayList<>(); + + for (PackageInfo pi : pkgs) { + if (pi.requestedPermissions == null || pi.requestedPermissions.length == 0) { + continue; + } + List requested = new ArrayList<>(); + List granted = new ArrayList<>(); + + for (int i = 0; i < pi.requestedPermissions.length; i++) { + String perm = pi.requestedPermissions[i]; + if (!TELEPHONY_PERMS.contains(perm)) continue; + + requested.add(perm); + boolean isGranted = false; + if (pi.requestedPermissionsFlags != null && pi.requestedPermissionsFlags.length > i) { + isGranted = (pi.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0; + } else { + isGranted = pm.checkPermission(perm, pi.packageName) == PackageManager.PERMISSION_GRANTED; + } + if (isGranted) { + granted.add(perm); + } + } + + if (!requested.isEmpty()) { + CharSequence label; + try { + label = pm.getApplicationLabel(pm.getApplicationInfo(pi.packageName, 0)); + } catch (PackageManager.NameNotFoundException e) { + label = pi.packageName; + } + result.add(new AppPerms(pi.packageName, label.toString(), requested, granted)); + } + } + + Collections.sort(result, new Comparator() { + @Override + public int compare(AppPerms o1, AppPerms o2) { + // Sort by granted count desc, then label + int g = Integer.valueOf(o2.relevantGrantedCount).compareTo(o1.relevantGrantedCount); + if (g != 0) return g; + return o1.label.compareToIgnoreCase(o2.label); + } + }); + + return result; + } + + private void showDetailsDialog(final AppPerms ap) { + StringBuilder sb = new StringBuilder(); + sb.append(getString(R.string.privacy_dialog_pkg)).append(" ").append(ap.packageName).append("\n\n"); + if (!ap.relevantRequested.isEmpty()) { + sb.append(getString(R.string.privacy_dialog_requested)).append("\n"); + for (String rp : ap.relevantRequested) { + sb.append("• ").append(humanizePermission(rp)); + if (ap.relevantGranted.contains(rp)) { + sb.append(" ").append(getString(R.string.privacy_dialog_granted)); + } else { + sb.append(" ").append(getString(R.string.privacy_dialog_denied)); + } + sb.append("\n"); + } + } + + final String adb = buildAdbCommands(ap.packageName, ap.relevantRequested); + + new AlertDialog.Builder(this) + .setTitle(getString(R.string.privacy_dialog_title, ap.label)) + .setMessage(sb.toString()) + .setPositiveButton(R.string.privacy_copy_cmds, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + copyToClipboard(adb); + } + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + } + + private String humanizePermission(String perm) { + if (android.Manifest.permission.READ_PHONE_STATE.equals(perm)) return getString(R.string.perm_read_phone_state); + if (android.Manifest.permission.READ_PHONE_NUMBERS.equals(perm)) return getString(R.string.perm_read_phone_numbers); + if (android.Manifest.permission.READ_SMS.equals(perm)) return getString(R.string.perm_read_sms); + if (android.Manifest.permission.READ_CALL_LOG.equals(perm)) return getString(R.string.perm_read_call_log); + return perm; + } + + private void copyToClipboard(String text) { + ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + if (cm != null) { + cm.setPrimaryClip(ClipData.newPlainText("adb", text)); + } + } + + private String buildAdbCommands(String pkg, List perms) { + StringBuilder sb = new StringBuilder(); + sb.append("# Replace PKG if needed\n"); + sb.append("PKG=").append(pkg).append("\n\n"); + for (String p : perms) { + sb.append("adb shell pm revoke $PKG ").append(p).append("\n"); + } + // App-ops clamps + sb.append("\n# App-ops clamps (Android 10+)\n"); + sb.append("adb shell cmd appops set $PKG READ_DEVICE_IDENTIFIERS ignore\n"); + sb.append("adb shell cmd appops set $PKG READ_PHONE_STATE ignore\n"); + sb.append("adb shell cmd appops set $PKG READ_PHONE_NUMBERS ignore\n"); + sb.append("adb shell cmd appops set $PKG READ_SMS ignore\n"); + sb.append("adb shell cmd appops set $PKG READ_CALL_LOG ignore\n"); + sb.append("\n# Reset app\n"); + sb.append("adb shell am force-stop $PKG\n"); + sb.append("adb shell pm clear $PKG\n"); + return sb.toString(); + } + + @AllArgsConstructor + @ToString + private static class AppPerms { + @Getter + final String packageName; + @Getter + final String label; + @Getter + final List relevantRequested; + @Getter + final List relevantGranted; + + final int relevantRequestedCount() { return relevantRequested == null ? 0 : relevantRequested.size(); } + final int relevantGrantedCount() { return relevantGranted == null ? 0 : relevantGranted.size(); } + } +} + + diff --git a/AIMSICD/src/main/res/layout/activity_privacy_advisor.xml b/AIMSICD/src/main/res/layout/activity_privacy_advisor.xml new file mode 100644 index 000000000..1fad2bddf --- /dev/null +++ b/AIMSICD/src/main/res/layout/activity_privacy_advisor.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + diff --git a/AIMSICD/src/main/res/menu/main_menu.xml b/AIMSICD/src/main/res/menu/main_menu.xml index ee63df847..1770d88f7 100644 --- a/AIMSICD/src/main/res/menu/main_menu.xml +++ b/AIMSICD/src/main/res/menu/main_menu.xml @@ -31,4 +31,9 @@ android:icon="@drawable/ic_action_computer" android:title="@string/debugging" app:showAsAction="never" /> - \ No newline at end of file + + diff --git a/AIMSICD/src/main/res/values/strings.xml b/AIMSICD/src/main/res/values/strings.xml index 5ecd90551..c7bbe5784 100644 --- a/AIMSICD/src/main/res/values/strings.xml +++ b/AIMSICD/src/main/res/values/strings.xml @@ -1,4 +1,18 @@ Antenna Map Viewer - \ No newline at end of file + Privacy Advisor + Apps requesting phone/SIM permissions (tap for details) + No installed apps request telephony-related permissions. + %1$d granted of %2$d requested + %1$s + Package: + Requested telephony permissions: + (granted) + (denied) + Copy ADB commands + Read phone state + Read phone numbers + Read SMS + Read call log +