Commit b9828671 authored by Max Lv's avatar Max Lv

Merge branch 'beta'

parents caf5731f 49171067
......@@ -29,7 +29,8 @@ The exclamation mark in the Wi-Fi/cellular icon appears because the system fails
1. Broken VPNService implementation, especially for IPv6;
2. Aggressive (or called broken) background service killing policy.
Fixes for MIUI: [#772](https://github.com/shadowsocks/shadowsocks-android/issues/772)
* Fixes for MIUI: [#772](https://github.com/shadowsocks/shadowsocks-android/issues/772)
* Fixes for Huawei: [#1091 (comment)](https://github.com/shadowsocks/shadowsocks-android/issues/1091#issuecomment-276949836)
### How to pause Shadowsocks service?
......
......@@ -30,7 +30,7 @@ _Put an `x` inside the [ ] that applies._
* [ ] Per-App Proxy
* [ ] Bypass mode
* [ ] UDP Forwarding
* KCP Parameters: (leave blank if not enabled)
* Plugin configuration (if applicable):
* [ ] Auto Connect
* [ ] TCP Fast Open
* [ ] NAT mode
......
classes
bin
gen
target
local.properties
.classpath
.project
.settings
tests/bin
tests/gen
tests/local.properties
NUL
gen_*
*.class
*.o
local.sbt
.deps
/proguard-sbt.txt
#Intellij IDEA
*.iml
*.ipr
*.iws
.idea/
out/
.d
#NDK
src/main/obj
src/main/libs
src/main/assets/armeabi-v7a/*
src/main/assets/x86/*
jni/Application.mk
mobile/src/main/libs
mobile/src/main/obj
[submodule "src/main/jni/shadowsocks-libev"]
path = src/main/jni/shadowsocks-libev
[submodule "mobile/src/main/jni/shadowsocks-libev"]
path = mobile/src/main/jni/shadowsocks-libev
url = https://github.com/shadowsocks/shadowsocks-libev
[submodule "src/main/jni/badvpn"]
path = src/main/jni/badvpn
[submodule "mobile/src/main/jni/badvpn"]
path = mobile/src/main/jni/badvpn
url = https://github.com/shadowsocks/badvpn.git
branch = shadowsocks-android
[submodule "src/main/jni/libancillary"]
path = src/main/jni/libancillary
[submodule "mobile/src/main/jni/libancillary"]
path = mobile/src/main/jni/libancillary
url = https://github.com/shadowsocks/libancillary.git
branch = shadowsocks-android
[submodule "src/main/jni/libevent"]
path = src/main/jni/libevent
[submodule "mobile/src/main/jni/libevent"]
path = mobile/src/main/jni/libevent
url = https://github.com/shadowsocks/libevent.git
branch = shadowsocks-android
[submodule "src/main/jni/redsocks"]
path = src/main/jni/redsocks
[submodule "mobile/src/main/jni/redsocks"]
path = mobile/src/main/jni/redsocks
url = https://github.com/shadowsocks/redsocks.git
branch = shadowsocks-android
[submodule "src/main/jni/pdnsd"]
path = src/main/jni/pdnsd
[submodule "mobile/src/main/jni/pdnsd"]
path = mobile/src/main/jni/pdnsd
url = https://github.com/shadowsocks/pdnsd.git
branch = shadowsocks-android
[submodule "kcptun/kcptun"]
path = kcptun/kcptun
url = https://github.com/shadowsocks/kcptun
[submodule "kcptun/go"]
path = kcptun/go
url = https://github.com/shadowsocks/go
[submodule "src/main/jni/mbedtls"]
path = src/main/jni/mbedtls
[submodule "mobile/src/main/jni/mbedtls"]
path = mobile/src/main/jni/mbedtls
url = https://github.com/ARMmbed/mbedtls
[submodule "src/main/jni/pcre"]
path = src/main/jni/pcre
[submodule "mobile/src/main/jni/pcre"]
path = mobile/src/main/jni/pcre
url = https://android.googlesource.com/platform/external/pcre
[submodule "mobile/src/main/jni/libsodium"]
path = mobile/src/main/jni/libsodium
url = https://github.com/jedisct1/libsodium.git
branch = stable
[submodule "mobile/src/main/jni/libev"]
path = mobile/src/main/jni/libev
url = https://github.com/shadowsocks/libev.git
[submodule "mobile/src/main/jni/libudns"]
path = mobile/src/main/jni/libudns
url = https://github.com/shadowsocks/libudns.git
......@@ -7,7 +7,6 @@ env:
global:
- NDK_VERSION=r12b
- NDK_CCACHE=ccache
- GOROOT_BOOTSTRAP=$GOROOT
- ANDROID_NDK_HOME=$HOME/.android/android-ndk-${NDK_VERSION}
- SBTPATH=$HOME/.sbt
- PATH=${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH}
......@@ -50,4 +49,4 @@ install:
fi
script:
- $SBTPATH/sbt -DNPROC=$(nproc) native-build android:package-debug
- $SBTPATH/sbt android:package
......@@ -12,7 +12,6 @@ A [shadowsocks](http://shadowsocks.org) client for Android, written in Scala.
* JDK 1.8
* SBT 0.13.0+
* Go 1.4+
* Android SDK
- Build Tools 25+
- Android Support Repository and Google Repository (see `build.sbt` for version)
......@@ -22,16 +21,15 @@ A [shadowsocks](http://shadowsocks.org) client for Android, written in Scala.
* Set environment variable `ANDROID_HOME` to `/path/to/android-sdk`
* Set environment variable `ANDROID_NDK_HOME` to `/path/to/android-ndk`
* Set environment variable `GOROOT_BOOTSTRAP` to `/path/to/go`
* Create your key following the instructions at https://developer.android.com/studio/publish/app-signing.html
* Create `local.properties` from `local.properties.example` with your own key information
* Create `mobile/local.properties` from `mobile/local.properties.example` with your own key information
* Invoke the building like this
```bash
git submodule update --init
git submodule update --init --recursive
# Build the App
sbt native-build clean android:package-release
sbt clean android:package-release
```
### TRANSLATE
......@@ -54,8 +52,8 @@ Translators can go to [POEditor](https://poeditor.com/join/project/u5VHO9vhSf) t
<li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li>
<li>pdnsd: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/pdnsd/COPYING">GPLv3</a></li>
<li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li>
<li>kcptun: <a href="https://github.com/xtaci/kcptun/commits/master/LICENSE.md">MIT</a></li>
<li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li>
<li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li>
</ul>
### LICENSE
......
scalaVersion := "2.11.8"
dexMaxHeap := "4g"
enablePlugins(AndroidApp)
android.useSupportVectors
name := "shadowsocks"
version := "3.4.2"
versionCode := Some(174)
// Speed up ndk-build by reading nproc from environment
// and default to 8
val nproc = sys.props.getOrElse("NPROC", default = "8")
ndkArgs := Seq(s"-j$nproc")
platformTarget := "android-25"
compileOrder := CompileOrder.JavaThenScala
javacOptions ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil
scalacOptions ++= "-target:jvm-1.7" :: "-Xexperimental" :: Nil
proguardVersion := "5.3.2"
proguardCache := Seq()
proguardOptions ++=
"-keep class com.github.shadowsocks.System { *; }" ::
"-dontwarn com.google.android.gms.internal.**" ::
"-dontwarn com.j256.ormlite.**" ::
"-dontwarn okio.**" ::
"-dontwarn org.xbill.**" ::
Nil
shrinkResources := true
typedResources := false
resConfigs := Seq("ja", "ru", "zh-rCN", "zh-rTW")
val supportLibsVersion = "25.1.0"
val playServicesVersion = "10.0.1"
resolvers += Resolver.jcenterRepo
libraryDependencies ++=
"com.android.support" % "cardview-v7" % supportLibsVersion ::
"com.android.support" % "customtabs" % supportLibsVersion ::
"com.android.support" % "design" % supportLibsVersion ::
"com.android.support" % "gridlayout-v7" % supportLibsVersion ::
"com.android.support" % "preference-v14" % supportLibsVersion ::
"com.futuremind.recyclerfastscroll" % "fastscroll" % "0.2.5" ::
"com.evernote" % "android-job" % "1.1.4" ::
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01" ::
"com.google.android.gms" % "play-services-ads" % playServicesVersion ::
"com.google.android.gms" % "play-services-analytics" % playServicesVersion ::
"com.google.android.gms" % "play-services-gcm" % playServicesVersion ::
"com.j256.ormlite" % "ormlite-android" % "5.0" ::
"com.mikepenz" % "crossfader" % "1.5.0" ::
"com.mikepenz" % "fastadapter" % "2.1.5" ::
"com.mikepenz" % "iconics-core" % "2.8.2" ::
"com.mikepenz" % "materialdrawer" % "5.8.1" ::
"com.mikepenz" % "materialize" % "1.0.0" ::
"com.squareup.okhttp3" % "okhttp" % "3.5.0" ::
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2" ::
"dnsjava" % "dnsjava" % "2.1.7" ::
"eu.chainfire" % "libsuperuser" % "1.0.0.201608240809" ::
"net.glxn.qrgen" % "android" % "2.0" ::
Nil
lazy val nativeBuild = TaskKey[Unit]("native-build", "Build native executables")
nativeBuild := {
val logger = streams.value.log
Process("./build.sh") ! logger match {
case 0 => // Success!
case n => sys.error(s"Native build script exit code: $n")
}
}
lazy val commonSettings = Seq(
scalaVersion := "2.11.8",
dexMaxHeap := "4g",
organization := "com.github.shadowsocks",
platformTarget := "android-25",
compileOrder := CompileOrder.JavaThenScala,
javacOptions ++= "-source" :: "1.7" :: "-target" :: "1.7" :: Nil,
scalacOptions ++= "-target:jvm-1.7" :: "-Xexperimental" :: Nil,
ndkArgs := "-j" :: java.lang.Runtime.getRuntime.availableProcessors.toString :: Nil,
proguardVersion := "5.3.2",
proguardCache := Seq(),
shrinkResources := true,
typedResources := false
)
val supportLibsVersion = "25.1.1"
lazy val root = Project(id = "shadowsocks-android", base = file("."))
.settings(commonSettings)
.aggregate(plugin, mobile)
install in Android := (install in (mobile, Android)).value
run in Android := (run in (mobile, Android)).evaluated
lazy val plugin = project
.settings(commonSettings)
.settings(
libraryDependencies += "com.android.support" % "preference-v14" % supportLibsVersion
)
lazy val mobile = project
.settings(commonSettings)
.settings(
libraryDependencies ++=
"com.android.support" % "cardview-v7" % supportLibsVersion ::
"com.android.support" % "customtabs" % supportLibsVersion ::
"com.android.support" % "design" % supportLibsVersion ::
"com.android.support" % "gridlayout-v7" % supportLibsVersion ::
Nil
)
.dependsOn(plugin)
#!/bin/bash
function try () {
"$@" || exit -1
}
pushd src/main
# Clean up old binaries (no longer used)
rm -rf assets/armeabi-v7a assets/x86 libs/armeabi-v7a libs/x86
mkdir -p libs/armeabi-v7a libs/x86
popd
# Build kcptun
pushd kcptun
try ./make.bash
popd
Subproject commit c3f75e654ddb95bd53351294337649c08e9f9409
Subproject commit c532a50e1aeeaa9dee2428b374c3651a5c95258a
#!/bin/bash
function try () {
"$@" || exit -1
}
[ -z "$ANDROID_NDK_HOME" ] && ANDROID_NDK_HOME=~/android-ndk-r12b
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
DEPS=$DIR/.deps
ANDROID_ARM_TOOLCHAIN=$DEPS/android-toolchain-16-arm
ANDROID_X86_TOOLCHAIN=$DEPS/android-toolchain-16-x86
ANDROID_ARM_CC=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-gcc
ANDROID_ARM_STRIP=$ANDROID_ARM_TOOLCHAIN/bin/arm-linux-androideabi-strip
ANDROID_X86_CC=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-gcc
ANDROID_X86_STRIP=$ANDROID_X86_TOOLCHAIN/bin/i686-linux-android-strip
if [ ! -d "$DEPS" ]; then
mkdir -p $DEPS
fi
if [ ! -d "$ANDROID_ARM_TOOLCHAIN" ]; then
echo "Make standalone toolchain for ARM arch"
$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --arch arm \
--api 16 --install-dir $ANDROID_ARM_TOOLCHAIN
fi
if [ ! -d "$ANDROID_X86_TOOLCHAIN" ]; then
echo "Make standalone toolchain for X86 arch"
$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py --arch x86 \
--api 16 --install-dir $ANDROID_X86_TOOLCHAIN
fi
if [ ! -d "$DIR/go/bin" ]; then
echo "Build the custom go"
pushd $DIR/go/src
try ./make.bash
popd
fi
export GOROOT=$DIR/go
export GOPATH=$DEPS/gopath
export GOBIN=$GOPATH/bin
mkdir -p $GOBIN
export PATH=$GOROOT/bin:$PATH
pushd kcptun/client
echo "Get dependences for kcptun"
go get -u github.com/xtaci/kcp-go
go get -u github.com/xtaci/smux
go get
echo "Cross compile kcptun for arm"
try env CGO_ENABLED=1 CC=$ANDROID_ARM_CC GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-s -w"
try $ANDROID_ARM_STRIP client
try mv client $DIR/../src/main/libs/armeabi-v7a/libkcptun.so
echo "Cross compile kcptun for x86"
try env CGO_ENABLED=1 CC=$ANDROID_X86_CC GOOS=android GOARCH=386 go build -ldflags="-s -w"
try $ANDROID_X86_STRIP client
try mv client $DIR/../src/main/libs/x86/libkcptun.so
popd
echo "Successfully build kcptun"
enablePlugins(AndroidApp)
android.useSupportVectors
name := "shadowsocks"
version := "4.0.1"
versionCode := Some(176)
proguardOptions ++=
"-keep class com.github.shadowsocks.JniHelper { *; }" ::
"-dontwarn com.google.android.gms.internal.**" ::
"-dontwarn com.j256.ormlite.**" ::
"-dontwarn okio.**" ::
"-dontwarn org.xbill.**" ::
Nil
resConfigs := Seq("ja", "ru", "zh-rCN", "zh-rTW")
val playServicesVersion = "10.0.1"
resolvers += Resolver.jcenterRepo
libraryDependencies ++=
"com.futuremind.recyclerfastscroll" % "fastscroll" % "0.2.5" ::
"com.evernote" % "android-job" % "1.1.5" ::
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01" ::
"com.google.android.gms" % "play-services-ads" % playServicesVersion ::
"com.google.android.gms" % "play-services-analytics" % playServicesVersion ::
"com.google.android.gms" % "play-services-gcm" % playServicesVersion ::
"com.j256.ormlite" % "ormlite-android" % "5.0" ::
"com.mikepenz" % "crossfader" % "1.5.0" ::
"com.mikepenz" % "fastadapter" % "2.1.6" ::
"com.mikepenz" % "iconics-core" % "2.8.2" ::
"com.mikepenz" % "materialdrawer" % "5.8.1" ::
"com.mikepenz" % "materialize" % "1.0.0" ::
"com.squareup.okhttp3" % "okhttp" % "3.6.0" ::
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2" ::
"dnsjava" % "dnsjava" % "2.1.8" ::
"eu.chainfire" % "libsuperuser" % "1.0.0.201608240809" ::
"net.glxn.qrgen" % "android" % "2.0" ::
Nil
......@@ -2,7 +2,6 @@
xmlns:tools="http://schemas.android.com/tools" package="com.github.shadowsocks">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.NFC" />
......@@ -18,14 +17,10 @@
android:targetSdkVersion="25"/>
<application
android:allowBackup="true"
android:name=".ShadowsocksApplication"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:backupAgent=".ShadowsocksBackupAgent"
android:label="@string/app_name"
android:theme="@style/Theme.Material"
android:banner="@drawable/ic_start_connected">
<meta-data android:name="com.google.android.gms.version"
......
......@@ -298,8 +298,8 @@ along with this program. If not, see <a href="http://www.gnu.org/licenses/">http
<li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li>
<li>pdnsd: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/pdnsd/COPYING">GPLv3</a></li>
<li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li>
<li>kcptun: <a href="https://github.com/xtaci/kcptun/commits/master/LICENSE.md">MIT</a></li>
<li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li>
<li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li>
</ul>
</body>
......
......@@ -38,12 +38,23 @@
package com.github.shadowsocks;
public class System {
static {
java.lang.System.loadLibrary("system");
}
import android.os.Build;
import android.system.ErrnoException;
public static native int exec(String cmd);
public static native int sendfd(int fd, String path);
public static native void jniclose(int fd);
public class JniHelper {
static {
System.loadLibrary("jni-helper");
}
@Deprecated // Use Process.destroy() since API 24
public static void sigtermCompat(Process process) throws Exception {
if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!");
int errno = sigterm(process);
if (errno != 0) throw Build.VERSION.SDK_INT >= 21
? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno);
}
private static native int sigterm(Process process);
public static native int sendFd(int fd, String path);
public static native void close(int fd);
}
package com.github.shadowsocks.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
/**
* Commandline objects help handling command lines specifying processes to
* execute.
*
* The class can be used to define a command line as nested elements or as a
* helper to define a command line by an application.
* <p>
* <code>
* &lt;someelement&gt;<br>
* &nbsp;&nbsp;&lt;acommandline executable="/executable/to/run"&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 1" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument line="argument_1 argument_2 argument_3" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 4" /&gt;<br>
* &nbsp;&nbsp;&lt;/acommandline&gt;<br>
* &lt;/someelement&gt;<br>
* </code>
*
* Based on: https://github.com/apache/ant/blob/588ce1f/src/main/org/apache/tools/ant/types/Commandline.java
*
* Adds support for escape character '\'.
*
* @author Mygod
*/
public final class Commandline {
private Commandline() { }
/**
* Quote the parts of the given array in way that makes them
* usable as command line arguments.
* @param args the list of arguments to quote.
* @return empty string for null or no command, else every argument split
* by spaces and quoted by quoting rules.
*/
public static String toString(Iterable<String> args) {
// empty path return empty string
if (args == null) {
return "";
}
// path containing one or more elements
final StringBuilder result = new StringBuilder();
for (String arg : args) {
if (result.length() > 0) result.append(' ');
for (int j = 0; j < arg.length(); ++j) {
char ch = arg.charAt(j);
switch (ch) {
case ' ': case '\\': case '"': case '\'': result.append('\\'); // intentionally no break
default: result.append(ch);
}
}
}
return result.toString();
}
/**
* Quote the parts of the given array in way that makes them
* usable as command line arguments.
* @param args the list of arguments to quote.
* @return empty string for null or no command, else every argument split
* by spaces and quoted by quoting rules.
*/
public static String toString(String[] args) {
return toString(Arrays.asList(args)); // thanks to Java, arrays aren't iterable
}
/**
* Crack a command line.
* @param toProcess the command line to process.
* @return the command line broken into strings.
* An empty or null toProcess parameter results in a zero sized array.
*/
public static String[] translateCommandline(String toProcess) {
if (toProcess == null || toProcess.length() == 0) {
//no command? no string
return new String[0];
}
// parse with a simple finite state machine
final int normal = 0;
final int inQuote = 1;
final int inDoubleQuote = 2;
int state = normal;
final StringTokenizer tok = new StringTokenizer(toProcess, "\\\"\' ", true);
final ArrayList<String> result = new ArrayList<>();
final StringBuilder current = new StringBuilder();
boolean lastTokenHasBeenQuoted = false;
boolean lastTokenIsSlash = false;
while (tok.hasMoreTokens()) {
String nextTok = tok.nextToken();
switch (state) {
case inQuote:
if ("\'".equals(nextTok)) {
lastTokenHasBeenQuoted = true;
state = normal;
} else {
current.append(nextTok);
}
break;
case inDoubleQuote:
if ("\"".equals(nextTok)) {
if (lastTokenIsSlash) {
current.append(nextTok);
lastTokenIsSlash = false;
} else {
lastTokenHasBeenQuoted = true;
state = normal;
}
} else if ("\\".equals(nextTok)) {
if (lastTokenIsSlash) {
current.append(nextTok);
lastTokenIsSlash = false;
} else lastTokenIsSlash = true;
} else {
if (lastTokenIsSlash) {
current.append("\\"); // unescaped
lastTokenIsSlash = false;
}
current.append(nextTok);
}
break;
default:
if (lastTokenIsSlash) {
current.append(nextTok);
lastTokenIsSlash = false;
} else if ("\\".equals(nextTok)) lastTokenIsSlash = true; else if ("\'".equals(nextTok)) {
state = inQuote;
} else if ("\"".equals(nextTok)) {
state = inDoubleQuote;
} else if (" ".equals(nextTok)) {
if (lastTokenHasBeenQuoted || current.length() != 0) {
result.add(current.toString());
current.setLength(0);
}
} else {
current.append(nextTok);
}
lastTokenHasBeenQuoted = false;
break;
}
}
if (lastTokenHasBeenQuoted || current.length() != 0) {
result.add(current.toString());
}
if (state == inQuote || state == inDoubleQuote) {
throw new IllegalArgumentException("unbalanced quotes in " + toProcess);
}
if (lastTokenIsSlash) throw new IllegalArgumentException("escape character following nothing in " + toProcess);
return result.toArray(new String[result.size()]);
}
}
APP_ABI := armeabi-v7a x86
APP_PLATFORM := android-16
APP_PLATFORM := android-19
APP_STL := stlport_static
NDK_TOOLCHAIN_VERSION := clang
File moved
#define LOG_TAG "Shadowsocks"
#define LOG_TAG "JniHelper"
#include "jni.h"
#include <android/log.h>
#include <sys/system_properties.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/un.h>
#include <sys/stat.h>
......@@ -16,35 +19,33 @@
#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0)
#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0)
#define THROW(env, clazz, msg) do { env->ThrowNew(env->FindClass(clazz), msg); } while (0)
jint Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring cmd) {
const char *cmd_str = env->GetStringUTFChars(cmd, 0);
static jclass ProcessImpl;
static jfieldID ProcessImpl_pid;
pid_t pid;
static int sdk_version() {
char version[PROP_VALUE_MAX + 1];
__system_property_get("ro.build.version.sdk", version);
return atoi(version);
}
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
env->ReleaseStringUTFChars(cmd, cmd_str);
jint Java_com_github_shadowsocks_jnihelper_sigterm(JNIEnv *env, jobject thiz, jobject process) {
if (!env->IsInstanceOf(process, ProcessImpl)) {
THROW(env, "java/lang/ClassCastException",
"Unsupported process object. Only java.lang.ProcessManager$ProcessImpl is accepted.");
return -1;
}
if (pid > 0) {
env->ReleaseStringUTFChars(cmd, cmd_str);
return pid;
}
execl("/system/bin/sh", "sh", "-c", cmd_str, NULL);
env->ReleaseStringUTFChars(cmd, cmd_str);
return 1;
jint pid = env->GetIntField(process, ProcessImpl_pid);
// Suppress "No such process" errors. We just want the process killed. It's fine if it's already killed.
return kill(pid, SIGTERM) == -1 && errno != ESRCH ? errno : 0;
}
void Java_com_github_shadowsocks_system_jniclose(JNIEnv *env, jobject thiz, jint fd) {
void Java_com_github_shadowsocks_jnihelper_close(JNIEnv *env, jobject thiz, jint fd) {
close(fd);
}
jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) {
jint Java_com_github_shadowsocks_jnihelper_sendfd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) {
int fd;
struct sockaddr_un addr;
const char *sock_str = env->GetStringUTFChars(path, 0);
......@@ -75,15 +76,15 @@ jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint t
return 0;
}
static const char *classPathName = "com/github/shadowsocks/System";
static const char *classPathName = "com/github/shadowsocks/JniHelper";
static JNINativeMethod method_table[] = {
{ "jniclose", "(I)V",
(void*) Java_com_github_shadowsocks_system_jniclose },
{ "sendfd", "(ILjava/lang/String;)I",
(void*) Java_com_github_shadowsocks_system_sendfd },
{ "exec", "(Ljava/lang/String;)I",
(void*) Java_com_github_shadowsocks_system_exec }
{ "close", "(I)V",
(void*) Java_com_github_shadowsocks_jnihelper_close },
{ "sendFd", "(ILjava/lang/String;)I",
(void*) Java_com_github_shadowsocks_jnihelper_sendfd },
{ "sigterm", "(Ljava/lang/Process;)I",
(void*) Java_com_github_shadowsocks_jnihelper_sigterm }
};
......@@ -139,20 +140,30 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
jint result = -1;
JNIEnv* env = NULL;
LOGI("JNI_OnLoad");
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed");
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) {
THROW(env, "java/lang/RuntimeException", "GetEnv failed");
goto bail;
}
env = uenv.env;
if (registerNatives(env) != JNI_TRUE) {
LOGE("ERROR: registerNatives failed");
THROW(env, "java/lang/RuntimeException", "registerNativeMethods failed");
goto bail;
}
result = JNI_VERSION_1_4;
if (sdk_version() < 24) {
if (!(ProcessImpl = env->FindClass("java/lang/ProcessManager$ProcessImpl"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl not found");
goto bail;
}
ProcessImpl = (jclass) env->NewGlobalRef((jobject) ProcessImpl);
if (!(ProcessImpl_pid = env->GetFieldID(ProcessImpl, "pid", "I"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.pid not found");
goto bail;
}
}
result = JNI_VERSION_1_6;
bail:
return result;
......
File moved
Subproject commit 981fb847e1e306bc40460de4a810f63f9bbc7212
File moved
Subproject commit e160de24fd146ab84b4eb397c7cffbf34775aa02
Subproject commit 53a1abd2b6fd7e3bf99ce6e2e267c636618d57ef
File moved
pcre @ 222bbf4b
File moved
File moved
File moved
Subproject commit f4b1641636942bc44c96160afad9f023fb6dbf0e
......@@ -10,6 +10,5 @@
<EditText android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textNoSuggestions"
android:lines="1"/>
android:inputType="textNoSuggestions|textMultiLine"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:paddingStart="12dp"
android:paddingEnd="12dp">
<ImageView android:id="@android:id/icon"
android:layout_width="52dp"
android:layout_height="52dp"/>
<Space android:layout_width="4dp"
android:layout_height="wrap_content"/>
<LinearLayout android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical">
<TextView android:id="@android:id/text1"
android:textAppearance="?android:attr/textAppearance"
android:textColor="@android:color/primary_text_light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end"/>
<TextView android:id="@android:id/text2"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end"/>
</LinearLayout>
</LinearLayout>
......@@ -24,7 +24,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:id="@+id/container">
<TextView android:id="@+id/title"
<TextView android:id="@android:id/text1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
......@@ -54,27 +54,29 @@
android:contentDescription="@string/edit"
android:focusable="true"/>
</LinearLayout>
<LinearLayout android:layout_width="match_parent"
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:id="@+id/details">
<TextView android:id="@+id/address"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:maxLines="2"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
android:layout_marginTop="4dp">
<TextView android:id="@android:id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_toStartOf="@+id/traffic"
android:layout_marginEnd="8dp"
android:maxLines="2"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
<TextView android:id="@+id/traffic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_alignParentEnd="true"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</com.github.shadowsocks.widget.BoundedCardView>
</FrameLayout>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment