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
685f8408
Unverified
Commit
685f8408
authored
Jun 10, 2019
by
Mygod
Committed by
GitHub
Jun 10, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2161 from shadowsocks/q-beta
Enhancements for Android Q beta
parents
2172abfe
0f0e0b26
Changes
30
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
173 additions
and
80 deletions
+173
-80
build.gradle
build.gradle
+5
-6
core/.gitignore
core/.gitignore
+1
-0
core/build.gradle
core/build.gradle
+4
-5
core/src/main/AndroidManifest.xml
core/src/main/AndroidManifest.xml
+1
-0
core/src/main/java/com/github/shadowsocks/Core.kt
core/src/main/java/com/github/shadowsocks/Core.kt
+2
-0
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
+1
-2
core/src/main/java/com/github/shadowsocks/bg/DnsResolverCompat.kt
.../main/java/com/github/shadowsocks/bg/DnsResolverCompat.kt
+83
-0
core/src/main/java/com/github/shadowsocks/bg/Executable.kt
core/src/main/java/com/github/shadowsocks/bg/Executable.kt
+1
-1
core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
.../src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
+1
-2
core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
+7
-4
core/src/main/java/com/github/shadowsocks/database/PrivateDatabase.kt
...n/java/com/github/shadowsocks/database/PrivateDatabase.kt
+1
-0
core/src/main/java/com/github/shadowsocks/database/PublicDatabase.kt
...in/java/com/github/shadowsocks/database/PublicDatabase.kt
+1
-0
core/src/main/java/com/github/shadowsocks/net/DefaultNetworkListener.kt
...java/com/github/shadowsocks/net/DefaultNetworkListener.kt
+5
-7
core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt
...rc/main/java/com/github/shadowsocks/net/LocalDnsServer.kt
+1
-1
core/src/main/java/com/github/shadowsocks/plugin/ResolvedPlugin.kt
...main/java/com/github/shadowsocks/plugin/ResolvedPlugin.kt
+2
-2
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
+12
-6
gradle.properties
gradle.properties
+0
-1
mobile/build.gradle
mobile/build.gradle
+1
-2
mobile/src/main/java/com/github/shadowsocks/AppManager.kt
mobile/src/main/java/com/github/shadowsocks/AppManager.kt
+2
-2
mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
...om/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
+4
-4
mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
...main/java/com/github/shadowsocks/ProfileConfigFragment.kt
+2
-2
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
.../src/main/java/com/github/shadowsocks/ProfilesFragment.kt
+4
-4
mobile/src/main/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
...in/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
+1
-1
mobile/src/main/java/com/github/shadowsocks/preference/BottomSheetPreferenceDialogFragment.kt
...owsocks/preference/BottomSheetPreferenceDialogFragment.kt
+1
-1
mobile/src/main/java/com/github/shadowsocks/widget/StatsBar.kt
...e/src/main/java/com/github/shadowsocks/widget/StatsBar.kt
+12
-9
plugin/build.gradle
plugin/build.gradle
+2
-3
plugin/src/main/java/com/github/shadowsocks/plugin/NativePluginProvider.kt
...ava/com/github/shadowsocks/plugin/NativePluginProvider.kt
+8
-7
plugin/src/main/java/com/github/shadowsocks/plugin/PathProvider.kt
...c/main/java/com/github/shadowsocks/plugin/PathProvider.kt
+4
-3
tv/build.gradle
tv/build.gradle
+0
-1
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
.../java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
+4
-4
No files found.
build.gradle
View file @
685f8408
...
...
@@ -7,12 +7,11 @@ buildscript {
javaVersion
=
JavaVersion
.
VERSION_1_8
kotlinVersion
=
'1.3.31'
minSdkVersion
=
21
sdkVersion
=
28
compileSdkVersion
=
28
buildToolsVersion
=
'28.0.3'
sdkVersion
=
29
compileSdkVersion
=
29
junitVersion
=
'4.12'
androidTestVersion
=
'1.
1.1
'
androidEspressoVersion
=
'3.
1.1
'
androidTestVersion
=
'1.
2.0
'
androidEspressoVersion
=
'3.
2.0
'
versionCode
=
4080050
versionName
=
'4.8.0-nightly'
resConfigs
=
[
'es'
,
'fa'
,
'fr'
,
'ja'
,
'ko'
,
'ru'
,
'tr'
,
'zh-rCN'
,
'zh-rTW'
]
...
...
@@ -27,7 +26,7 @@ buildscript {
}
dependencies
{
classpath
'com.android.tools.build:gradle:3.
4.1
'
classpath
'com.android.tools.build:gradle:3.
5.0-beta04
'
classpath
'com.github.ben-manes:gradle-versions-plugin:0.21.0'
classpath
'com.google.gms:google-services:4.2.0'
classpath
'com.vanniktech:gradle-maven-publish-plugin:0.8.0'
...
...
core/.gitignore
View file @
685f8408
/build
/.cxx/
core/build.gradle
View file @
685f8408
...
...
@@ -4,7 +4,6 @@ apply plugin: 'kotlin-android-extensions'
apply
plugin:
'kotlin-kapt'
android
{
buildToolsVersion
rootProject
.
buildToolsVersion
compileSdkVersion
rootProject
.
compileSdkVersion
defaultConfig
{
...
...
@@ -48,14 +47,14 @@ androidExtensions {
experimental
=
true
}
def
lifecycleVersion
=
'2.
0.0
'
def
roomVersion
=
'2.
0.0
'
def
lifecycleVersion
=
'2.
1.0-beta01
'
def
roomVersion
=
'2.
1.0-rc01
'
dependencies
{
api
project
(
':plugin'
)
api
"androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
api
"androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
api
"androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
api
'androidx.preference:preference:1.1.0-
alpha05
'
api
'androidx.preference:preference:1.1.0-
beta01
'
api
"androidx.room:room-runtime:$roomVersion"
api
'androidx.work:work-runtime-ktx:2.0.1'
api
'com.crashlytics.sdk.android:crashlytics:2.10.1'
...
...
@@ -69,5 +68,5 @@ dependencies {
androidTestImplementation
"androidx.room:room-testing:$roomVersion"
androidTestImplementation
"androidx.test:runner:$androidTestVersion"
androidTestImplementation
"androidx.test.espresso:espresso-core:$androidEspressoVersion"
androidTestImplementation
'androidx.test.ext:junit-ktx:1.1.
0
'
androidTestImplementation
'androidx.test.ext:junit-ktx:1.1.
1-beta01
'
}
core/src/main/AndroidManifest.xml
View file @
685f8408
...
...
@@ -17,6 +17,7 @@
android:icon=
"@mipmap/ic_launcher"
android:allowBackup=
"true"
android:backupAgent=
"com.github.shadowsocks.ConfigBackupHelper"
android:extractNativeLibs=
"true"
android:fullBackupContent=
"@xml/backup_descriptor"
android:fullBackupOnly=
"true"
android:label=
"@string/app_name"
...
...
core/src/main/java/com/github/shadowsocks/Core.kt
View file @
685f8408
...
...
@@ -31,6 +31,7 @@ import android.content.Intent
import
android.content.IntentFilter
import
android.content.pm.PackageInfo
import
android.content.pm.PackageManager
import
android.net.ConnectivityManager
import
android.os.Build
import
android.os.UserManager
import
androidx.annotation.RequiresApi
...
...
@@ -61,6 +62,7 @@ object Core {
lateinit
var
app
:
Application
lateinit
var
configureIntent
:
(
Context
)
->
PendingIntent
val
connectivity
by
lazy
{
app
.
getSystemService
<
ConnectivityManager
>()
!!
}
val
packageInfo
:
PackageInfo
by
lazy
{
getPackageInfo
(
app
.
packageName
)
}
val
deviceStorage
by
lazy
{
if
(
Build
.
VERSION
.
SDK_INT
<
24
)
app
else
DeviceStorageApp
(
app
)
}
val
analytics
:
FirebaseAnalytics
by
lazy
{
FirebaseAnalytics
.
getInstance
(
deviceStorage
)
}
...
...
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
View file @
685f8408
...
...
@@ -46,7 +46,6 @@ import com.google.firebase.analytics.FirebaseAnalytics
import
kotlinx.coroutines.*
import
java.io.File
import
java.net.BindException
import
java.net.InetAddress
import
java.net.URL
import
java.net.UnknownHostException
import
java.util.*
...
...
@@ -298,7 +297,7 @@ object BaseService {
listOfNotNull
(
data
.
proxy
,
data
.
udpFallback
).
forEach
{
it
.
trafficMonitor
?.
persistStats
(
it
.
profile
.
id
)
}
suspend
fun
preInit
()
{
}
suspend
fun
resolver
(
host
:
String
)
=
InetAddress
.
getAllByName
(
host
)
suspend
fun
resolver
(
host
:
String
)
=
DnsResolverCompat
.
resolveOnActiveNetwork
(
host
)
suspend
fun
openConnection
(
url
:
URL
)
=
url
.
openConnection
()
fun
onStartCommand
(
intent
:
Intent
?,
flags
:
Int
,
startId
:
Int
):
Int
{
...
...
core/src/main/java/com/github/shadowsocks/bg/DnsResolverCompat.kt
0 → 100644
View file @
685f8408
/*******************************************************************************
* *
* Copyright (C) 2019 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2019 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
package
com.github.shadowsocks.bg
import
android.annotation.TargetApi
import
android.net.DnsResolver
import
android.net.Network
import
android.os.Build
import
android.os.CancellationSignal
import
com.github.shadowsocks.Core
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.async
import
kotlinx.coroutines.suspendCancellableCoroutine
import
java.net.InetAddress
import
java.util.concurrent.Executor
import
kotlin.coroutines.resume
import
kotlin.coroutines.resumeWithException
sealed
class
DnsResolverCompat
{
companion
object
:
DnsResolverCompat
()
{
private
val
instance
by
lazy
{
if
(
Build
.
VERSION
.
SDK_INT
>=
29
)
DnsResolverCompat29
else
DnsResolverCompat21
}
override
suspend
fun
resolve
(
network
:
Network
,
host
:
String
)
=
instance
.
resolve
(
network
,
host
)
override
suspend
fun
resolveOnActiveNetwork
(
host
:
String
)
=
instance
.
resolveOnActiveNetwork
(
host
)
}
abstract
suspend
fun
resolve
(
network
:
Network
,
host
:
String
):
Array
<
InetAddress
>
abstract
suspend
fun
resolveOnActiveNetwork
(
host
:
String
):
Array
<
InetAddress
>
private
object
DnsResolverCompat21
:
DnsResolverCompat
()
{
override
suspend
fun
resolve
(
network
:
Network
,
host
:
String
)
=
GlobalScope
.
async
(
Dispatchers
.
IO
)
{
network
.
getAllByName
(
host
)
}.
await
()
override
suspend
fun
resolveOnActiveNetwork
(
host
:
String
)
=
GlobalScope
.
async
(
Dispatchers
.
IO
)
{
InetAddress
.
getAllByName
(
host
)
}.
await
()
}
@TargetApi
(
29
)
private
object
DnsResolverCompat29
:
DnsResolverCompat
()
{
/**
* This executor will run on its caller directly. On Q beta 3, this results in calling in main thread.
*/
private
object
InPlaceExecutor
:
Executor
{
override
fun
execute
(
command
:
Runnable
?)
=
command
!!
.
run
()
}
override
suspend
fun
resolve
(
network
:
Network
,
host
:
String
):
Array
<
InetAddress
>
{
return
suspendCancellableCoroutine
{
cont
->
val
signal
=
CancellationSignal
()
cont
.
invokeOnCancellation
{
signal
.
cancel
()
}
// retry should be handled by client instead
DnsResolver
.
getInstance
().
query
(
network
,
host
,
DnsResolver
.
FLAG_NO_RETRY
,
InPlaceExecutor
,
signal
,
object
:
DnsResolver
.
Callback
<
Collection
<
InetAddress
>>
{
override
fun
onAnswer
(
answer
:
Collection
<
InetAddress
>,
rcode
:
Int
)
=
cont
.
resume
(
answer
.
toTypedArray
())
override
fun
onError
(
error
:
DnsResolver
.
DnsException
)
=
cont
.
resumeWithException
(
error
)
})
}
}
override
suspend
fun
resolveOnActiveNetwork
(
host
:
String
):
Array
<
InetAddress
>
{
return
resolve
(
Core
.
connectivity
.
activeNetwork
?:
return
emptyArray
(),
host
)
}
}
}
core/src/main/java/com/github/shadowsocks/bg/Executable.kt
View file @
685f8408
...
...
@@ -37,7 +37,7 @@ object Executable {
private
val
EXECUTABLES
=
setOf
(
SS_LOCAL
,
REDSOCKS
,
TUN2SOCKS
)
fun
killAll
()
{
for
(
process
in
File
(
"/proc"
).
listFiles
{
_
,
name
->
TextUtils
.
isDigitsOnly
(
name
)
})
{
for
(
process
in
File
(
"/proc"
).
listFiles
{
_
,
name
->
TextUtils
.
isDigitsOnly
(
name
)
}
?:
return
)
{
val
exe
=
File
(
try
{
File
(
process
,
"cmdline"
).
inputStream
().
bufferedReader
().
readText
()
}
catch
(
_
:
IOException
)
{
...
...
core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
View file @
685f8408
...
...
@@ -84,8 +84,7 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro
if
(
profile
.
host
.
parseNumericAddress
()
==
null
)
{
var
retries
=
0
while
(
true
)
try
{
val
io
=
GlobalScope
.
async
(
Dispatchers
.
IO
)
{
service
.
resolver
(
profile
.
host
)
}
profile
.
host
=
io
.
await
().
firstOrNull
()
?.
hostAddress
?:
throw
UnknownHostException
()
profile
.
host
=
service
.
resolver
(
profile
.
host
).
firstOrNull
()
?.
hostAddress
?:
throw
UnknownHostException
()
return
}
catch
(
e
:
UnknownHostException
)
{
// retries are only needed on Chrome OS where arc0 is brought up/down during VPN changes
...
...
core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
View file @
685f8408
...
...
@@ -108,8 +108,8 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
if
(
active
&&
Build
.
VERSION
.
SDK_INT
>=
22
)
setUnderlyingNetworks
(
underlyingNetworks
)
}
private
val
underlyingNetworks
get
()
=
// clearing underlyingNetworks makes Android 9
+
consider the network to be metered
if
(
Build
.
VERSION
.
SDK_INT
>
=
28
&&
metered
)
null
else
underlyingNetwork
?.
let
{
arrayOf
(
it
)
}
// clearing underlyingNetworks makes Android 9 consider the network to be metered
if
(
Build
.
VERSION
.
SDK_INT
=
=
28
&&
metered
)
null
else
underlyingNetwork
?.
let
{
arrayOf
(
it
)
}
override
fun
onBind
(
intent
:
Intent
)
=
when
(
intent
.
action
)
{
SERVICE_INTERFACE
->
super
<
BaseVpnService
>.
onBind
(
intent
)
...
...
@@ -139,7 +139,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
}
override
suspend
fun
preInit
()
=
DefaultNetworkListener
.
start
(
this
)
{
underlyingNetwork
=
it
}
override
suspend
fun
resolver
(
host
:
String
)
=
D
efaultNetworkListener
.
get
().
getAllByName
(
host
)
override
suspend
fun
resolver
(
host
:
String
)
=
D
nsResolverCompat
.
resolve
(
DefaultNetworkListener
.
get
(),
host
)
override
suspend
fun
openConnection
(
url
:
URL
)
=
DefaultNetworkListener
.
get
().
openConnection
(
url
)
override
suspend
fun
startProcesses
()
{
...
...
@@ -195,7 +195,10 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
metered
=
profile
.
metered
active
=
true
// possible race condition here?
if
(
Build
.
VERSION
.
SDK_INT
>=
22
)
builder
.
setUnderlyingNetworks
(
underlyingNetworks
)
if
(
Build
.
VERSION
.
SDK_INT
>=
22
)
{
builder
.
setUnderlyingNetworks
(
underlyingNetworks
)
if
(
Build
.
VERSION
.
SDK_INT
>=
29
)
builder
.
setMetered
(
metered
)
}
val
conn
=
builder
.
establish
()
?:
throw
NullConnectionException
()
this
.
conn
=
conn
...
...
core/src/main/java/com/github/shadowsocks/database/PrivateDatabase.kt
View file @
685f8408
...
...
@@ -39,6 +39,7 @@ abstract class PrivateDatabase : RoomDatabase() {
Migration27
,
Migration28
)
.
enableMultiInstanceInvalidation
()
.
fallbackToDestructiveMigration
()
.
allowMainThreadQueries
()
.
build
()
...
...
core/src/main/java/com/github/shadowsocks/database/PublicDatabase.kt
View file @
685f8408
...
...
@@ -36,6 +36,7 @@ abstract class PublicDatabase : RoomDatabase() {
.
addMigrations
(
Migration3
)
.
enableMultiInstanceInvalidation
()
.
fallbackToDestructiveMigration
()
.
build
()
}
...
...
core/src/main/java/com/github/shadowsocks/net/DefaultNetworkListener.kt
View file @
685f8408
...
...
@@ -26,9 +26,8 @@ import android.net.Network
import
android.net.NetworkCapabilities
import
android.net.NetworkRequest
import
android.os.Build
import
androidx.core.content.getSystemService
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.Core
.app
import
com.github.shadowsocks.Core
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
...
...
@@ -84,7 +83,7 @@ object DefaultNetworkListener {
suspend
fun
start
(
key
:
Any
,
listener
:
(
Network
?)
->
Unit
)
=
networkActor
.
send
(
NetworkMessage
.
Start
(
key
,
listener
))
suspend
fun
get
()
=
if
(
fallback
)
@TargetApi
(
23
)
{
connectivity
.
activeNetwork
?:
throw
UnknownHostException
()
// failed to listen, return current if available
Core
.
connectivity
.
activeNetwork
?:
throw
UnknownHostException
()
// failed to listen, return current if available
}
else
NetworkMessage
.
Get
().
run
{
networkActor
.
send
(
this
)
response
.
await
()
...
...
@@ -102,7 +101,6 @@ object DefaultNetworkListener {
}
private
var
fallback
=
false
private
val
connectivity
=
app
.
getSystemService
<
ConnectivityManager
>()
!!
private
val
request
=
NetworkRequest
.
Builder
().
apply
{
addCapability
(
NetworkCapabilities
.
NET_CAPABILITY_INTERNET
)
addCapability
(
NetworkCapabilities
.
NET_CAPABILITY_NOT_RESTRICTED
)
...
...
@@ -119,16 +117,16 @@ object DefaultNetworkListener {
*/
private
fun
register
()
{
if
(
Build
.
VERSION
.
SDK_INT
in
24
..
27
)
@TargetApi
(
24
)
{
connectivity
.
registerDefaultNetworkCallback
(
Callback
)
Core
.
connectivity
.
registerDefaultNetworkCallback
(
Callback
)
}
else
try
{
fallback
=
false
// we want REQUEST here instead of LISTEN
connectivity
.
requestNetwork
(
request
,
Callback
)
Core
.
connectivity
.
requestNetwork
(
request
,
Callback
)
}
catch
(
e
:
SecurityException
)
{
// known bug: https://stackoverflow.com/a/33509180/2245107
if
(
Build
.
VERSION
.
SDK_INT
!=
23
)
Crashlytics
.
logException
(
e
)
fallback
=
true
}
}
private
fun
unregister
()
=
connectivity
.
unregisterNetworkCallback
(
Callback
)
private
fun
unregister
()
=
Core
.
connectivity
.
unregisterNetworkCallback
(
Callback
)
}
core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt
View file @
685f8408
...
...
@@ -126,7 +126,7 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd
if
(
forwardOnly
)
return
@supervisorScope
remote
.
await
()
if
(
remoteDomainMatcher
?.
containsMatchIn
(
host
)
==
true
)
return
@supervisorScope
remote
.
await
()
val
localResults
=
try
{
withTimeout
(
TIMEOUT
)
{
GlobalScope
.
async
(
Dispatchers
.
IO
)
{
localResolver
(
host
)
}.
await
(
)
}
withTimeout
(
TIMEOUT
)
{
localResolver
(
host
)
}
}
catch
(
_
:
TimeoutCancellationException
)
{
Crashlytics
.
log
(
Log
.
WARN
,
TAG
,
"Local resolving timed out, falling back to remote resolving"
)
return
@supervisorScope
remote
.
await
()
...
...
core/src/main/java/com/github/shadowsocks/plugin/ResolvedPlugin.kt
View file @
685f8408
...
...
@@ -30,10 +30,10 @@ import com.github.shadowsocks.utils.signaturesCompat
abstract
class
ResolvedPlugin
(
protected
val
resolveInfo
:
ResolveInfo
)
:
Plugin
()
{
protected
abstract
val
metaData
:
Bundle
override
val
id
:
String
by
lazy
{
metaData
.
getString
(
PluginContract
.
METADATA_KEY_ID
)
}
override
val
id
:
String
by
lazy
{
metaData
.
getString
(
PluginContract
.
METADATA_KEY_ID
)
!!
}
override
val
label
:
CharSequence
by
lazy
{
resolveInfo
.
loadLabel
(
app
.
packageManager
)
}
override
val
icon
:
Drawable
by
lazy
{
resolveInfo
.
loadIcon
(
app
.
packageManager
)
}
override
val
defaultConfig
:
String
by
lazy
{
metaData
.
getString
(
PluginContract
.
METADATA_KEY_DEFAULT_CONFIG
)
}
override
val
defaultConfig
:
String
?
by
lazy
{
metaData
.
getString
(
PluginContract
.
METADATA_KEY_DEFAULT_CONFIG
)
}
override
val
packageName
:
String
get
()
=
resolveInfo
.
resolvePackageName
override
val
trusted
by
lazy
{
Core
.
getPackageInfo
(
packageName
).
signaturesCompat
.
any
(
PluginManager
.
trustedSignatures
::
contains
)
...
...
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
View file @
685f8408
...
...
@@ -20,6 +20,7 @@
package
com.github.shadowsocks.utils
import
android.annotation.SuppressLint
import
android.content.BroadcastReceiver
import
android.content.ContentResolver
import
android.content.Context
...
...
@@ -36,25 +37,30 @@ import android.util.TypedValue
import
androidx.annotation.AttrRes
import
androidx.preference.Preference
import
com.crashlytics.android.Crashlytics
import
kotlinx.coroutines.*
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.suspendCancellableCoroutine
import
kotlinx.coroutines.withContext
import
java.net.HttpURLConnection
import
java.net.InetAddress
import
kotlin.coroutines.resume
val
Throwable
.
readableMessage
get
()
=
localizedMessage
?:
javaClass
.
name
private
val
parseNumericAddress
by
lazy
{
private
val
parseNumericAddress
by
lazy
@SuppressLint
(
"DiscouragedPrivateApi"
)
{
InetAddress
::
class
.
java
.
getDeclaredMethod
(
"parseNumericAddress"
,
String
::
class
.
java
).
apply
{
isAccessible
=
true
}
}
/**
* A slightly more performant variant of
InetAddress.
parseNumericAddress.
* A slightly more performant variant of parseNumericAddress.
*
* Bug: https://issuetracker.google.com/issues/123456213
* Bug
in Android 9.0 and lower
: https://issuetracker.google.com/issues/123456213
*/
fun
String
.
parseNumericAddress
():
InetAddress
?
=
Os
.
inet_pton
(
OsConstants
.
AF_INET
,
this
)
?:
Os
.
inet_pton
(
OsConstants
.
AF_INET6
,
this
)
?.
let
{
parseNumericAddress
.
invoke
(
null
,
this
)
as
InetAddress
}
fun
String
?.
parseNumericAddress
():
InetAddress
?
=
Os
.
inet_pton
(
OsConstants
.
AF_INET
,
this
)
?:
Os
.
inet_pton
(
OsConstants
.
AF_INET6
,
this
)
?.
let
{
if
(
Build
.
VERSION
.
SDK_INT
>=
29
)
it
else
parseNumericAddress
.
invoke
(
null
,
this
)
as
InetAddress
}
fun
<
K
,
V
>
MutableMap
<
K
,
V
>.
computeIfAbsentCompat
(
key
:
K
,
value
:
()
->
V
)
=
if
(
Build
.
VERSION
.
SDK_INT
>=
24
)
computeIfAbsent
(
key
)
{
value
()
}
else
this
[
key
]
?:
value
().
also
{
put
(
key
,
it
)
}
...
...
gradle.properties
View file @
685f8408
...
...
@@ -10,7 +10,6 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
android.enableJetifier
=
true
android.enableR8
=
true
android.enableR8.fullMode
=
true
android.useAndroidX
=
true
...
...
mobile/build.gradle
View file @
685f8408
...
...
@@ -17,7 +17,6 @@ def getCurrentFlavor() {
}
android
{
buildToolsVersion
rootProject
.
buildToolsVersion
compileSdkVersion
rootProject
.
compileSdkVersion
defaultConfig
{
applicationId
"com.github.shadowsocks"
...
...
@@ -61,7 +60,7 @@ androidExtensions {
dependencies
{
implementation
project
(
':core'
)
implementation
'androidx.browser:browser:1.0.0'
implementation
'androidx.constraintlayout:constraintlayout:
1.1.3
'
implementation
'androidx.constraintlayout:constraintlayout:
2.0.0-beta1
'
implementation
'com.google.android.gms:play-services-vision:17.0.2'
implementation
'com.google.firebase:firebase-ads:17.2.1'
implementation
'com.takisoft.preferencex:preferencex-simplemenu:1.0.0'
...
...
mobile/src/main/java/com/github/shadowsocks/AppManager.kt
View file @
685f8408
...
...
@@ -266,8 +266,8 @@ class AppManager : AppCompatActivity() {
return
true
}
R
.
id
.
action_export_clipboard
->
{
clipboard
.
primaryClip
=
ClipData
.
newPlainText
(
Key
.
individual
,
"${DataStore.bypass}\n${DataStore.individual}"
)
clipboard
.
setPrimaryClip
(
ClipData
.
newPlainText
(
Key
.
individual
,
"${DataStore.bypass}\n${DataStore.individual}"
)
)
Snackbar
.
make
(
list
,
R
.
string
.
action_export_msg
,
Snackbar
.
LENGTH_LONG
).
show
()
return
true
}
...
...
mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
View file @
685f8408
...
...
@@ -78,15 +78,15 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
tfo
.
summary
=
getString
(
R
.
string
.
tcp_fastopen_summary_unsupported
,
System
.
getProperty
(
"os.version"
))
}
hosts
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Monospace
hosts
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Monospace
)
hosts
.
summaryProvider
=
HostsSummaryProvider
val
serviceMode
=
findPreference
<
Preference
>(
Key
.
serviceMode
)
!!
val
portProxy
=
findPreference
<
EditTextPreference
>(
Key
.
portProxy
)
!!
portProxy
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Port
portProxy
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Port
)
val
portLocalDns
=
findPreference
<
EditTextPreference
>(
Key
.
portLocalDns
)
!!
portLocalDns
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Port
portLocalDns
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Port
)
val
portTransproxy
=
findPreference
<
EditTextPreference
>(
Key
.
portTransproxy
)
!!
portTransproxy
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Port
portTransproxy
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Port
)
val
onServiceModeChange
=
Preference
.
OnPreferenceChangeListener
{
_
,
newValue
->
val
(
enabledLocalDns
,
enabledTransproxy
)
=
when
(
newValue
as
String
?)
{
Key
.
modeProxy
->
Pair
(
false
,
false
)
...
...
mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
View file @
685f8408
...
...
@@ -74,7 +74,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
val
activity
=
requireActivity
()
profileId
=
activity
.
intent
.
getLongExtra
(
Action
.
EXTRA_PROFILE_ID
,
-
1L
)
addPreferencesFromResource
(
R
.
xml
.
pref_profile
)
findPreference
<
EditTextPreference
>(
Key
.
remotePort
)
!!
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Port
findPreference
<
EditTextPreference
>(
Key
.
remotePort
)
!!
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Port
)
findPreference
<
EditTextPreference
>(
Key
.
password
)
!!
.
summaryProvider
=
PasswordSummaryProvider
val
serviceMode
=
DataStore
.
serviceMode
findPreference
<
Preference
>(
Key
.
remoteDns
)
!!
.
isEnabled
=
serviceMode
!=
Key
.
modeProxy
...
...
@@ -104,7 +104,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
}
true
}
pluginConfigure
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Monospace
pluginConfigure
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Monospace
)
pluginConfigure
.
onPreferenceChangeListener
=
this
initPlugins
()
receiver
=
Core
.
listenForPackageChanges
(
false
)
{
initPlugins
()
}
...
...
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
View file @
685f8408
...
...
@@ -185,7 +185,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
true
}
R
.
id
.
action_export_clipboard
->
{
clipboard
.
primaryClip
=
ClipData
.
newPlainText
(
null
,
this
.
item
.
toString
(
))
clipboard
.
setPrimaryClip
(
ClipData
.
newPlainText
(
null
,
this
.
item
.
toString
()
))
true
}
else
->
false
...
...
@@ -381,7 +381,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
R
.
id
.
action_export_clipboard
->
{
val
profiles
=
ProfileManager
.
getAllProfiles
()
(
activity
as
MainActivity
).
snackbar
().
setText
(
if
(
profiles
!=
null
)
{
clipboard
.
primaryClip
=
ClipData
.
newPlainText
(
null
,
profiles
.
joinToString
(
"\n"
))
clipboard
.
setPrimaryClip
(
ClipData
.
newPlainText
(
null
,
profiles
.
joinToString
(
"\n"
)
))
R
.
string
.
action_export_msg
}
else
R
.
string
.
action_export_err
).
show
()
true
...
...
@@ -413,7 +413,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
try
{
ProfileManager
.
createProfilesFromJson
(
data
!!
.
datas
.
asSequence
().
map
{
activity
.
contentResolver
.
openInputStream
(
it
)
})
}
.
filterNotNull
()
)
}
catch
(
e
:
Exception
)
{
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
...
...
@@ -423,7 +423,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
try
{
ProfileManager
.
createProfilesFromJson
(
data
!!
.
datas
.
asSequence
().
map
{
activity
.
contentResolver
.
openInputStream
(
it
)
},
true
)
}
.
filterNotNull
()
,
true
)
}
catch
(
e
:
Exception
)
{
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
...
...
mobile/src/main/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
View file @
685f8408
...
...
@@ -427,7 +427,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
is
URL
->
acl
.
urls
.
add
(
it
)
}
}
clipboard
.
primaryClip
=
ClipData
.
newPlainText
(
null
,
acl
.
toString
(
))
clipboard
.
setPrimaryClip
(
ClipData
.
newPlainText
(
null
,
acl
.
toString
()
))
}
override
fun
onMenuItemClick
(
item
:
MenuItem
):
Boolean
=
when
(
item
.
itemId
)
{
...
...
mobile/src/main/java/com/github/shadowsocks/preference/BottomSheetPreferenceDialogFragment.kt
View file @
685f8408
...
...
@@ -99,7 +99,7 @@ class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
}
fun
setArg
(
key
:
String
)
{
arguments
=
bundleOf
(
PreferenceDialogFragmentCompat
.
ARG_KEY
to
key
)
arguments
=
bundleOf
(
ARG_KEY
to
key
)
}
private
val
preference
by
lazy
{
getPreference
()
as
IconListPreference
}
...
...
mobile/src/main/java/com/github/shadowsocks/widget/StatsBar.kt
View file @
685f8408
...
...
@@ -45,17 +45,20 @@ class StatsBar @JvmOverloads constructor(context: Context, attrs: AttributeSet?
private
lateinit
var
txRateText
:
TextView
private
lateinit
var
rxRateText
:
TextView
private
val
tester
=
ViewModelProviders
.
of
(
context
as
FragmentActivity
).
get
<
HttpsTest
>()
private
val
behavior
=
object
:
Behavior
()
{
val
threshold
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
stats_bar_scroll_threshold
)
override
fun
onNestedScroll
(
coordinatorLayout
:
CoordinatorLayout
,
child
:
BottomAppBar
,
target
:
View
,
dxConsumed
:
Int
,
dyConsumed
:
Int
,
dxUnconsumed
:
Int
,
dyUnconsumed
:
Int
,
type
:
Int
,
consumed
:
IntArray
)
{
val
dy
=
dyConsumed
+
dyUnconsumed
super
.
onNestedScroll
(
coordinatorLayout
,
child
,
target
,
dxConsumed
,
if
(
Math
.
abs
(
dy
)
>=
threshold
)
dy
else
0
,
dxUnconsumed
,
0
,
type
,
consumed
)
private
lateinit
var
behavior
:
Behavior
override
fun
getBehavior
():
Behavior
{
if
(!
this
::
behavior
.
isInitialized
)
behavior
=
object
:
Behavior
()
{
val
threshold
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
stats_bar_scroll_threshold
)
override
fun
onNestedScroll
(
coordinatorLayout
:
CoordinatorLayout
,
child
:
BottomAppBar
,
target
:
View
,
dxConsumed
:
Int
,
dyConsumed
:
Int
,
dxUnconsumed
:
Int
,
dyUnconsumed
:
Int
,
type
:
Int
,
consumed
:
IntArray
)
{
val
dy
=
dyConsumed
+
dyUnconsumed
super
.
onNestedScroll
(
coordinatorLayout
,
child
,
target
,
dxConsumed
,
if
(
Math
.
abs
(
dy
)
>=
threshold
)
dy
else
0
,
dxUnconsumed
,
0
,
type
,
consumed
)
}
}
return
behavior
}
override
fun
getBehavior
()
=
behavior
override
fun
setOnClickListener
(
l
:
OnClickListener
?)
{
statusText
=
findViewById
(
R
.
id
.
status
)
...
...
plugin/build.gradle
View file @
685f8408
...
...
@@ -14,7 +14,6 @@ def getRepositoryPassword() {
}
android
{
buildToolsVersion
rootProject
.
buildToolsVersion
compileSdkVersion
rootProject
.
compileSdkVersion
defaultConfig
{
...
...
@@ -54,8 +53,8 @@ mavenPublish {
}
dependencies
{
api
'androidx.core:core-ktx:1.
0.2
'
api
'com.google.android.material:material:1.1.0-alpha0
6
'
api
'androidx.core:core-ktx:1.
1.0-rc01
'
api
'com.google.android.material:material:1.1.0-alpha0
7
'
api
"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
testImplementation
"junit:junit:$junitVersion"
androidTestImplementation
"androidx.test:runner:$androidTestVersion"
...
...
plugin/src/main/java/com/github/shadowsocks/plugin/NativePluginProvider.kt
View file @
685f8408
...
...
@@ -49,7 +49,7 @@ import androidx.core.os.bundleOf
*</manifest></pre>
*/
abstract
class
NativePluginProvider
:
ContentProvider
()
{
override
fun
getType
(
p0
:
Uri
?):
String
=
"application/x-elf"
override
fun
getType
(
uri
:
Uri
):
String
?
=
"application/x-elf"
override
fun
onCreate
():
Boolean
=
true
...
...
@@ -61,7 +61,7 @@ abstract class NativePluginProvider : ContentProvider() {
protected
abstract
fun
populateFiles
(
provider
:
PathProvider
)
override
fun
query
(
uri
:
Uri
,
projection
:
Array
<
out
String
>?,
selection
:
String
?,
selectionArgs
:
Array
<
out
String
>?,
sortOrder
:
String
?):
Cursor
{
sortOrder
:
String
?):
Cursor
?
{
check
(
selection
==
null
&&
selectionArgs
==
null
&&
sortOrder
==
null
)
val
result
=
MatrixCursor
(
projection
)
populateFiles
(
PathProvider
(
uri
,
result
))
...
...
@@ -78,8 +78,8 @@ abstract class NativePluginProvider : ContentProvider() {
*/
open
fun
getExecutable
():
String
=
throw
UnsupportedOperationException
()
abstract
fun
openFile
(
uri
:
Uri
?
):
ParcelFileDescriptor
override
fun
openFile
(
uri
:
Uri
?,
mode
:
String
?
):
ParcelFileDescriptor
{
abstract
fun
openFile
(
uri
:
Uri
):
ParcelFileDescriptor
override
fun
openFile
(
uri
:
Uri
,
mode
:
String
):
ParcelFileDescriptor
{
check
(
mode
==
"r"
)
return
openFile
(
uri
)
}
...
...
@@ -90,8 +90,9 @@ abstract class NativePluginProvider : ContentProvider() {
}
// Methods that should not be used
override
fun
insert
(
p0
:
Uri
?,
p1
:
ContentValues
?):
Uri
=
throw
UnsupportedOperationException
()
override
fun
update
(
p0
:
Uri
?,
p1
:
ContentValues
?,
p2
:
String
?,
p3
:
Array
<
out
String
>?):
Int
=
override
fun
insert
(
uri
:
Uri
,
values
:
ContentValues
?):
Uri
?
=
throw
UnsupportedOperationException
()
override
fun
update
(
uri
:
Uri
,
values
:
ContentValues
?,
selection
:
String
?,
selectionArgs
:
Array
<
out
String
>?):
Int
=
throw
UnsupportedOperationException
()
override
fun
delete
(
uri
:
Uri
,
selection
:
String
?,
selectionArgs
:
Array
<
out
String
>?):
Int
=
throw
UnsupportedOperationException
()
override
fun
delete
(
p0
:
Uri
?,
p1
:
String
?,
p2
:
Array
<
out
String
>?):
Int
=
throw
UnsupportedOperationException
()
}
plugin/src/main/java/com/github/shadowsocks/plugin/PathProvider.kt
View file @
685f8408
...
...
@@ -41,13 +41,14 @@ class PathProvider internal constructor(baseUri: Uri, private val cursor: Matrix
var
sub
=
to
+
file
.
name
if
(
basePath
.
startsWith
(
sub
))
if
(
file
.
isDirectory
)
{
sub
+=
'/'
file
.
listFiles
().
forEach
{
addTo
(
it
,
sub
,
mode
)
}
file
.
listFiles
()
!!
.
forEach
{
addTo
(
it
,
sub
,
mode
)
}
}
else
addPath
(
sub
,
mode
)
return
this
}
fun
addAt
(
file
:
File
,
at
:
String
=
""
,
mode
:
Int
=
0b110100100
):
PathProvider
{
if
(
basePath
.
startsWith
(
at
))
if
(
file
.
isDirectory
)
file
.
listFiles
().
forEach
{
addTo
(
it
,
at
,
mode
)
}
else
addPath
(
at
,
mode
)
if
(
basePath
.
startsWith
(
at
))
{
if
(
file
.
isDirectory
)
file
.
listFiles
()
!!
.
forEach
{
addTo
(
it
,
at
,
mode
)
}
else
addPath
(
at
,
mode
)
}
return
this
}
}
tv/build.gradle
View file @
685f8408
...
...
@@ -17,7 +17,6 @@ def getCurrentFlavor() {
}
android
{
buildToolsVersion
rootProject
.
buildToolsVersion
compileSdkVersion
rootProject
.
compileSdkVersion
defaultConfig
{
applicationId
"com.github.shadowsocks.tv"
...
...
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
View file @
685f8408
...
...
@@ -184,11 +184,11 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
serviceMode
=
findPreference
(
Key
.
serviceMode
)
!!
shareOverLan
=
findPreference
(
Key
.
shareOverLan
)
!!
portProxy
=
findPreference
(
Key
.
portProxy
)
!!
portProxy
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Port
portProxy
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Port
)
portLocalDns
=
findPreference
(
Key
.
portLocalDns
)
!!
portLocalDns
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Port
portLocalDns
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Port
)
portTransproxy
=
findPreference
(
Key
.
portTransproxy
)
!!
portTransproxy
.
onBindEditTextListener
=
EditTextPreferenceModifiers
.
Port
portTransproxy
.
setOnBindEditTextListener
(
EditTextPreferenceModifiers
.
Port
)
serviceMode
.
onPreferenceChangeListener
=
onServiceModeChange
findPreference
<
Preference
>(
Key
.
about
)
!!
.
summary
=
getString
(
R
.
string
.
about_title
,
BuildConfig
.
VERSION_NAME
)
...
...
@@ -299,7 +299,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
try
{
ProfileManager
.
createProfilesFromJson
(
data
!!
.
datas
.
asSequence
().
map
{
context
.
contentResolver
.
openInputStream
(
it
)
},
true
)
}
.
filterNotNull
()
,
true
)
}
catch
(
e
:
Exception
)
{
printLog
(
e
)
Toast
.
makeText
(
context
,
e
.
readableMessage
,
Toast
.
LENGTH_SHORT
).
show
()
...
...
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