mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-06-16 21:10:57 +08:00
parent
68d661d625
commit
c0ec3e6421
@ -19,28 +19,97 @@
|
||||
|
||||
package com.emanuelef.remote_capture.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.emanuelef.remote_capture.R;
|
||||
import com.emanuelef.remote_capture.Utils;
|
||||
import com.emanuelef.remote_capture.fragments.AppOverview;
|
||||
import com.emanuelef.remote_capture.fragments.ConnectionsFragment;
|
||||
import com.emanuelef.remote_capture.model.FilterDescriptor;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
public class AppDetailsActivity extends BaseActivity {
|
||||
private static final String TAG = "AppDetailsActivity";
|
||||
public static final String APP_UID_EXTRA = "app_uid";
|
||||
private ViewPager2 mPager;
|
||||
private int mUid;
|
||||
|
||||
private static final int POS_OVERVIEW = 0;
|
||||
private static final int POS_CONNECTIONS = 1;
|
||||
private static final int POS_TOTAL = 2;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(R.string.app_details);
|
||||
displayBackAction();
|
||||
setContentView(R.layout.fragment_activity);
|
||||
setContentView(R.layout.tabs_activity);
|
||||
|
||||
int uid = getIntent().getIntExtra(APP_UID_EXTRA, Utils.UID_UNKNOWN);
|
||||
mUid = getIntent().getIntExtra(APP_UID_EXTRA, Utils.UID_UNKNOWN);
|
||||
setupUidFilter();
|
||||
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.fragment, AppOverview.newInstance(uid))
|
||||
.commit();
|
||||
mPager = findViewById(R.id.pager);
|
||||
setupTabs();
|
||||
}
|
||||
|
||||
private void setupUidFilter() {
|
||||
Intent intent = getIntent();
|
||||
if(intent == null) {
|
||||
intent = new Intent();
|
||||
setIntent(intent);
|
||||
}
|
||||
|
||||
FilterDescriptor filter = new FilterDescriptor();
|
||||
filter.uid = mUid;
|
||||
intent.putExtra(ConnectionsFragment.FILTER_EXTRA, filter);
|
||||
}
|
||||
|
||||
private class StateAdapter extends FragmentStateAdapter {
|
||||
StateAdapter(final FragmentActivity fa) { super(fa); }
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
//Log.d(TAG, "createFragment");
|
||||
switch (position) {
|
||||
case POS_CONNECTIONS:
|
||||
// APP_UID_EXTRA is passed (see setupUidFilter)
|
||||
return new ConnectionsFragment();
|
||||
case POS_OVERVIEW:
|
||||
default:
|
||||
return AppOverview.newInstance(mUid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return POS_TOTAL;
|
||||
}
|
||||
|
||||
public int getPageTitle(final int position) {
|
||||
switch(position) {
|
||||
case POS_CONNECTIONS:
|
||||
return R.string.connections_view;
|
||||
case POS_OVERVIEW:
|
||||
default:
|
||||
return R.string.overview;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupTabs() {
|
||||
StateAdapter pageAdapter = new StateAdapter(this);
|
||||
mPager.setAdapter(pageAdapter);
|
||||
|
||||
new TabLayoutMediator(findViewById(R.id.tablayout), mPager, (tab, position) ->
|
||||
tab.setText(getString(pageAdapter.getPageTitle(position)))
|
||||
).attach();
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ public class EditFilterActivity extends BaseActivity {
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if(item.getItemId() == R.id.reset_changes) {
|
||||
mFilter = new FilterDescriptor();
|
||||
mFilter.clear();
|
||||
model2view();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@ import com.emanuelef.remote_capture.CaptureService;
|
||||
import com.emanuelef.remote_capture.ConnectionsRegister;
|
||||
import com.emanuelef.remote_capture.R;
|
||||
import com.emanuelef.remote_capture.Utils;
|
||||
import com.emanuelef.remote_capture.activities.ConnectionsActivity;
|
||||
import com.emanuelef.remote_capture.model.AppDescriptor;
|
||||
import com.emanuelef.remote_capture.model.AppStats;
|
||||
|
||||
@ -61,6 +60,7 @@ public class AppOverview extends Fragment {
|
||||
private TextView mBlockedConnections;
|
||||
private TableLayout mTable;
|
||||
private TextView mPermissions;
|
||||
private PackageInfo mPinfo;
|
||||
|
||||
public static AppOverview newInstance(int uid) {
|
||||
AppOverview fragment = new AppOverview();
|
||||
@ -100,21 +100,22 @@ public class AppOverview extends Fragment {
|
||||
|
||||
((TextView)view.findViewById(R.id.uid)).setText(Utils.formatInteger(ctx, dsc.getUid()));
|
||||
((TextView)view.findViewById(R.id.name)).setText(dsc.getName());
|
||||
PackageInfo pinfo = dsc.getPackageInfo();
|
||||
((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(dsc.getIcon());
|
||||
|
||||
if(pinfo != null) {
|
||||
((TextView)view.findViewById(R.id.package_name)).setText(dsc.getPackageName());
|
||||
((TextView)view.findViewById(R.id.version)).setText(pinfo.versionName);
|
||||
((TextView)view.findViewById(R.id.target_sdk)).setText(Utils.formatInteger(ctx, pinfo.applicationInfo.targetSdkVersion));
|
||||
((TextView)view.findViewById(R.id.install_date)).setText(Utils.formatEpochFull(ctx, pinfo.firstInstallTime / 1000));
|
||||
((TextView)view.findViewById(R.id.last_update)).setText(Utils.formatEpochFull(ctx, pinfo.lastUpdateTime / 1000));
|
||||
mPinfo = dsc.getPackageInfo();
|
||||
|
||||
if((pinfo.requestedPermissions != null) && (pinfo.requestedPermissions.length != 0)) {
|
||||
if(mPinfo != null) {
|
||||
((TextView)view.findViewById(R.id.package_name)).setText(dsc.getPackageName());
|
||||
((TextView)view.findViewById(R.id.version)).setText(mPinfo.versionName);
|
||||
((TextView)view.findViewById(R.id.target_sdk)).setText(Utils.formatInteger(ctx, mPinfo.applicationInfo.targetSdkVersion));
|
||||
((TextView)view.findViewById(R.id.install_date)).setText(Utils.formatEpochFull(ctx, mPinfo.firstInstallTime / 1000));
|
||||
((TextView)view.findViewById(R.id.last_update)).setText(Utils.formatEpochFull(ctx, mPinfo.lastUpdateTime / 1000));
|
||||
|
||||
if((mPinfo.requestedPermissions != null) && (mPinfo.requestedPermissions.length != 0)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
||||
for(String perm: pinfo.requestedPermissions) {
|
||||
for(String perm: mPinfo.requestedPermissions) {
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
@ -146,22 +147,11 @@ public class AppOverview extends Fragment {
|
||||
view.findViewById(R.id.last_update_row).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.permissions_label).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.permissions).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.app_settings).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
mTable = view.findViewById(R.id.table);
|
||||
|
||||
view.findViewById(R.id.app_settings).setOnClickListener(v -> {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.fromParts("package", dsc.getPackageName(), null));
|
||||
Utils.startActivity(ctx, intent);
|
||||
});
|
||||
|
||||
view.findViewById(R.id.show_connections).setOnClickListener(v -> {
|
||||
Intent intent = new Intent(ctx, ConnectionsActivity.class);
|
||||
intent.putExtra(ConnectionsFragment.QUERY_EXTRA, dsc.getPackageName());
|
||||
startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -189,14 +179,22 @@ public class AppOverview extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater menuInflater) {
|
||||
menuInflater.inflate(R.menu.copy_share_menu, menu);
|
||||
menuInflater.inflate(R.menu.app_overview_menu, menu);
|
||||
|
||||
if(mPinfo == null)
|
||||
menu.findItem(R.id.app_info).setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
if(id == R.id.copy_to_clipboard) {
|
||||
if(id == R.id.app_info) {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.fromParts("package", mPinfo.packageName, null));
|
||||
Utils.startActivity(requireContext(), intent);
|
||||
return true;
|
||||
} else if(id == R.id.copy_to_clipboard) {
|
||||
Utils.copyToClipboard(requireContext(), asString());
|
||||
return true;
|
||||
} else if(id == R.id.share) {
|
||||
|
||||
@ -33,7 +33,6 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -58,10 +57,9 @@ import com.emanuelef.remote_capture.model.Prefs;
|
||||
public class FirewallStatus extends Fragment {
|
||||
private static final String TAG = "FirewallStatus";
|
||||
private Handler mHandler;
|
||||
SharedPreferences mPrefs;
|
||||
private SharedPreferences mPrefs;
|
||||
private SwitchCompat mToggle;
|
||||
private ImageView mStatusIcon;
|
||||
private View mConnectionsCard;
|
||||
private TextView mStatus;
|
||||
private TextView mNumBlocked;
|
||||
private TextView mNumChecked;
|
||||
@ -86,7 +84,6 @@ public class FirewallStatus extends Fragment {
|
||||
mStatus = view.findViewById(R.id.status);
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mStatusIcon = view.findViewById(R.id.status_icon);
|
||||
mConnectionsCard = view.findViewById(R.id.show_connections);
|
||||
mNumBlocked = view.findViewById(R.id.num_blocked);
|
||||
mNumChecked = view.findViewById(R.id.num_checked);
|
||||
mNumRules = view.findViewById(R.id.num_rules);
|
||||
@ -96,7 +93,7 @@ public class FirewallStatus extends Fragment {
|
||||
mWarnColor = ContextCompat.getColor(ctx, R.color.warning);
|
||||
mGrayColor = ContextCompat.getColor(ctx, R.color.lightGray);
|
||||
|
||||
mConnectionsCard.setOnClickListener(v -> {
|
||||
view.findViewById(R.id.show_connections).setOnClickListener(v -> {
|
||||
FilterDescriptor filter = new FilterDescriptor();
|
||||
filter.onlyBLocked = true;
|
||||
|
||||
|
||||
@ -33,12 +33,17 @@ import com.google.android.material.chip.ChipGroup;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class FilterDescriptor implements Serializable {
|
||||
public Status status = Status.STATUS_INVALID;
|
||||
public boolean showMasked = true;
|
||||
public boolean onlyBLocked = false;
|
||||
public boolean onlyBlacklisted = false;
|
||||
public DecryptionStatus decStatus = DecryptionStatus.INVALID;
|
||||
public Status status;
|
||||
public boolean showMasked;
|
||||
public boolean onlyBLocked;
|
||||
public boolean onlyBlacklisted;
|
||||
public DecryptionStatus decStatus;
|
||||
public String iface;
|
||||
public int uid = -2; // this is persistent and used internally (AppDetailsActivity)
|
||||
|
||||
public FilterDescriptor() {
|
||||
clear();
|
||||
}
|
||||
|
||||
public boolean isSet() {
|
||||
return (status != Status.STATUS_INVALID)
|
||||
@ -46,6 +51,7 @@ public class FilterDescriptor implements Serializable {
|
||||
|| (iface != null)
|
||||
|| onlyBLocked
|
||||
|| onlyBlacklisted
|
||||
|| (uid != 2)
|
||||
|| (!showMasked && !PCAPdroid.getInstance().getVisualizationMask().isEmpty());
|
||||
}
|
||||
|
||||
@ -55,7 +61,8 @@ public class FilterDescriptor implements Serializable {
|
||||
&& (!onlyBlacklisted || conn.isBlacklisted())
|
||||
&& ((status == Status.STATUS_INVALID) || (conn.getStatus().equals(status)))
|
||||
&& ((decStatus == DecryptionStatus.INVALID) || (conn.getDecryptionStatus() == decStatus))
|
||||
&& ((iface == null) || (CaptureService.getInterfaceName(conn.ifidx).equals(iface)));
|
||||
&& ((iface == null) || (CaptureService.getInterfaceName(conn.ifidx).equals(iface)))
|
||||
&& ((uid == -2) || (uid == conn.uid));
|
||||
}
|
||||
|
||||
private void addChip(LayoutInflater inflater, ChipGroup group, int id, String text) {
|
||||
@ -100,4 +107,13 @@ public class FilterDescriptor implements Serializable {
|
||||
else if(filter_id == R.id.capture_interface)
|
||||
iface = null;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
showMasked = true;
|
||||
onlyBLocked = false;
|
||||
onlyBlacklisted = false;
|
||||
status = Status.STATUS_INVALID;
|
||||
decStatus = DecryptionStatus.INVALID;
|
||||
iface = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxHeight="80dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@ -171,8 +172,7 @@
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginTop="16dp">
|
||||
android:layout_marginBottom="4dp">
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
@ -228,35 +228,6 @@
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/table">
|
||||
|
||||
<Button
|
||||
android:id="@+id/app_settings"
|
||||
android:text="@string/title_activity_settings"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="42dip"
|
||||
android:layout_weight="1"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:textColor="@color/colorTabText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/show_connections"
|
||||
android:text="@string/connections_view"
|
||||
android:nextFocusDown="@id/permissions"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="42dip"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/vapp_info"
|
||||
android:layout_width="wrap_content"
|
||||
@ -265,16 +236,16 @@
|
||||
android:textStyle="italic"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/buttons" />
|
||||
app:layout_constraintTop_toBottomOf="@id/table" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/permissions_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/buttons"
|
||||
app:layout_constraintTop_toBottomOf="@id/table"
|
||||
android:text="@string/permissions"/>
|
||||
|
||||
<HorizontalScrollView
|
||||
|
||||
26
app/src/main/res/menu/app_overview_menu.xml
Normal file
26
app/src/main/res/menu/app_overview_menu.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/app_info"
|
||||
android:title="@string/app_info"
|
||||
android:orderInCategory="5"
|
||||
android:icon="@drawable/ic_settings"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/copy_to_clipboard"
|
||||
android:title="@string/copy_to_clipboard"
|
||||
android:orderInCategory="10"
|
||||
android:icon="@drawable/ic_content_copy"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/share"
|
||||
android:title="@string/share"
|
||||
android:orderInCategory="20"
|
||||
android:icon="@drawable/ic_share"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
@ -347,4 +347,5 @@
|
||||
<string name="last_firewall_block">Last block</string>
|
||||
<string name="firewall_is_disabled">Firewall is disabled</string>
|
||||
<string name="firewall_is_enabled">Firewall is enabled</string>
|
||||
<string name="app_info">App info</string>
|
||||
</resources>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user