-
Notifications
You must be signed in to change notification settings - Fork 621
Expand file tree
/
Copy pathIPNService.java
More file actions
128 lines (102 loc) · 4 KB
/
IPNService.java
File metadata and controls
128 lines (102 loc) · 4 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package com.tailscale.ipn;
import android.os.Build;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.VpnService;
import android.system.OsConstants;
import org.gioui.GioActivity;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
public class IPNService extends VpnService {
public static final String ACTION_CONNECT = "com.tailscale.ipn.CONNECT";
public static final String ACTION_DISCONNECT = "com.tailscale.ipn.DISCONNECT";
@Override public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && ACTION_DISCONNECT.equals(intent.getAction())) {
((App)getApplicationContext()).autoConnect = false;
close();
return START_NOT_STICKY;
}
connect();
App app = ((App)getApplicationContext());
if (app.vpnReady && app.autoConnect) {
directConnect();
}
return START_STICKY;
}
private void close() {
stopForeground(true);
disconnect();
}
@Override public void onDestroy() {
close();
super.onDestroy();
}
@Override public void onRevoke() {
close();
super.onRevoke();
}
private PendingIntent configIntent() {
return PendingIntent.getActivity(this, 0, new Intent(this, IPNActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
private void disallowApp(VpnService.Builder b, String name) {
try {
b.addDisallowedApplication(name);
} catch (PackageManager.NameNotFoundException e) {
return;
}
}
protected VpnService.Builder newBuilder() {
VpnService.Builder b = new VpnService.Builder()
.setConfigureIntent(configIntent())
.allowFamily(OsConstants.AF_INET)
.allowFamily(OsConstants.AF_INET6);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
b.setMetered(false); // Inherit the metered status from the underlying networks.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
b.setUnderlyingNetworks(null); // Use all available networks.
// RCS/Jibe https://github.com/tailscale/tailscale/issues/2322
this.disallowApp(b, "com.google.android.apps.messaging");
// Stadia https://github.com/tailscale/tailscale/issues/3460
this.disallowApp(b, "com.google.stadia.android");
// Android Auto https://github.com/tailscale/tailscale/issues/3828
this.disallowApp(b, "com.google.android.projection.gearhead");
// GoPro https://github.com/tailscale/tailscale/issues/2554
this.disallowApp(b, "com.gopro.smarty");
// Sonos https://github.com/tailscale/tailscale/issues/2548
this.disallowApp(b, "com.sonos.acr");
this.disallowApp(b, "com.sonos.acr2");
// Google Chromecast https://github.com/tailscale/tailscale/issues/3636
this.disallowApp(b, "com.google.android.apps.chromecast.app");
return b;
}
public void notify(String title, String message) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, App.NOTIFY_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(configIntent())
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManagerCompat nm = NotificationManagerCompat.from(this);
nm.notify(App.NOTIFY_NOTIFICATION_ID, builder.build());
}
public void updateStatusNotification(String title, String message) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, App.STATUS_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(configIntent())
.setPriority(NotificationCompat.PRIORITY_LOW);
startForeground(App.STATUS_NOTIFICATION_ID, builder.build());
}
public static native void setAuthKeyForNextConnect(String authKey);
private native void connect();
private native void disconnect();
public native void directConnect();
}