66import android .content .BroadcastReceiver ;
77import android .content .Context ;
88import android .content .Intent ;
9- import androidx .work .Data ;
109
10+ import androidx .work .Data ;
11+ import androidx .work .ExistingWorkPolicy ;
1112import androidx .work .OneTimeWorkRequest ;
13+ import androidx .work .OutOfQuotaPolicy ;
1214import androidx .work .WorkManager ;
1315
1416import java .util .Objects ;
@@ -20,26 +22,56 @@ public class IPNReceiver extends BroadcastReceiver {
2022
2123 public static final String INTENT_CONNECT_VPN = "com.tailscale.ipn.CONNECT_VPN" ;
2224 public static final String INTENT_DISCONNECT_VPN = "com.tailscale.ipn.DISCONNECT_VPN" ;
23-
2425 private static final String INTENT_USE_EXIT_NODE = "com.tailscale.ipn.USE_EXIT_NODE" ;
2526
27+ // Unique work names prevent connect/disconnect flapping from enqueuing a long backlog.
28+ private static final String WORK_CONNECT = "ipn-connect-vpn" ;
29+ private static final String WORK_DISCONNECT = "ipn-disconnect-vpn" ;
30+ private static final String WORK_USE_EXIT_NODE = "ipn-use-exit-node" ;
31+
2632 @ Override
2733 public void onReceive (Context context , Intent intent ) {
28- WorkManager workManager = WorkManager . getInstance ( context ) ;
34+ if ( intent == null ) return ;
2935
30- // On the relevant action, start the relevant worker, which can stay active for longer than this receiver can.
31- if (Objects .equals (intent .getAction (), INTENT_CONNECT_VPN )) {
32- workManager .enqueue (new OneTimeWorkRequest .Builder (StartVPNWorker .class ).build ());
33- } else if (Objects .equals (intent .getAction (), INTENT_DISCONNECT_VPN )) {
34- workManager .enqueue (new OneTimeWorkRequest .Builder (StopVPNWorker .class ).build ());
35- }
36- else if (Objects .equals (intent .getAction (), INTENT_USE_EXIT_NODE )) {
36+ final WorkManager workManager = WorkManager .getInstance (context );
37+ final String action = intent .getAction ();
38+
39+ if (Objects .equals (action , INTENT_CONNECT_VPN )) {
40+ OneTimeWorkRequest req =
41+ new OneTimeWorkRequest .Builder (StartVPNWorker .class )
42+ .setExpedited (OutOfQuotaPolicy .RUN_AS_NON_EXPEDITED_WORK_REQUEST )
43+ .addTag (WORK_CONNECT )
44+ .build ();
45+
46+ workManager .enqueueUniqueWork (WORK_CONNECT , ExistingWorkPolicy .REPLACE , req );
47+
48+ } else if (Objects .equals (action , INTENT_DISCONNECT_VPN )) {
49+ OneTimeWorkRequest req =
50+ new OneTimeWorkRequest .Builder (StopVPNWorker .class )
51+ .setExpedited (OutOfQuotaPolicy .RUN_AS_NON_EXPEDITED_WORK_REQUEST )
52+ .addTag (WORK_DISCONNECT )
53+ .build ();
54+
55+ workManager .enqueueUniqueWork (WORK_DISCONNECT , ExistingWorkPolicy .REPLACE , req );
56+
57+ } else if (Objects .equals (action , INTENT_USE_EXIT_NODE )) {
3758 String exitNode = intent .getStringExtra ("exitNode" );
3859 boolean allowLanAccess = intent .getBooleanExtra ("allowLanAccess" , false );
39- Data .Builder workData = new Data .Builder ();
40- workData .putString (UseExitNodeWorker .EXIT_NODE_NAME , exitNode );
41- workData .putBoolean (UseExitNodeWorker .ALLOW_LAN_ACCESS , allowLanAccess );
42- workManager .enqueue (new OneTimeWorkRequest .Builder (UseExitNodeWorker .class ).setInputData (workData .build ()).build ());
60+
61+ Data input =
62+ new Data .Builder ()
63+ .putString (UseExitNodeWorker .EXIT_NODE_NAME , exitNode )
64+ .putBoolean (UseExitNodeWorker .ALLOW_LAN_ACCESS , allowLanAccess )
65+ .build ();
66+
67+ OneTimeWorkRequest req =
68+ new OneTimeWorkRequest .Builder (UseExitNodeWorker .class )
69+ .setInputData (input )
70+ .setExpedited (OutOfQuotaPolicy .RUN_AS_NON_EXPEDITED_WORK_REQUEST )
71+ .addTag (WORK_USE_EXIT_NODE )
72+ .build ();
73+
74+ workManager .enqueueUniqueWork (WORK_USE_EXIT_NODE , ExistingWorkPolicy .REPLACE , req );
4375 }
4476 }
4577}
0 commit comments