5
5
6
6
package com .wireguard .android .backend ;
7
7
8
+ import android .app .ForegroundServiceStartNotAllowedException ;
9
+ import android .app .Notification ;
8
10
import android .content .Context ;
9
11
import android .content .Intent ;
12
+ import android .content .pm .ServiceInfo ;
10
13
import android .os .Build ;
11
14
import android .os .ParcelFileDescriptor ;
12
15
import android .system .OsConstants ;
24
27
import com .wireguard .util .NonNullForAll ;
25
28
26
29
import java .net .InetAddress ;
27
- import java .time .Instant ;
28
30
import java .util .Collections ;
29
31
import java .util .Set ;
30
32
import java .util .concurrent .ExecutionException ;
35
37
36
38
import androidx .annotation .Nullable ;
37
39
import androidx .collection .ArraySet ;
40
+ import androidx .core .app .NotificationCompat ;
41
+ import androidx .core .app .ServiceCompat ;
38
42
39
43
/**
40
44
* Implementation of {@link Backend} that uses the wireguard-go userspace implementation to provide
@@ -392,6 +396,9 @@ public GhettoCompletableFuture<V> newIncompleteFuture() {
392
396
* {@link android.net.VpnService} implementation for {@link GoBackend}
393
397
*/
394
398
public static class VpnService extends android .net .VpnService {
399
+
400
+ private static final int NOTIFICATION_ID = 999 ;
401
+ private static final String CHANNEL_ID = "VPN_CHANNEL" ;
395
402
@ Nullable private GoBackend owner ;
396
403
397
404
public Builder getBuilder () {
@@ -423,6 +430,7 @@ public void onDestroy() {
423
430
424
431
@ Override
425
432
public int onStartCommand (@ Nullable final Intent intent , final int flags , final int startId ) {
433
+ startForeground ();
426
434
vpnService .complete (this );
427
435
if (intent == null || intent .getComponent () == null || !intent .getComponent ().getPackageName ().equals (getPackageName ())) {
428
436
Log .d (TAG , "Service started by Always-on VPN feature" );
@@ -435,5 +443,20 @@ public int onStartCommand(@Nullable final Intent intent, final int flags, final
435
443
public void setOwner (final GoBackend owner ) {
436
444
this .owner = owner ;
437
445
}
446
+
447
+ private void startForeground () {
448
+ try {
449
+ final Notification notification = new NotificationCompat
450
+ .Builder (this , CHANNEL_ID )
451
+ .build ();
452
+ ServiceCompat .startForeground (this , NOTIFICATION_ID , notification , ServiceInfo .FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED );
453
+ } catch (final Exception ex ) {
454
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S &&
455
+ ex instanceof ForegroundServiceStartNotAllowedException
456
+ ) {
457
+ Log .d (TAG , "App not in a valid state to start foreground service" );
458
+ }
459
+ }
460
+ }
438
461
}
439
462
}
0 commit comments