Skip to content

Commit

Permalink
Merge branch 'master' into preference-1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Mygod committed Mar 15, 2019
2 parents 5493bce + 3aad5fc commit 50d09e7
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 8 deletions.
173 changes: 173 additions & 0 deletions core/schemas/com.github.shadowsocks.database.PrivateDatabase/28.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
{
"formatVersion": 1,
"database": {
"version": 28,
"identityHash": "b60ecca4d684ffe73173478bffd50a17",
"entities": [
{
"tableName": "Profile",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `host` TEXT NOT NULL, `remotePort` INTEGER NOT NULL, `password` TEXT NOT NULL, `method` TEXT NOT NULL, `route` TEXT NOT NULL, `remoteDns` TEXT NOT NULL, `proxyApps` INTEGER NOT NULL, `bypass` INTEGER NOT NULL, `udpdns` INTEGER NOT NULL, `ipv6` INTEGER NOT NULL, `metered` INTEGER NOT NULL, `individual` TEXT NOT NULL, `tx` INTEGER NOT NULL, `rx` INTEGER NOT NULL, `userOrder` INTEGER NOT NULL, `plugin` TEXT, `udpFallback` INTEGER)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "host",
"columnName": "host",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "remotePort",
"columnName": "remotePort",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "method",
"columnName": "method",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "route",
"columnName": "route",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "remoteDns",
"columnName": "remoteDns",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "proxyApps",
"columnName": "proxyApps",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "bypass",
"columnName": "bypass",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "udpdns",
"columnName": "udpdns",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "ipv6",
"columnName": "ipv6",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "metered",
"columnName": "metered",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "individual",
"columnName": "individual",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "tx",
"columnName": "tx",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "rx",
"columnName": "rx",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "userOrder",
"columnName": "userOrder",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "plugin",
"columnName": "plugin",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "udpFallback",
"columnName": "udpFallback",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "KeyValuePair",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `valueType` INTEGER NOT NULL, `value` BLOB NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "valueType",
"columnName": "valueType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "BLOB",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"key"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"b60ecca4d684ffe73173478bffd50a17\")"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,11 @@ class MigrationTest {
db.close()
privateDatabase.runMigrationsAndValidate(TEST_DB, 27, true, PrivateDatabase.Migration27)
}
@Test
@Throws(IOException::class)
fun migrate28() {
val db = privateDatabase.createDatabase(TEST_DB, 27)
db.close()
privateDatabase.runMigrationsAndValidate(TEST_DB, 28, true, PrivateDatabase.Migration28)
}
}
6 changes: 5 additions & 1 deletion core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,15 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
private var conn: ParcelFileDescriptor? = null
private var worker: ProtectWorker? = null
private var active = false
private var metered = false
private var underlyingNetwork: Network? = null
set(value) {
field = value
if (active && Build.VERSION.SDK_INT >= 22) setUnderlyingNetworks(underlyingNetworks)
}
private val underlyingNetworks get() = underlyingNetwork?.let { arrayOf(it) }
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) }

override fun onBind(intent: Intent) = when (intent.action) {
SERVICE_INTERFACE -> super<BaseVpnService>.onBind(intent)
Expand Down Expand Up @@ -190,6 +193,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
}
}

metered = profile.metered
active = true // possible race condition here?
if (Build.VERSION.SDK_INT >= 22) builder.setUnderlyingNetworks(underlyingNetworks)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ import com.github.shadowsocks.Core.app
import com.github.shadowsocks.database.migration.RecreateSchemaMigration
import com.github.shadowsocks.utils.Key

@Database(entities = [Profile::class, KeyValuePair::class], version = 27)
@Database(entities = [Profile::class, KeyValuePair::class], version = 28)
abstract class PrivateDatabase : RoomDatabase() {
companion object {
private val instance by lazy {
Room.databaseBuilder(app, PrivateDatabase::class.java, Key.DB_PROFILE)
.addMigrations(
Migration26,
Migration27
Migration27,
Migration28
)
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
Expand All @@ -61,4 +62,8 @@ abstract class PrivateDatabase : RoomDatabase() {
override fun migrate(database: SupportSQLiteDatabase) =
database.execSQL("ALTER TABLE `Profile` ADD COLUMN `udpFallback` INTEGER")
}
object Migration28 : Migration(27, 28) {
override fun migrate(database: SupportSQLiteDatabase) =
database.execSQL("ALTER TABLE `Profile` ADD COLUMN `metered` INTEGER NOT NULL DEFAULT 0")
}
}
10 changes: 9 additions & 1 deletion core/src/main/java/com/github/shadowsocks/database/Profile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package com.github.shadowsocks.database

import android.annotation.TargetApi
import android.net.Uri
import android.os.Parcelable
import android.util.Base64
Expand Down Expand Up @@ -58,6 +59,8 @@ data class Profile(
var bypass: Boolean = false,
var udpdns: Boolean = false,
var ipv6: Boolean = true,
@TargetApi(28)
var metered: Boolean = false,
var individual: String = "",
var tx: Long = 0,
var rx: Long = 0,
Expand All @@ -70,7 +73,7 @@ data class Profile(
) : Parcelable, Serializable {
companion object {
private const val TAG = "ShadowParser"
private const val serialVersionUID = 0L
private const val serialVersionUID = 1L
private val pattern =
"""(?i)ss://[-a-zA-Z0-9+&@#/%?=.~*'()|!:,;\[\]]*[-a-zA-Z0-9+&@#/%=.~*'()|\[\]]""".toRegex()
private val userInfoPattern = "^(.+?):(.*)$".toRegex()
Expand Down Expand Up @@ -156,6 +159,7 @@ data class Profile(
if (fallback) return@apply
remoteDns = json.optString("remote_dns", remoteDns)
ipv6 = json.optBoolean("ipv6", ipv6)
metered = json.optBoolean("metered", metered)
json.optJSONObject("proxy_apps")?.also {
proxyApps = it.optBoolean("enabled", proxyApps)
bypass = it.optBoolean("bypass", bypass)
Expand Down Expand Up @@ -232,6 +236,7 @@ data class Profile(
fun copyFeatureSettingsTo(profile: Profile) {
profile.route = route
profile.ipv6 = ipv6
profile.metered = metered
profile.proxyApps = proxyApps
profile.bypass = bypass
profile.individual = individual
Expand Down Expand Up @@ -269,6 +274,7 @@ data class Profile(
put("route", route)
put("remote_dns", remoteDns)
put("ipv6", ipv6)
put("metered", metered)
put("proxy_apps", JSONObject().apply {
put("enabled", proxyApps)
if (proxyApps) {
Expand All @@ -295,6 +301,7 @@ data class Profile(
DataStore.bypass = bypass
DataStore.privateStore.putBoolean(Key.udpdns, udpdns)
DataStore.privateStore.putBoolean(Key.ipv6, ipv6)
DataStore.privateStore.putBoolean(Key.metered, metered)
DataStore.individual = individual
DataStore.plugin = plugin ?: ""
DataStore.udpFallback = udpFallback
Expand All @@ -315,6 +322,7 @@ data class Profile(
bypass = DataStore.bypass
udpdns = DataStore.privateStore.getBoolean(Key.udpdns, false)
ipv6 = DataStore.privateStore.getBoolean(Key.ipv6, false)
metered = DataStore.privateStore.getBoolean(Key.metered, false)
individual = DataStore.individual
plugin = DataStore.plugin
udpFallback = DataStore.udpFallback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ object Key {
const val bypass = "isBypassApps"
const val udpdns = "isUdpDns"
const val ipv6 = "isIpv6"
const val metered = "metered"

const val host = "proxy"
const val password = "sitekey"
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
<!-- feature category -->
<string name="ipv6">IPv6 Route</string>
<string name="ipv6_summary">Redirect IPv6 traffic to remote</string>
<string name="metered">Metered Hint</string>
<string name="metered_summary">Hint system to treat VPN as metered</string>
<string name="route_list">Route</string>
<string name="route_entry_all">All</string>
<string name="route_entry_bypass_lan">Bypass LAN</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import android.app.Activity
import android.content.BroadcastReceiver
import android.content.DialogInterface
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.view.MenuItem
Expand All @@ -34,10 +35,7 @@ import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.plugin.*
import com.github.shadowsocks.preference.*
import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.readableMessage
import com.github.shadowsocks.utils.*
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.parcel.Parcelize

Expand Down Expand Up @@ -80,13 +78,17 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
findPreference<EditTextPreference>(Key.password)!!.summaryProvider = PasswordSummaryProvider
val serviceMode = DataStore.serviceMode
findPreference<Preference>(Key.remoteDns)!!.isEnabled = serviceMode != Key.modeProxy
findPreference<Preference>(Key.ipv6)!!.isEnabled = serviceMode == Key.modeVpn
isProxyApps = findPreference(Key.proxyApps)!!
isProxyApps.isEnabled = serviceMode == Key.modeVpn
isProxyApps.setOnPreferenceClickListener {
startActivity(Intent(activity, AppManager::class.java))
isProxyApps.isChecked = true
false
}
findPreference<Preference>(Key.metered)!!.apply {
if (Build.VERSION.SDK_INT >= 28) isEnabled = serviceMode == Key.modeVpn else remove()
}
findPreference<Preference>(Key.udpdns)!!.isEnabled = serviceMode != Key.modeProxy
plugin = findPreference(Key.plugin)!!
pluginConfigure = findPreference(Key.pluginConfigure)!!
Expand Down
6 changes: 6 additions & 0 deletions mobile/src/main/res/drawable/ic_device_data_usage.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?attr/colorControlNormal">
<path android:fillColor="#FF000000" android:pathData="M13,2.05v3.03c3.39,0.49 6,3.39 6,6.92 0,0.9 -0.18,1.75 -0.48,2.54l2.6,1.53c0.56,-1.24 0.88,-2.62 0.88,-4.07 0,-5.18 -3.95,-9.45 -9,-9.95zM12,19c-3.87,0 -7,-3.13 -7,-7 0,-3.53 2.61,-6.43 6,-6.92V2.05c-5.06,0.5 -9,4.76 -9,9.95 0,5.52 4.47,10 9.99,10 3.31,0 6.24,-1.61 8.06,-4.09l-2.6,-1.53C16.17,17.98 14.21,19 12,19z"/>
</vector>
5 changes: 5 additions & 0 deletions mobile/src/main/res/xml/pref_profile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@
app:icon="@drawable/ic_action_dns"
app:summary="@string/udp_dns_summary"
app:title="@string/udp_dns"/>
<SwitchPreference
app:key="metered"
app:icon="@drawable/ic_device_data_usage"
app:summary="@string/metered_summary"
app:title="@string/metered"/>

</PreferenceCategory>

Expand Down

0 comments on commit 50d09e7

Please sign in to comment.