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
a5df60ae
Commit
a5df60ae
authored
Dec 09, 2016
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refine code style
parent
c9b404fa
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
301 additions
and
335 deletions
+301
-335
src/main/scala/be/mygod/preference/EditTextPreference.scala
src/main/scala/be/mygod/preference/EditTextPreference.scala
+3
-3
src/main/scala/be/mygod/preference/EditTextPreferenceDialogFragment.scala
...e/mygod/preference/EditTextPreferenceDialogFragment.scala
+3
-2
src/main/scala/be/mygod/preference/NumberPickerPreference.scala
...in/scala/be/mygod/preference/NumberPickerPreference.scala
+7
-7
src/main/scala/be/mygod/preference/NumberPickerPreferenceDialogFragment.scala
...god/preference/NumberPickerPreferenceDialogFragment.scala
+3
-2
src/main/scala/be/mygod/preference/PreferenceFragment.scala
src/main/scala/be/mygod/preference/PreferenceFragment.scala
+5
-5
src/main/scala/be/mygod/preference/PreferenceGroupAdapter.scala
...in/scala/be/mygod/preference/PreferenceGroupAdapter.scala
+27
-25
src/main/scala/be/mygod/preference/SummaryPreference.scala
src/main/scala/be/mygod/preference/SummaryPreference.scala
+1
-1
src/main/scala/com/github/shadowsocks/AppManager.scala
src/main/scala/com/github/shadowsocks/AppManager.scala
+8
-8
src/main/scala/com/github/shadowsocks/BaseService.scala
src/main/scala/com/github/shadowsocks/BaseService.scala
+23
-22
src/main/scala/com/github/shadowsocks/BootReceiver.scala
src/main/scala/com/github/shadowsocks/BootReceiver.scala
+3
-3
src/main/scala/com/github/shadowsocks/GuardedProcess.scala
src/main/scala/com/github/shadowsocks/GuardedProcess.scala
+14
-25
src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala
...scala/com/github/shadowsocks/ProfileManagerActivity.scala
+35
-36
src/main/scala/com/github/shadowsocks/ScannerActivity.scala
src/main/scala/com/github/shadowsocks/ScannerActivity.scala
+3
-4
src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala
...in/scala/com/github/shadowsocks/ServiceBoundContext.scala
+10
-10
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
+12
-12
src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala
...scala/com/github/shadowsocks/ShadowsocksApplication.scala
+18
-15
src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
.../scala/com/github/shadowsocks/ShadowsocksNatService.scala
+9
-12
src/main/scala/com/github/shadowsocks/ShadowsocksNotification.scala
...cala/com/github/shadowsocks/ShadowsocksNotification.scala
+9
-9
src/main/scala/com/github/shadowsocks/ShadowsocksQuickSwitchActivity.scala
...m/github/shadowsocks/ShadowsocksQuickSwitchActivity.scala
+5
-5
src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala
...la/com/github/shadowsocks/ShadowsocksRunnerActivity.scala
+2
-3
src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala
...ala/com/github/shadowsocks/ShadowsocksRunnerService.scala
+2
-3
src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
...in/scala/com/github/shadowsocks/ShadowsocksSettings.scala
+9
-9
src/main/scala/com/github/shadowsocks/ShadowsocksTileService.scala
...scala/com/github/shadowsocks/ShadowsocksTileService.scala
+9
-9
src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
.../scala/com/github/shadowsocks/ShadowsocksVpnService.scala
+7
-10
src/main/scala/com/github/shadowsocks/ShadowsocksVpnThread.scala
...n/scala/com/github/shadowsocks/ShadowsocksVpnThread.scala
+3
-2
src/main/scala/com/github/shadowsocks/TaskerActivity.scala
src/main/scala/com/github/shadowsocks/TaskerActivity.scala
+7
-7
src/main/scala/com/github/shadowsocks/TaskerReceiver.scala
src/main/scala/com/github/shadowsocks/TaskerReceiver.scala
+3
-5
src/main/scala/com/github/shadowsocks/database/DBHelper.scala
...main/scala/com/github/shadowsocks/database/DBHelper.scala
+2
-2
src/main/scala/com/github/shadowsocks/database/Profile.scala
src/main/scala/com/github/shadowsocks/database/Profile.scala
+2
-2
src/main/scala/com/github/shadowsocks/database/ProfileManager.scala
...cala/com/github/shadowsocks/database/ProfileManager.scala
+2
-2
src/main/scala/com/github/shadowsocks/job/AclSyncJob.scala
src/main/scala/com/github/shadowsocks/job/AclSyncJob.scala
+1
-1
src/main/scala/com/github/shadowsocks/job/DonaldTrump.scala
src/main/scala/com/github/shadowsocks/job/DonaldTrump.scala
+1
-1
src/main/scala/com/github/shadowsocks/utils/CloseUtils.scala
src/main/scala/com/github/shadowsocks/utils/CloseUtils.scala
+4
-4
src/main/scala/com/github/shadowsocks/utils/IOUtils.scala
src/main/scala/com/github/shadowsocks/utils/IOUtils.scala
+2
-1
src/main/scala/com/github/shadowsocks/utils/Parser.scala
src/main/scala/com/github/shadowsocks/utils/Parser.scala
+19
-19
src/main/scala/com/github/shadowsocks/utils/TaskerSettings.scala
...n/scala/com/github/shadowsocks/utils/TaskerSettings.scala
+3
-3
src/main/scala/com/github/shadowsocks/utils/TcpFastOpen.scala
...main/scala/com/github/shadowsocks/utils/TcpFastOpen.scala
+2
-2
src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala
...n/scala/com/github/shadowsocks/utils/TrafficMonitor.scala
+1
-1
src/main/scala/com/github/shadowsocks/utils/TrafficMonitorThread.scala
...a/com/github/shadowsocks/utils/TrafficMonitorThread.scala
+1
-1
src/main/scala/com/github/shadowsocks/utils/Utils.scala
src/main/scala/com/github/shadowsocks/utils/Utils.scala
+10
-32
src/main/scala/com/github/shadowsocks/widget/FloatingActionMenuBehavior.scala
...ithub/shadowsocks/widget/FloatingActionMenuBehavior.scala
+6
-5
src/main/scala/com/github/shadowsocks/widget/UndoSnackbarManager.scala
...a/com/github/shadowsocks/widget/UndoSnackbarManager.scala
+5
-5
No files found.
src/main/scala/be/mygod/preference/EditTextPreference.scala
View file @
a5df60ae
...
...
@@ -37,7 +37,7 @@ class EditTextPreference(context: Context, attrs: AttributeSet = null) extends P
override
def
createDialog
()
=
new
EditTextPreferenceDialogFragment
()
override
protected
def
getSummaryValue
=
{
override
protected
def
getSummaryValue
:
String
=
{
var
text
=
getText
if
(
text
==
null
)
text
=
""
val
inputType
=
editText
.
getInputType
...
...
@@ -47,8 +47,8 @@ class EditTextPreference(context: Context, attrs: AttributeSet = null) extends P
"\u2022"
*
text
.
length
else
text
}
override
def
setText
(
text
:
String
)
=
{
override
def
setText
(
text
:
String
)
:
Unit
=
{
super
.
setText
(
text
)
notifyChanged
notifyChanged
()
}
}
src/main/scala/be/mygod/preference/EditTextPreferenceDialogFragment.scala
View file @
a5df60ae
...
...
@@ -22,13 +22,14 @@ package be.mygod.preference
import
android.content.Context
import
android.support.v14.preference.PreferenceDialogFragment
import
android.support.v7.widget.AppCompatEditText
import
android.view.
{
View
,
ViewGroup
}
class
EditTextPreferenceDialogFragment
extends
PreferenceDialogFragment
{
private
lazy
val
preference
=
getPreference
.
asInstanceOf
[
EditTextPreference
]
private
lazy
val
editText
=
preference
.
editText
override
protected
def
onCreateDialogView
(
context
:
Context
)
=
{
override
protected
def
onCreateDialogView
(
context
:
Context
)
:
AppCompatEditText
=
{
val
parent
=
editText
.
getParent
.
asInstanceOf
[
ViewGroup
]
if
(
parent
!=
null
)
parent
.
removeView
(
editText
)
editText
...
...
@@ -43,7 +44,7 @@ class EditTextPreferenceDialogFragment extends PreferenceDialogFragment {
override
protected
def
needInputMethod
=
true
def
onDialogClosed
(
positiveResult
:
Boolean
)
=
if
(
positiveResult
)
{
def
onDialogClosed
(
positiveResult
:
Boolean
)
:
Unit
=
if
(
positiveResult
)
{
val
value
=
editText
.
getText
.
toString
if
(
preference
.
callChangeListener
(
value
))
preference
.
setText
(
value
)
}
...
...
src/main/scala/be/mygod/preference/NumberPickerPreference.scala
View file @
a5df60ae
...
...
@@ -37,23 +37,23 @@ class NumberPickerPreference(private val context: Context, attrs: AttributeSet =
val
a
:
TypedArray
=
context
.
obtainStyledAttributes
(
attrs
,
R
.
styleable
.
NumberPickerPreference
)
setMin
(
a
.
getInt
(
R
.
styleable
.
NumberPickerPreference_min
,
0
))
setMax
(
a
.
getInt
(
R
.
styleable
.
NumberPickerPreference_max
,
Int
.
MaxValue
-
1
))
a
.
recycle
a
.
recycle
()
}
override
def
createDialog
()
=
new
NumberPickerPreferenceDialogFragment
()
def
getValue
=
value
def
getMin
=
if
(
picker
==
null
)
0
else
picker
.
getMinValue
def
getMax
=
picker
.
getMaxValue
def
getValue
:
Int
=
value
def
getMin
:
Int
=
if
(
picker
==
null
)
0
else
picker
.
getMinValue
def
getMax
:
Int
=
picker
.
getMaxValue
def
setValue
(
i
:
Int
)
{
if
(
i
==
value
)
return
picker
.
setValue
(
i
)
value
=
picker
.
getValue
persistInt
(
value
)
notifyChanged
notifyChanged
()
}
def
setMin
(
value
:
Int
)
=
picker
.
setMinValue
(
value
)
def
setMax
(
value
:
Int
)
=
picker
.
setMaxValue
(
value
)
def
setMin
(
value
:
Int
)
:
Unit
=
picker
.
setMinValue
(
value
)
def
setMax
(
value
:
Int
)
:
Unit
=
picker
.
setMaxValue
(
value
)
override
protected
def
onGetDefaultValue
(
a
:
TypedArray
,
index
:
Int
)
:
AnyRef
=
a
.
getInt
(
index
,
getMin
).
asInstanceOf
[
AnyRef
]
...
...
src/main/scala/be/mygod/preference/NumberPickerPreferenceDialogFragment.scala
View file @
a5df60ae
...
...
@@ -23,12 +23,13 @@ package be.mygod.preference
import
android.content.Context
import
android.support.v14.preference.PreferenceDialogFragment
import
android.view.
{
View
,
ViewGroup
}
import
android.widget.NumberPicker
class
NumberPickerPreferenceDialogFragment
extends
PreferenceDialogFragment
{
private
lazy
val
preference
=
getPreference
.
asInstanceOf
[
NumberPickerPreference
]
private
lazy
val
picker
=
preference
.
picker
override
protected
def
onCreateDialogView
(
context
:
Context
)
=
{
override
protected
def
onCreateDialogView
(
context
:
Context
)
:
NumberPicker
=
{
val
parent
=
picker
.
getParent
.
asInstanceOf
[
ViewGroup
]
if
(
parent
!=
null
)
parent
.
removeView
(
picker
)
picker
...
...
@@ -42,7 +43,7 @@ class NumberPickerPreferenceDialogFragment extends PreferenceDialogFragment {
override
protected
def
needInputMethod
=
true
def
onDialogClosed
(
positiveResult
:
Boolean
)
{
picker
.
clearFocus
// commit changes
picker
.
clearFocus
()
// commit changes
if
(
positiveResult
)
{
val
value
=
picker
.
getValue
if
(
preference
.
callChangeListener
(
value
))
preference
.
setValue
(
value
)
...
...
src/main/scala/be/mygod/preference/PreferenceFragment.scala
View file @
a5df60ae
...
...
@@ -24,10 +24,10 @@ import android.app.DialogFragment
import
android.os.Bundle
import
android.support.v14.preference.
{
PreferenceFragment
=>
Base
}
import
android.support.v7.preference.
{
Preference
,
PreferenceScreen
}
import
android.view.
{
LayoutInflater
,
ViewGroup
}
import
android.view.
{
LayoutInflater
,
View
,
View
Group
}
abstract
class
PreferenceFragment
extends
Base
{
override
def
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
,
savedInstanceState
:
Bundle
)
=
override
def
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
,
savedInstanceState
:
Bundle
)
:
View
=
super
.
onCreateView
(
inflater
,
container
,
savedInstanceState
)
protected
final
def
displayPreferenceDialog
(
key
:
String
,
fragment
:
DialogFragment
)
{
...
...
@@ -40,15 +40,15 @@ abstract class PreferenceFragment extends Base {
.
commitAllowingStateLoss
()
}
override
def
onDisplayPreferenceDialog
(
preference
:
Preference
)
=
preference
match
{
override
def
onDisplayPreferenceDialog
(
preference
:
Preference
)
:
Unit
=
preference
match
{
case
dpp
:
DialogPreferencePlus
=>
displayPreferenceDialog
(
preference
.
getKey
,
dpp
.
createDialog
())
case
_
=>
super
.
onDisplayPreferenceDialog
(
preference
)
}
override
protected
def
onCreateAdapter
(
screen
:
PreferenceScreen
)
=
new
PreferenceGroupAdapter
(
screen
)
override
def
onResume
{
super
.
onResume
override
def
onResume
()
{
super
.
onResume
()
getListView
.
scrollBy
(
0
,
0
)
}
}
src/main/scala/be/mygod/preference/PreferenceGroupAdapter.scala
View file @
a5df60ae
...
...
@@ -21,7 +21,7 @@
package
be.mygod.preference
import
java.lang.reflect.Field
import
java.util
.List
import
java.util
import
android.os.Build
import
android.support.v4.content.ContextCompat
...
...
@@ -57,29 +57,31 @@ object PreferenceGroupAdapter {
class
PreferenceGroupAdapter
(
group
:
PreferenceGroup
)
extends
Old
(
group
)
{
import
PreferenceGroupAdapter._
protected
lazy
val
preferenceLayouts
=
preferenceLayoutsField
.
get
(
this
).
asInstanceOf
[
List
[
AnyRef
]]
protected
lazy
val
preferenceLayouts
:
util.List
[
AnyRef
]
=
preferenceLayoutsField
.
get
(
this
).
asInstanceOf
[
util.List
[
AnyRef
]]
override
def
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
)
=
if
(
Build
.
VERSION
.
SDK_INT
<
21
)
{
val
context
=
parent
.
getContext
val
inflater
=
LayoutInflater
.
from
(
context
)
val
pl
=
preferenceLayouts
.
get
(
viewType
)
val
view
=
inflater
.
inflate
(
fieldResId
.
get
(
pl
).
asInstanceOf
[
Int
],
parent
,
false
)
if
(
view
.
getBackground
==
null
)
{
val
array
=
context
.
obtainStyledAttributes
(
null
,
R
.
styleable
.
BackgroundStyle
)
var
background
=
array
.
getDrawable
(
R
.
styleable
.
BackgroundStyle_android_selectableItemBackground
)
if
(
background
==
null
)
background
=
ContextCompat
.
getDrawable
(
context
,
android
.
R
.
drawable
.
list_selector_background
)
array
.
recycle
val
(
s
,
t
,
e
,
b
)
=
(
ViewCompat
.
getPaddingStart
(
view
),
view
.
getPaddingTop
,
ViewCompat
.
getPaddingEnd
(
view
),
view
.
getPaddingBottom
)
view
.
setBackground
(
background
)
ViewCompat
.
setPaddingRelative
(
view
,
s
,
t
,
e
,
b
)
}
val
widgetFrame
=
view
.
findViewById
(
android
.
R
.
id
.
widget_frame
).
asInstanceOf
[
ViewGroup
]
if
(
widgetFrame
!=
null
)
{
val
widgetResId
=
fieldWidgetResId
.
get
(
pl
).
asInstanceOf
[
Int
]
if
(
widgetResId
!=
0
)
inflater
.
inflate
(
widgetResId
,
widgetFrame
)
else
widgetFrame
.
setVisibility
(
View
.
GONE
)
}
preferenceViewHolderConstructor
.
newInstance
(
view
)
}
else
super
.
onCreateViewHolder
(
parent
,
viewType
)
override
def
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
)
:
PreferenceViewHolder
=
if
(
Build
.
VERSION
.
SDK_INT
<
21
)
{
val
context
=
parent
.
getContext
val
inflater
=
LayoutInflater
.
from
(
context
)
val
pl
=
preferenceLayouts
.
get
(
viewType
)
val
view
=
inflater
.
inflate
(
fieldResId
.
get
(
pl
).
asInstanceOf
[
Int
],
parent
,
false
)
if
(
view
.
getBackground
==
null
)
{
val
array
=
context
.
obtainStyledAttributes
(
null
,
R
.
styleable
.
BackgroundStyle
)
var
background
=
array
.
getDrawable
(
R
.
styleable
.
BackgroundStyle_android_selectableItemBackground
)
if
(
background
==
null
)
background
=
ContextCompat
.
getDrawable
(
context
,
android
.
R
.
drawable
.
list_selector_background
)
array
.
recycle
()
val
(
s
,
t
,
e
,
b
)
=
(
ViewCompat
.
getPaddingStart
(
view
),
view
.
getPaddingTop
,
ViewCompat
.
getPaddingEnd
(
view
),
view
.
getPaddingBottom
)
view
.
setBackground
(
background
)
ViewCompat
.
setPaddingRelative
(
view
,
s
,
t
,
e
,
b
)
}
val
widgetFrame
=
view
.
findViewById
(
android
.
R
.
id
.
widget_frame
).
asInstanceOf
[
ViewGroup
]
if
(
widgetFrame
!=
null
)
{
val
widgetResId
=
fieldWidgetResId
.
get
(
pl
).
asInstanceOf
[
Int
]
if
(
widgetResId
!=
0
)
inflater
.
inflate
(
widgetResId
,
widgetFrame
)
else
widgetFrame
.
setVisibility
(
View
.
GONE
)
}
preferenceViewHolderConstructor
.
newInstance
(
view
)
}
else
super
.
onCreateViewHolder
(
parent
,
viewType
)
}
src/main/scala/be/mygod/preference/SummaryPreference.scala
View file @
a5df60ae
...
...
@@ -38,7 +38,7 @@ trait SummaryPreference extends Preference {
*
* @return the summary with appropriate string substitution
*/
override
def
getSummary
=
{
override
def
getSummary
:
String
=
{
val
summary
=
super
.
getSummary
if
(
summary
==
null
)
null
else
String
.
format
(
summary
.
toString
,
getSummaryValue
)
}
...
...
src/main/scala/com/github/shadowsocks/AppManager.scala
View file @
a5df60ae
...
...
@@ -53,7 +53,7 @@ object AppManager {
val
filter
=
new
IntentFilter
(
Intent
.
ACTION_PACKAGE_ADDED
)
filter
.
addAction
(
Intent
.
ACTION_PACKAGE_REMOVED
)
filter
.
addDataScheme
(
"package"
)
app
.
registerReceiver
((
context
:
Context
,
intent
:
Intent
)
=>
app
.
registerReceiver
((
_
:
Context
,
intent
:
Intent
)
=>
if
(
intent
.
getAction
!=
Intent
.
ACTION_PACKAGE_REMOVED
||
!
intent
.
getBooleanExtra
(
Intent
.
EXTRA_REPLACING
,
false
))
{
synchronized
(
cachedApps
=
null
)
...
...
@@ -111,8 +111,8 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
if
(
aProxied
^
proxiedApps
.
contains
(
b
.
packageName
))
aProxied
else
a
.
name
.
compareToIgnoreCase
(
b
.
name
)
<
0
})
def
getItemCount
=
apps
.
length
def
onBindViewHolder
(
vh
:
AppViewHolder
,
i
:
Int
)
=
vh
.
bind
(
apps
(
i
))
def
getItemCount
:
Int
=
apps
.
length
def
onBindViewHolder
(
vh
:
AppViewHolder
,
i
:
Int
)
:
Unit
=
vh
.
bind
(
apps
(
i
))
def
onCreateViewHolder
(
vg
:
ViewGroup
,
i
:
Int
)
=
new
AppViewHolder
(
LayoutInflater
.
from
(
vg
.
getContext
).
inflate
(
R
.
layout
.
layout_apps_item
,
vg
,
false
))
}
...
...
@@ -148,8 +148,8 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
p
.
individual
=
proxiedAppString
app
.
profileManager
.
updateProfile
(
p
)
})
Toast
.
makeText
(
this
,
R
.
string
.
action_apply_all
,
Toast
.
LENGTH_SHORT
).
show
case
_
=>
Toast
.
makeText
(
this
,
R
.
string
.
action_export_err
,
Toast
.
LENGTH_SHORT
).
show
Toast
.
makeText
(
this
,
R
.
string
.
action_apply_all
,
Toast
.
LENGTH_SHORT
).
show
()
case
_
=>
Toast
.
makeText
(
this
,
R
.
string
.
action_export_err
,
Toast
.
LENGTH_SHORT
).
show
()
}
return
true
case
R
.
id
.
action_export
=>
...
...
@@ -180,7 +180,7 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
return
true
}
catch
{
case
_:
IllegalArgumentException
=>
Toast
.
makeText
(
this
,
R
.
string
.
action_import_err
,
Toast
.
LENGTH_SHORT
).
show
Toast
.
makeText
(
this
,
R
.
string
.
action_import_err
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
}
...
...
@@ -239,7 +239,7 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
loadAppsAsync
()
}
def
reloadApps
()
=
if
(!
appsLoading
.
compareAndSet
(
true
,
false
))
loadAppsAsync
()
def
reloadApps
()
:
Unit
=
if
(!
appsLoading
.
compareAndSet
(
true
,
false
))
loadAppsAsync
()
def
loadAppsAsync
()
{
if
(!
appsLoading
.
compareAndSet
(
false
,
true
))
return
Utils
.
ThrowableFuture
{
...
...
@@ -255,7 +255,7 @@ class AppManager extends AppCompatActivity with OnMenuItemClickListener {
}
}
override
def
onKeyUp
(
keyCode
:
Int
,
event
:
KeyEvent
)
=
keyCode
match
{
override
def
onKeyUp
(
keyCode
:
Int
,
event
:
KeyEvent
)
:
Boolean
=
keyCode
match
{
case
KeyEvent
.
KEYCODE_MENU
=>
if
(
toolbar
.
isOverflowMenuShowing
)
toolbar
.
hideOverflowMenu
else
toolbar
.
showOverflowMenu
case
_
=>
super
.
onKeyUp
(
keyCode
,
event
)
...
...
src/main/scala/com/github/shadowsocks/BaseService.scala
View file @
a5df60ae
...
...
@@ -52,19 +52,19 @@ trait BaseService extends Service {
var
callbacksCount
:
Int
=
_
lazy
val
handler
=
new
Handler
(
getMainLooper
)
lazy
val
restartHanlder
=
new
Handler
(
getMainLooper
)
lazy
val
protectPath
=
getApplicationInfo
.
dataDir
+
"/protect_path"
lazy
val
protectPath
:
String
=
getApplicationInfo
.
dataDir
+
"/protect_path"
private
val
closeReceiver
:
BroadcastReceiver
=
(
context
:
Context
,
intent
:
Intent
)
=>
{
private
val
closeReceiver
:
BroadcastReceiver
=
(
context
:
Context
,
_
:
Intent
)
=>
{
Toast
.
makeText
(
context
,
R
.
string
.
stopping
,
Toast
.
LENGTH_SHORT
).
show
()
stopRunner
(
true
)
stopRunner
(
stopService
=
true
)
}
var
closeReceiverRegistered
:
Boolean
=
_
var
kcptunProcess
:
GuardedProcess
=
_
private
val
networkReceiver
:
BroadcastReceiver
=
(
context
:
Context
,
intent
:
Intent
)
=>
{
private
val
networkReceiver
:
BroadcastReceiver
=
(
context
:
Context
,
_
:
Intent
)
=>
{
val
cm
=
context
.
getSystemService
(
Context
.
CONNECTIVITY_SERVICE
).
asInstanceOf
[
ConnectivityManager
]
val
activeNetwork
=
cm
.
getActiveNetworkInfo
()
val
isConnected
=
activeNetwork
!=
null
&&
activeNetwork
.
isConnected
()
val
activeNetwork
=
cm
.
getActiveNetworkInfo
val
isConnected
=
activeNetwork
!=
null
&&
activeNetwork
.
isConnected
if
(
isConnected
&&
profile
.
kcp
&&
kcptunProcess
!=
null
)
{
restartHanlder
.
removeCallbacks
(
null
)
...
...
@@ -95,7 +95,7 @@ trait BaseService extends Service {
callbacksCount
+=
1
if
(
callbacksCount
!=
0
&&
timer
==
null
)
{
val
task
=
new
TimerTask
{
def
run
{
def
run
()
{
if
(
TrafficMonitor
.
updateRate
())
updateTrafficRate
()
}
}
...
...
@@ -107,27 +107,27 @@ trait BaseService extends Service {
}
}
override
def
use
(
profileId
:
Int
)
=
synchronized
(
if
(
profileId
<
0
)
stopRunner
(
true
)
else
{
override
def
use
(
profileId
:
Int
)
:
Unit
=
synchronized
(
if
(
profileId
<
0
)
stopRunner
(
stopService
=
true
)
else
{
val
profile
=
app
.
profileManager
.
getProfile
(
profileId
).
orNull
if
(
profile
==
null
)
stopRunner
(
true
)
else
state
match
{
if
(
profile
==
null
)
stopRunner
(
stopService
=
true
)
else
state
match
{
case
State
.
STOPPED
=>
if
(
checkProfile
(
profile
))
startRunner
(
profile
)
case
State
.
CONNECTED
=>
if
(
profileId
!=
BaseService
.
this
.
profile
.
id
&&
checkProfile
(
profile
))
{
stopRunner
(
false
)
stopRunner
(
stopService
=
false
)
startRunner
(
profile
)
}
case
_
=>
Log
.
w
(
BaseService
.
this
.
getClass
.
getSimpleName
,
"Illegal state when invoking use: "
+
state
)
}
})
override
def
useSync
(
profileId
:
Int
)
=
use
(
profileId
)
override
def
useSync
(
profileId
:
Int
)
:
Unit
=
use
(
profileId
)
}
def
checkProfile
(
profile
:
Profile
)
=
if
(
TextUtils
.
isEmpty
(
profile
.
host
)
||
TextUtils
.
isEmpty
(
profile
.
password
))
{
stopRunner
(
true
,
getString
(
R
.
string
.
proxy_empty
))
def
checkProfile
(
profile
:
Profile
)
:
Boolean
=
if
(
TextUtils
.
isEmpty
(
profile
.
host
)
||
TextUtils
.
isEmpty
(
profile
.
password
))
{
stopRunner
(
stopService
=
true
,
getString
(
R
.
string
.
proxy_empty
))
false
}
else
true
def
connect
()
=
if
(
profile
.
host
==
"198.199.101.152"
)
{
def
connect
()
:
Unit
=
if
(
profile
.
host
==
"198.199.101.152"
)
{
val
holder
=
app
.
containerHolder
val
container
=
holder
.
getContainer
val
url
=
container
.
getString
(
"proxy_url"
)
...
...
@@ -175,15 +175,16 @@ trait BaseService extends Service {
changeState
(
State
.
CONNECTING
)
if
(
profile
.
isMethodUnsafe
)
handler
.
post
(()
=>
Toast
.
makeText
(
this
,
R
.
string
.
method_unsafe
,
Toast
.
LENGTH_LONG
).
show
)
if
(
profile
.
isMethodUnsafe
)
handler
.
post
(()
=>
Toast
.
makeText
(
this
,
R
.
string
.
method_unsafe
,
Toast
.
LENGTH_LONG
).
show
())
Utils
.
ThrowableFuture
(
try
connect
catch
{
case
_:
NameNotResolvedException
=>
stopRunner
(
true
,
getString
(
R
.
string
.
invalid_server
))
Utils
.
ThrowableFuture
(
try
connect
()
catch
{
case
_:
NameNotResolvedException
=>
stopRunner
(
stopService
=
true
,
getString
(
R
.
string
.
invalid_server
))
case
exc
:
KcpcliParseException
=>
stopRunner
(
true
,
getString
(
R
.
string
.
service_failed
)
+
": "
+
exc
.
cause
.
getMessage
)
case
_:
NullConnectionException
=>
stopRunner
(
true
,
getString
(
R
.
string
.
reboot_required
))
stopRunner
(
stopService
=
true
,
getString
(
R
.
string
.
service_failed
)
+
": "
+
exc
.
cause
.
getMessage
)
case
_:
NullConnectionException
=>
stopRunner
(
stopService
=
true
,
getString
(
R
.
string
.
reboot_required
))
case
exc
:
Throwable
=>
stopRunner
(
true
,
getString
(
R
.
string
.
service_failed
)
+
": "
+
exc
.
getMessage
)
stopRunner
(
stopService
=
true
,
getString
(
R
.
string
.
service_failed
)
+
": "
+
exc
.
getMessage
)
exc
.
printStackTrace
()
app
.
track
(
exc
)
})
...
...
@@ -283,7 +284,7 @@ trait BaseService extends Service {
})
}
def
getBlackList
=
{
def
getBlackList
:
String
=
{
val
default
=
getString
(
R
.
string
.
black_list
)
try
{
val
container
=
app
.
containerHolder
.
getContainer
...
...
@@ -291,7 +292,7 @@ trait BaseService extends Service {
val
list
=
if
(
update
==
null
||
update
.
isEmpty
)
default
else
update
"exclude = "
+
list
+
";"
}
catch
{
case
ex
:
Exception
=>
"exclude = "
+
default
+
";"
case
_
:
Exception
=>
"exclude = "
+
default
+
";"
}
}
}
src/main/scala/com/github/shadowsocks/BootReceiver.scala
View file @
a5df60ae
...
...
@@ -25,16 +25,16 @@ import android.content.{BroadcastReceiver, ComponentName, Context, Intent}
import
com.github.shadowsocks.utils._
object
BootReceiver
{
def
getEnabled
(
context
:
Context
)
=
PackageManager
.
COMPONENT_ENABLED_STATE_ENABLED
==
def
getEnabled
(
context
:
Context
)
:
Boolean
=
PackageManager
.
COMPONENT_ENABLED_STATE_ENABLED
==
context
.
getPackageManager
.
getComponentEnabledSetting
(
new
ComponentName
(
context
,
classOf
[
BootReceiver
]))
def
setEnabled
(
context
:
Context
,
enabled
:
Boolean
)
=
context
.
getPackageManager
.
setComponentEnabledSetting
(
def
setEnabled
(
context
:
Context
,
enabled
:
Boolean
)
:
Unit
=
context
.
getPackageManager
.
setComponentEnabledSetting
(
new
ComponentName
(
context
,
classOf
[
BootReceiver
]),
if
(
enabled
)
PackageManager
.
COMPONENT_ENABLED_STATE_ENABLED
else
PackageManager
.
COMPONENT_ENABLED_STATE_DISABLED
,
PackageManager
.
DONT_KILL_APP
)
}
class
BootReceiver
extends
BroadcastReceiver
{
def
onReceive
(
context
:
Context
,
intent
:
Intent
)
=
{
def
onReceive
(
context
:
Context
,
intent
:
Intent
)
:
Unit
=
{
Utils
.
startSsService
(
context
)
}
}
src/main/scala/com/github/shadowsocks/GuardedProcess.scala
View file @
a5df60ae
...
...
@@ -25,24 +25,16 @@ import java.lang.System.currentTimeMillis
import
java.util.concurrent.Semaphore
import
android.util.Log
import
com.github.shadowsocks.utils.CloseUtils._
import
scala.collection.JavaConversions._
import
scala.collection.immutable.Stream
import
scala.util.control.Exception._
class
StreamLogger
(
is
:
InputStream
,
tag
:
String
)
extends
Thread
{
def
withCloseable
[
T
<:
Closeable
,
R
](
t
:
T
)(
f
:
T
=>
R
)
:
R
=
{
allCatch
.
andFinally
{
t
.
close
}
apply
{
f
(
t
)
}
}
override
def
run
()
{
withCloseable
(
new
BufferedReader
(
new
InputStreamReader
(
is
)))
{
br
=>
try
Stream
.
continually
(
br
.
readLine
()).
takeWhile
(
_
!=
null
).
foreach
(
Log
.
i
(
tag
,
_
))
catch
{
case
ignore
:
IOException
=>
}
}
}
override
def
run
()
:
Unit
=
autoClose
(
new
BufferedReader
(
new
InputStreamReader
(
is
)))(
br
=>
try
Stream
.
continually
(
br
.
readLine
()).
takeWhile
(
_
!=
null
).
foreach
(
Log
.
i
(
tag
,
_
))
catch
{
case
_:
IOException
=>
})
}
/**
...
...
@@ -58,7 +50,7 @@ class GuardedProcess(cmd: Seq[String]) {
def
start
(
onRestartCallback
:
()
=>
Unit
=
null
)
:
GuardedProcess
=
{
val
semaphore
=
new
Semaphore
(
1
)
semaphore
.
acquire
semaphore
.
acquire
()
@volatile
var
ioException
:
IOException
=
null
guardThread
=
new
Thread
(()
=>
{
...
...
@@ -71,11 +63,11 @@ class GuardedProcess(cmd: Seq[String]) {
process
=
new
ProcessBuilder
(
cmd
).
redirectErrorStream
(
true
).
start
val
is
=
process
.
getInputStream
new
StreamLogger
(
is
,
TAG
).
start
new
StreamLogger
(
is
,
TAG
).
start
()
if
(
callback
==
null
)
callback
=
onRestartCallback
else
callback
()
semaphore
.
release
semaphore
.
release
()
process
.
waitFor
this
.
synchronized
{
...
...
@@ -88,22 +80,19 @@ class GuardedProcess(cmd: Seq[String]) {
}
}
}
}
}
catch
{
case
ignored
:
InterruptedException
=>
case
_
:
InterruptedException
=>
Log
.
i
(
TAG
,
"thread interrupt, destroy process: "
+
cmd
)
process
.
destroy
()
case
e
:
IOException
=>
ioException
=
e
}
finally
semaphore
.
release
}
finally
semaphore
.
release
()
},
"GuardThread-"
+
cmd
)
guardThread
.
start
()
semaphore
.
acquire
semaphore
.
acquire
()
if
(
ioException
!=
null
)
{
throw
ioException
}
if
(
ioException
!=
null
)
throw
ioException
this
}
...
...
@@ -113,7 +102,7 @@ class GuardedProcess(cmd: Seq[String]) {
guardThread
.
interrupt
()
process
.
destroy
()
try
guardThread
.
join
()
catch
{
case
ignored
:
InterruptedException
=>
case
_
:
InterruptedException
=>
}
}
...
...
@@ -125,7 +114,7 @@ class GuardedProcess(cmd: Seq[String]) {
}
@throws
(
classOf
[
InterruptedException
])
def
waitFor
=
{
def
waitFor
:
Int
=
{
guardThread
.
join
()
0
}
...
...
src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala
View file @
a5df60ae
...
...
@@ -22,7 +22,7 @@ package com.github.shadowsocks
import
java.nio.charset.Charset
import
android.app.
{
Activity
,
TaskStackBuilder
}
import
android.app.
TaskStackBuilder
import
android.content._
import
android.content.pm.PackageManager
import
android.nfc.NfcAdapter.CreateNdefMessageCallback
...
...
@@ -97,7 +97,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
})
shareBtn
.
setOnLongClickListener
(
_
=>
{
Utils
.
positionToast
(
Toast
.
makeText
(
ProfileManagerActivity
.
this
,
R
.
string
.
share
,
Toast
.
LENGTH_SHORT
),
shareBtn
,
getWindow
,
0
,
Utils
.
dpToPx
(
ProfileManagerActivity
.
this
,
8
)).
show
getWindow
,
0
,
Utils
.
dpToPx
(
ProfileManagerActivity
.
this
,
8
)).
show
()
true
})
}
...
...
@@ -131,41 +131,42 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
def
onClick
(
v
:
View
)
{
app
.
switchProfile
(
item
.
id
)
finish
finish
()
}
def
onKey
(
v
:
View
,
keyCode
:
Int
,
event
:
KeyEvent
)
=
if
(
event
.
getAction
==
KeyEvent
.
ACTION_DOWN
)
keyCode
match
{
case
KeyEvent
.
KEYCODE_DPAD_LEFT
=>
val
index
=
getAdapterPosition
if
(
index
>=
0
)
{
profilesAdapter
.
remove
(
index
)
undoManager
.
remove
(
index
,
item
)
true
}
else
false
case
_
=>
false
}
else
false
def
onKey
(
v
:
View
,
keyCode
:
Int
,
event
:
KeyEvent
)
:
Boolean
=
if
(
event
.
getAction
==
KeyEvent
.
ACTION_DOWN
)
keyCode
match
{
case
KeyEvent
.
KEYCODE_DPAD_LEFT
=>
val
index
=
getAdapterPosition
if
(
index
>=
0
)
{
profilesAdapter
.
remove
(
index
)
undoManager
.
remove
(
index
,
item
)
true
}
else
false
case
_
=>
false
}
else
false
}
private
class
ProfilesAdapter
extends
RecyclerView
.
Adapter
[
ProfileViewHolder
]
{
var
profiles
=
new
ArrayBuffer
[
Profile
]
profiles
++=
app
.
profileManager
.
getAllProfiles
.
getOrElse
(
List
.
empty
[
Profile
])
def
getItemCount
=
profiles
.
length
def
getItemCount
:
Int
=
profiles
.
length
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
=
vh
.
bind
(
profiles
(
i
))
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
:
Unit
=
vh
.
bind
(
profiles
(
i
))
def
onCreateViewHolder
(
vg
:
ViewGroup
,
i
:
Int
)
=
new
ProfileViewHolder
(
LayoutInflater
.
from
(
vg
.
getContext
).
inflate
(
R
.
layout
.
layout_profiles_item
,
vg
,
false
))
def
add
(
item
:
Profile
)
{
undoManager
.
flush
undoManager
.
flush
()
val
pos
=
getItemCount
profiles
+=
item
notifyItemInserted
(
pos
)
}
def
move
(
from
:
Int
,
to
:
Int
)
{
undoManager
.
flush
undoManager
.
flush
()
val
step
=
if
(
from
<
to
)
1
else
-
1
val
first
=
profiles
(
from
)
var
previousOrder
=
profiles
(
from
).
userOrder
...
...
@@ -187,11 +188,11 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
profiles
.
remove
(
pos
)
notifyItemRemoved
(
pos
)
}
def
undo
(
actions
:
Iterator
[(
Int
,
Profile
)])
=
for
((
index
,
item
)
<-
actions
)
{
def
undo
(
actions
:
Iterator
[(
Int
,
Profile
)])
:
Unit
=
for
((
index
,
item
)
<-
actions
)
{
profiles
.
insert
(
index
,
item
)
notifyItemInserted
(
index
)
}
def
commit
(
actions
:
Iterator
[(
Int
,
Profile
)])
=
for
((
index
,
item
)
<-
actions
)
{
def
commit
(
actions
:
Iterator
[(
Int
,
Profile
)])
:
Unit
=
for
((
_
,
item
)
<-
actions
)
{
app
.
profileManager
.
delProfile
(
item
.
id
)
if
(
item
.
id
==
app
.
profileId
)
app
.
profileId
(-
1
)
}
...
...
@@ -214,8 +215,6 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
private
var
isNfcEnabled
:
Boolean
=
_
private
var
isNfcBeamEnabled
:
Boolean
=
_
private
val
REQUEST_QRCODE
=
1
override
def
onCreate
(
savedInstanceState
:
Bundle
)
{
super
.
onCreate
(
savedInstanceState
)
setContentView
(
R
.
layout
.
layout_profiles
)
...
...
@@ -246,27 +245,27 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
undoManager
=
new
UndoSnackbarManager
[
Profile
](
profilesList
,
profilesAdapter
.
undo
,
profilesAdapter
.
commit
)
new
ItemTouchHelper
(
new
SimpleCallback
(
ItemTouchHelper
.
UP
|
ItemTouchHelper
.
DOWN
,
ItemTouchHelper
.
START
|
ItemTouchHelper
.
END
)
{
def
onSwiped
(
viewHolder
:
ViewHolder
,
direction
:
Int
)
=
{
def
onSwiped
(
viewHolder
:
ViewHolder
,
direction
:
Int
)
{
val
index
=
viewHolder
.
getAdapterPosition
profilesAdapter
.
remove
(
index
)
undoManager
.
remove
(
index
,
viewHolder
.
asInstanceOf
[
ProfileViewHolder
].
item
)
}
def
onMove
(
recyclerView
:
RecyclerView
,
viewHolder
:
ViewHolder
,
target
:
ViewHolder
)
=
{
def
onMove
(
recyclerView
:
RecyclerView
,
viewHolder
:
ViewHolder
,
target
:
ViewHolder
)
:
Boolean
=
{
profilesAdapter
.
move
(
viewHolder
.
getAdapterPosition
,
target
.
getAdapterPosition
)
true
}
}).
attachToRecyclerView
(
profilesList
)
attachService
(
new
IShadowsocksServiceCallback
.
Stub
{
def
stateChanged
(
state
:
Int
,
profileName
:
String
,
msg
:
String
)
=
()
// ignore
def
trafficUpdated
(
txRate
:
Long
,
rxRate
:
Long
,
txTotal
:
Long
,
rxTotal
:
Long
)
=
def
stateChanged
(
state
:
Int
,
profileName
:
String
,
msg
:
String
)
:
Unit
=
()
// ignore
def
trafficUpdated
(
txRate
:
Long
,
rxRate
:
Long
,
txTotal
:
Long
,
rxTotal
:
Long
)
:
Unit
=
if
(
selectedItem
!=
null
)
selectedItem
.
updateText
(
txTotal
,
rxTotal
)
})
if
(
app
.
settings
.
getBoolean
(
Key
.
profileTip
,
true
))
{
app
.
editor
.
putBoolean
(
Key
.
profileTip
,
false
).
apply
app
.
editor
.
putBoolean
(
Key
.
profileTip
,
false
).
apply
()
new
AlertDialog
.
Builder
(
this
).
setTitle
(
R
.
string
.
profile_manager_dialog
)
.
setMessage
(
R
.
string
.
profile_manager_dialog_content
).
setPositiveButton
(
R
.
string
.
gotcha
,
null
).
create
.
show
.
setMessage
(
R
.
string
.
profile_manager_dialog_content
).
setPositiveButton
(
R
.
string
.
gotcha
,
null
).
create
().
show
()
}
val
intent
=
getIntent
...
...
@@ -311,7 +310,7 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
val
profile
=
app
.
profileManager
.
createProfile
()
app
.
profileManager
.
updateProfile
(
profile
)
app
.
switchProfile
(
profile
.
id
)
finish
finish
()
case
R
.
id
.
fab_qrcode_add
=>
menu
.
toggle
(
false
)
val
intent
=
new
Intent
(
this
,
classOf
[
ScannerActivity
])
...
...
@@ -331,18 +330,18 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
}
else
{
dialog
.
setMessage
(
getString
(
R
.
string
.
add_profile_nfc_hint
))
}
dialog
.
show
dialog
.
show
()
case
R
.
id
.
fab_import_add
=>
menu
.
toggle
(
true
)
if
(
clipboard
.
hasPrimaryClip
)
{
val
profiles
=
Parser
.
findAll
(
clipboard
.
getPrimaryClip
.
getItemAt
(
0
).
getText
)
if
(
profiles
.
nonEmpty
)
{
profiles
.
foreach
(
app
.
profileManager
.
createProfile
)
Toast
.
makeText
(
this
,
R
.
string
.
action_import_msg
,
Toast
.
LENGTH_SHORT
).
show
Toast
.
makeText
(
this
,
R
.
string
.
action_import_msg
,
Toast
.
LENGTH_SHORT
).
show
()
return
}
}
Toast
.
makeText
(
this
,
R
.
string
.
action_import_err
,
Toast
.
LENGTH_SHORT
).
show
Toast
.
makeText
(
this
,
R
.
string
.
action_import_err
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
...
...
@@ -398,11 +397,11 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
unregisterCallback
}
override
def
onDestroy
{
override
def
onDestroy
()
{
detachService
()
undoManager
.
flush
undoManager
.
flush
()
app
.
profileManager
.
setProfileAddedListener
(
null
)
super
.
onDestroy
super
.
onDestroy
()
}
override
def
onBackPressed
()
{
...
...
@@ -417,8 +416,8 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
app
.
profileManager
.
getAllProfiles
match
{
case
Some
(
profiles
)
=>
clipboard
.
setPrimaryClip
(
ClipData
.
newPlainText
(
null
,
profiles
.
mkString
(
"\n"
)))
Toast
.
makeText
(
this
,
R
.
string
.
action_export_msg
,
Toast
.
LENGTH_SHORT
).
show
case
_
=>
Toast
.
makeText
(
this
,
R
.
string
.
action_export_err
,
Toast
.
LENGTH_SHORT
).
show
Toast
.
makeText
(
this
,
R
.
string
.
action_export_msg
,
Toast
.
LENGTH_SHORT
).
show
()
case
_
=>
Toast
.
makeText
(
this
,
R
.
string
.
action_export_err
,
Toast
.
LENGTH_SHORT
).
show
()
}
true
case
_
=>
false
...
...
src/main/scala/com/github/shadowsocks/ScannerActivity.scala
View file @
a5df60ae
...
...
@@ -20,8 +20,7 @@
package
com.github.shadowsocks
import
android.app.
{
Activity
,
TaskStackBuilder
}
import
android.content.Intent
import
android.app.TaskStackBuilder
import
android.content.pm.
{
PackageManager
,
ShortcutManager
}
import
android.os.
{
Build
,
Bundle
}
import
android.support.v4.app.ActivityCompat
...
...
@@ -30,9 +29,9 @@ import android.support.v7.app.AppCompatActivity
import
android.support.v7.widget.Toolbar
import
android.text.TextUtils
import
android.widget.Toast
import
com.google.zxing.Result
import
com.github.shadowsocks.ShadowsocksApplication.app
import
com.github.shadowsocks.utils.Parser
import
com.google.zxing.Result
import
me.dm7.barcodescanner.zxing.ZXingScannerView
object
ScannerActivity
{
...
...
@@ -95,7 +94,7 @@ class ScannerActivity extends AppCompatActivity with ZXingScannerView.ResultHand
scannerView
.
stopCamera
()
// Stop camera on pause
}
override
def
handleResult
(
rawResult
:
Result
)
=
{
override
def
handleResult
(
rawResult
:
Result
)
{
val
uri
=
rawResult
.
getText
if
(!
TextUtils
.
isEmpty
(
uri
))
Parser
.
findAll
(
uri
).
foreach
(
app
.
profileManager
.
createProfile
)
...
...
src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala
View file @
a5df60ae
...
...
@@ -35,34 +35,34 @@ trait ServiceBoundContext extends Context with IBinder.DeathRecipient {
binder
=
service
service
.
linkToDeath
(
ServiceBoundContext
.
this
,
0
)
bgService
=
IShadowsocksService
.
Stub
.
asInterface
(
service
)
registerCallback
registerCallback
()
ServiceBoundContext
.
this
.
onServiceConnected
()
}
override
def
onServiceDisconnected
(
name
:
ComponentName
)
{
unregisterCallback
unregisterCallback
()
ServiceBoundContext
.
this
.
onServiceDisconnected
()
bgService
=
null
binder
=
null
}
}
protected
def
registerCallback
=
if
(
bgService
!=
null
&&
callback
!=
null
&&
!
callbackRegistered
)
try
{
protected
def
registerCallback
()
:
Unit
=
if
(
bgService
!=
null
&&
callback
!=
null
&&
!
callbackRegistered
)
try
{
bgService
.
registerCallback
(
callback
)
callbackRegistered
=
true
}
catch
{
case
ignored
:
RemoteException
=>
// Nothing
case
_
:
RemoteException
=>
// Nothing
}
protected
def
unregisterCallback
=
{
protected
def
unregisterCallback
()
{
if
(
bgService
!=
null
&&
callback
!=
null
&&
callbackRegistered
)
try
bgService
.
unregisterCallback
(
callback
)
catch
{
case
ignored
:
RemoteException
=>
case
_
:
RemoteException
=>
}
callbackRegistered
=
false
}
def
onServiceConnected
()
=
()
def
onServiceDisconnected
()
=
()
override
def
binderDied
=
()
def
onServiceConnected
()
:
Unit
=
()
def
onServiceDisconnected
()
:
Unit
=
()
override
def
binderDied
()
:
Unit
=
()
private
var
callback
:
IShadowsocksServiceCallback.Stub
=
_
private
var
connection
:
ShadowsocksServiceConnection
=
_
...
...
@@ -86,7 +86,7 @@ trait ServiceBoundContext extends Context with IBinder.DeathRecipient {
}
def
detachService
()
{
unregisterCallback
unregisterCallback
()
callback
=
null
if
(
connection
!=
null
)
{
try
unbindService
(
connection
)
catch
{
...
...
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
View file @
a5df60ae
...
...
@@ -123,7 +123,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
getString
(
R
.
string
.
vpn_error
).
formatLocal
(
Locale
.
ENGLISH
,
m
),
Snackbar
.
LENGTH_LONG
)
if
(
m
==
getString
(
R
.
string
.
nat_no_root
))
snackbar
.
setAction
(
R
.
string
.
switch_to_vpn
,
(
_
=>
preferences
.
natSwitch
.
setChecked
(
false
))
:
View.OnClickListener
)
snackbar
.
show
snackbar
.
show
()
Log
.
e
(
TAG
,
"Error to start VPN service: "
+
m
)
}
preferences
.
setEnabled
(
true
)
...
...
@@ -151,7 +151,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
rxRateText
.
setText
(
TrafficMonitor
.
formatTraffic
(
rxRate
)
+
"/s"
)
}
def
attachService
:
Unit
=
attachService
(
callback
)
def
attachService
Callback
()
:
Unit
=
attachService
(
callback
)
override
def
onServiceConnected
()
{
// Update the UI
...
...
@@ -160,7 +160,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
if
(
Build
.
VERSION
.
SDK_INT
>=
21
&&
app
.
isNatEnabled
)
{
val
snackbar
=
Snackbar
.
make
(
findViewById
(
android
.
R
.
id
.
content
),
R
.
string
.
nat_deprecated
,
Snackbar
.
LENGTH_LONG
)
snackbar
.
setAction
(
R
.
string
.
switch_to_vpn
,
(
_
=>
preferences
.
natSwitch
.
setChecked
(
false
))
:
View.OnClickListener
)
snackbar
.
show
snackbar
.
show
()
}
}
...
...
@@ -168,10 +168,10 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
if
(
fab
!=
null
)
fab
.
setEnabled
(
false
)
}
override
def
binderDied
{
override
def
binderDied
()
{
detachService
()
app
.
crashRecovery
()
attachService
attachService
Callback
()
}
private
var
testCount
:
Int
=
_
...
...
@@ -243,7 +243,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
title
.
setOnClickListener
(
_
=>
startActivity
(
new
Intent
(
this
,
classOf
[
ProfileManagerActivity
])))
val
typedArray
=
obtainStyledAttributes
(
Array
(
R
.
attr
.
selectableItemBackgroundBorderless
))
title
.
setBackgroundResource
(
typedArray
.
getResourceId
(
0
,
0
))
typedArray
.
recycle
typedArray
.
recycle
()
val
tf
=
Typefaces
.
get
(
this
,
"fonts/Iceland.ttf"
)
if
(
tf
!=
null
)
title
.
setTypeface
(
tf
)
title
.
setCompoundDrawablesWithIntrinsicBounds
(
0
,
0
,
R
.
drawable
.
ic_arrow_drop_down
,
0
)
...
...
@@ -287,7 +287,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
synchronized
(
if
(
testCount
==
id
&&
app
.
isVpnEnabled
)
handler
.
post
(()
=>
if
(
success
)
connectionTestText
.
setText
(
result
)
else
{
connectionTestText
.
setText
(
R
.
string
.
connection_test_fail
)
Snackbar
.
make
(
findViewById
(
android
.
R
.
id
.
content
),
result
,
Snackbar
.
LENGTH_LONG
).
show
Snackbar
.
make
(
findViewById
(
android
.
R
.
id
.
content
),
result
,
Snackbar
.
LENGTH_LONG
).
show
()
}))
}
}
...
...
@@ -301,12 +301,12 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
else
changeSwitch
(
checked
=
false
))
fab
.
setOnLongClickListener
((
v
:
View
)
=>
{
Utils
.
positionToast
(
Toast
.
makeText
(
this
,
if
(
serviceStarted
)
R
.
string
.
stop
else
R
.
string
.
connect
,
Toast
.
LENGTH_SHORT
),
fab
,
getWindow
,
0
,
Utils
.
dpToPx
(
this
,
8
)).
show
Toast
.
LENGTH_SHORT
),
fab
,
getWindow
,
0
,
Utils
.
dpToPx
(
this
,
8
)).
show
()
true
})
updateTraffic
(
0
,
0
,
0
,
0
)
handler
.
post
(
()
=>
attachService
)
handler
.
post
(
attachServiceCallback
)
}
private
def
hideCircle
()
{
...
...
@@ -412,11 +412,11 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
override
def
onStart
()
{
super
.
onStart
()
registerCallback
registerCallback
()
}
override
def
onStop
()
{
super
.
onStop
()
unregisterCallback
unregisterCallback
()
clearDialog
()
}
...
...
@@ -436,7 +436,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
}
}
override
def
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
)
=
resultCode
match
{
override
def
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
)
:
Unit
=
resultCode
match
{
case
Activity
.
RESULT_OK
=>
serviceLoad
()
case
_
=>
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala
View file @
a5df60ae
...
...
@@ -27,17 +27,18 @@ import java.util.concurrent.TimeUnit
import
android.annotation.SuppressLint
import
android.app.Application
import
android.content.SharedPreferences
import
android.content.res.Configuration
import
android.os.
{
Build
,
LocaleList
}
import
android.preference.PreferenceManager
import
android.support.v7.app.AppCompatDelegate
import
android.util.Log
import
com.evernote.android.job.JobManager
import
com.github.shadowsocks.database.
{
DBHelper
,
ProfileManager
}
import
com.github.shadowsocks.database.
{
DBHelper
,
Profile
,
Profile
Manager
}
import
com.github.shadowsocks.job.DonaldTrump
import
com.github.shadowsocks.utils.CloseUtils._
import
com.github.shadowsocks.utils._
import
com.google.android.gms.analytics.
{
GoogleAnalytics
,
HitBuilders
,
StandardExceptionParser
}
import
com.google.android.gms.analytics.
{
GoogleAnalytics
,
HitBuilders
,
StandardExceptionParser
,
Tracker
}
import
com.google.android.gms.common.api.ResultCallback
import
com.google.android.gms.tagmanager.
{
ContainerHolder
,
TagManager
}
import
com.j256.ormlite.logger.LocalLog
...
...
@@ -64,29 +65,29 @@ class ShadowsocksApplication extends Application {
final
val
SIG_FUNC
=
"getSignature"
var
containerHolder
:
ContainerHolder
=
_
lazy
val
tracker
=
GoogleAnalytics
.
getInstance
(
this
).
newTracker
(
R
.
xml
.
tracker
)
lazy
val
settings
=
PreferenceManager
.
getDefaultSharedPreferences
(
this
)
lazy
val
editor
=
settings
.
edit
lazy
val
tracker
:
Tracker
=
GoogleAnalytics
.
getInstance
(
this
).
newTracker
(
R
.
xml
.
tracker
)
lazy
val
settings
:
SharedPreferences
=
PreferenceManager
.
getDefaultSharedPreferences
(
this
)
lazy
val
editor
:
SharedPreferences.Editor
=
settings
.
edit
lazy
val
profileManager
=
new
ProfileManager
(
new
DBHelper
(
this
))
def
isNatEnabled
=
settings
.
getBoolean
(
Key
.
isNAT
,
false
)
def
isVpnEnabled
=
!
isNatEnabled
def
isNatEnabled
:
Boolean
=
settings
.
getBoolean
(
Key
.
isNAT
,
false
)
def
isVpnEnabled
:
Boolean
=
!
isNatEnabled
// send event
def
track
(
category
:
String
,
action
:
String
)
=
tracker
.
send
(
new
HitBuilders
.
EventBuilder
()
def
track
(
category
:
String
,
action
:
String
)
:
Unit
=
tracker
.
send
(
new
HitBuilders
.
EventBuilder
()
.
setAction
(
action
)
.
setLabel
(
BuildConfig
.
VERSION_NAME
)
.
build
())
def
track
(
t
:
Throwable
)
=
tracker
.
send
(
new
HitBuilders
.
ExceptionBuilder
()
def
track
(
t
:
Throwable
)
:
Unit
=
tracker
.
send
(
new
HitBuilders
.
ExceptionBuilder
()
.
setDescription
(
new
StandardExceptionParser
(
this
,
null
).
getDescription
(
Thread
.
currentThread
.
getName
,
t
))
.
setFatal
(
false
)
.
build
())
def
profileId
=
settings
.
getInt
(
Key
.
id
,
-
1
)
def
profileId
(
i
:
Int
)
=
editor
.
putInt
(
Key
.
id
,
i
).
apply
def
currentProfile
=
profileManager
.
getProfile
(
profileId
)
def
profileId
:
Int
=
settings
.
getInt
(
Key
.
id
,
-
1
)
def
profileId
(
i
:
Int
)
:
Unit
=
editor
.
putInt
(
Key
.
id
,
i
).
apply
()
def
currentProfile
:
Option
[
Profile
]
=
profileManager
.
getProfile
(
profileId
)
def
switchProfile
(
id
:
Int
)
=
{
def
switchProfile
(
id
:
Int
)
:
Profile
=
{
profileId
(
id
)
profileManager
.
getProfile
(
id
)
getOrElse
profileManager
.
createProfile
()
}
...
...
@@ -128,9 +129,11 @@ class ShadowsocksApplication extends Application {
res
.
updateConfiguration
(
newConfig
,
res
.
getDisplayMetrics
)
}
}
else
{
//noinspection ScalaDeprecation
val
newLocale
=
checkChineseLocale
(
config
.
locale
)
if
(
newLocale
!=
null
)
{
val
newConfig
=
new
Configuration
(
config
)
//noinspection ScalaDeprecation
newConfig
.
locale
=
newLocale
val
res
=
getResources
res
.
updateConfiguration
(
newConfig
,
res
.
getDisplayMetrics
)
...
...
@@ -171,7 +174,7 @@ class ShadowsocksApplication extends Application {
TcpFastOpen
.
enabled
(
settings
.
getBoolean
(
Key
.
tfo
,
TcpFastOpen
.
sendEnabled
))
}
def
refreshContainerHolder
{
def
refreshContainerHolder
()
{
val
holder
=
app
.
containerHolder
if
(
holder
!=
null
)
holder
.
refresh
()
}
...
...
@@ -215,5 +218,5 @@ class ShadowsocksApplication extends Application {
editor
.
putInt
(
Key
.
currentVersionCode
,
BuildConfig
.
VERSION_CODE
).
apply
()
}
def
updateAssets
()
=
if
(
settings
.
getInt
(
Key
.
currentVersionCode
,
-
1
)
!=
BuildConfig
.
VERSION_CODE
)
copyAssets
()
def
updateAssets
()
:
Unit
=
if
(
settings
.
getInt
(
Key
.
currentVersionCode
,
-
1
)
!=
BuildConfig
.
VERSION_CODE
)
copyAssets
()
}
src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
View file @
a5df60ae
...
...
@@ -40,11 +40,11 @@ class ShadowsocksNatService extends BaseService {
val
TAG
=
"ShadowsocksNatService"
val
CMD_IPTABLES_DNAT_ADD_SOCKS
=
"iptables -t nat -A OUTPUT -p tcp "
+
"-j DNAT --to-destination 127.0.0.1:8123"
val
CMD_IPTABLES_DNAT_ADD_SOCKS
=
"
iptables -t nat -A OUTPUT -p tcp
-j DNAT --to-destination 127.0.0.1:8123"
private
var
notification
:
ShadowsocksNotification
=
_
val
myUid
=
android
.
os
.
Process
.
myUid
()
val
myUid
:
Int
=
android
.
os
.
Process
.
myUid
()
var
sslocalProcess
:
GuardedProcess
=
_
var
sstunnelProcess
:
GuardedProcess
=
_
...
...
@@ -169,20 +169,17 @@ class ShadowsocksNatService extends BaseService {
val
reject
=
if
(
profile
.
ipv6
)
"224.0.0.0/3"
else
"224.0.0.0/3, ::/0"
val
conf
=
profile
.
route
match
{
case
Route
.
BYPASS_CHN
|
Route
.
BYPASS_LAN_CHN
|
Route
.
GFWLIST
=>
{
case
Route
.
BYPASS_CHN
|
Route
.
BYPASS_LAN_CHN
|
Route
.
GFWLIST
=>
ConfigUtils
.
PDNSD_DIRECT
.
formatLocal
(
Locale
.
ENGLISH
,
""
,
getApplicationInfo
.
dataDir
,
"127.0.0.1"
,
profile
.
localPort
+
53
,
"114.114.114.114, 223.5.5.5, 1.2.4.8"
,
getBlackList
,
reject
,
profile
.
localPort
+
63
,
reject
)
}
case
Route
.
CHINALIST
=>
{
case
Route
.
CHINALIST
=>
ConfigUtils
.
PDNSD_DIRECT
.
formatLocal
(
Locale
.
ENGLISH
,
""
,
getApplicationInfo
.
dataDir
,
"127.0.0.1"
,
profile
.
localPort
+
53
,
"8.8.8.8, 8.8.4.4, 208.67.222.222"
,
""
,
reject
,
profile
.
localPort
+
63
,
reject
)
}
case
_
=>
{
case
_
=>
ConfigUtils
.
PDNSD_LOCAL
.
formatLocal
(
Locale
.
ENGLISH
,
""
,
getApplicationInfo
.
dataDir
,
"127.0.0.1"
,
profile
.
localPort
+
53
,
profile
.
localPort
+
63
,
reject
)
}
}
Utils
.
printToFile
(
new
File
(
getApplicationInfo
.
dataDir
+
"/pdnsd-nat.conf"
))(
p
=>
{
...
...
@@ -254,7 +251,7 @@ class ShadowsocksNatService extends BaseService {
su
.
addCommand
(
"iptables -t nat -F OUTPUT"
)
}
def
setupIptables
()
=
{
def
setupIptables
()
{
val
init_sb
=
new
ArrayBuffer
[
String
]
val
http_sb
=
new
ArrayBuffer
[
String
]
...
...
@@ -291,14 +288,14 @@ class ShadowsocksNatService extends BaseService {
su
.
addCommand
((
init_sb
++
http_sb
).
toArray
)
}
override
def
startRunner
(
profile
:
Profile
)
=
if
(
su
==
null
)
override
def
startRunner
(
profile
:
Profile
)
:
Unit
=
if
(
su
==
null
)
su
=
new
Shell
.
Builder
().
useSU
().
setWantSTDERR
(
true
).
setWatchdogTimeout
(
10
).
open
((
_
,
exitCode
,
_
)
=>
if
(
exitCode
==
0
)
super
.
startRunner
(
profile
)
else
{
if
(
su
!=
null
)
{
su
.
close
()
su
=
null
}
super
.
stopRunner
(
true
,
getString
(
R
.
string
.
nat_no_root
))
super
.
stopRunner
(
stopService
=
true
,
getString
(
R
.
string
.
nat_no_root
))
})
override
def
connect
()
{
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksNotification.scala
View file @
a5df60ae
...
...
@@ -39,7 +39,7 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
private
val
keyGuard
=
service
.
getSystemService
(
Context
.
KEYGUARD_SERVICE
).
asInstanceOf
[
KeyguardManager
]
private
lazy
val
nm
=
service
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
).
asInstanceOf
[
NotificationManager
]
private
lazy
val
callback
=
new
Stub
{
override
def
stateChanged
(
state
:
Int
,
profileName
:
String
,
msg
:
String
)
=
()
// ignore
override
def
stateChanged
(
state
:
Int
,
profileName
:
String
,
msg
:
String
)
:
Unit
=
()
// ignore
override
def
trafficUpdated
(
txRate
:
Long
,
rxRate
:
Long
,
txTotal
:
Long
,
rxTotal
:
Long
)
{
val
txr
=
TrafficMonitor
.
formatTraffic
(
txRate
)
val
rxr
=
TrafficMonitor
.
formatTraffic
(
rxRate
)
...
...
@@ -71,8 +71,8 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
private
lazy
val
style
=
new
BigTextStyle
(
builder
)
private
var
isVisible
=
true
update
(
if
(
service
.
getSystemService
(
Context
.
POWER_SERVICE
).
asInstanceOf
[
PowerManager
].
isScreenOn
)
Intent
.
ACTION_SCREEN_ON
else
Intent
.
ACTION_SCREEN_OFF
,
true
)
lockReceiver
=
(
context
:
Context
,
intent
:
Intent
)
=>
update
(
intent
.
getAction
)
Intent
.
ACTION_SCREEN_ON
else
Intent
.
ACTION_SCREEN_OFF
,
forceShow
=
true
)
lockReceiver
=
(
_
:
Context
,
intent
:
Intent
)
=>
update
(
intent
.
getAction
)
val
screenFilter
=
new
IntentFilter
()
screenFilter
.
addAction
(
Intent
.
ACTION_SCREEN_ON
)
screenFilter
.
addAction
(
Intent
.
ACTION_SCREEN_OFF
)
...
...
@@ -83,33 +83,33 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
if
(
forceShow
||
service
.
getState
==
State
.
CONNECTED
)
action
match
{
case
Intent
.
ACTION_SCREEN_OFF
=>
setVisible
(
visible
&&
!
Utils
.
isLollipopOrAbove
,
forceShow
)
unregisterCallback
// unregister callback to save battery
unregisterCallback
()
// unregister callback to save battery
case
Intent
.
ACTION_SCREEN_ON
=>
setVisible
(
visible
&&
Utils
.
isLollipopOrAbove
&&
!
keyGuard
.
inKeyguardRestrictedInputMode
,
forceShow
)
service
.
binder
.
registerCallback
(
callback
)
callbackRegistered
=
true
case
Intent
.
ACTION_USER_PRESENT
=>
setVisible
(
true
,
forceShow
)
case
Intent
.
ACTION_USER_PRESENT
=>
setVisible
(
visible
=
true
,
forceShow
=
forceShow
)
}
private
def
unregisterCallback
=
if
(
callbackRegistered
)
{
private
def
unregisterCallback
()
=
if
(
callbackRegistered
)
{
service
.
binder
.
unregisterCallback
(
callback
)
callbackRegistered
=
false
}
def
setVisible
(
visible
:
Boolean
,
forceShow
:
Boolean
=
false
)
=
if
(
isVisible
!=
visible
)
{
def
setVisible
(
visible
:
Boolean
,
forceShow
:
Boolean
=
false
)
:
Unit
=
if
(
isVisible
!=
visible
)
{
isVisible
=
visible
builder
.
setPriority
(
if
(
visible
)
NotificationCompat
.
PRIORITY_LOW
else
NotificationCompat
.
PRIORITY_MIN
)
show
()
}
else
if
(
forceShow
)
show
()
def
show
()
=
service
.
startForeground
(
1
,
builder
.
build
)
def
show
()
:
Unit
=
service
.
startForeground
(
1
,
builder
.
build
)
def
destroy
()
{
if
(
lockReceiver
!=
null
)
{
service
.
unregisterReceiver
(
lockReceiver
)
lockReceiver
=
null
}
unregisterCallback
unregisterCallback
()
service
.
stopForeground
(
true
)
nm
.
cancel
(
1
)
}
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksQuickSwitchActivity.scala
View file @
a5df60ae
...
...
@@ -40,7 +40,7 @@ class ShadowsocksQuickSwitchActivity extends AppCompatActivity {
{
val
typedArray
=
obtainStyledAttributes
(
Array
(
android
.
R
.
attr
.
selectableItemBackground
))
view
.
setBackgroundResource
(
typedArray
.
getResourceId
(
0
,
0
))
typedArray
.
recycle
typedArray
.
recycle
()
}
private
var
item
:
Profile
=
_
private
val
text
=
itemView
.
findViewById
(
android
.
R
.
id
.
text1
).
asInstanceOf
[
CheckedTextView
]
...
...
@@ -55,16 +55,16 @@ class ShadowsocksQuickSwitchActivity extends AppCompatActivity {
def
onClick
(
v
:
View
)
{
app
.
switchProfile
(
item
.
id
)
Utils
.
startSsService
(
ShadowsocksQuickSwitchActivity
.
this
)
finish
finish
()
}
}
private
class
ProfilesAdapter
extends
RecyclerView
.
Adapter
[
ProfileViewHolder
]
{
val
profiles
=
app
.
profileManager
.
getAllProfiles
.
getOrElse
(
List
.
empty
[
Profile
])
val
profiles
:
List
[
Profile
]
=
app
.
profileManager
.
getAllProfiles
.
getOrElse
(
List
.
empty
[
Profile
])
def
getItemCount
=
profiles
.
length
def
getItemCount
:
Int
=
profiles
.
length
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
=
i
match
{
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
:
Unit
=
i
match
{
case
_
=>
vh
.
bind
(
profiles
(
i
))
}
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala
View file @
a5df60ae
...
...
@@ -25,7 +25,6 @@ import android.content.{BroadcastReceiver, Context, Intent, IntentFilter}
import
android.net.VpnService
import
android.os.
{
Bundle
,
Handler
}
import
android.util.Log
import
com.github.shadowsocks.utils.ConfigUtils
import
com.github.shadowsocks.ShadowsocksApplication.app
object
ShadowsocksRunnerActivity
{
...
...
@@ -65,7 +64,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext {
val
locked
=
km
.
inKeyguardRestrictedInputMode
if
(
locked
)
{
val
filter
=
new
IntentFilter
(
Intent
.
ACTION_USER_PRESENT
)
receiver
=
(
context
:
Context
,
intent
:
Intent
)
=>
{
receiver
=
(
_
:
Context
,
intent
:
Intent
)
=>
{
if
(
intent
.
getAction
==
Intent
.
ACTION_USER_PRESENT
)
{
attachService
()
}
...
...
@@ -74,7 +73,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext {
}
else
{
attachService
()
}
finish
finish
()
}
override
def
onDestroy
()
{
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksRunnerService.scala
View file @
a5df60ae
...
...
@@ -23,8 +23,7 @@ package com.github.shadowsocks
import
android.app.Service
import
android.content.Intent
import
android.net.VpnService
import
android.os.
{
IBinder
,
Handler
}
import
com.github.shadowsocks.utils.ConfigUtils
import
android.os.
{
Handler
,
IBinder
}
import
com.github.shadowsocks.ShadowsocksApplication.app
class
ShadowsocksRunnerService
extends
Service
with
ServiceBoundContext
{
...
...
@@ -44,7 +43,7 @@ class ShadowsocksRunnerService extends Service with ServiceBoundContext {
},
1000
)
}
def
startBackgroundService
()
=
bgService
.
useSync
(
app
.
profileId
)
def
startBackgroundService
()
:
Unit
=
bgService
.
useSync
(
app
.
profileId
)
override
def
onCreate
()
{
super
.
onCreate
()
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
View file @
a5df60ae
...
...
@@ -97,7 +97,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
import
ShadowsocksSettings._
private
def
activity
=
getActivity
.
asInstanceOf
[
Shadowsocks
]
lazy
val
natSwitch
=
findPreference
(
Key
.
isNAT
).
asInstanceOf
[
SwitchPreference
]
lazy
val
natSwitch
:
SwitchPreference
=
findPreference
(
Key
.
isNAT
).
asInstanceOf
[
SwitchPreference
]
private
var
isProxyApps
:
SwitchPreference
=
_
...
...
@@ -182,7 +182,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
})
if
(
getPreferenceManager
.
getSharedPreferences
.
getBoolean
(
Key
.
isAutoConnect
,
false
))
{
BootReceiver
.
setEnabled
(
activity
,
true
)
getPreferenceManager
.
getSharedPreferences
.
edit
.
remove
(
Key
.
isAutoConnect
).
apply
getPreferenceManager
.
getSharedPreferences
.
edit
.
remove
(
Key
.
isAutoConnect
).
apply
()
}
switch
.
setChecked
(
BootReceiver
.
getEnabled
(
activity
))
...
...
@@ -200,13 +200,13 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
tfo
.
setSummary
(
getString
(
R
.
string
.
tcp_fastopen_summary_unsupported
,
java
.
lang
.
System
.
getProperty
(
"os.version"
)))
}
findPreference
(
"recovery"
).
setOnPreferenceClickListener
(
(
preference
:
Preference
)
=>
{
findPreference
(
"recovery"
).
setOnPreferenceClickListener
(
_
=>
{
app
.
track
(
TAG
,
"reset"
)
activity
.
recovery
()
true
})
findPreference
(
"about"
).
setOnPreferenceClickListener
(
(
preference
:
Preference
)
=>
{
findPreference
(
"about"
).
setOnPreferenceClickListener
(
_
=>
{
app
.
track
(
TAG
,
"about"
)
val
web
=
new
WebView
(
activity
)
web
.
loadUrl
(
"file:///android_asset/pages/about.html"
)
...
...
@@ -231,7 +231,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
})
}
override
def
onDisplayPreferenceDialog
(
preference
:
Preference
)
=
preference
.
getKey
match
{
override
def
onDisplayPreferenceDialog
(
preference
:
Preference
)
:
Unit
=
preference
.
getKey
match
{
case
Key
.
kcpcli
=>
displayPreferenceDialog
(
Key
.
kcpcli
,
new
KcpCliPreferenceDialogFragment
())
case
_
=>
super
.
onDisplayPreferenceDialog
(
preference
)
}
...
...
@@ -253,16 +253,16 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
isProxyApps
.
setChecked
(
profile
.
proxyApps
)
}
override
def
onDestroy
{
override
def
onDestroy
()
{
super
.
onDestroy
()
app
.
settings
.
unregisterOnSharedPreferenceChangeListener
(
this
)
}
def
onSharedPreferenceChanged
(
pref
:
SharedPreferences
,
key
:
String
)
=
key
match
{
def
onSharedPreferenceChanged
(
pref
:
SharedPreferences
,
key
:
String
)
:
Unit
=
key
match
{
case
Key
.
isNAT
=>
activity
.
handler
.
post
(()
=>
{
activity
.
detachService
activity
.
attachService
activity
.
detachService
()
activity
.
attachService
Callback
()
})
case
_
=>
}
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksTileService.scala
View file @
a5df60ae
...
...
@@ -36,7 +36,7 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
private
lazy
val
iconBusy
=
Icon
.
createWithResource
(
this
,
R
.
drawable
.
ic_start_busy
)
private
lazy
val
iconConnected
=
Icon
.
createWithResource
(
this
,
R
.
drawable
.
ic_start_connected
)
private
lazy
val
callback
=
new
IShadowsocksServiceCallback
.
Stub
{
def
trafficUpdated
(
txRate
:
Long
,
rxRate
:
Long
,
txTotal
:
Long
,
rxTotal
:
Long
)
=
()
def
trafficUpdated
(
txRate
:
Long
,
rxRate
:
Long
,
txTotal
:
Long
,
rxTotal
:
Long
)
:
Unit
=
()
def
stateChanged
(
state
:
Int
,
profileName
:
String
,
msg
:
String
)
{
val
tile
=
getQsTile
if
(
tile
!=
null
)
{
...
...
@@ -54,23 +54,23 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
tile
.
setLabel
(
getString
(
R
.
string
.
app_name
))
tile
.
setState
(
Tile
.
STATE_UNAVAILABLE
)
}
tile
.
updateTile
tile
.
updateTile
()
}
}
}
override
def
onServiceConnected
()
=
callback
.
stateChanged
(
bgService
.
getState
,
bgService
.
getProfileName
,
null
)
override
def
onServiceConnected
()
:
Unit
=
callback
.
stateChanged
(
bgService
.
getState
,
bgService
.
getProfileName
,
null
)
override
def
onStartListening
{
super
.
onStartListening
override
def
onStartListening
()
{
super
.
onStartListening
()
attachService
(
callback
)
}
override
def
onStopListening
{
super
.
onStopListening
detachService
// just in case the user switches to NAT mode, also saves battery
override
def
onStopListening
()
{
super
.
onStopListening
()
detachService
()
// just in case the user switches to NAT mode, also saves battery
}
override
def
onClick
()
=
if
(
isLocked
)
unlockAndRun
(
toggle
)
else
toggle
()
override
def
onClick
()
:
Unit
=
if
(
isLocked
)
unlockAndRun
(
toggle
)
else
toggle
()
private
def
toggle
()
=
if
(
bgService
!=
null
)
bgService
.
getState
match
{
case
State
.
STOPPED
=>
Utils
.
startSsService
(
this
)
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
View file @
a5df60ae
...
...
@@ -61,7 +61,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
override
def
onRevoke
()
{
stopRunner
(
true
)
stopRunner
(
stopService
=
true
)
}
override
def
stopRunner
(
stopService
:
Boolean
,
msg
:
String
=
null
)
{
...
...
@@ -120,14 +120,14 @@ class ShadowsocksVpnService extends VpnService with BaseService {
val
i
=
new
Intent
(
this
,
classOf
[
ShadowsocksRunnerActivity
])
i
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
startActivity
(
i
)
stopRunner
(
true
)
stopRunner
(
stopService
=
true
)
return
}
super
.
startRunner
(
profile
)
}
override
def
connect
()
=
{
override
def
connect
()
{
super
.
connect
()
vpnThread
=
new
ShadowsocksVpnThread
(
this
)
...
...
@@ -253,7 +253,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
sslocalProcess
=
new
GuardedProcess
(
cmd
).
start
()
}
def
startDnsTunnel
()
=
{
def
startDnsTunnel
()
{
val
conf
=
if
(
profile
.
kcp
)
{
ConfigUtils
.
SHADOWSOCKS
.
formatLocal
(
Locale
.
ENGLISH
,
"127.0.0.1"
,
profile
.
localPort
+
90
,
profile
.
localPort
+
63
,
...
...
@@ -291,20 +291,17 @@ class ShadowsocksVpnService extends VpnService with BaseService {
val
reject
=
if
(
profile
.
ipv6
)
"224.0.0.0/3"
else
"224.0.0.0/3, ::/0"
val
protect
=
"protect = \""
+
protectPath
+
"\";"
val
conf
=
profile
.
route
match
{
case
Route
.
BYPASS_CHN
|
Route
.
BYPASS_LAN_CHN
|
Route
.
GFWLIST
=>
{
case
Route
.
BYPASS_CHN
|
Route
.
BYPASS_LAN_CHN
|
Route
.
GFWLIST
=>
ConfigUtils
.
PDNSD_DIRECT
.
formatLocal
(
Locale
.
ENGLISH
,
protect
,
getApplicationInfo
.
dataDir
,
"0.0.0.0"
,
profile
.
localPort
+
53
,
"114.114.114.114, 223.5.5.5, 1.2.4.8"
,
getBlackList
,
reject
,
profile
.
localPort
+
63
,
reject
)
}
case
Route
.
CHINALIST
=>
{
case
Route
.
CHINALIST
=>
ConfigUtils
.
PDNSD_DIRECT
.
formatLocal
(
Locale
.
ENGLISH
,
protect
,
getApplicationInfo
.
dataDir
,
"0.0.0.0"
,
profile
.
localPort
+
53
,
"8.8.8.8, 8.8.4.4, 208.67.222.222"
,
""
,
reject
,
profile
.
localPort
+
63
,
reject
)
}
case
_
=>
{
case
_
=>
ConfigUtils
.
PDNSD_LOCAL
.
formatLocal
(
Locale
.
ENGLISH
,
protect
,
getApplicationInfo
.
dataDir
,
"0.0.0.0"
,
profile
.
localPort
+
53
,
profile
.
localPort
+
63
,
reject
)
}
}
Utils
.
printToFile
(
new
File
(
getApplicationInfo
.
dataDir
+
"/pdnsd-vpn.conf"
))(
p
=>
{
p
.
println
(
conf
)
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksVpnThread.scala
View file @
a5df60ae
...
...
@@ -21,6 +21,7 @@
package
com.github.shadowsocks
import
java.io.
{
File
,
FileDescriptor
,
IOException
}
import
java.lang.reflect.Method
import
java.util.concurrent.Executors
import
android.net.
{
LocalServerSocket
,
LocalSocket
,
LocalSocketAddress
}
...
...
@@ -28,14 +29,14 @@ import android.util.Log
import
com.github.shadowsocks.ShadowsocksApplication.app
object
ShadowsocksVpnThread
{
val
getInt
=
classOf
[
FileDescriptor
].
getDeclaredMethod
(
"getInt$"
)
val
getInt
:
Method
=
classOf
[
FileDescriptor
].
getDeclaredMethod
(
"getInt$"
)
}
class
ShadowsocksVpnThread
(
vpnService
:
ShadowsocksVpnService
)
extends
Thread
{
import
ShadowsocksVpnThread._
val
TAG
=
"ShadowsocksVpnService"
lazy
val
PATH
=
vpnService
.
getApplicationInfo
.
dataDir
+
"/protect_path"
lazy
val
PATH
:
String
=
vpnService
.
getApplicationInfo
.
dataDir
+
"/protect_path"
@volatile
var
isRunning
:
Boolean
=
true
@volatile
var
serverSocket
:
LocalServerSocket
=
_
...
...
src/main/scala/com/github/shadowsocks/TaskerActivity.scala
View file @
a5df60ae
...
...
@@ -39,13 +39,13 @@ class TaskerActivity extends AppCompatActivity {
{
val
typedArray
=
obtainStyledAttributes
(
Array
(
android
.
R
.
attr
.
selectableItemBackground
))
view
.
setBackgroundResource
(
typedArray
.
getResourceId
(
0
,
0
))
typedArray
.
recycle
typedArray
.
recycle
()
}
private
var
item
:
Profile
=
_
private
val
text
=
itemView
.
findViewById
(
android
.
R
.
id
.
text1
).
asInstanceOf
[
CheckedTextView
]
itemView
.
setOnClickListener
(
this
)
def
bindDefault
{
def
bindDefault
()
{
item
=
null
text
.
setText
(
R
.
string
.
profile_default
)
text
.
setChecked
(
taskerOption
.
profileId
<
0
)
...
...
@@ -60,15 +60,15 @@ class TaskerActivity extends AppCompatActivity {
taskerOption
.
switchOn
=
switch
.
isChecked
taskerOption
.
profileId
=
if
(
item
==
null
)
-
1
else
item
.
id
setResult
(
Activity
.
RESULT_OK
,
taskerOption
.
toIntent
(
TaskerActivity
.
this
))
finish
finish
()
}
}
private
class
ProfilesAdapter
extends
RecyclerView
.
Adapter
[
ProfileViewHolder
]
{
val
profiles
=
app
.
profileManager
.
getAllProfiles
.
getOrElse
(
List
.
empty
[
Profile
])
def
getItemCount
=
1
+
profiles
.
length
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
=
i
match
{
case
0
=>
vh
.
bindDefault
val
profiles
:
List
[
Profile
]
=
app
.
profileManager
.
getAllProfiles
.
getOrElse
(
List
.
empty
[
Profile
])
def
getItemCount
:
Int
=
1
+
profiles
.
length
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
:
Unit
=
i
match
{
case
0
=>
vh
.
bindDefault
()
case
_
=>
vh
.
bind
(
profiles
(
i
-
1
))
}
private
val
name
=
"select_dialog_singlechoice_"
+
(
if
(
Build
.
VERSION
.
SDK_INT
>=
21
)
"material"
else
"holo"
)
...
...
src/main/scala/com/github/shadowsocks/TaskerReceiver.scala
View file @
a5df60ae
...
...
@@ -30,11 +30,9 @@ import com.github.shadowsocks.ShadowsocksApplication.app
class
TaskerReceiver
extends
BroadcastReceiver
{
override
def
onReceive
(
context
:
Context
,
intent
:
Intent
)
{
val
settings
=
TaskerSettings
.
fromIntent
(
intent
)
val
switched
=
app
.
profileManager
.
getProfile
(
settings
.
profileId
)
match
{
case
Some
(
p
)
=>
app
.
switchProfile
(
settings
.
profileId
)
true
case
_
=>
false
app
.
profileManager
.
getProfile
(
settings
.
profileId
)
match
{
case
Some
(
_
)
=>
app
.
switchProfile
(
settings
.
profileId
)
case
_
=>
}
if
(
settings
.
switchOn
)
Utils
.
startSsService
(
context
)
else
Utils
.
stopSsService
(
context
)
}
...
...
src/main/scala/com/github/shadowsocks/database/DBHelper.scala
View file @
a5df60ae
...
...
@@ -36,9 +36,9 @@ object DBHelper {
final
val
PROFILE
=
"profile.db"
private
var
apps
:
mutable.Buffer
[
ApplicationInfo
]
=
_
def
isAllDigits
(
x
:
String
)
=
!
x
.
isEmpty
&&
(
x
forall
Character
.
isDigit
)
def
isAllDigits
(
x
:
String
)
:
Boolean
=
!
x
.
isEmpty
&&
(
x
forall
Character
.
isDigit
)
def
updateProxiedApps
(
context
:
Context
,
old
:
String
)
=
{
def
updateProxiedApps
(
context
:
Context
,
old
:
String
)
:
String
=
{
synchronized
(
if
(
apps
==
null
)
apps
=
context
.
getPackageManager
.
getInstalledApplications
(
0
).
asScala
)
val
uidSet
=
old
.
split
(
'|'
).
filter
(
isAllDigits
).
map
(
_
.
toInt
).
toSet
apps
.
filter
(
ai
=>
uidSet
.
contains
(
ai
.
uid
)).
map
(
_
.
packageName
).
mkString
(
"\n"
)
...
...
src/main/scala/com/github/shadowsocks/database/Profile.scala
View file @
a5df60ae
...
...
@@ -95,9 +95,9 @@ class Profile {
@DatabaseField
var
kcpcli
:
String
=
"--crypt none --mode normal --mtu 1200 --nocomp --dscp 46 --parityshard 0"
override
def
toString
=
"ss://"
+
Base64
.
encodeToString
(
"%s%s:%s@%s:%d"
.
formatLocal
(
Locale
.
ENGLISH
,
override
def
toString
:
String
=
"ss://"
+
Base64
.
encodeToString
(
"%s%s:%s@%s:%d"
.
formatLocal
(
Locale
.
ENGLISH
,
method
,
if
(
auth
)
"-auth"
else
""
,
password
,
host
,
remotePort
).
getBytes
,
Base64
.
NO_PADDING
|
Base64
.
NO_WRAP
)
+
'#'
+
URLEncoder
.
encode
(
name
,
"utf-8"
)
def
isMethodUnsafe
=
"table"
.
equalsIgnoreCase
(
method
)
||
"rc4"
.
equalsIgnoreCase
(
method
)
def
isMethodUnsafe
:
Boolean
=
"table"
.
equalsIgnoreCase
(
method
)
||
"rc4"
.
equalsIgnoreCase
(
method
)
}
src/main/scala/com/github/shadowsocks/database/ProfileManager.scala
View file @
a5df60ae
...
...
@@ -31,7 +31,7 @@ class ProfileManager(dbHelper: DBHelper) {
import
ProfileManager._
var
profileAddedListener
:
Profile
=>
Any
=
_
def
setProfileAddedListener
(
listener
:
Profile
=>
Any
)
=
this
.
profileAddedListener
=
listener
def
setProfileAddedListener
(
listener
:
Profile
=>
Any
)
:
Unit
=
this
.
profileAddedListener
=
listener
def
createProfile
(
p
:
Profile
=
null
)
:
Profile
=
{
val
profile
=
if
(
p
==
null
)
new
Profile
else
p
...
...
@@ -99,7 +99,7 @@ class ProfileManager(dbHelper: DBHelper) {
}
}
def
getFirstProfile
=
{
def
getFirstProfile
:
Option
[
Profile
]
=
{
try
{
val
result
=
dbHelper
.
profileDao
.
query
(
dbHelper
.
profileDao
.
queryBuilder
.
limit
(
1L
).
prepare
)
if
(
result
.
size
==
1
)
Option
(
result
.
get
(
0
))
else
None
...
...
src/main/scala/com/github/shadowsocks/job/AclSyncJob.scala
View file @
a5df60ae
...
...
@@ -36,7 +36,7 @@ import com.github.shadowsocks.utils.IOUtils
object
AclSyncJob
{
final
val
TAG
=
"AclSyncJob"
def
schedule
(
route
:
String
)
=
new
JobRequest
.
Builder
(
AclSyncJob
.
TAG
+
':'
+
route
)
def
schedule
(
route
:
String
)
:
Int
=
new
JobRequest
.
Builder
(
AclSyncJob
.
TAG
+
':'
+
route
)
.
setExecutionWindow
(
1
,
TimeUnit
.
DAYS
.
toMillis
(
28
))
.
setRequirementsEnforced
(
true
)
.
setRequiredNetworkType
(
JobRequest
.
NetworkType
.
UNMETERED
)
...
...
src/main/scala/com/github/shadowsocks/job/DonaldTrump.scala
View file @
a5df60ae
...
...
@@ -32,7 +32,7 @@ import com.evernote.android.job.JobCreator
* @author !Mygod
*/
object
DonaldTrump
extends
JobCreator
{
def
create
(
tag
:
String
)
=
{
def
create
(
tag
:
String
)
:
AclSyncJob
=
{
val
parts
=
tag
.
split
(
":"
)
parts
(
0
)
match
{
case
AclSyncJob
.
TAG
=>
new
AclSyncJob
(
parts
(
1
))
...
...
src/main/scala/com/github/shadowsocks/utils/CloseUtils.scala
View file @
a5df60ae
...
...
@@ -35,9 +35,9 @@ object CloseUtils {
block
(
a
.
get
)
}
finally
if
(
a
.
nonEmpty
)
try
{
val
v
=
a
.
get
if
(
v
ne
null
)
v
.
close
if
(
v
ne
null
)
v
.
close
()
}
catch
{
case
ignore
:
Exception
=>
case
_
:
Exception
=>
}
}
def
autoDisconnect
[
A
<:
Disconnectable
,
B
](
x
:
=>
A
)(
block
:
A
=>
B
)
:
B
=
{
...
...
@@ -47,9 +47,9 @@ object CloseUtils {
block
(
a
.
get
)
}
finally
if
(
a
.
nonEmpty
)
try
{
val
v
=
a
.
get
if
(
v
ne
null
)
v
.
disconnect
if
(
v
ne
null
)
v
.
disconnect
()
}
catch
{
case
ignore
:
Exception
=>
case
_
:
Exception
=>
}
}
}
src/main/scala/com/github/shadowsocks/utils/IOUtils.scala
View file @
a5df60ae
...
...
@@ -47,5 +47,6 @@ object IOUtils {
null
}
def
writeString
(
file
:
String
,
content
:
String
)
=
autoClose
(
new
FileWriter
(
file
))(
writer
=>
writer
.
write
(
content
))
def
writeString
(
file
:
String
,
content
:
String
)
:
Unit
=
autoClose
(
new
FileWriter
(
file
))(
writer
=>
writer
.
write
(
content
))
}
src/main/scala/com/github/shadowsocks/utils/Parser.scala
View file @
a5df60ae
...
...
@@ -30,23 +30,23 @@ object Parser {
private
val
pattern
=
"(?i)ss://([A-Za-z0-9+-/=_]+)(#(.+))?"
.
r
private
val
decodedPattern
=
"(?i)^((.+?)(-auth)??:(.*)@(.+?):(\\d+?))$"
.
r
def
findAll
(
data
:
CharSequence
)
=
pattern
.
findAllMatchIn
(
if
(
data
==
null
)
""
else
data
).
map
(
m
=>
try
decodedPattern
.
findFirstMatchIn
(
new
String
(
Base64
.
decode
(
m
.
group
(
1
),
Base64
.
NO_PADDING
),
"UTF-8"
))
match
{
case
Some
(
ss
)
=>
val
profile
=
new
Profile
profile
.
method
=
ss
.
group
(
2
).
toLowerCas
e
if
(
ss
.
group
(
3
)
!=
null
)
profile
.
auth
=
tru
e
profile
.
password
=
ss
.
group
(
4
)
profile
.
name
=
ss
.
group
(
5
)
profile
.
host
=
profile
.
name
profile
.
remotePort
=
ss
.
group
(
6
).
toInt
if
(
m
.
group
(
2
)
!=
null
)
profile
.
name
=
URLDecoder
.
decode
(
m
.
group
(
3
),
"utf-8"
)
profile
case
_
=>
null
}
catch
{
case
ex
:
Exception
=>
Log
.
e
(
TAG
,
"parser error: "
+
m
.
source
,
ex
)
// Ignore
null
}).
filter
(
_
!=
null
)
def
findAll
(
data
:
CharSequence
)
:
Iterator
[
Profile
]
=
pattern
.
findAllMatchIn
(
if
(
data
==
null
)
""
else
data
).
map
(
m
=>
try
decodedPattern
.
findFirstMatchIn
(
new
String
(
Base64
.
decode
(
m
.
group
(
1
),
Base64
.
NO_PADDING
),
"UTF-8"
))
match
{
case
Some
(
ss
)
=>
val
profile
=
new
Profil
e
profile
.
method
=
ss
.
group
(
2
).
toLowerCas
e
if
(
ss
.
group
(
3
)
!=
null
)
profile
.
auth
=
true
profile
.
password
=
ss
.
group
(
4
)
profile
.
name
=
ss
.
group
(
5
)
profile
.
host
=
profile
.
name
profile
.
remotePort
=
ss
.
group
(
6
).
toInt
if
(
m
.
group
(
2
)
!=
null
)
profile
.
name
=
URLDecoder
.
decode
(
m
.
group
(
3
),
"utf-8"
)
profile
case
_
=>
null
}
catch
{
case
ex
:
Exception
=>
Log
.
e
(
TAG
,
"parser error: "
+
m
.
source
,
ex
)
// Ignore
null
}).
filter
(
_
!=
null
)
}
src/main/scala/com/github/shadowsocks/utils/TaskerSettings.scala
View file @
a5df60ae
...
...
@@ -37,10 +37,10 @@ object TaskerSettings {
class
TaskerSettings
(
bundle
:
Bundle
)
{
import
TaskerSettings._
var
switchOn
=
bundle
.
getBoolean
(
KEY_SWITCH_ON
,
true
)
var
profileId
=
bundle
.
getInt
(
KEY_PROFILE_ID
,
-
1
)
var
switchOn
:
Boolean
=
bundle
.
getBoolean
(
KEY_SWITCH_ON
,
true
)
var
profileId
:
Int
=
bundle
.
getInt
(
KEY_PROFILE_ID
,
-
1
)
def
toIntent
(
context
:
Context
)
=
{
def
toIntent
(
context
:
Context
)
:
Intent
=
{
val
bundle
=
new
Bundle
()
if
(!
switchOn
)
bundle
.
putBoolean
(
KEY_SWITCH_ON
,
false
)
if
(
profileId
>=
0
)
bundle
.
putInt
(
KEY_PROFILE_ID
,
profileId
)
...
...
src/main/scala/com/github/shadowsocks/utils/TcpFastOpen.scala
View file @
a5df60ae
...
...
@@ -33,7 +33,7 @@ object TcpFastOpen {
/**
* Is kernel version >= 3.7.1.
*/
lazy
val
supported
=
"^(\\d+)\\.(\\d+)\\.(\\d+)"
.
r
.
findFirstMatchIn
(
System
.
getProperty
(
"os.version"
))
match
{
lazy
val
supported
:
Boolean
=
"^(\\d+)\\.(\\d+)\\.(\\d+)"
.
r
.
findFirstMatchIn
(
System
.
getProperty
(
"os.version"
))
match
{
case
Some
(
m
)
=>
val
kernel
=
m
.
group
(
1
).
toInt
if
(
kernel
<
3
)
false
else
if
(
kernel
>
3
)
true
else
{
...
...
@@ -43,7 +43,7 @@ object TcpFastOpen {
case
_
=>
false
}
def
sendEnabled
=
{
def
sendEnabled
:
Boolean
=
{
val
file
=
new
File
(
"/proc/sys/net/ipv4/tcp_fastopen"
)
file
.
canRead
&&
(
Utils
.
readAllLines
(
file
).
toInt
&
1
)
>
0
}
...
...
src/main/scala/com/github/shadowsocks/utils/TrafficMonitor.scala
View file @
a5df60ae
...
...
@@ -53,7 +53,7 @@ object TrafficMonitor {
else
numberFormat
.
format
(
n
)
+
' '
+
units
(
i
)
}
def
updateRate
()
=
{
def
updateRate
()
:
Boolean
=
{
val
now
=
System
.
currentTimeMillis
()
val
delta
=
now
-
timestampLast
var
updated
=
false
...
...
src/main/scala/com/github/shadowsocks/utils/TrafficMonitorThread.scala
View file @
a5df60ae
...
...
@@ -32,7 +32,7 @@ import com.github.shadowsocks.ShadowsocksApplication.app
class
TrafficMonitorThread
(
context
:
Context
)
extends
Thread
{
val
TAG
=
"TrafficMonitorThread"
lazy
val
PATH
=
context
.
getApplicationInfo
.
dataDir
+
"/stat_path"
lazy
val
PATH
:
String
=
context
.
getApplicationInfo
.
dataDir
+
"/stat_path"
@volatile
var
serverSocket
:
LocalServerSocket
=
_
@volatile
var
isRunning
:
Boolean
=
true
...
...
src/main/scala/com/github/shadowsocks/utils/Utils.scala
View file @
a5df60ae
...
...
@@ -66,7 +66,7 @@ object Utils {
*/
// Based on: http://stackoverflow.com/a/21026866/2245107
def
positionToast
(
toast
:
Toast
,
view
:
View
,
window
:
Window
,
offsetX
:
Int
=
0
,
offsetY
:
Int
=
0
)
=
{
def
positionToast
(
toast
:
Toast
,
view
:
View
,
window
:
Window
,
offsetX
:
Int
=
0
,
offsetY
:
Int
=
0
)
:
Toast
=
{
val
rect
=
new
Rect
window
.
getDecorView
.
getWindowVisibleDisplayFrame
(
rect
)
val
viewLocation
=
new
Array
[
Int
](
2
)
...
...
@@ -88,11 +88,11 @@ object Utils {
to
.
setVisibility
(
View
.
VISIBLE
)
to
.
animate
().
alpha
(
1
).
setDuration
(
shortAnimTime
)
from
.
animate
().
alpha
(
0
).
setDuration
(
shortAnimTime
).
setListener
(
new
AnimatorListenerAdapter
{
override
def
onAnimationEnd
(
animation
:
Animator
)
=
from
.
setVisibility
(
View
.
GONE
)
override
def
onAnimationEnd
(
animation
:
Animator
)
:
Unit
=
from
.
setVisibility
(
View
.
GONE
)
})
}
def
readAllLines
(
f
:
File
)
=
{
def
readAllLines
(
f
:
File
)
:
String
=
{
val
scanner
=
new
Scanner
(
f
)
try
{
scanner
.
useDelimiter
(
"\\Z"
)
...
...
@@ -168,40 +168,18 @@ object Utils {
}
}
}
catch
{
case
e
:
Exception
=>
case
_
:
Exception
=>
}
None
}
def
resolve
(
host
:
String
)
:
Option
[
String
]
=
{
try
{
val
addr
=
InetAddress
.
getByName
(
host
)
Some
(
addr
.
getHostAddress
)
}
catch
{
case
e
:
UnknownHostException
=>
None
}
def
resolve
(
host
:
String
)
:
Option
[
String
]
=
try
Some
(
InetAddress
.
getByName
(
host
).
getHostAddress
)
catch
{
case
_:
UnknownHostException
=>
None
}
def
resolve
(
host
:
String
,
enableIPv6
:
Boolean
)
:
Option
[
String
]
=
{
if
(
enableIPv6
&&
Utils
.
isIPv6Support
)
{
resolve
(
host
,
Type
.
AAAA
)
match
{
case
Some
(
addr
)
=>
return
Some
(
addr
)
case
None
=>
}
}
resolve
(
host
,
Type
.
A
)
match
{
case
Some
(
addr
)
=>
return
Some
(
addr
)
case
None
=>
}
resolve
(
host
)
match
{
case
Some
(
addr
)
=>
return
Some
(
addr
)
case
None
=>
}
None
}
def
resolve
(
host
:
String
,
enableIPv6
:
Boolean
)
:
Option
[
String
]
=
(
if
(
enableIPv6
&&
Utils
.
isIPv6Support
)
resolve
(
host
,
Type
.
AAAA
)
else
None
).
orElse
(
resolve
(
host
,
Type
.
A
))
.
orElse
(
resolve
(
host
))
private
lazy
val
isNumericMethod
=
classOf
[
InetAddress
].
getMethod
(
"isNumeric"
,
classOf
[
String
])
def
isNumeric
(
address
:
String
)
:
Boolean
=
isNumericMethod
.
invoke
(
null
,
address
).
asInstanceOf
[
Boolean
]
...
...
@@ -242,5 +220,5 @@ object Utils {
case
_
=>
}
def
ThrowableFuture
[
T
](
f
:
=>
T
)
=
Future
(
f
)
onComplete
handleFailure
def
ThrowableFuture
[
T
](
f
:
=>
T
)
:
Unit
=
Future
(
f
)
onComplete
handleFailure
}
src/main/scala/com/github/shadowsocks/widget/FloatingActionMenuBehavior.scala
View file @
a5df60ae
...
...
@@ -42,10 +42,11 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
private
var
fabTranslationYAnimator
:
ValueAnimator
=
_
private
var
fabTranslationY
:
Float
=
_
override
def
layoutDependsOn
(
parent
:
CoordinatorLayout
,
child
:
FloatingActionMenu
,
dependency
:
View
)
=
override
def
layoutDependsOn
(
parent
:
CoordinatorLayout
,
child
:
FloatingActionMenu
,
dependency
:
View
)
:
Boolean
=
dependency
.
isInstanceOf
[
SnackbarLayout
]
override
def
onDependentViewChanged
(
parent
:
CoordinatorLayout
,
child
:
FloatingActionMenu
,
dependency
:
View
)
=
{
override
def
onDependentViewChanged
(
parent
:
CoordinatorLayout
,
child
:
FloatingActionMenu
,
dependency
:
View
)
:
Boolean
=
{
dependency
match
{
case
_:
SnackbarLayout
=>
var
targetTransY
=
parent
.
getDependencies
(
child
).
asScala
...
...
@@ -54,7 +55,7 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
if
(
targetTransY
>
0
)
targetTransY
=
0
if
(
fabTranslationY
!=
targetTransY
)
{
val
currentTransY
=
child
.
getTranslationY
if
(
fabTranslationYAnimator
!=
null
&&
fabTranslationYAnimator
.
isRunning
)
fabTranslationYAnimator
.
cancel
if
(
fabTranslationYAnimator
!=
null
&&
fabTranslationYAnimator
.
isRunning
)
fabTranslationYAnimator
.
cancel
()
if
(
child
.
isShown
&&
Math
.
abs
(
currentTransY
-
targetTransY
)
>
child
.
getHeight
*
0.667F
)
{
if
(
fabTranslationYAnimator
==
null
)
{
fabTranslationYAnimator
=
new
ValueAnimator
...
...
@@ -63,7 +64,7 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
child
.
setTranslationY
(
animation
.
getAnimatedValue
.
asInstanceOf
[
Float
]))
}
fabTranslationYAnimator
.
setFloatValues
(
currentTransY
,
targetTransY
)
fabTranslationYAnimator
.
start
fabTranslationYAnimator
.
start
()
}
else
child
.
setTranslationY
(
targetTransY
)
fabTranslationY
=
targetTransY
}
...
...
@@ -74,7 +75,7 @@ class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
override
def
onStartNestedScroll
(
parent
:
CoordinatorLayout
,
child
:
FloatingActionMenu
,
directTargetChild
:
View
,
target
:
View
,
nestedScrollAxes
:
Int
)
=
true
override
def
onNestedScroll
(
parent
:
CoordinatorLayout
,
child
:
FloatingActionMenu
,
target
:
View
,
dxConsumed
:
Int
,
dyConsumed
:
Int
,
dxUnconsumed
:
Int
,
dyUnconsumed
:
Int
)
=
{
dyConsumed
:
Int
,
dxUnconsumed
:
Int
,
dyUnconsumed
:
Int
)
{
super
.
onNestedScroll
(
parent
,
child
,
target
,
dxConsumed
,
dyConsumed
,
dxUnconsumed
,
dyUnconsumed
)
val
dy
=
dyConsumed
+
dyUnconsumed
if
(
child
.
isMenuButtonHidden
)
{
...
...
src/main/scala/com/github/shadowsocks/widget/UndoSnackbarManager.scala
View file @
a5df60ae
...
...
@@ -37,12 +37,12 @@ class UndoSnackbarManager[T](view: View, undo: Iterator[(Int, T)] => Unit,
commit
:
Iterator
[(
Int
,
T
)]
=>
Unit
=
null
)
{
private
val
recycleBin
=
new
ArrayBuffer
[(
Int
,
T
)]
private
val
removedCallback
=
new
Snackbar
.
Callback
{
override
def
onDismissed
(
snackbar
:
Snackbar
,
event
:
Int
)
=
{
override
def
onDismissed
(
snackbar
:
Snackbar
,
event
:
Int
)
{
event
match
{
case
Snackbar
.
Callback
.
DISMISS_EVENT_SWIPE
|
Snackbar
.
Callback
.
DISMISS_EVENT_MANUAL
|
Snackbar
.
Callback
.
DISMISS_EVENT_TIMEOUT
=>
if
(
commit
!=
null
)
commit
(
recycleBin
.
iterator
)
recycleBin
.
clear
recycleBin
.
clear
()
case
_
=>
}
last
=
null
...
...
@@ -50,7 +50,7 @@ class UndoSnackbarManager[T](view: View, undo: Iterator[(Int, T)] => Unit,
}
private
var
last
:
Snackbar
=
_
def
remove
(
index
:
Int
,
item
:
T
)
=
{
def
remove
(
index
:
Int
,
item
:
T
)
{
recycleBin
.
append
((
index
,
item
))
val
count
=
recycleBin
.
length
last
=
Snackbar
...
...
@@ -59,8 +59,8 @@ class UndoSnackbarManager[T](view: View, undo: Iterator[(Int, T)] => Unit,
undo
(
recycleBin
.
reverseIterator
)
recycleBin
.
clear
})
:
View.OnClickListener
)
last
.
show
last
.
show
()
}
def
flush
=
if
(
last
!=
null
)
last
.
dismiss
def
flush
()
:
Unit
=
if
(
last
!=
null
)
last
.
dismiss
()
}
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