The stats might become null between these two checks, when a tunnel
flips off, resulting in a null pointer dereference:
at com.wireguard.android.model.ObservableTunnel.getStatisticsAsync (ObservableTunnel.java:103)
at com.wireguard.android.fragment.TunnelDetailFragment.updateStats (TunnelDetailFragment.java:108)
at com.wireguard.android.fragment.TunnelDetailFragment.access$updateStats (TunnelDetailFragment.java:27)
at com.wireguard.android.fragment.TunnelDetailFragment$onResume$1.run (TunnelDetailFragment.java:74)
at java.util.TimerThread.mainLoop (TimerThread.java:562)
at java.util.TimerThread.run (TimerThread.java:512)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
When tunnel deletion is triggered we don't bother with animation theatrics
because the resulting Snackbar needs this fab to be its anchor, which it can't
do if its outside the screen or busy animating.
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
Long press a tunnel item. SIGKILL the app. Reenter it. Boom:
kotlin.KotlinNullPointerException:
at com.wireguard.android.fragment.TunnelListFragment$ActionModeListener.onCreateActionMode (TunnelListFragment.java:347)
at androidx.appcompat.app.AppCompatDelegateImpl$ActionModeCallbackWrapperV9.onCreateActionMode (AppCompatDelegateImpl.java:2442)
at androidx.appcompat.app.WindowDecorActionBar$ActionModeImpl.dispatchOnCreate (WindowDecorActionBar.java:1062)
at androidx.appcompat.app.WindowDecorActionBar.startActionMode (WindowDecorActionBar.java:530)
at androidx.appcompat.app.AppCompatDelegateImpl.startSupportActionMode (AppCompatDelegateImpl.java:1055)
at androidx.appcompat.app.AppCompatActivity.startSupportActionMode (AppCompatActivity.java:316)
at com.wireguard.android.fragment.TunnelListFragment$ActionModeListener.setItemChecked (TunnelListFragment.java:371)
at com.wireguard.android.fragment.TunnelListFragment.onActivityCreated (TunnelListFragment.java:174)
at androidx.fragment.app.Fragment.performActivityCreated (Fragment.java:2717)
at androidx.fragment.app.FragmentStateManager.activityCreated (FragmentStateManager.java:346)
at androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1188)
at androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:161)
at androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:5)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState (FragmentManager.java:1434)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState (FragmentManager.java:5)
at androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1497)
at androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:389)
at androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:2625)
at androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:677)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated (FragmentManager.java:2577)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated (FragmentManager.java:9)
at androidx.fragment.app.FragmentController.dispatchActivityCreated (FragmentController.java:247)
at androidx.fragment.app.FragmentActivity.onStart (FragmentActivity.java:541)
at androidx.appcompat.app.AppCompatActivity.onStart (AppCompatActivity.java:201)
at android.app.Instrumentation.callActivityOnStart (Instrumentation.java:1440)
at android.app.Activity.performStart (Activity.java:8109)
at android.app.ActivityThread.handleStartActivity (ActivityThread.java:3806)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence (TransactionExecutor.java:235)
at android.app.servertransaction.TransactionExecutor.cycleToPath (TransactionExecutor.java:215)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:187)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:105)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2386)
at android.os.Handler.dispatchMessage (Handler.java:107)
at android.os.Looper.loop (Looper.java:213)
at android.app.ActivityThread.main (ActivityThread.java:8178)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1101)
This commit avoids the crash. But it's not clear to me that this is
really the right solution. However, in testing it appears to work.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
When biometric hardware is available, it will be used to authenticate
the user before private keys are shown on screen or when zip exports
are executed.
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
The correct way to retrieve the value inside a getter/setter is to use `field` to ensure
you don't invoke the getter while inside the getter and trigger a stack overflow
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This contains a share button and a save button, the former using a
custom content provider.
Co-authored-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>