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
8e2c5812
Commit
8e2c5812
authored
Apr 21, 2020
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate to open source Firebase crashlytics
Fixes #2439.
parent
6cb488a9
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
156 additions
and
153 deletions
+156
-153
build.gradle
build.gradle
+1
-4
core/build.gradle
core/build.gradle
+4
-3
core/src/main/java/com/github/shadowsocks/Core.kt
core/src/main/java/com/github/shadowsocks/Core.kt
+23
-11
core/src/main/java/com/github/shadowsocks/VpnRequestActivity.kt
...rc/main/java/com/github/shadowsocks/VpnRequestActivity.kt
+2
-4
core/src/main/java/com/github/shadowsocks/acl/Acl.kt
core/src/main/java/com/github/shadowsocks/acl/Acl.kt
+2
-4
core/src/main/java/com/github/shadowsocks/acl/AclSyncer.kt
core/src/main/java/com/github/shadowsocks/acl/AclSyncer.kt
+2
-1
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
+14
-10
core/src/main/java/com/github/shadowsocks/bg/Executable.kt
core/src/main/java/com/github/shadowsocks/bg/Executable.kt
+3
-5
core/src/main/java/com/github/shadowsocks/bg/GuardedProcessPool.kt
...main/java/com/github/shadowsocks/bg/GuardedProcessPool.kt
+10
-13
core/src/main/java/com/github/shadowsocks/bg/LocalDnsWorker.kt
...src/main/java/com/github/shadowsocks/bg/LocalDnsWorker.kt
+4
-6
core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
.../src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
+2
-1
core/src/main/java/com/github/shadowsocks/bg/RemoteConfig.kt
core/src/main/java/com/github/shadowsocks/bg/RemoteConfig.kt
+8
-7
core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
+11
-7
core/src/main/java/com/github/shadowsocks/database/Profile.kt
.../src/main/java/com/github/shadowsocks/database/Profile.kt
+5
-6
core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt
...in/java/com/github/shadowsocks/database/ProfileManager.kt
+5
-5
core/src/main/java/com/github/shadowsocks/net/ConcurrentLocalSocketListener.kt
...m/github/shadowsocks/net/ConcurrentLocalSocketListener.kt
+2
-2
core/src/main/java/com/github/shadowsocks/net/DefaultNetworkListener.kt
...java/com/github/shadowsocks/net/DefaultNetworkListener.kt
+2
-2
core/src/main/java/com/github/shadowsocks/net/DnsResolverCompat.kt
...main/java/com/github/shadowsocks/net/DnsResolverCompat.kt
+3
-3
core/src/main/java/com/github/shadowsocks/net/LocalSocketListener.kt
...in/java/com/github/shadowsocks/net/LocalSocketListener.kt
+2
-2
core/src/main/java/com/github/shadowsocks/plugin/PluginConfiguration.kt
...java/com/github/shadowsocks/plugin/PluginConfiguration.kt
+2
-3
core/src/main/java/com/github/shadowsocks/plugin/PluginManager.kt
.../main/java/com/github/shadowsocks/plugin/PluginManager.kt
+10
-12
core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt
...om/github/shadowsocks/subscription/SubscriptionService.kt
+6
-6
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
+2
-7
core/src/main/java/com/github/shadowsocks/widget/AutoCollapseTextView.kt
...ava/com/github/shadowsocks/widget/AutoCollapseTextView.kt
+3
-3
mobile/build.gradle
mobile/build.gradle
+1
-1
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
+6
-5
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
.../src/main/java/com/github/shadowsocks/ProfilesFragment.kt
+4
-5
mobile/src/main/java/com/github/shadowsocks/ScannerActivity.kt
...e/src/main/java/com/github/shadowsocks/ScannerActivity.kt
+6
-5
mobile/src/main/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
...in/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
+6
-2
tv/build.gradle
tv/build.gradle
+1
-1
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
.../java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
+4
-7
No files found.
build.gradle
View file @
8e2c5812
...
...
@@ -22,9 +22,6 @@ buildscript {
repositories
{
google
()
jcenter
()
maven
{
url
'https://maven.fabric.io/public'
}
maven
{
url
"https://plugins.gradle.org/m2/"
}
...
...
@@ -34,10 +31,10 @@ buildscript {
classpath
'com.android.tools.build:gradle:4.0.0-beta04'
classpath
'com.github.ben-manes:gradle-versions-plugin:0.28.0'
classpath
'com.google.android.gms:oss-licenses-plugin:0.10.2'
classpath
'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04'
classpath
'com.google.gms:google-services:4.3.3'
classpath
'com.vanniktech:gradle-maven-publish-plugin:0.11.1'
classpath
'gradle.plugin.org.mozilla.rust-android-gradle:plugin:0.8.3'
classpath
'io.fabric.tools:gradle:1.31.2'
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}
...
...
core/build.gradle
View file @
8e2c5812
...
...
@@ -82,11 +82,12 @@ dependencies {
api
"androidx.room:room-runtime:$roomVersion"
api
"androidx.work:work-runtime-ktx:$workVersion"
api
"androidx.work:work-gcm:$workVersion"
api
'com.crashlytics.sdk.android:crashlytics:2.10.1'
api
'com.google.android.gms:play-services-oss-licenses:17.0.0'
api
'com.google.code.gson:gson:2.8.6'
api
'com.google.firebase:firebase-analytics:17.3.0'
api
'com.google.firebase:firebase-config:19.1.3'
api
'com.google.firebase:firebase-analytics-ktx:17.3.0'
api
'com.google.firebase:firebase-config-ktx:19.1.3'
api
'com.google.firebase:firebase-crashlytics:17.0.0-beta04'
api
'com.jakewharton.timber:timber:4.7.1'
api
'dnsjava:dnsjava:3.0.2'
api
"org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
api
"org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutinesVersion"
...
...
core/src/main/java/com/github/shadowsocks/Core.kt
View file @
8e2c5812
...
...
@@ -29,35 +29,38 @@ import android.content.pm.PackageManager
import
android.net.ConnectivityManager
import
android.os.Build
import
android.os.UserManager
import
android.util.Log
import
androidx.annotation.RequiresApi
import
androidx.annotation.VisibleForTesting
import
androidx.core.content.ContextCompat
import
androidx.core.content.getSystemService
import
androidx.work.Configuration
import
androidx.work.WorkManager
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.acl.Acl
import
com.github.shadowsocks.aidl.ShadowsocksConnection
import
com.github.shadowsocks.core.BuildConfig
import
com.github.shadowsocks.core.R
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.subscription.SubscriptionService
import
com.github.shadowsocks.utils.*
import
com.google.firebase.FirebaseApp
import
com.google.firebase.analytics.FirebaseAnalytics
import
io.fabric.sdk.android.Fabric
import
com.github.shadowsocks.utils.Action
import
com.github.shadowsocks.utils.DeviceStorageApp
import
com.github.shadowsocks.utils.DirectBoot
import
com.github.shadowsocks.utils.Key
import
com.google.firebase.crashlytics.FirebaseCrashlytics
import
com.google.firebase.ktx.Firebase
import
com.google.firebase.ktx.initialize
import
kotlinx.coroutines.DEBUG_PROPERTY_NAME
import
kotlinx.coroutines.DEBUG_PROPERTY_VALUE_ON
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
import
kotlin.reflect.KClass
object
Core
{
const
val
TAG
=
"Core"
lateinit
var
app
:
Application
@VisibleForTesting
set
lateinit
var
configureIntent
:
(
Context
)
->
PendingIntent
...
...
@@ -66,7 +69,6 @@ object Core {
val
notification
by
lazy
{
app
.
getSystemService
<
NotificationManager
>()
!!
}
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
)
}
val
directBootSupported
by
lazy
{
Build
.
VERSION
.
SDK_INT
>=
24
&&
app
.
getSystemService
<
DevicePolicyManager
>()
?.
storageEncryptionStatus
==
DevicePolicyManager
.
ENCRYPTION_STATUS_ACTIVE_PER_USER
...
...
@@ -104,8 +106,18 @@ object Core {
// overhead of debug mode is minimal: https://github.com/Kotlin/kotlinx.coroutines/blob/f528898/docs/debugging.md#debug-mode
System
.
setProperty
(
DEBUG_PROPERTY_NAME
,
DEBUG_PROPERTY_VALUE_ON
)
Fabric
.
with
(
deviceStorage
,
Crashlytics
())
// multiple processes needs manual set-up
FirebaseApp
.
initializeApp
(
deviceStorage
)
Firebase
.
initialize
(
deviceStorage
)
// multiple processes needs manual set-up
Timber
.
plant
(
object
:
Timber
.
DebugTree
()
{
override
fun
log
(
priority
:
Int
,
tag
:
String
?,
message
:
String
,
t
:
Throwable
?)
{
if
(
t
==
null
)
{
if
(
priority
!=
Log
.
DEBUG
||
BuildConfig
.
DEBUG
)
Log
.
println
(
priority
,
tag
,
message
)
FirebaseCrashlytics
.
getInstance
().
log
(
"${"
XXVDIWEF
".getOrElse(priority) { 'X' }}/$tag: $message"
)
}
else
{
if
(
priority
>=
Log
.
WARN
||
priority
==
Log
.
DEBUG
)
Log
.
println
(
priority
,
tag
,
message
)
if
(
priority
>=
Log
.
INFO
)
FirebaseCrashlytics
.
getInstance
().
recordException
(
t
)
}
}
})
WorkManager
.
initialize
(
deviceStorage
,
Configuration
.
Builder
().
apply
{
setExecutor
{
GlobalScope
.
launch
{
it
.
run
()
}
}
setTaskExecutor
{
GlobalScope
.
launch
{
it
.
run
()
}
}
...
...
@@ -121,7 +133,7 @@ object Core {
File
(
deviceStorage
.
noBackupFilesDir
,
file
).
outputStream
().
use
{
output
->
input
.
copyTo
(
output
)
}
}
}
catch
(
e
:
IOException
)
{
printLog
(
e
)
Timber
.
w
(
e
)
}
DataStore
.
publicStore
.
putLong
(
Key
.
assetUpdateTime
,
packageInfo
.
lastUpdateTime
)
}
...
...
core/src/main/java/com/github/shadowsocks/VpnRequestActivity.kt
View file @
8e2c5812
...
...
@@ -26,19 +26,17 @@ import android.content.Intent
import
android.content.IntentFilter
import
android.net.VpnService
import
android.os.Bundle
import
android.util.Log
import
android.widget.Toast
import
androidx.appcompat.app.AppCompatActivity
import
androidx.core.content.getSystemService
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.core.R
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.broadcastReceiver
import
timber.log.Timber
class
VpnRequestActivity
:
AppCompatActivity
()
{
companion
object
{
private
const
val
TAG
=
"VpnRequestActivity"
private
const
val
REQUEST_CONNECT
=
1
}
...
...
@@ -66,7 +64,7 @@ class VpnRequestActivity : AppCompatActivity() {
if
(
requestCode
!=
REQUEST_CONNECT
)
return
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
if
(
resultCode
==
RESULT_OK
)
Core
.
startService
()
else
{
Toast
.
makeText
(
this
,
R
.
string
.
vpn_permission_denied
,
Toast
.
LENGTH_LONG
).
show
()
Crashlytics
.
log
(
Log
.
ERROR
,
TAG
,
"Failed to start VpnService from onActivityResult: $data"
)
Timber
.
e
(
"Failed to start VpnService from onActivityResult: $data"
)
}
finish
()
}
...
...
core/src/main/java/com/github/shadowsocks/acl/Acl.kt
View file @
8e2c5812
...
...
@@ -21,9 +21,7 @@
package
com.github.shadowsocks.acl
import
android.content.Context
import
android.util.Log
import
androidx.recyclerview.widget.SortedList
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.net.Subnet
import
com.github.shadowsocks.preference.DataStore
...
...
@@ -33,6 +31,7 @@ import com.github.shadowsocks.utils.asIterable
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.ensureActive
import
kotlinx.coroutines.runBlocking
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
import
java.io.Reader
...
...
@@ -42,7 +41,6 @@ import kotlin.coroutines.coroutineContext
class
Acl
{
companion
object
{
const
val
TAG
=
"Acl"
const
val
ALL
=
"all"
const
val
BYPASS_LAN
=
"bypass-lan"
const
val
BYPASS_CHN
=
"bypass-china"
...
...
@@ -159,7 +157,7 @@ class Acl {
val
child
=
Acl
().
fromReader
(
connect
(
url
).
getInputStream
().
bufferedReader
(),
bypass
)
child
.
flatten
(
depth
-
1
,
connect
)
if
(
bypass
!=
child
.
bypass
)
{
Crashlytics
.
log
(
Log
.
WARN
,
TAG
,
"Imported network ACL has a conflicting mode set. "
+
Timber
.
w
(
"Imported network ACL has a conflicting mode set. "
+
"This will probably not work as intended. URL: $url"
)
child
.
subnets
.
clear
()
// subnets for the different mode are discarded
child
.
bypass
=
bypass
...
...
core/src/main/java/com/github/shadowsocks/acl/AclSyncer.kt
View file @
8e2c5812
...
...
@@ -24,6 +24,7 @@ import android.content.Context
import
androidx.work.*
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.utils.useCancellable
import
timber.log.Timber
import
java.io.IOException
import
java.net.HttpURLConnection
import
java.net.URL
...
...
@@ -52,7 +53,7 @@ class AclSyncer(context: Context, workerParams: WorkerParameters) : CoroutineWor
Acl
.
getFile
(
route
).
printWriter
().
use
{
it
.
write
(
acl
)
}
Result
.
success
()
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
(
)
Timber
.
d
(
e
)
if
(
runAttemptCount
>
5
)
Result
.
failure
()
else
Result
.
retry
()
}
}
core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
View file @
8e2c5812
...
...
@@ -25,10 +25,7 @@ import android.content.Context
import
android.content.Intent
import
android.content.IntentFilter
import
android.os.*
import
android.util.Log
import
androidx.core.content.getSystemService
import
androidx.core.os.bundleOf
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.BootReceiver
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.Core.app
...
...
@@ -40,9 +37,16 @@ import com.github.shadowsocks.core.R
import
com.github.shadowsocks.net.DnsResolverCompat
import
com.github.shadowsocks.net.HostsFile
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.*
import
com.github.shadowsocks.utils.Action
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.broadcastReceiver
import
com.github.shadowsocks.utils.readableMessage
import
com.google.firebase.analytics.FirebaseAnalytics
import
com.google.firebase.analytics.ktx.analytics
import
com.google.firebase.analytics.ktx.logEvent
import
com.google.firebase.ktx.Firebase
import
kotlinx.coroutines.*
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
import
java.net.URL
...
...
@@ -122,7 +126,7 @@ object BaseService {
work
(
callbacks
.
getBroadcastItem
(
it
))
}
catch
(
_
:
RemoteException
)
{
}
catch
(
e
:
Exception
)
{
printLog
(
e
)
Timber
.
w
(
e
)
}
}
}
finally
{
...
...
@@ -229,7 +233,7 @@ object BaseService {
when
{
s
==
State
.
Stopped
->
startRunner
()
s
.
canStop
->
stopRunner
(
true
)
else
->
Crashlytics
.
log
(
Log
.
WARN
,
tag
,
"Illegal state when invoking use: $s
"
)
else
->
Timber
.
w
(
"Illegal state $s when invoking use
"
)
}
}
...
...
@@ -271,7 +275,7 @@ object BaseService {
// channge the state
data
.
changeState
(
State
.
Stopping
)
GlobalScope
.
launch
(
Dispatchers
.
Main
.
immediate
)
{
Core
.
analytics
.
logEvent
(
"stop"
,
bundleOf
(
Pair
(
FirebaseAnalytics
.
Param
.
METHOD
,
tag
)))
Firebase
.
analytics
.
logEvent
(
"stop"
)
{
param
(
FirebaseAnalytics
.
Param
.
METHOD
,
tag
)
}
data
.
connectingJob
?.
cancelAndJoin
()
// ensure stop connecting first
this
@Interface
as
Service
// we use a coroutineScope here to allow clean-up in parallel
...
...
@@ -344,7 +348,7 @@ object BaseService {
}
data
.
notification
=
createNotification
(
profile
.
formattedName
)
Core
.
analytics
.
logEvent
(
"start"
,
bundleOf
(
Pair
(
FirebaseAnalytics
.
Param
.
METHOD
,
tag
)))
Firebase
.
analytics
.
logEvent
(
"start"
)
{
param
(
FirebaseAnalytics
.
Param
.
METHOD
,
tag
)
}
data
.
changeState
(
State
.
Connecting
)
data
.
connectingJob
=
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
...
...
@@ -365,7 +369,7 @@ object BaseService {
}
data
.
processes
=
GuardedProcessPool
{
printLog
(
it
)
Timber
.
w
(
it
)
stopRunner
(
false
,
it
.
readableMessage
)
}
startProcesses
(
hosts
)
...
...
@@ -379,7 +383,7 @@ object BaseService {
}
catch
(
_
:
UnknownHostException
)
{
stopRunner
(
false
,
getString
(
R
.
string
.
invalid_server
))
}
catch
(
exc
:
Throwable
)
{
if
(
exc
is
ExpectedException
)
exc
.
printStackTrace
()
else
printLog
(
exc
)
if
(
exc
is
ExpectedException
)
Timber
.
d
(
exc
)
else
Timber
.
w
(
exc
)
stopRunner
(
false
,
"${getString(R.string.service_failed)}: ${exc.readableMessage}"
)
}
finally
{
data
.
connectingJob
=
null
...
...
core/src/main/java/com/github/shadowsocks/bg/Executable.kt
View file @
8e2c5812
...
...
@@ -24,8 +24,7 @@ import android.system.ErrnoException
import
android.system.Os
import
android.system.OsConstants
import
android.text.TextUtils
import
android.util.Log
import
com.crashlytics.android.Crashlytics
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
...
...
@@ -47,9 +46,8 @@ object Executable {
Os
.
kill
(
process
.
name
.
toInt
(),
OsConstants
.
SIGKILL
)
}
catch
(
e
:
ErrnoException
)
{
if
(
e
.
errno
!=
OsConstants
.
ESRCH
)
{
e
.
printStackTrace
()
Crashlytics
.
log
(
Log
.
WARN
,
"kill"
,
"SIGKILL ${exe.absolutePath} (${process.name}) failed"
)
Crashlytics
.
logException
(
e
)
Timber
.
w
(
"SIGKILL ${exe.absolutePath} (${process.name}) failed"
)
Timber
.
w
(
e
)
}
}
}
...
...
core/src/main/java/com/github/shadowsocks/bg/GuardedProcessPool.kt
View file @
8e2c5812
...
...
@@ -25,13 +25,12 @@ import android.os.SystemClock
import
android.system.ErrnoException
import
android.system.Os
import
android.system.OsConstants
import
android.util.Log
import
androidx.annotation.MainThread
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.utils.Commandline
import
kotlinx.coroutines.*
import
kotlinx.coroutines.channels.Channel
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
import
java.io.InputStream
...
...
@@ -39,7 +38,6 @@ import kotlin.concurrent.thread
class
GuardedProcessPool
(
private
val
onFatal
:
suspend
(
IOException
)
->
Unit
)
:
CoroutineScope
{
companion
object
{
private
const
val
TAG
=
"GuardedProcessPool"
private
val
pid
by
lazy
{
Class
.
forName
(
"java.lang.ProcessManager\$ProcessImpl"
).
getDeclaredField
(
"pid"
).
apply
{
isAccessible
=
true
}
}
...
...
@@ -63,10 +61,10 @@ class GuardedProcessPool(private val onFatal: suspend (IOException) -> Unit) : C
try
{
while
(
true
)
{
thread
(
name
=
"stderr-$cmdName"
)
{
streamLogger
(
process
.
errorStream
)
{
Crashlytics
.
log
(
Log
.
ERROR
,
cmdName
,
it
)
}
streamLogger
(
process
.
errorStream
)
{
Timber
.
tag
(
cmdName
).
e
(
it
)
}
}
thread
(
name
=
"stdout-$cmdName"
)
{
streamLogger
(
process
.
inputStream
)
{
Crashlytics
.
log
(
Log
.
VERBOSE
,
cmdName
,
it
)
}
streamLogger
(
process
.
inputStream
)
{
Timber
.
tag
(
cmdName
).
v
(
it
)
}
// this thread also acts as a daemon thread for waitFor
runBlocking
{
exitChannel
.
send
(
process
.
waitFor
())
}
}
...
...
@@ -76,17 +74,16 @@ class GuardedProcessPool(private val onFatal: suspend (IOException) -> Unit) : C
when
{
SystemClock
.
elapsedRealtime
()
-
startTime
<
1000
->
throw
IOException
(
"$cmdName exits too fast (exit code: $exitCode)"
)
exitCode
==
128
+
OsConstants
.
SIGKILL
->
Crashlytics
.
log
(
Log
.
WARN
,
TAG
,
"$cmdName was killed"
)
else
->
Crashlytics
.
logException
(
IOException
(
"$cmdName unexpectedly exits with code $exitCode"
))
exitCode
==
128
+
OsConstants
.
SIGKILL
->
Timber
.
w
(
"$cmdName was killed"
)
else
->
Timber
.
w
(
IOException
(
"$cmdName unexpectedly exits with code $exitCode"
))
}
Crashlytics
.
log
(
Log
.
DEBUG
,
TAG
,
"restart process: ${Commandline.toString(cmd)} (last exit code: $exitCode)"
)
Timber
.
i
(
"restart process: ${Commandline.toString(cmd)} (last exit code: $exitCode)"
)
start
()
running
=
true
onRestartCallback
?.
invoke
()
}
}
catch
(
e
:
IOException
)
{
Crashlytics
.
log
(
Log
.
WARN
,
TAG
,
"error occurred. stop guard: "
+
Commandline
.
toString
(
cmd
)
)
Timber
.
w
(
"error occurred. stop guard: ${Commandline.toString(cmd)}"
)
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
onFatal
(
e
)
}
}
finally
{
if
(
running
)
withContext
(
NonCancellable
)
{
// clean-up cannot be cancelled
...
...
@@ -94,9 +91,9 @@ class GuardedProcessPool(private val onFatal: suspend (IOException) -> Unit) : C
try
{
Os
.
kill
(
pid
.
get
(
process
)
as
Int
,
OsConstants
.
SIGTERM
)
}
catch
(
e
:
ErrnoException
)
{
if
(
e
.
errno
!=
OsConstants
.
ESRCH
)
Crashlytics
.
logException
(
e
)
if
(
e
.
errno
!=
OsConstants
.
ESRCH
)
Timber
.
w
(
e
)
}
catch
(
e
:
ReflectiveOperationException
)
{
Crashlytics
.
logException
(
e
)
Timber
.
w
(
e
)
}
if
(
withTimeoutOrNull
(
500
)
{
exitChannel
.
receive
()
}
!=
null
)
return
@withContext
}
...
...
@@ -115,7 +112,7 @@ class GuardedProcessPool(private val onFatal: suspend (IOException) -> Unit) : C
@MainThread
fun
start
(
cmd
:
List
<
String
>,
onRestartCallback
:
(
suspend
()
->
Unit
)?
=
null
)
{
Crashlytics
.
log
(
Log
.
DEBUG
,
TAG
,
"start process: "
+
Commandline
.
toString
(
cmd
)
)
Timber
.
i
(
"start process: ${Commandline.toString(cmd)}"
)
Guard
(
cmd
).
apply
{
start
()
// if start fails, IOException will be thrown directly
launch
{
looper
(
onRestartCallback
)
}
...
...
core/src/main/java/com/github/shadowsocks/bg/LocalDnsWorker.kt
View file @
8e2c5812
package
com.github.shadowsocks.bg
import
android.net.LocalSocket
import
android.util.Log
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.net.ConcurrentLocalSocketListener
import
com.github.shadowsocks.net.DnsResolverCompat
import
com.github.shadowsocks.utils.printLog
import
kotlinx.coroutines.CancellationException
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.TimeoutCancellationException
import
kotlinx.coroutines.launch
import
org.xbill.DNS.Message
import
org.xbill.DNS.Rcode
import
timber.log.Timber
import
java.io.DataInputStream
import
java.io.DataOutputStream
import
java.io.File
...
...
@@ -31,10 +29,10 @@ class LocalDnsWorker(private val resolver: suspend (ByteArray) -> ByteArray) : C
resolver
(
query
)
}
catch
(
e
:
Exception
)
{
when
(
e
)
{
is
TimeoutCancellationException
->
Crashlytics
.
log
(
Log
.
WARN
,
name
,
"Resolving timed out"
)
is
TimeoutCancellationException
->
Timber
.
w
(
"Resolving timed out"
)
is
CancellationException
->
{
}
// ignore
is
IOException
->
Crashlytics
.
log
(
Log
.
WARN
,
name
,
e
.
messag
e
)
else
->
printLog
(
e
)
is
IOException
->
Timber
.
d
(
e
)
else
->
Timber
.
w
(
e
)
}
try
{
DnsResolverCompat
.
prepareDnsResponse
(
Message
(
query
)).
apply
{
...
...
core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
View file @
8e2c5812
...
...
@@ -34,6 +34,7 @@ import com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.parseNumericAddress
import
com.github.shadowsocks.utils.signaturesCompat
import
com.github.shadowsocks.utils.useCancellable
import
com.google.firebase.remoteconfig.ktx.get
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
...
...
@@ -60,7 +61,7 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro
scheduleConfigUpdate
=
!
success
val
conn
=
withContext
(
Dispatchers
.
IO
)
{
// Network.openConnection might use networking, see https://issuetracker.google.com/issues/135242093
service
.
openConnection
(
URL
(
config
.
getString
(
"proxy_url"
)))
as
HttpURLConnection
service
.
openConnection
(
URL
(
config
[
"proxy_url"
].
asString
(
)))
as
HttpURLConnection
}
conn
.
requestMethod
=
"POST"
conn
.
doOutput
=
true
...
...
core/src/main/java/com/github/shadowsocks/bg/RemoteConfig.kt
View file @
8e2c5812
...
...
@@ -20,19 +20,20 @@
package
com.github.shadowsocks.bg
import
android.util.Log
import
androidx.core.os.bundleOf
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.core.R
import
com.google.firebase.remoteconfig.FirebaseRemoteConfig
import
com.google.firebase.analytics.ktx.analytics
import
com.google.firebase.analytics.ktx.logEvent
import
com.google.firebase.ktx.Firebase
import
com.google.firebase.remoteconfig.ktx.remoteConfig
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.async
import
kotlinx.coroutines.tasks.await
import
timber.log.Timber
object
RemoteConfig
{
private
val
config
=
GlobalScope
.
async
(
Dispatchers
.
Main
.
immediate
)
{
Firebase
RemoteConfig
.
getInstance
()
.
apply
{
setDefaultsAsync
(
R
.
xml
.
default_configs
).
await
()
}
Firebase
.
remoteConfig
.
apply
{
setDefaultsAsync
(
R
.
xml
.
default_configs
).
await
()
}
}
fun
fetchAsync
()
=
GlobalScope
.
async
(
Dispatchers
.
Main
.
immediate
)
{
fetch
()
}
...
...
@@ -42,8 +43,8 @@ object RemoteConfig {
fetch
().
await
()
this
to
true
}
catch
(
e
:
Exception
)
{
Log
.
w
(
"RemoteConfig"
,
e
)
Core
.
analytics
.
logEvent
(
"femote_config_failure"
,
bundleOf
(
Pair
(
javaClass
.
simpleName
,
e
.
message
)))
Timber
.
d
(
e
)
Firebase
.
analytics
.
logEvent
(
"femote_config_failure"
)
{
param
(
"message"
,
e
.
toString
())
}
this
to
false
}
}
...
...
core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
View file @
8e2c5812
...
...
@@ -39,9 +39,13 @@ import com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.closeQuietly
import
com.github.shadowsocks.utils.int
import
com.github.shadowsocks.utils.printLog
import
kotlinx.coroutines.*
import
java.io.*
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
java.io.File
import
java.io.FileDescriptor
import
java.io.IOException
import
java.net.URL
import
android.net.VpnService
as
BaseVpnService
...
...
@@ -67,13 +71,13 @@ class VpnService : BaseVpnService(), BaseService.Interface {
}
catch
(
e
:
IOException
)
{
when
((
e
.
cause
as
?
ErrnoException
)
?.
errno
)
{
// also suppress ENONET (Machine is not on the network)
OsConstants
.
EPERM
,
64
->
e
.
printStackTrace
(
)
else
->
printLog
(
e
)
OsConstants
.
EPERM
,
64
->
Timber
.
d
(
e
)
else
->
Timber
.
w
(
e
)
}
return
@let
false
}
catch
(
e
:
ReflectiveOperationException
)
{
check
(
Build
.
VERSION
.
SDK_INT
<
23
)
printLog
(
e
)
Timber
.
w
(
e
)
}
protect
(
fd
.
int
)
})
0
else
1
)
...
...
@@ -169,7 +173,7 @@ class VpnService : BaseVpnService(), BaseService.Interface {
if
(
profile
.
bypass
)
builder
.
addDisallowedApplication
(
it
)
else
builder
.
addAllowedApplication
(
it
)
}
catch
(
ex
:
PackageManager
.
NameNotFoundException
)
{
printLog
(
ex
)
Timber
.
w
(
ex
)
}
}
if
(!
profile
.
bypass
)
builder
.
addAllowedApplication
(
me
)
...
...
core/src/main/java/com/github/shadowsocks/database/Profile.kt
View file @
8e2c5812
...
...
@@ -24,7 +24,6 @@ import android.annotation.TargetApi
import
android.net.Uri
import
android.os.Parcelable
import
android.util.Base64
import
android.util.Log
import
android.util.LongSparseArray
import
androidx.core.net.toUri
import
androidx.room.*
...
...
@@ -40,6 +39,7 @@ import com.google.gson.JsonPrimitive
import
kotlinx.android.parcel.Parcelize
import
org.json.JSONArray
import
org.json.JSONObject
import
timber.log.Timber
import
java.io.Serializable
import
java.net.URI
import
java.net.URISyntaxException
...
...
@@ -100,7 +100,6 @@ data class Profile(
}
companion
object
{
private
const
val
TAG
=
"ShadowParser"
private
const
val
serialVersionUID
=
1L
private
const
val
sponsored
=
"198.199.101.152"
private
val
pattern
=
...
...
@@ -124,7 +123,7 @@ data class Profile(
profile
.
name
=
uri
.
fragment
profile
}
else
{
Log
.
e
(
TAG
,
"Unrecognized URI: ${it.value}"
)
Timber
.
e
(
"Unrecognized URI: ${it.value}"
)
null
}
}
else
{
...
...
@@ -147,16 +146,16 @@ data class Profile(
profile
.
name
=
uri
.
fragment
?:
""
profile
}
catch
(
e
:
URISyntaxException
)
{
Log
.
e
(
TAG
,
"Invalid URI: ${it.value}"
)
Timber
.
e
(
"Invalid URI: ${it.value}"
)
null
}
}
else
{
Log
.
e
(
TAG
,
"Unknown user info: ${it.value}"
)
Timber
.
e
(
"Unknown user info: ${it.value}"
)
null
}
}
}
catch
(
e
:
IllegalArgumentException
)
{
Log
.
e
(
TAG
,
"Invalid base64 detected: ${it.value}"
)
Timber
.
e
(
"Invalid base64 detected: ${it.value}"
)
null
}
}.
filterNotNull
()
...
...
core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt
View file @
8e2c5812
...
...
@@ -26,9 +26,9 @@ import com.github.shadowsocks.Core
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.DirectBoot
import
com.github.shadowsocks.utils.forEachTry
import
com.github.shadowsocks.utils.printLog
import
com.google.gson.JsonStreamParser
import
org.json.JSONArray
import
timber.log.Timber
import
java.io.IOException
import
java.io.InputStream
import
java.sql.SQLException
...
...
@@ -94,7 +94,7 @@ object ProfileManager {
}
catch
(
ex
:
SQLiteCantOpenDatabaseException
)
{
throw
IOException
(
ex
)
}
catch
(
ex
:
SQLException
)
{
printLog
(
ex
)
Timber
.
w
(
ex
)
null
}
...
...
@@ -122,7 +122,7 @@ object ProfileManager {
}
catch
(
ex
:
SQLiteCantOpenDatabaseException
)
{
throw
IOException
(
ex
)
}
catch
(
ex
:
SQLException
)
{
printLog
(
ex
)
Timber
.
w
(
ex
)
false
}
if
(!
nonEmpty
)
DataStore
.
profileId
=
createProfile
().
id
...
...
@@ -134,7 +134,7 @@ object ProfileManager {
}
catch
(
ex
:
SQLiteCantOpenDatabaseException
)
{
throw
IOException
(
ex
)
}
catch
(
ex
:
SQLException
)
{
printLog
(
ex
)
Timber
.
w
(
ex
)
null
}
...
...
@@ -144,7 +144,7 @@ object ProfileManager {
}
catch
(
ex
:
SQLiteCantOpenDatabaseException
)
{
throw
IOException
(
ex
)
}
catch
(
ex
:
SQLException
)
{
printLog
(
ex
)
Timber
.
w
(
ex
)
null
}
}
core/src/main/java/com/github/shadowsocks/net/ConcurrentLocalSocketListener.kt
View file @
8e2c5812
...
...
@@ -21,13 +21,13 @@
package
com.github.shadowsocks.net
import
android.net.LocalSocket
import
com.github.shadowsocks.utils.printLog
import
kotlinx.coroutines.*
import
timber.log.Timber
import
java.io.File
abstract
class
ConcurrentLocalSocketListener
(
name
:
String
,
socketFile
:
File
)
:
LocalSocketListener
(
name
,
socketFile
),
CoroutineScope
{
override
val
coroutineContext
=
Dispatchers
.
IO
+
SupervisorJob
()
+
CoroutineExceptionHandler
{
_
,
t
->
printLog
(
t
)
}
override
val
coroutineContext
=
Dispatchers
.
IO
+
SupervisorJob
()
+
CoroutineExceptionHandler
{
_
,
t
->
Timber
.
w
(
t
)
}
override
fun
accept
(
socket
:
LocalSocket
)
{
launch
{
super
.
accept
(
socket
)
}
...
...
core/src/main/java/com/github/shadowsocks/net/DefaultNetworkListener.kt
View file @
8e2c5812
...
...
@@ -27,12 +27,12 @@ import android.net.NetworkCapabilities
import
android.net.NetworkRequest
import
android.os.Build
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.utils.printLog
import
kotlinx.coroutines.CompletableDeferred
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.channels.actor
import
kotlinx.coroutines.runBlocking
import
timber.log.Timber
import
java.net.UnknownHostException
object
DefaultNetworkListener
{
...
...
@@ -124,7 +124,7 @@ object DefaultNetworkListener {
Core
.
connectivity
.
requestNetwork
(
request
,
Callback
)
}
catch
(
e
:
SecurityException
)
{
// known bug: https://stackoverflow.com/a/33509180/2245107
if
(
Build
.
VERSION
.
SDK_INT
!=
23
)
printLog
(
e
)
if
(
Build
.
VERSION
.
SDK_INT
!=
23
)
Timber
.
w
(
e
)
fallback
=
true
}
}
...
...
core/src/main/java/com/github/shadowsocks/net/DnsResolverCompat.kt
View file @
8e2c5812
...
...
@@ -34,9 +34,9 @@ import com.github.shadowsocks.Core
import
com.github.shadowsocks.utils.closeQuietly
import
com.github.shadowsocks.utils.int
import
com.github.shadowsocks.utils.parseNumericAddress
import
com.github.shadowsocks.utils.printLog
import
kotlinx.coroutines.*
import
org.xbill.DNS.*
import
timber.log.Timber
import
java.io.FileDescriptor
import
java.io.IOException
import
java.net.Inet4Address
...
...
@@ -80,7 +80,7 @@ sealed class DnsResolverCompat {
false
}
catch
(
e
:
ReflectiveOperationException
)
{
check
(
Build
.
VERSION
.
SDK_INT
<
23
)
printLog
(
e
)
Timber
.
w
(
e
)
checkConnectivity
(
network
,
addr
)
}
private
fun
checkConnectivity
(
network
:
Network
,
addr
:
InetAddress
):
Boolean
{
...
...
@@ -88,7 +88,7 @@ sealed class DnsResolverCompat {
try
{
it
.
matches
(
addr
)
}
catch
(
e
:
RuntimeException
)
{
printLog
(
e
)
Timber
.
w
(
e
)
false
}
}
==
true
...
...
core/src/main/java/com/github/shadowsocks/net/LocalSocketListener.kt
View file @
8e2c5812
...
...
@@ -26,11 +26,11 @@ import android.net.LocalSocketAddress
import
android.system.ErrnoException
import
android.system.Os
import
android.system.OsConstants
import
com.github.shadowsocks.utils.printLog
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.channels.Channel
import
kotlinx.coroutines.channels.sendBlocking
import
kotlinx.coroutines.launch
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
...
...
@@ -55,7 +55,7 @@ abstract class LocalSocketListener(name: String, socketFile: File) : Thread(name
try
{
accept
(
serverSocket
.
accept
())
}
catch
(
e
:
IOException
)
{
if
(
running
)
printLog
(
e
)
if
(
running
)
Timber
.
w
(
e
)
continue
}
}
...
...
core/src/main/java/com/github/shadowsocks/plugin/PluginConfiguration.kt
View file @
8e2c5812
...
...
@@ -20,9 +20,8 @@
package
com.github.shadowsocks.plugin
import
android.util.Log
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.utils.Commandline
import
timber.log.Timber
import
java.util.*
class
PluginConfiguration
(
val
pluginsOptions
:
Map
<
String
,
PluginOptions
>,
val
selected
:
String
)
{
...
...
@@ -44,7 +43,7 @@ class PluginConfiguration(val pluginsOptions: Map<String, PluginOptions>, val se
}
}
}
catch
(
exc
:
Exception
)
{
Crashlytics
.
log
(
Log
.
WARN
,
"PluginConfiguration"
,
exc
.
message
)
Timber
.
w
(
exc
)
}
opt
}
else
PluginOptions
(
line
)
...
...
core/src/main/java/com/github/shadowsocks/plugin/PluginManager.kt
View file @
8e2c5812
...
...
@@ -30,23 +30,20 @@ import android.content.pm.ProviderInfo
import
android.content.pm.Signature
import
android.database.Cursor
import
android.net.Uri
import
android.os.Build
import
android.system.Os
import
android.util.Base64
import
android.util.Log
import
androidx.core.os.bundleOf
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.Core.app
import
com.github.shadowsocks.bg.BaseService
import
com.github.shadowsocks.utils.listenForPackageChanges
import
com.github.shadowsocks.utils.printLog
import
com.github.shadowsocks.utils.signaturesCompat
import
timber.log.Timber
import
java.io.File
import
java.io.FileNotFoundException
object
PluginManager
{
private
const
val
TAG
=
"PluginManager"
class
PluginNotFoundException
(
private
val
plugin
:
String
)
:
FileNotFoundException
(
plugin
),
BaseService
.
ExpectedException
{
override
fun
getLocalizedMessage
()
=
app
.
getString
(
com
.
github
.
shadowsocks
.
core
.
R
.
string
.
plugin_unknown
,
plugin
)
...
...
@@ -130,7 +127,7 @@ object PluginManager {
val
result
=
initNative
(
configuration
)
if
(
result
!=
null
)
return
result
}
catch
(
t
:
Throwable
)
{
if
(
throwable
==
null
)
throwable
=
t
else
printLog
(
t
)
if
(
throwable
==
null
)
throwable
=
t
else
Timber
.
w
(
t
)
}
// add other plugin types here
...
...
@@ -139,11 +136,12 @@ object PluginManager {
}
private
fun
initNative
(
configuration
:
PluginConfiguration
):
Pair
<
String
,
PluginOptions
>?
{
var
flags
=
PackageManager
.
GET_META_DATA
if
(
Build
.
VERSION
.
SDK_INT
>=
24
)
{
flags
=
flags
or
PackageManager
.
MATCH_DIRECT_BOOT_UNAWARE
or
PackageManager
.
MATCH_DIRECT_BOOT_AWARE
}
val
providers
=
app
.
packageManager
.
queryIntentContentProviders
(
Intent
(
PluginContract
.
ACTION_NATIVE_PLUGIN
,
buildUri
(
configuration
.
selected
)),
PackageManager
.
GET_META_DATA
or
PackageManager
.
MATCH_DIRECT_BOOT_UNAWARE
or
PackageManager
.
MATCH_DIRECT_BOOT_AWARE
)
Intent
(
PluginContract
.
ACTION_NATIVE_PLUGIN
,
buildUri
(
configuration
.
selected
)),
flags
)
if
(
providers
.
isEmpty
())
return
null
val
provider
=
providers
.
single
().
providerInfo
val
options
=
configuration
.
getOptions
{
provider
.
loadString
(
PluginContract
.
METADATA_KEY_DEFAULT_CONFIG
)
}
...
...
@@ -151,7 +149,7 @@ object PluginManager {
try
{
initNativeFaster
(
provider
)
?.
also
{
return
it
to
options
}
}
catch
(
t
:
Throwable
)
{
Crashlytics
.
log
(
Log
.
WARN
,
TAG
,
"Initializing native plugin faster mode failed"
)
Timber
.
w
(
"Initializing native plugin faster mode failed"
)
failure
=
t
}
...
...
@@ -162,7 +160,7 @@ object PluginManager {
try
{
return
initNativeFast
(
app
.
contentResolver
,
options
,
uri
)
?.
let
{
it
to
options
}
}
catch
(
t
:
Throwable
)
{
Crashlytics
.
log
(
Log
.
WARN
,
TAG
,
"Initializing native plugin fast mode failed"
)
Timber
.
w
(
"Initializing native plugin fast mode failed"
)
failure
?.
also
{
t
.
addSuppressed
(
it
)
}
failure
=
t
}
...
...
core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt
View file @
8e2c5812
...
...
@@ -27,7 +27,6 @@ import android.app.Service
import
android.content.Intent
import
android.content.IntentFilter
import
android.os.IBinder
import
android.util.Log
import
android.widget.Toast
import
androidx.annotation.RequiresApi
import
androidx.core.app.NotificationCompat
...
...
@@ -42,6 +41,7 @@ import com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.*
import
com.google.gson.JsonStreamParser
import
kotlinx.coroutines.*
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
import
java.io.InputStream
...
...
@@ -59,7 +59,7 @@ class SubscriptionService : Service(), CoroutineScope {
app
.
getText
(
R
.
string
.
service_subscription
),
NotificationManager
.
IMPORTANCE_LOW
)
}
override
val
coroutineContext
=
SupervisorJob
()
+
CoroutineExceptionHandler
{
_
,
t
->
printLog
(
t
)
}
override
val
coroutineContext
=
SupervisorJob
()
+
CoroutineExceptionHandler
{
_
,
t
->
Timber
.
w
(
t
)
}
private
var
worker
:
Job
?
=
null
private
val
cancelReceiver
=
broadcastReceiver
{
_
,
_
->
worker
?.
cancel
()
}
private
var
counter
=
0
...
...
@@ -135,7 +135,7 @@ class SubscriptionService : Service(), CoroutineScope {
}
return
tempFile
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
(
)
Timber
.
d
(
e
)
launch
(
Dispatchers
.
Main
)
{
Toast
.
makeText
(
this
@SubscriptionService
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
}
...
...
@@ -175,8 +175,8 @@ class SubscriptionService : Service(), CoroutineScope {
subscriptions
.
compute
(
it
.
name
to
it
.
formattedAddress
)
{
_
,
oldProfile
->
when
(
oldProfile
?.
subscription
)
{
Profile
.
SubscriptionStatus
.
Active
->
{
Log
.
w
(
"SubscriptionService"
,
"Duplicate profiles detected. Please use different profile
"
+
"
names and/or
address:port for better subscription support."
)
Timber
.
w
(
"Duplicate profiles detected. Please use different profile names and/or
"
+
"address:port for better subscription support."
)
oldProfile
}
Profile
.
SubscriptionStatus
.
Obsolete
->
{
...
...
@@ -195,7 +195,7 @@ class SubscriptionService : Service(), CoroutineScope {
}
!!
}
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
(
)
Timber
.
d
(
e
)
Toast
.
makeText
(
this
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
}
...
...
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
View file @
8e2c5812
...
...
@@ -34,11 +34,11 @@ import android.system.OsConstants
import
android.util.TypedValue
import
androidx.annotation.AttrRes
import
androidx.preference.Preference
import
com.crashlytics.android.Crashlytics
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.suspendCancellableCoroutine
import
timber.log.Timber
import
java.io.FileDescriptor
import
java.net.HttpURLConnection
import
java.net.InetAddress
...
...
@@ -53,7 +53,7 @@ fun <T> Iterable<T>.forEachTry(action: (T) -> Unit) {
if
(
result
==
null
)
result
=
e
else
result
.
addSuppressed
(
e
)
}
if
(
result
!=
null
)
{
result
.
printStackTrace
(
)
Timber
.
d
(
result
)
throw
result
}
}
...
...
@@ -140,9 +140,4 @@ fun Resources.Theme.resolveResourceId(@AttrRes resId: Int): Int {
val
Intent
.
datas
get
()
=
listOfNotNull
(
data
)
+
(
clipData
?.
asIterable
()
?.
mapNotNull
{
it
.
uri
}
?:
emptyList
())
fun
printLog
(
t
:
Throwable
)
{
Crashlytics
.
logException
(
t
)
t
.
printStackTrace
()
}
fun
Preference
.
remove
()
=
parent
!!
.
removePreference
(
this
)
core/src/main/java/com/github/shadowsocks/widget/AutoCollapseTextView.kt
View file @
8e2c5812
...
...
@@ -26,7 +26,7 @@ import android.util.AttributeSet
import
android.view.MotionEvent
import
androidx.appcompat.widget.AppCompatTextView
import
androidx.core.view.isGone
import
com.github.shadowsocks.utils.printLog
import
timber.log.Timber
class
AutoCollapseTextView
@JvmOverloads
constructor
(
context
:
Context
,
attrs
:
AttributeSet
?
=
null
,
defStyleAttr
:
Int
=
0
)
:
...
...
@@ -40,13 +40,13 @@ class AutoCollapseTextView @JvmOverloads constructor(context: Context, attrs: At
override
fun
onFocusChanged
(
focused
:
Boolean
,
direction
:
Int
,
previouslyFocusedRect
:
Rect
?)
=
try
{
super
.
onFocusChanged
(
focused
,
direction
,
previouslyFocusedRect
)
}
catch
(
e
:
IndexOutOfBoundsException
)
{
printLog
(
e
)
Timber
.
w
(
e
)
}
override
fun
onTouchEvent
(
event
:
MotionEvent
?)
=
try
{
super
.
onTouchEvent
(
event
)
}
catch
(
e
:
IndexOutOfBoundsException
)
{
printLog
(
e
)
Timber
.
w
(
e
)
false
}
}
mobile/build.gradle
View file @
8e2c5812
...
...
@@ -4,8 +4,8 @@ import java.util.regex.Pattern
apply
plugin:
'com.android.application'
apply
plugin:
'com.google.android.gms.oss-licenses-plugin'
apply
plugin:
'com.google.firebase.crashlytics'
apply
plugin:
'com.google.gms.google-services'
apply
plugin:
'io.fabric'
apply
plugin:
'kotlin-android'
apply
plugin:
'kotlin-android-extensions'
...
...
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
View file @
8e2c5812
...
...
@@ -28,7 +28,6 @@ import android.net.VpnService
import
android.os.Bundle
import
android.os.Handler
import
android.os.RemoteException
import
android.util.Log
import
android.view.*
import
androidx.appcompat.app.AppCompatActivity
import
androidx.browser.customtabs.CustomTabColorSchemeParams
...
...
@@ -40,7 +39,6 @@ import androidx.core.view.GravityCompat
import
androidx.core.view.updateLayoutParams
import
androidx.drawerlayout.widget.DrawerLayout
import
androidx.preference.PreferenceDataStore
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.acl.CustomRulesFragment
import
com.github.shadowsocks.aidl.IShadowsocksService
import
com.github.shadowsocks.aidl.ShadowsocksConnection
...
...
@@ -56,11 +54,14 @@ import com.github.shadowsocks.widget.ServiceButton
import
com.github.shadowsocks.widget.StatsBar
import
com.google.android.material.navigation.NavigationView
import
com.google.android.material.snackbar.Snackbar
import
com.google.firebase.analytics.ktx.analytics
import
com.google.firebase.analytics.ktx.logEvent
import
com.google.firebase.ktx.Firebase
import
timber.log.Timber
class
MainActivity
:
AppCompatActivity
(),
ShadowsocksConnection
.
Callback
,
OnPreferenceDataStoreChangeListener
,
NavigationView
.
OnNavigationItemSelectedListener
{
companion
object
{
private
const
val
TAG
=
"ShadowsocksMainActivity"
private
const
val
REQUEST_CONNECT
=
1
var
stateListener
:
((
BaseService
.
State
)
->
Unit
)?
=
null
...
...
@@ -148,7 +149,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
resultCode
==
Activity
.
RESULT_OK
->
Core
.
startService
()
else
->
{
snackbar
().
setText
(
R
.
string
.
vpn_permission_denied
).
show
()
Crashlytics
.
log
(
Log
.
ERROR
,
TAG
,
"Failed to start VpnService from onActivityResult: $data"
)
Timber
.
e
(
"Failed to start VpnService from onActivityResult: $data"
)
}
}
}
...
...
@@ -208,7 +209,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
}
R
.
id
.
globalSettings
->
displayFragment
(
GlobalSettingsFragment
())
R
.
id
.
about
->
{
Core
.
analytics
.
logEvent
(
"about"
,
Bundle
())
Firebase
.
analytics
.
logEvent
(
"about"
)
{
}
displayFragment
(
AboutFragment
())
}
R
.
id
.
faq
->
{
...
...
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
View file @
8e2c5812
...
...
@@ -44,7 +44,6 @@ import androidx.core.os.bundleOf
import
androidx.fragment.app.DialogFragment
import
androidx.lifecycle.lifecycleScope
import
androidx.recyclerview.widget.*
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.aidl.TrafficStats
import
com.github.shadowsocks.bg.BaseService
import
com.github.shadowsocks.database.Profile
...
...
@@ -54,7 +53,6 @@ import com.github.shadowsocks.plugin.showAllowingStateLoss
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.Action
import
com.github.shadowsocks.utils.datas
import
com.github.shadowsocks.utils.printLog
import
com.github.shadowsocks.utils.readableMessage
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.MainListListener
...
...
@@ -69,6 +67,7 @@ import com.google.zxing.MultiFormatWriter
import
com.google.zxing.WriterException
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
timber.log.Timber
import
java.nio.charset.StandardCharsets
class
ProfilesFragment
:
ToolbarFragment
(),
Toolbar
.
OnMenuItemClickListener
{
...
...
@@ -146,7 +145,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
})
}
}
catch
(
e
:
WriterException
)
{
Crashlytics
.
logException
(
e
)
Timber
.
w
(
e
)
(
activity
as
MainActivity
).
snackbar
().
setText
(
e
.
readableMessage
).
show
()
dismiss
()
null
...
...
@@ -515,7 +514,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
return
true
}
}
catch
(
exc
:
Exception
)
{
exc
.
printStackTrace
(
)
Timber
.
d
(
exc
)
}
(
activity
as
MainActivity
).
snackbar
().
setText
(
R
.
string
.
action_import_err
).
show
()
true
...
...
@@ -600,7 +599,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
it
.
write
(
profiles
.
toString
(
2
))
}
}
catch
(
e
:
Exception
)
{
printLog
(
e
)
Timber
.
w
(
e
)
(
activity
as
MainActivity
).
snackbar
(
e
.
readableMessage
).
show
()
}
}
...
...
mobile/src/main/java/com/github/shadowsocks/ScannerActivity.kt
View file @
8e2c5812
...
...
@@ -29,7 +29,6 @@ import android.hardware.camera2.CameraManager
import
android.net.Uri
import
android.os.Build
import
android.os.Bundle
import
android.util.Log
import
android.util.SparseArray
import
android.view.Menu
import
android.view.MenuItem
...
...
@@ -37,21 +36,23 @@ import android.widget.Toast
import
androidx.appcompat.app.AppCompatActivity
import
androidx.core.content.getSystemService
import
androidx.core.util.forEach
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.utils.*
import
com.github.shadowsocks.utils.datas
import
com.github.shadowsocks.utils.forEachTry
import
com.github.shadowsocks.utils.openBitmap
import
com.github.shadowsocks.utils.readableMessage
import
com.google.android.gms.common.GoogleApiAvailability
import
com.google.android.gms.samples.vision.barcodereader.BarcodeCapture
import
com.google.android.gms.samples.vision.barcodereader.BarcodeGraphic
import
com.google.android.gms.vision.Frame
import
com.google.android.gms.vision.barcode.Barcode
import
com.google.android.gms.vision.barcode.BarcodeDetector
import
timber.log.Timber
import
xyz.belvi.mobilevisionbarcodescanner.BarcodeRetriever
class
ScannerActivity
:
AppCompatActivity
(),
BarcodeRetriever
{
companion
object
{
private
const
val
TAG
=
"ScannerActivity"
private
const
val
REQUEST_IMPORT
=
2
private
const
val
REQUEST_IMPORT_OR_FINISH
=
3
private
const
val
REQUEST_GOOGLE_API
=
4
...
...
@@ -109,7 +110,7 @@ class ScannerActivity : AppCompatActivity(), BarcodeRetriever {
}
override
fun
onRetrievedMultiple
(
closetToClick
:
Barcode
?,
barcode
:
MutableList
<
BarcodeGraphic
>?)
=
check
(
false
)
override
fun
onBitmapScanned
(
sparseArray
:
SparseArray
<
Barcode
>?)
{
}
override
fun
onRetrievedFailed
(
reason
:
String
?)
=
Crashlytics
.
log
(
Log
.
WARN
,
TAG
,
reason
)
override
fun
onRetrievedFailed
(
reason
:
String
?)
=
Timber
.
w
(
reason
)
override
fun
onPermissionRequestDenied
()
{
Toast
.
makeText
(
this
,
R
.
string
.
add_profile_scanner_permission_required
,
Toast
.
LENGTH_SHORT
).
show
()
startImport
()
...
...
mobile/src/main/java/com/github/shadowsocks/acl/CustomRulesFragment.kt
View file @
8e2c5812
...
...
@@ -32,7 +32,10 @@ import android.os.Parcelable
import
android.text.Editable
import
android.text.TextWatcher
import
android.view.*
import
android.widget.*
import
android.widget.AdapterView
import
android.widget.EditText
import
android.widget.Spinner
import
android.widget.TextView
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.widget.Toolbar
import
androidx.core.content.ContextCompat
...
...
@@ -57,6 +60,7 @@ import com.github.shadowsocks.widget.UndoSnackbarManager
import
com.google.android.material.textfield.TextInputLayout
import
kotlinx.android.parcel.Parcelize
import
me.zhanghai.android.fastscroll.FastScrollerBuilder
import
timber.log.Timber
import
java.net.IDN
import
java.net.MalformedURLException
import
java.net.URL
...
...
@@ -449,7 +453,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
check
(
adapter
.
addToProxy
(
clipboard
.
primaryClip
!!
.
getItemAt
(
0
).
text
.
toString
())
!=
null
)
}
catch
(
exc
:
Exception
)
{
(
activity
as
MainActivity
).
snackbar
().
setText
(
R
.
string
.
action_import_err
).
show
()
exc
.
printStackTrace
(
)
Timber
.
d
(
exc
)
}
true
}
...
...
tv/build.gradle
View file @
8e2c5812
...
...
@@ -4,8 +4,8 @@ import java.util.regex.Pattern
apply
plugin:
'com.android.application'
apply
plugin:
'com.google.android.gms.oss-licenses-plugin'
apply
plugin:
'com.google.firebase.crashlytics'
apply
plugin:
'com.google.gms.google-services'
apply
plugin:
'io.fabric'
apply
plugin:
'kotlin-android'
apply
plugin:
'kotlin-kapt'
...
...
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
View file @
8e2c5812
...
...
@@ -29,13 +29,11 @@ import android.os.Bundle
import
android.os.Handler
import
android.os.RemoteException
import
android.text.format.Formatter
import
android.util.Log
import
android.widget.Toast
import
androidx.fragment.app.viewModels
import
androidx.leanback.preference.LeanbackPreferenceFragmentCompat
import
androidx.lifecycle.observe
import
androidx.preference.*
import
com.crashlytics.android.Crashlytics
import
com.github.shadowsocks.BootReceiver
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.aidl.IShadowsocksService
...
...
@@ -50,9 +48,9 @@ import com.github.shadowsocks.preference.HostsSummaryProvider
import
com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.datas
import
com.github.shadowsocks.utils.printLog
import
com.github.shadowsocks.utils.readableMessage
import
com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import
timber.log.Timber
class
MainPreferenceFragment
:
LeanbackPreferenceFragmentCompat
(),
ShadowsocksConnection
.
Callback
,
OnPreferenceDataStoreChangeListener
{
...
...
@@ -61,7 +59,6 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
private
const
val
REQUEST_REPLACE_PROFILES
=
2
private
const
val
REQUEST_EXPORT_PROFILES
=
3
private
const
val
REQUEST_HOSTS
=
4
private
const
val
TAG
=
"MainPreferenceFragment"
}
private
lateinit
var
fab
:
ListPreference
...
...
@@ -266,7 +263,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
when
(
requestCode
)
{
REQUEST_CONNECT
->
if
(
resultCode
==
Activity
.
RESULT_OK
)
Core
.
startService
()
else
{
Toast
.
makeText
(
requireContext
(),
R
.
string
.
vpn_permission_denied
,
Toast
.
LENGTH_SHORT
).
show
()
Crashlytics
.
log
(
Log
.
ERROR
,
TAG
,
"Failed to start VpnService from onActivityResult: $data"
)
Timber
.
e
(
"Failed to start VpnService from onActivityResult: $data"
)
}
REQUEST_REPLACE_PROFILES
->
{
if
(
resultCode
!=
Activity
.
RESULT_OK
)
return
...
...
@@ -276,7 +273,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
context
.
contentResolver
.
openInputStream
(
it
)
}.
filterNotNull
(),
true
)
}
catch
(
e
:
Exception
)
{
printLog
(
e
)
Timber
.
w
(
e
)
Toast
.
makeText
(
context
,
e
.
readableMessage
,
Toast
.
LENGTH_SHORT
).
show
()
}
populateProfiles
()
...
...
@@ -290,7 +287,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
it
.
write
(
profiles
.
toString
(
2
))
}
}
catch
(
e
:
Exception
)
{
printLog
(
e
)
Timber
.
w
(
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