1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
/*
* Copyright (c) 2012-2023 Arne Schwabe
* Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt
*/
package de.blinkt.openvpn.core;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.VpnService;
import android.os.PersistableBundle;
import de.blinkt.openvpn.LaunchVPN;
import de.blinkt.openvpn.VpnProfile;
/**
* This is a task that is run periodically to restart the VPN if tit has died for
* some reason in the background
*/
public class keepVPNAlive extends JobService implements VpnStatus.StateListener {
private ConnectionStatus mLevel = ConnectionStatus.UNKNOWN_LEVEL;
private static final int JOBID_KEEPVPNALIVE = 6231;
@Override
public void onCreate() {
super.onCreate();
VpnStatus.addStateListener(this);
}
@Override
public void onDestroy() {
super.onDestroy();
VpnStatus.removeStateListener(this);
}
@Override
public boolean onStartJob(JobParameters jobParameters) {
if (mLevel == ConnectionStatus.UNKNOWN_LEVEL || mLevel == ConnectionStatus.LEVEL_NOTCONNECTED) {
String vpnUUID = jobParameters.getExtras().getString(LaunchVPN.EXTRA_KEY);
VpnProfile vp = ProfileManager.get(this, vpnUUID);
if (vp == null) {
VpnStatus.logError("Keepalive service cannot find VPN");
unscheduleKeepVPNAliveJobService(this);
return false;
}
VPNLaunchHelper.startOpenVpn(vp, getApplicationContext(), "VPN keep alive Job");
} else {
VpnStatus.logDebug("Keepalive service called but VPN still connected.");
}
/* The job has finished */
return false;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
/* not doing anything */
return true;
}
@Override
public void updateState(String state, String logmessage,
int localizedResId, ConnectionStatus level, Intent Intent) {
mLevel = level;
}
@Override
public void setConnectedVPN(String uuid) {
}
public static void scheduleKeepVPNAliveJobService(Context c, VpnProfile vp) {
ComponentName keepVPNAliveComponent = new ComponentName(c, keepVPNAlive.class);
JobInfo.Builder jib = new JobInfo.Builder(JOBID_KEEPVPNALIVE, keepVPNAliveComponent);
/* set the VPN that should be restarted if we get killed */
PersistableBundle extraBundle = new PersistableBundle();
extraBundle.putString(de.blinkt.openvpn.LaunchVPN.EXTRA_KEY, vp.getUUIDString());
jib.setExtras(extraBundle);
/* periodic timing */
/* The current limits are 15 minutes and 5 minutes for flex and periodic timer
* but we use a minimum of 5 minutes and 2 minutes to avoid problems if there is some
* strange Android build that allows lower lmits.
*/
long initervalMillis = Math.max(JobInfo.getMinPeriodMillis(), 5 * 60 * 1000L);
long flexMillis = Math.max(JobInfo.getMinFlexMillis(), 2 * 60 * 1000L);
jib.setPeriodic(initervalMillis, flexMillis);
jib.setPersisted(true);
JobScheduler jobScheduler = c.getSystemService(JobScheduler.class);
jobScheduler.schedule(jib.build());
VpnStatus.logDebug("Scheduling VPN keep alive for VPN " + vp.mName);
}
public static void unscheduleKeepVPNAliveJobService(Context c) {
JobScheduler jobScheduler = c.getSystemService(JobScheduler.class);
jobScheduler.cancel(JOBID_KEEPVPNALIVE);
VpnStatus.logDebug("Unscheduling VPN keep alive");
}
}
|