diff --git a/app/src/main/java/com/emanuelef/remote_capture/AppStateListener.java b/app/src/main/java/com/emanuelef/remote_capture/AppStateListener.java index e0c3253b..0d746517 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/AppStateListener.java +++ b/app/src/main/java/com/emanuelef/remote_capture/AppStateListener.java @@ -19,9 +19,14 @@ package com.emanuelef.remote_capture; -interface AppStateListener { - void appStateReady(); - void appStateStarting(); - void appStateRunning(); - void appStateStopping(); +/* App state handling: ready -> starting -> running -> stopping -> ready */ +enum AppState { + ready, + starting, + running, + stopping +} + +interface AppStateListener { + void appStateChanged(AppState state); } diff --git a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java index 926a5bc5..6ada9aec 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java +++ b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java @@ -364,4 +364,5 @@ public class CaptureService extends VpnService implements Runnable { public static native void runPacketLoop(int fd, CaptureService vpn, int sdk); public static native void stopPacketLoop(); + public static native void askConnectionsDump(); } diff --git a/app/src/main/java/com/emanuelef/remote_capture/ConnectionsFragment.java b/app/src/main/java/com/emanuelef/remote_capture/ConnectionsFragment.java index 03b3df4f..63f83f08 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/ConnectionsFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/ConnectionsFragment.java @@ -39,20 +39,21 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; public class ConnectionsFragment extends Fragment { private static final String TAG = "ConnectionsFragment"; - private MainActivity activity; + private MainActivity mActivity; private ConnectionsAdapter mAdapter; @Override public void onAttach(@NonNull Context context) { super.onAttach(context); - activity = (MainActivity) context; + mActivity = (MainActivity) context; } @Override public void onDestroy() { - activity.setConnectionsFragment(null); super.onDestroy(); + + mActivity = null; } @Override @@ -67,7 +68,7 @@ public class ConnectionsFragment extends Fragment { TextView emptyText = view.findViewById(R.id.no_connections); connList.setEmptyView(emptyText); - mAdapter = new ConnectionsAdapter(activity); + mAdapter = new ConnectionsAdapter(mActivity); connList.setAdapter(mAdapter); connList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -76,7 +77,7 @@ public class ConnectionsFragment extends Fragment { if(item != null) { Intent intent = new Intent(getContext(), ConnectionDetails.class); - AppDescriptor app = activity.findAppByUid(item.uid); + AppDescriptor app = mActivity.findAppByUid(item.uid); String app_name = null;//;1051 if(app != null) @@ -96,7 +97,7 @@ public class ConnectionsFragment extends Fragment { } }); - LocalBroadcastManager bcast_man = LocalBroadcastManager.getInstance(activity); + LocalBroadcastManager bcast_man = LocalBroadcastManager.getInstance(mActivity); /* Register for connections update */ bcast_man.registerReceiver(new BroadcastReceiver() { @@ -105,34 +106,13 @@ public class ConnectionsFragment extends Fragment { processConnectionsDump(intent); } }, new IntentFilter(CaptureService.ACTION_CONNECTIONS_DUMP)); - - if(savedInstanceState != null) { - ConnDescriptor connections[] = (ConnDescriptor[]) savedInstanceState.getSerializable("connections"); - - if(connections != null) { - mAdapter.updateConnections(connections); - Log.d(TAG, "Restored " + connections.length + " connections"); - } - } - - /* Important: call this after all the fields have been initialized */ - activity.setConnectionsFragment(this); } @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - ConnDescriptor items[] = new ConnDescriptor[mAdapter.getCount()]; + public void onResume() { + super.onResume(); - for(int i = 0; i>, AppStateListener { +public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks> { SharedPreferences mPrefs; Menu mMenu; Drawable mFilterIcon; @@ -65,10 +65,9 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa boolean mOpenAppsWhenDone; List mInstalledApps; AppState mState; - StatusFragment mStatusFragment; - ConnectionsFragment mConnectionsFragment; ViewPager2 viewPager2; TabLayout tabLayout; + AppStateListener mStateListener; private final static int POS_STATUS = 0; private final static int POS_CONNECTIONS = 1; private final static int TOTAL_COUNT = 2; @@ -81,14 +80,6 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa public static final String GITHUB_PROJECT_URL = "https://github.com/emanuele-f/PCAPdroid"; public static final String GITHUB_DOCS_URL = "https://emanuele-f.github.io/PCAPdroid"; - /* App state handling: ready -> starting -> running -> stopping -> ready */ - enum AppState { - ready, - starting, - running, - stopping - } - private static class MainStateAdapter extends FragmentStateAdapter { MainStateAdapter(final FragmentActivity fa) { super(fa); @@ -119,8 +110,7 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa mFilterApp = CaptureService.getAppFilter(); mOpenAppsWhenDone = false; mInstalledApps = null; - mStatusFragment = null; - mConnectionsFragment = null; + mStateListener = null; CaocConfig.Builder.create() .errorDrawable(R.drawable.ic_app_crash) @@ -148,10 +138,6 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - if (savedInstanceState != null) { - mConnectionsFragment = (ConnectionsFragment) getSupportFragmentManager().getFragment(savedInstanceState, "ConnectionsFragment"); - } - startLoadingApps(); LocalBroadcastManager bcast_man = LocalBroadcastManager.getInstance(this); @@ -173,53 +159,38 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa }, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS)); } - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - if(mConnectionsFragment != null) - getSupportFragmentManager().putFragment(outState, "ConnectionsFragment", mConnectionsFragment); - } - - @Override public void appStateReady() { mState = AppState.ready; - if (mStatusFragment != null) - mStatusFragment.appStateReady(); - mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(true); + + if(mStateListener != null) + mStateListener.appStateChanged(AppState.ready); } - @Override public void appStateStarting() { mState = AppState.starting; - if (mStatusFragment != null) - mStatusFragment.appStateStarting(); - mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(false); + + if(mStateListener != null) + mStateListener.appStateChanged(AppState.starting); } - @Override public void appStateRunning() { mState = AppState.running; mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(false); - if (mStatusFragment != null) - mStatusFragment.appStateRunning(); - - if (mConnectionsFragment != null) - mConnectionsFragment.reset(); + if(mStateListener != null) + mStateListener.appStateChanged(AppState.running); } - @Override public void appStateStopping() { mState = AppState.stopping; - if (mStatusFragment != null) - mStatusFragment.appStateStopping(); + if(mStateListener != null) + mStateListener.appStateChanged(AppState.stopping); mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).setEnabled(false); } @@ -231,7 +202,7 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa mMenu = menu; mFilterIcon = mMenu.getItem(MENU_ITEM_APP_SELECTOR_IDX).getIcon(); - recheckFragments(); + initAppState(); return true; } @@ -379,8 +350,7 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa return (null); } - /* Try to determine the current app state */ - private void setAppState() { + private void initAppState() { boolean is_active = CaptureService.isServiceActive(); if (!is_active) @@ -419,22 +389,8 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa } } - void setStatusFragment(StatusFragment screen) { - mStatusFragment = screen; - recheckFragments(); - } - - void setConnectionsFragment(ConnectionsFragment view) { - mConnectionsFragment = view; - recheckFragments(); - } - - private void recheckFragments() { - /* Must wait for the fragments to properly update them */ - if((mStatusFragment != null) && (mConnectionsFragment != null) && (mMenu != null)) { - // Possibly set an initial app state - setAppState(); - } + void setAppStateListener(AppStateListener listener) { + mStateListener = listener; } AppState getState() { diff --git a/app/src/main/java/com/emanuelef/remote_capture/StatusFragment.java b/app/src/main/java/com/emanuelef/remote_capture/StatusFragment.java index 5f8747a0..1a6dcec7 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/StatusFragment.java +++ b/app/src/main/java/com/emanuelef/remote_capture/StatusFragment.java @@ -58,7 +58,7 @@ public class StatusFragment extends Fragment implements AppStateListener { @Override public void onDestroy() { - mActivity.setStatusFragment(null); + mActivity.setAppStateListener(null); mActivity = null; super.onDestroy(); } @@ -101,7 +101,7 @@ public class StatusFragment extends Fragment implements AppStateListener { mPrefs.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { - if((mActivity != null) && (mActivity.getState() == MainActivity.AppState.ready)) + if((mActivity != null) && (mActivity.getState() == AppState.ready)) refreshPcapDumpInfo(); } }); @@ -125,35 +125,7 @@ public class StatusFragment extends Fragment implements AppStateListener { }, new IntentFilter(CaptureService.ACTION_TRAFFIC_STATS_UPDATE)); /* Important: call this after all the fields have been initialized */ - mActivity.setStatusFragment(this); - } - - @Override - public void appStateReady() { - mStartButton.setText(R.string.start_button); - mStartButton.setEnabled(true); - mCaptureStatus.setText(R.string.ready); - - refreshPcapDumpInfo(); - } - - @Override - public void appStateStarting() { - mStartButton.setEnabled(false); - } - - @Override - public void appStateRunning() { - mStartButton.setText(R.string.stop_button); - mStartButton.setEnabled(true); - mCaptureStatus.setText(Utils.formatBytes(CaptureService.getBytes())); - - refreshPcapDumpInfo(); - } - - @Override - public void appStateStopping() { - mStartButton.setEnabled(false); + mActivity.setAppStateListener(this); } private void processStatsUpdateIntent(Intent intent) { @@ -203,4 +175,30 @@ public class StatusFragment extends Fragment implements AppStateListener { mCollectorInfo.setText(info); } + + @Override + public void appStateChanged(AppState state) { + switch(state) { + case starting: + mStartButton.setEnabled(false); + break; + case stopping: + mStartButton.setEnabled(false); + break; + case ready: + mStartButton.setText(R.string.start_button); + mStartButton.setEnabled(true); + mCaptureStatus.setText(R.string.ready); + + refreshPcapDumpInfo(); + break; + case running: + mStartButton.setText(R.string.stop_button); + mStartButton.setEnabled(true); + mCaptureStatus.setText(Utils.formatBytes(CaptureService.getBytes())); + + refreshPcapDumpInfo(); + break; + } + } } diff --git a/app/src/main/jni/vpnproxy-jni/vpnproxy.c b/app/src/main/jni/vpnproxy-jni/vpnproxy.c index 3f622a81..ed621785 100644 --- a/app/src/main/jni/vpnproxy-jni/vpnproxy.c +++ b/app/src/main/jni/vpnproxy-jni/vpnproxy.c @@ -79,6 +79,7 @@ typedef struct jni_classes { static jni_classes_t cls; static jni_methods_t mids; static bool running = false; +static bool dump_connections_now = false; /* TCP/IP packet to hold the mitmproxy header */ static char mitmproxy_pkt_buffer[] = { @@ -1000,7 +1001,8 @@ housekeeping: sendCaptureStats(&proxy); proxy.capture_stats.new_stats = false; proxy.capture_stats.last_update_ms = now_ms; - } else if((now_ms - last_connections_dump) >= CONNECTION_DUMP_UPDATE_FREQUENCY_MS) { + } else if(((now_ms - last_connections_dump) >= CONNECTION_DUMP_UPDATE_FREQUENCY_MS) || dump_connections_now) { + dump_connections_now = false; sendConnectionsDump(tun, &proxy); last_connections_dump = now_ms; } else if((proxy.java_dump.buffer_idx > 0) @@ -1065,3 +1067,9 @@ Java_com_emanuelef_remote_1capture_CaptureService_runPacketLoop(JNIEnv *env, jcl run_tun(env, vpn, tapfd, sdk); close(tapfd); } + +JNIEXPORT void JNICALL +Java_com_emanuelef_remote_1capture_CaptureService_askConnectionsDump(JNIEnv *env, jclass clazz) { + if(running) + dump_connections_now = true; +} \ No newline at end of file