2 * Copyright (C) 2018 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 package org
.strongswan
.android
.ui
;
18 import android
.annotation
.TargetApi
;
19 import android
.app
.Service
;
20 import android
.content
.ComponentName
;
21 import android
.content
.Context
;
22 import android
.content
.Intent
;
23 import android
.content
.ServiceConnection
;
24 import android
.content
.SharedPreferences
;
25 import android
.graphics
.drawable
.Icon
;
26 import android
.os
.Build
;
27 import android
.os
.IBinder
;
28 import android
.preference
.PreferenceManager
;
29 import android
.service
.quicksettings
.Tile
;
30 import android
.service
.quicksettings
.TileService
;
32 import org
.strongswan
.android
.R
;
33 import org
.strongswan
.android
.data
.VpnProfile
;
34 import org
.strongswan
.android
.data
.VpnProfileDataSource
;
35 import org
.strongswan
.android
.logic
.VpnStateService
;
36 import org
.strongswan
.android
.utils
.Constants
;
38 @TargetApi(Build
.VERSION_CODES
.N
)
39 public class VpnTileService
extends TileService
implements VpnStateService
.VpnStateListener
41 private boolean mListening
;
42 private VpnProfileDataSource mDataSource
;
43 private VpnStateService mService
;
44 private final ServiceConnection mServiceConnection
= new ServiceConnection()
47 public void onServiceDisconnected(ComponentName name
)
53 public void onServiceConnected(ComponentName name
, IBinder service
)
55 mService
= ((VpnStateService
.LocalBinder
)service
).getService();
58 mService
.registerListener(VpnTileService
.this);
65 public void onCreate()
69 Context context
= getApplicationContext();
70 context
.bindService(new Intent(context
, VpnStateService
.class),
71 mServiceConnection
, Service
.BIND_AUTO_CREATE
);
73 mDataSource
= new VpnProfileDataSource(this);
78 public void onDestroy()
83 getApplicationContext().unbindService(mServiceConnection
);
89 public void onStartListening()
91 super.onStartListening();
95 mService
.registerListener(this);
101 public void onStopListening()
103 super.onStopListening();
105 if (mService
!= null)
107 mService
.unregisterListener(this);
111 private VpnProfile
getProfile()
113 SharedPreferences pref
= PreferenceManager
.getDefaultSharedPreferences(this);
114 String uuid
= pref
.getString(Constants
.PREF_DEFAULT_VPN_PROFILE
, null);
115 if (uuid
== null || uuid
.equals(Constants
.PREF_DEFAULT_VPN_PROFILE_MRU
))
117 uuid
= pref
.getString(Constants
.PREF_MRU_VPN_PROFILE
, null);
120 return mDataSource
.getVpnProfile(uuid
);
124 public void onClick()
126 if (mService
!= null)
128 /* we operate on the current/most recently used profile, but fall back to configuration */
129 VpnProfile profile
= mService
.getProfile();
132 profile
= getProfile();
135 /* open the main activity in case of an error. since the state is still CONNECTING
136 * there is a popup confirmation dialog if we connect again, disconnect would work
137 * but doing two operations is not ideal */
138 if (mService
.getErrorState() == VpnStateService
.ErrorState
.NO_ERROR
)
140 switch (mService
.getState())
144 Runnable disconnect
= new Runnable()
149 mService
.disconnect();
154 unlockAndRun(disconnect
);
164 Intent intent
= new Intent(this, VpnProfileControlActivity
.class);
165 intent
.addFlags(Intent
.FLAG_ACTIVITY_NEW_TASK
);
166 intent
.setAction(VpnProfileControlActivity
.START_PROFILE
);
167 intent
.putExtra(VpnProfileControlActivity
.EXTRA_VPN_PROFILE_ID
, profile
.getUUID().toString());
168 startActivity(intent
);
173 Intent intent
= new Intent(this, MainActivity
.class);
174 intent
.addFlags(Intent
.FLAG_ACTIVITY_NEW_TASK
);
175 startActivityAndCollapse(intent
);
179 public void stateChanged()
184 private void updateTile()
186 VpnProfile profile
= mService
.getProfile();
187 VpnStateService
.State state
= mService
.getState();
188 VpnStateService
.ErrorState error
= mService
.getErrorState();
190 /* same as above, only use the configured profile if we have no active profile */
193 profile
= getProfile();
196 Tile tile
= getQsTile();
198 if (error
!= VpnStateService
.ErrorState
.NO_ERROR
)
200 tile
.setState(Tile
.STATE_INACTIVE
);
201 tile
.setIcon(Icon
.createWithResource(this, R
.drawable
.ic_notification_warning
));
202 tile
.setLabel(getString(R
.string
.tile_connect
));
210 tile
.setState(Tile
.STATE_INACTIVE
);
211 tile
.setIcon(Icon
.createWithResource(this, R
.drawable
.ic_notification_disconnected
));
212 tile
.setLabel(getString(R
.string
.tile_connect
));
215 tile
.setState(Tile
.STATE_ACTIVE
);
216 tile
.setIcon(Icon
.createWithResource(this, R
.drawable
.ic_notification_connecting
));
217 tile
.setLabel(getString(R
.string
.tile_disconnect
));
220 tile
.setState(Tile
.STATE_ACTIVE
);
221 tile
.setIcon(Icon
.createWithResource(this, R
.drawable
.ic_notification
));
222 tile
.setLabel(getString(R
.string
.tile_disconnect
));
226 if (profile
!= null && !isSecure())
228 tile
.setLabel(profile
.getName());