Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
com.ccwangluo.accelerator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sheteng
com.ccwangluo.accelerator
Commits
dca0da09
Commit
dca0da09
authored
Feb 23, 2019
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow stop service while connecting
parent
cf0ad396
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
103 additions
and
101 deletions
+103
-101
core/src/main/java/com/github/shadowsocks/aidl/ShadowsocksConnection.kt
...java/com/github/shadowsocks/aidl/ShadowsocksConnection.kt
+3
-2
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
+28
-26
core/src/main/java/com/github/shadowsocks/bg/ServiceNotification.kt
...ain/java/com/github/shadowsocks/bg/ServiceNotification.kt
+1
-1
mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
...om/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
+2
-2
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
+11
-11
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
.../src/main/java/com/github/shadowsocks/ProfilesFragment.kt
+4
-10
mobile/src/main/java/com/github/shadowsocks/QuickToggleShortcut.kt
...c/main/java/com/github/shadowsocks/QuickToggleShortcut.kt
+5
-4
mobile/src/main/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
...in/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
+2
-5
mobile/src/main/java/com/github/shadowsocks/bg/TileService.kt
...le/src/main/java/com/github/shadowsocks/bg/TileService.kt
+18
-11
mobile/src/main/java/com/github/shadowsocks/widget/ServiceButton.kt
.../main/java/com/github/shadowsocks/widget/ServiceButton.kt
+6
-6
mobile/src/main/java/com/github/shadowsocks/widget/StatsBar.kt
...e/src/main/java/com/github/shadowsocks/widget/StatsBar.kt
+5
-5
tv/src/main/java/com/github/shadowsocks/tv/MainFragment.kt
tv/src/main/java/com/github/shadowsocks/tv/MainFragment.kt
+1
-1
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
.../java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
+17
-17
No files found.
core/src/main/java/com/github/shadowsocks/aidl/ShadowsocksConnection.kt
View file @
dca0da09
...
...
@@ -28,6 +28,7 @@ import android.os.DeadObjectException
import
android.os.Handler
import
android.os.IBinder
import
android.os.RemoteException
import
com.github.shadowsocks.bg.BaseService
import
com.github.shadowsocks.bg.ProxyService
import
com.github.shadowsocks.bg.TransproxyService
import
com.github.shadowsocks.bg.VpnService
...
...
@@ -51,7 +52,7 @@ class ShadowsocksConnection(private val handler: Handler = Handler(),
}
interface
Callback
{
fun
stateChanged
(
state
:
Int
,
profileName
:
String
?,
msg
:
String
?)
fun
stateChanged
(
state
:
BaseService
.
State
,
profileName
:
String
?,
msg
:
String
?)
fun
trafficUpdated
(
profileId
:
Long
,
stats
:
TrafficStats
)
{
}
fun
trafficPersisted
(
profileId
:
Long
)
{
}
...
...
@@ -69,7 +70,7 @@ class ShadowsocksConnection(private val handler: Handler = Handler(),
private
val
serviceCallback
=
object
:
IShadowsocksServiceCallback
.
Stub
()
{
override
fun
stateChanged
(
state
:
Int
,
profileName
:
String
?,
msg
:
String
?)
{
val
callback
=
callback
?:
return
handler
.
post
{
callback
.
stateChanged
(
state
,
profileName
,
msg
)
}
handler
.
post
{
callback
.
stateChanged
(
BaseService
.
State
.
values
()[
state
]
,
profileName
,
msg
)
}
}
override
fun
trafficUpdated
(
profileId
:
Long
,
stats
:
TrafficStats
)
{
val
callback
=
callback
?:
return
...
...
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
View file @
dca0da09
...
...
@@ -53,20 +53,22 @@ import java.util.*
* This object uses WeakMap to simulate the effects of multi-inheritance.
*/
object
BaseService
{
/**
* IDLE state is only used by UI and will never be returned by BaseService.
*/
const
val
IDLE
=
0
const
val
CONNECTING
=
1
const
val
CONNECTED
=
2
const
val
STOPPING
=
3
const
val
STOPPED
=
4
enum
class
State
(
val
canStop
:
Boolean
=
false
)
{
/**
* Idle state is only used by UI and will never be returned by BaseService.
*/
Idle
,
Connecting
(
true
),
Connected
(
true
),
Stopping
,
Stopped
,
}
const
val
CONFIG_FILE
=
"shadowsocks.conf"
const
val
CONFIG_FILE_UDP
=
"shadowsocks-udp.conf"
class
Data
internal
constructor
(
private
val
service
:
Interface
)
{
var
state
=
S
TOPPED
var
state
=
S
tate
.
Stopped
var
processes
:
GuardedProcessPool
?
=
null
var
proxy
:
ProxyInstance
?
=
null
var
udpFallback
:
ProxyInstance
?
=
null
...
...
@@ -83,7 +85,7 @@ object BaseService {
val
binder
=
Binder
(
this
)
var
connectingJob
:
Job
?
=
null
fun
changeState
(
s
:
Int
,
msg
:
String
?
=
null
)
{
fun
changeState
(
s
:
State
,
msg
:
String
?
=
null
)
{
if
(
state
==
s
&&
msg
==
null
)
return
binder
.
stateChanged
(
s
,
msg
)
state
=
s
...
...
@@ -104,7 +106,7 @@ object BaseService {
private
val
bandwidthListeners
=
mutableMapOf
<
IBinder
,
Long
>()
// the binder is the real identifier
private
val
handler
=
Handler
()
override
fun
getState
():
Int
=
data
!!
.
state
override
fun
getState
():
Int
=
data
!!
.
state
.
ordinal
override
fun
getProfileName
():
String
=
data
!!
.
proxy
?.
profile
?.
name
?:
"Idle"
override
fun
registerCallback
(
cb
:
IShadowsocksServiceCallback
)
{
...
...
@@ -126,12 +128,12 @@ object BaseService {
handler
.
postDelayed
(
this
::
onTimeout
,
bandwidthListeners
.
values
.
min
()
?:
return
)
}
private
fun
onTimeout
()
{
val
proxies
=
listOfNotNull
(
data
!!
.
proxy
,
data
!!
.
udpFallback
)
val
proxies
=
listOfNotNull
(
data
?.
proxy
,
data
?
.
udpFallback
)
val
stats
=
proxies
.
map
{
Pair
(
it
.
profile
.
id
,
it
.
trafficMonitor
?.
requestUpdate
())
}
.
filter
{
it
.
second
!=
null
}
.
map
{
Triple
(
it
.
first
,
it
.
second
!!
.
first
,
it
.
second
!!
.
second
)
}
if
(
stats
.
any
{
it
.
third
}
&&
state
==
CONNECTED
&&
bandwidthListeners
.
isNotEmpty
())
{
if
(
stats
.
any
{
it
.
third
}
&&
data
!!
.
state
==
State
.
Connected
&&
bandwidthListeners
.
isNotEmpty
())
{
val
sum
=
stats
.
fold
(
TrafficStats
())
{
a
,
b
->
a
+
b
.
second
}
broadcast
{
item
->
if
(
bandwidthListeners
.
contains
(
item
.
asBinder
()))
{
...
...
@@ -147,7 +149,7 @@ object BaseService {
val
wasEmpty
=
bandwidthListeners
.
isEmpty
()
if
(
bandwidthListeners
.
put
(
cb
.
asBinder
(),
timeout
)
==
null
)
{
if
(
wasEmpty
)
registerTimeout
()
if
(
state
!=
CONNECTED
)
return
if
(
data
!!
.
state
!=
State
.
Connected
)
return
var
sum
=
TrafficStats
()
val
proxy
=
data
!!
.
proxy
?:
return
proxy
.
trafficMonitor
?.
out
.
also
{
stats
->
...
...
@@ -179,9 +181,9 @@ object BaseService {
callbacks
.
unregister
(
cb
)
}
fun
stateChanged
(
s
:
Int
,
msg
:
String
?)
{
fun
stateChanged
(
s
:
State
,
msg
:
String
?)
{
val
profileName
=
profileName
broadcast
{
it
.
stateChanged
(
s
,
profileName
,
msg
)
}
broadcast
{
it
.
stateChanged
(
s
.
ordinal
,
profileName
,
msg
)
}
}
fun
trafficPersisted
(
ids
:
List
<
Long
>)
{
...
...
@@ -213,9 +215,9 @@ object BaseService {
return
}
val
s
=
data
.
state
when
(
s
)
{
STOPPED
->
startRunner
()
CONNECTED
->
stopRunner
(
true
)
when
{
s
==
State
.
Stopped
->
startRunner
()
s
.
canStop
->
stopRunner
(
true
)
else
->
Crashlytics
.
log
(
Log
.
WARN
,
tag
,
"Illegal state when invoking use: $s"
)
}
}
...
...
@@ -251,11 +253,12 @@ object BaseService {
}
fun
stopRunner
(
restart
:
Boolean
=
false
,
msg
:
String
?
=
null
)
{
if
(
data
.
state
==
S
TOPPING
)
return
if
(
data
.
state
==
S
tate
.
Stopping
)
return
// channge the state
data
.
changeState
(
S
TOPPING
)
data
.
changeState
(
S
tate
.
Stopping
)
GlobalScope
.
launch
(
Dispatchers
.
Main
,
CoroutineStart
.
UNDISPATCHED
)
{
Core
.
analytics
.
logEvent
(
"stop"
,
bundleOf
(
Pair
(
FirebaseAnalytics
.
Param
.
METHOD
,
tag
)))
data
.
connectingJob
?.
cancelAndJoin
()
// ensure stop connecting first
this
@Interface
as
Service
// we use a coroutineScope here to allow clean-up in parallel
coroutineScope
{
...
...
@@ -280,7 +283,7 @@ object BaseService {
}
// change the state
data
.
changeState
(
S
TOPPED
,
msg
)
data
.
changeState
(
S
tate
.
Stopped
,
msg
)
// stop the service if nothing has bound to it
if
(
restart
)
startRunner
()
else
stopSelf
()
...
...
@@ -293,7 +296,7 @@ object BaseService {
fun
onStartCommand
(
intent
:
Intent
?,
flags
:
Int
,
startId
:
Int
):
Int
{
val
data
=
data
if
(
data
.
state
!=
S
TOPPED
)
return
Service
.
START_NOT_STICKY
if
(
data
.
state
!=
S
tate
.
Stopped
)
return
Service
.
START_NOT_STICKY
val
profilePair
=
Core
.
currentProfile
this
as
Context
if
(
profilePair
==
null
)
{
...
...
@@ -320,7 +323,7 @@ object BaseService {
data
.
notification
=
createNotification
(
profile
.
formattedName
)
Core
.
analytics
.
logEvent
(
"start"
,
bundleOf
(
Pair
(
FirebaseAnalytics
.
Param
.
METHOD
,
tag
)))
data
.
changeState
(
CONNECTING
)
data
.
changeState
(
State
.
Connecting
)
data
.
connectingJob
=
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
try
{
Executable
.
killAll
()
// clean up old processes
...
...
@@ -330,7 +333,6 @@ object BaseService {
data
.
processes
=
GuardedProcessPool
{
printLog
(
it
)
data
.
connectingJob
?.
cancelAndJoin
()
stopRunner
(
false
,
it
.
readableMessage
)
}
startProcesses
()
...
...
@@ -339,7 +341,7 @@ object BaseService {
data
.
udpFallback
?.
scheduleUpdate
()
RemoteConfig
.
fetch
()
data
.
changeState
(
CONNECTED
)
data
.
changeState
(
State
.
Connected
)
}
catch
(
_
:
CancellationException
)
{
// if the job was cancelled, it is canceller's responsibility to call stopRunner
}
catch
(
_
:
UnknownHostException
)
{
...
...
core/src/main/java/com/github/shadowsocks/bg/ServiceNotification.kt
View file @
dca0da09
...
...
@@ -94,7 +94,7 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam
}
private
fun
update
(
action
:
String
?,
forceShow
:
Boolean
=
false
)
{
if
(
forceShow
||
service
.
data
.
state
==
BaseService
.
CONNECTED
)
when
(
action
)
{
if
(
forceShow
||
service
.
data
.
state
==
BaseService
.
State
.
Connected
)
when
(
action
)
{
Intent
.
ACTION_SCREEN_OFF
->
{
setVisible
(
false
,
forceShow
)
unregisterCallback
()
// unregister callback to save battery
...
...
mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
View file @
dca0da09
...
...
@@ -83,8 +83,8 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
portTransproxy
.
isEnabled
=
enabledTransproxy
true
}
val
listener
:
(
Int
)
->
Unit
=
{
if
(
it
==
BaseService
.
S
TOPPED
)
{
val
listener
:
(
BaseService
.
State
)
->
Unit
=
{
if
(
it
==
BaseService
.
S
tate
.
Stopped
)
{
tfo
.
isEnabled
=
true
serviceMode
.
isEnabled
=
true
portProxy
.
isEnabled
=
true
...
...
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
View file @
dca0da09
...
...
@@ -70,7 +70,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
private
const
val
TAG
=
"ShadowsocksMainActivity"
private
const
val
REQUEST_CONNECT
=
1
var
stateListener
:
((
Int
)
->
Unit
)?
=
null
var
stateListener
:
((
BaseService
.
State
)
->
Unit
)?
=
null
}
@Parcelize
...
...
@@ -107,12 +107,12 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
}
// service
var
state
=
BaseService
.
IDLE
override
fun
stateChanged
(
state
:
Int
,
profileName
:
String
?,
msg
:
String
?)
=
changeState
(
state
,
msg
,
true
)
var
state
=
BaseService
.
State
.
Idle
override
fun
stateChanged
(
state
:
BaseService
.
State
,
profileName
:
String
?,
msg
:
String
?)
=
changeState
(
state
,
msg
,
true
)
override
fun
trafficUpdated
(
profileId
:
Long
,
stats
:
TrafficStats
)
{
if
(
profileId
==
0L
)
this
@MainActivity
.
stats
.
updateTraffic
(
stats
.
txRate
,
stats
.
rxRate
,
stats
.
txTotal
,
stats
.
rxTotal
)
if
(
state
!=
BaseService
.
S
TOPPING
)
{
if
(
state
!=
BaseService
.
S
tate
.
Stopping
)
{
(
supportFragmentManager
.
findFragmentById
(
R
.
id
.
fragment_holder
)
as
?
ToolbarFragment
)
?.
onTrafficUpdated
(
profileId
,
stats
)
}
...
...
@@ -121,7 +121,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
ProfilesFragment
.
instance
?.
onTrafficPersisted
(
profileId
)
}
private
fun
changeState
(
state
:
Int
,
msg
:
String
?
=
null
,
animate
:
Boolean
=
false
)
{
private
fun
changeState
(
state
:
BaseService
.
State
,
msg
:
String
?
=
null
,
animate
:
Boolean
=
false
)
{
fab
.
changeState
(
state
,
animate
)
stats
.
changeState
(
state
)
if
(
msg
!=
null
)
snackbar
(
getString
(
R
.
string
.
vpn_error
,
msg
)).
show
()
...
...
@@ -131,7 +131,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
}
private
fun
toggle
()
=
when
{
state
==
BaseService
.
CONNECTED
->
Core
.
stopService
()
state
.
canStop
->
Core
.
stopService
()
DataStore
.
serviceMode
==
Key
.
modeVpn
->
{
val
intent
=
VpnService
.
prepare
(
this
)
if
(
intent
!=
null
)
startActivityForResult
(
intent
,
REQUEST_CONNECT
)
...
...
@@ -143,11 +143,11 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
private
val
handler
=
Handler
()
private
val
connection
=
ShadowsocksConnection
(
handler
,
true
)
override
fun
onServiceConnected
(
service
:
IShadowsocksService
)
=
changeState
(
try
{
service
.
state
BaseService
.
State
.
values
()[
service
.
state
]
}
catch
(
_
:
DeadObjectException
)
{
BaseService
.
IDLE
BaseService
.
State
.
Idle
})
override
fun
onServiceDisconnected
()
=
changeState
(
BaseService
.
IDLE
)
override
fun
onServiceDisconnected
()
=
changeState
(
BaseService
.
State
.
Idle
)
override
fun
onBinderDied
()
{
connection
.
disconnect
(
this
)
connection
.
connect
(
this
,
this
)
...
...
@@ -168,7 +168,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
layout_main
)
stats
=
findViewById
(
R
.
id
.
stats
)
stats
.
setOnClickListener
{
if
(
state
==
BaseService
.
CONNECTED
)
stats
.
testConnection
()
}
stats
.
setOnClickListener
{
if
(
state
==
BaseService
.
State
.
Connected
)
stats
.
testConnection
()
}
drawer
=
findViewById
(
R
.
id
.
drawer
)
navigation
=
findViewById
(
R
.
id
.
navigation
)
navigation
.
setNavigationItemSelectedListener
(
this
)
...
...
@@ -180,7 +180,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
fab
=
findViewById
(
R
.
id
.
fab
)
fab
.
setOnClickListener
{
toggle
()
}
changeState
(
BaseService
.
IDLE
)
// reset everything to init state
changeState
(
BaseService
.
State
.
Idle
)
// reset everything to init state
connection
.
connect
(
this
,
this
)
DataStore
.
publicStore
.
registerChangeListener
(
this
)
...
...
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
View file @
dca0da09
...
...
@@ -72,15 +72,9 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
/**
* Is ProfilesFragment editable at all.
*/
private
val
isEnabled
get
()
=
when
((
activity
as
MainActivity
).
state
)
{
BaseService
.
CONNECTED
,
BaseService
.
STOPPED
->
true
else
->
false
}
private
fun
isProfileEditable
(
id
:
Long
)
=
when
((
activity
as
MainActivity
).
state
)
{
BaseService
.
CONNECTED
->
id
!
in
Core
.
activeProfileIds
BaseService
.
STOPPED
->
true
else
->
false
}
private
val
isEnabled
get
()
=
(
activity
as
MainActivity
).
state
.
let
{
it
.
canStop
||
it
==
BaseService
.
State
.
Stopped
}
private
fun
isProfileEditable
(
id
:
Long
)
=
(
activity
as
MainActivity
).
state
==
BaseService
.
State
.
Stopped
||
id
!
in
Core
.
activeProfileIds
@SuppressLint
(
"ValidFragment"
)
class
QRCodeDialog
()
:
DialogFragment
()
{
...
...
@@ -203,7 +197,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
Core
.
switchProfile
(
item
.
id
)
profilesAdapter
.
refreshId
(
old
)
itemView
.
isSelected
=
true
if
(
activity
.
state
==
BaseService
.
CONNECTED
)
Core
.
reloadService
()
if
(
activity
.
state
.
canStop
)
Core
.
reloadService
()
}
}
...
...
mobile/src/main/java/com/github/shadowsocks/QuickToggleShortcut.kt
View file @
dca0da09
...
...
@@ -55,14 +55,15 @@ class QuickToggleShortcut : Activity(), ShadowsocksConnection.Callback {
}
override
fun
onServiceConnected
(
service
:
IShadowsocksService
)
{
when
(
service
.
state
)
{
BaseService
.
STOPPED
->
Core
.
startService
()
BaseService
.
CONNECTED
->
Core
.
stopService
()
val
state
=
BaseService
.
State
.
values
()[
service
.
state
]
when
{
state
.
canStop
->
Core
.
stopService
()
state
==
BaseService
.
State
.
Stopped
->
Core
.
startService
()
}
finish
()
}
override
fun
stateChanged
(
state
:
Int
,
profileName
:
String
?,
msg
:
String
?)
{
}
override
fun
stateChanged
(
state
:
BaseService
.
State
,
profileName
:
String
?,
msg
:
String
?)
{
}
override
fun
onDestroy
()
{
connection
.
disconnect
(
this
)
...
...
mobile/src/main/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
View file @
dca0da09
...
...
@@ -346,11 +346,8 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
}
}
private
val
isEnabled
get
()
=
when
((
activity
as
MainActivity
).
state
)
{
BaseService
.
CONNECTED
->
Core
.
currentProfile
?.
first
?.
route
!=
Acl
.
CUSTOM_RULES
BaseService
.
STOPPED
->
true
else
->
false
}
private
val
isEnabled
get
()
=
(
activity
as
MainActivity
).
state
==
BaseService
.
State
.
Stopped
||
Core
.
currentProfile
?.
first
?.
route
!=
Acl
.
CUSTOM_RULES
private
val
selectedItems
=
HashSet
<
Any
>()
private
val
adapter
by
lazy
{
AclRulesAdapter
()
}
...
...
mobile/src/main/java/com/github/shadowsocks/bg/TileService.kt
View file @
dca0da09
...
...
@@ -41,9 +41,9 @@ class TileService : BaseTileService(), ShadowsocksConnection.Callback {
private
var
tapPending
=
false
private
val
connection
=
ShadowsocksConnection
()
override
fun
stateChanged
(
state
:
Int
,
profileName
:
String
?,
msg
:
String
?)
=
updateTile
(
state
)
{
profileName
}
override
fun
stateChanged
(
state
:
BaseService
.
State
,
profileName
:
String
?,
msg
:
String
?)
=
updateTile
(
state
)
{
profileName
}
override
fun
onServiceConnected
(
service
:
IShadowsocksService
)
{
updateTile
(
service
.
state
)
{
service
.
profileName
}
updateTile
(
BaseService
.
State
.
values
()[
service
.
state
]
)
{
service
.
profileName
}
if
(
tapPending
)
{
tapPending
=
false
onClick
()
...
...
@@ -63,23 +63,28 @@ class TileService : BaseTileService(), ShadowsocksConnection.Callback {
if
(
isLocked
&&
!
DataStore
.
canToggleLocked
)
unlockAndRun
(
this
::
toggle
)
else
toggle
()
}
private
fun
updateTile
(
serviceState
:
Int
,
profileName
:
()
->
String
?)
{
private
fun
updateTile
(
serviceState
:
BaseService
.
State
,
profileName
:
()
->
String
?)
{
qsTile
?.
apply
{
label
=
null
when
(
serviceState
)
{
BaseService
.
STOPPED
->
{
icon
=
iconIdle
state
=
Tile
.
STATE_INACTIVE
BaseService
.
State
.
Idle
->
throw
IllegalStateException
(
"serviceState"
)
BaseService
.
State
.
Connecting
->
{
icon
=
iconBusy
state
=
Tile
.
STATE_ACTIVE
}
BaseService
.
CONNECTED
->
{
BaseService
.
State
.
Connected
->
{
icon
=
iconConnected
if
(!
keyguard
.
isDeviceLocked
)
label
=
profileName
()
state
=
Tile
.
STATE_ACTIVE
}
else
->
{
BaseService
.
State
.
Stopping
->
{
icon
=
iconBusy
state
=
Tile
.
STATE_UNAVAILABLE
}
BaseService
.
State
.
Stopped
->
{
icon
=
iconIdle
state
=
Tile
.
STATE_INACTIVE
}
}
label
=
label
?:
getString
(
R
.
string
.
app_name
)
updateTile
()
...
...
@@ -88,9 +93,11 @@ class TileService : BaseTileService(), ShadowsocksConnection.Callback {
private
fun
toggle
()
{
val
service
=
connection
.
service
if
(
service
==
null
)
tapPending
=
true
else
when
(
service
.
state
)
{
BaseService
.
STOPPED
->
Core
.
startService
()
BaseService
.
CONNECTED
->
Core
.
stopService
()
if
(
service
==
null
)
tapPending
=
true
else
BaseService
.
State
.
values
()[
service
.
state
].
let
{
state
->
when
{
state
.
canStop
->
Core
.
stopService
()
state
==
BaseService
.
State
.
Stopped
->
Core
.
startService
()
}
}
}
}
mobile/src/main/java/com/github/shadowsocks/widget/ServiceButton.kt
View file @
dca0da09
...
...
@@ -68,14 +68,14 @@ class ServiceButton @JvmOverloads constructor(context: Context, attrs: Attribute
return
drawableState
}
fun
changeState
(
state
:
Int
,
animate
:
Boolean
)
{
fun
changeState
(
state
:
BaseService
.
State
,
animate
:
Boolean
)
{
when
(
state
)
{
BaseService
.
CONNECTING
->
changeState
(
iconConnecting
,
animate
)
BaseService
.
CONNECTED
->
changeState
(
iconConnected
,
animate
)
BaseService
.
S
TOPPING
->
changeState
(
iconStopping
,
animate
)
BaseService
.
State
.
Connecting
->
changeState
(
iconConnecting
,
animate
)
BaseService
.
State
.
Connected
->
changeState
(
iconConnected
,
animate
)
BaseService
.
S
tate
.
Stopping
->
changeState
(
iconStopping
,
animate
)
else
->
changeState
(
iconStopped
,
animate
)
}
if
(
state
==
BaseService
.
CONNECTED
)
{
if
(
state
==
BaseService
.
State
.
Connected
)
{
checked
=
true
TooltipCompat
.
setTooltipText
(
this
,
context
.
getString
(
R
.
string
.
stop
))
}
else
{
...
...
@@ -83,7 +83,7 @@ class ServiceButton @JvmOverloads constructor(context: Context, attrs: Attribute
TooltipCompat
.
setTooltipText
(
this
,
context
.
getString
(
R
.
string
.
connect
))
}
refreshDrawableState
()
isEnabled
=
state
==
BaseService
.
CONNECTED
||
state
==
BaseService
.
STOPPED
isEnabled
=
state
.
canStop
||
state
==
BaseService
.
State
.
Stopped
}
private
fun
counters
(
a
:
AnimatedVectorDrawableCompat
,
b
:
AnimatedVectorDrawableCompat
):
Boolean
=
...
...
mobile/src/main/java/com/github/shadowsocks/widget/StatsBar.kt
View file @
dca0da09
...
...
@@ -65,15 +65,15 @@ class StatsBar @JvmOverloads constructor(context: Context, attrs: AttributeSet?
super
.
setOnClickListener
(
l
)
}
fun
changeState
(
state
:
Int
)
{
fun
changeState
(
state
:
BaseService
.
State
)
{
val
activity
=
context
as
MainActivity
if
(
state
!=
BaseService
.
CONNECTED
)
{
if
(
state
!=
BaseService
.
State
.
Connected
)
{
updateTraffic
(
0
,
0
,
0
,
0
)
tester
.
status
.
removeObservers
(
activity
)
if
(
state
!=
BaseService
.
IDLE
)
tester
.
invalidate
()
if
(
state
!=
BaseService
.
State
.
Idle
)
tester
.
invalidate
()
statusText
.
setText
(
when
(
state
)
{
BaseService
.
CONNECTING
->
R
.
string
.
connecting
BaseService
.
S
TOPPING
->
R
.
string
.
stopping
BaseService
.
State
.
Connecting
->
R
.
string
.
connecting
BaseService
.
S
tate
.
Stopping
->
R
.
string
.
stopping
else
->
R
.
string
.
not_connected
})
}
else
{
...
...
tv/src/main/java/com/github/shadowsocks/tv/MainFragment.kt
View file @
dca0da09
...
...
@@ -42,7 +42,7 @@ class MainFragment : LeanbackSettingsFragmentCompat() {
override
fun
onPreferenceDisplayDialog
(
caller
:
PreferenceFragmentCompat
,
pref
:
Preference
?):
Boolean
{
if
(
pref
?.
key
==
Key
.
id
)
{
if
((
childFragmentManager
.
findFragmentById
(
R
.
id
.
settings_preference_fragment_container
)
as
MainPreferenceFragment
).
state
==
BaseService
.
S
TOPPED
)
{
as
MainPreferenceFragment
).
state
==
BaseService
.
S
tate
.
Stopped
)
{
startPreferenceFragment
(
ProfilesDialogFragment
().
apply
{
arguments
=
bundleOf
(
Pair
(
LeanbackPreferenceDialogFragmentCompat
.
ARG_KEY
,
Key
.
id
))
setTargetFragment
(
caller
,
0
)
...
...
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
View file @
dca0da09
...
...
@@ -88,9 +88,9 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
private
lateinit
var
tester
:
HttpsTest
// service
var
state
=
BaseService
.
IDLE
var
state
=
BaseService
.
State
.
Idle
private
set
override
fun
stateChanged
(
state
:
Int
,
profileName
:
String
?,
msg
:
String
?)
=
changeState
(
state
,
msg
)
override
fun
stateChanged
(
state
:
BaseService
.
State
,
profileName
:
String
?,
msg
:
String
?)
=
changeState
(
state
,
msg
)
override
fun
trafficUpdated
(
profileId
:
Long
,
stats
:
TrafficStats
)
{
if
(
profileId
==
0L
)
requireContext
().
let
{
context
->
this
.
stats
.
summary
=
getString
(
R
.
string
.
stat_summary
,
...
...
@@ -101,26 +101,26 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
}
}
private
fun
changeState
(
state
:
Int
,
msg
:
String
?
=
null
)
{
fab
.
isEnabled
=
state
==
BaseService
.
STOPPED
||
state
==
BaseService
.
CONNECTED
private
fun
changeState
(
state
:
BaseService
.
State
,
msg
:
String
?
=
null
)
{
fab
.
isEnabled
=
state
.
canStop
||
state
==
BaseService
.
State
.
Stopped
fab
.
setTitle
(
when
(
state
)
{
BaseService
.
CONNECTING
->
R
.
string
.
connecting
BaseService
.
CONNECTED
->
R
.
string
.
stop
BaseService
.
S
TOPPING
->
R
.
string
.
stopping
BaseService
.
State
.
Connecting
->
R
.
string
.
connecting
BaseService
.
State
.
Connected
->
R
.
string
.
stop
BaseService
.
S
tate
.
Stopping
->
R
.
string
.
stopping
else
->
R
.
string
.
connect
})
stats
.
setTitle
(
R
.
string
.
connection_test_pending
)
stats
.
isVisible
=
state
==
BaseService
.
CONNECTED
if
(
state
!=
BaseService
.
CONNECTED
)
{
stats
.
isVisible
=
state
==
BaseService
.
State
.
Connected
if
(
state
!=
BaseService
.
State
.
Connected
)
{
trafficUpdated
(
0
,
TrafficStats
())
tester
.
status
.
removeObservers
(
this
)
if
(
state
!=
BaseService
.
IDLE
)
tester
.
invalidate
()
if
(
state
!=
BaseService
.
State
.
Idle
)
tester
.
invalidate
()
}
else
tester
.
status
.
observe
(
this
,
Observer
{
it
.
retrieve
(
stats
::
setTitle
)
{
Toast
.
makeText
(
requireContext
(),
it
,
Toast
.
LENGTH_LONG
).
show
()
}
})
if
(
msg
!=
null
)
Toast
.
makeText
(
requireContext
(),
getString
(
R
.
string
.
vpn_error
,
msg
),
Toast
.
LENGTH_SHORT
).
show
()
this
.
state
=
state
if
(
state
==
BaseService
.
S
TOPPED
)
{
if
(
state
==
BaseService
.
S
tate
.
Stopped
)
{
controlImport
.
isEnabled
=
true
tfo
.
isEnabled
=
true
serviceMode
.
isEnabled
=
true
...
...
@@ -141,11 +141,11 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
private
val
handler
=
Handler
()
private
val
connection
=
ShadowsocksConnection
(
handler
,
true
)
override
fun
onServiceConnected
(
service
:
IShadowsocksService
)
=
changeState
(
try
{
service
.
state
BaseService
.
State
.
values
()[
service
.
state
]
}
catch
(
_
:
DeadObjectException
)
{
BaseService
.
IDLE
BaseService
.
State
.
Idle
})
override
fun
onServiceDisconnected
()
=
changeState
(
BaseService
.
IDLE
)
override
fun
onServiceDisconnected
()
=
changeState
(
BaseService
.
State
.
Idle
)
override
fun
onBinderDied
()
{
connection
.
disconnect
(
requireContext
())
connection
.
connect
(
requireContext
(),
this
)
...
...
@@ -200,7 +200,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
}
tester
=
ViewModelProviders
.
of
(
this
).
get
()
changeState
(
BaseService
.
IDLE
)
// reset everything to init state
changeState
(
BaseService
.
State
.
Idle
)
// reset everything to init state
connection
.
connect
(
requireContext
(),
this
)
DataStore
.
publicStore
.
registerChangeListener
(
this
)
}
...
...
@@ -225,7 +225,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
fun
startService
()
{
when
{
state
!=
BaseService
.
S
TOPPED
->
return
state
!=
BaseService
.
S
tate
.
Stopped
->
return
DataStore
.
serviceMode
==
Key
.
modeVpn
->
{
val
intent
=
VpnService
.
prepare
(
requireContext
())
if
(
intent
!=
null
)
startActivityForResult
(
intent
,
REQUEST_CONNECT
)
...
...
@@ -251,7 +251,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
override
fun
onPreferenceTreeClick
(
preference
:
Preference
?)
=
when
(
preference
?.
key
)
{
Key
.
id
->
{
if
(
state
==
BaseService
.
CONNECTED
)
Core
.
stopService
()
if
(
state
==
BaseService
.
State
.
Connected
)
Core
.
stopService
()
true
}
Key
.
controlStats
->
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment