Skip to content

Commit

Permalink
Use an Activity as entry point
Browse files Browse the repository at this point in the history
Recent versions of Android refuse to directly start a Service or a
BroadcastReceiver, so always use an (invisible) Activity to receive
intents.

This fixes many cases where the confirmation dialog were not displayed:
<https://github.com/Genymobile/gnirehtet/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3Anodialog>
  • Loading branch information
rom1v committed Sep 7, 2019
1 parent d7afaa2 commit f868180
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 175 deletions.
24 changes: 11 additions & 13 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.genymobile.gnirehtet">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
xmlns:tools="http://schemas.android.com/tools"
package="com.genymobile.gnirehtet">

<application
android:allowBackup="false"
Expand All @@ -13,15 +10,17 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<receiver
android:name="com.genymobile.gnirehtet.GnirehtetControlReceiver"
<activity
android:name="com.genymobile.gnirehtet.GnirehtetActivity"
android:exported="true"
android:permission="android.permission.WRITE_SECURE_SETTINGS">
android:permission="android.permission.WRITE_SECURE_SETTINGS"
android:theme="@style/Theme.Transparent">
<intent-filter>
<action android:name="com.genymobile.gnirehtet.START" />
<action android:name="com.genymobile.gnirehtet.STOP" />
</intent-filter>
</receiver>
</activity>

<service
android:name="com.genymobile.gnirehtet.GnirehtetService"
android:enabled="true"
Expand All @@ -31,10 +30,9 @@
<action android:name="android.net.VpnService" />
</intent-filter>
</service>

<activity
android:name="com.genymobile.gnirehtet.AuthorizationActivity"
android:theme="@style/Theme.Transparent" />
</application>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

</manifest>

This file was deleted.

97 changes: 97 additions & 0 deletions app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.genymobile.gnirehtet;

import android.app.Activity;
import android.content.Intent;
import android.net.VpnService;
import android.os.Bundle;
import android.util.Log;

/**
* This (invisible) activity receives the {@link #ACTION_GNIREHTET_START START} and
* {@link #ACTION_GNIREHTET_STOP} actions from the command line.
* <p>
* Recent versions of Android refuse to directly start a {@link android.app.Service Service} or a
* {@link android.content.BroadcastReceiver BroadcastReceiver}, so actions are always managed by
* this activity.
*/
public class GnirehtetActivity extends Activity {

private static final String TAG = GnirehtetActivity.class.getSimpleName();

public static final String ACTION_GNIREHTET_START = "com.genymobile.gnirehtet.START";
public static final String ACTION_GNIREHTET_STOP = "com.genymobile.gnirehtet.STOP";

public static final String EXTRA_DNS_SERVERS = "dnsServers";
public static final String EXTRA_ROUTES = "routes";

private static final int VPN_REQUEST_CODE = 0;

private VpnConfiguration config;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handleIntent(getIntent());
}

private void handleIntent(Intent intent) {
String action = intent.getAction();
Log.d(TAG, "Received request " + action);
boolean finish = true;
if (ACTION_GNIREHTET_START.equals(action)) {
VpnConfiguration config = createConfig(intent);
finish = startGnirehtet(config);
} else if (ACTION_GNIREHTET_STOP.equals(action)) {
stopGnirehtet();
}

if (finish) {
finish();
}
}

private static VpnConfiguration createConfig(Intent intent) {
String[] dnsServers = intent.getStringArrayExtra(EXTRA_DNS_SERVERS);
if (dnsServers == null) {
dnsServers = new String[0];
}
String[] routes = intent.getStringArrayExtra(EXTRA_ROUTES);
if (routes == null) {
routes = new String[0];
}
return new VpnConfiguration(Net.toInetAddresses(dnsServers), Net.toCIDRs(routes));
}

private boolean startGnirehtet(VpnConfiguration config) {
Intent vpnIntent = VpnService.prepare(this);
if (vpnIntent == null) {
Log.d(TAG, "VPN was already authorized");
// we got the permission, start the service now
GnirehtetService.start(this, config);
return true;
}

Log.w(TAG, "VPN requires the authorization from the user, requesting...");
requestAuthorization(vpnIntent, config);
return false; // do not finish now
}

private void stopGnirehtet() {
GnirehtetService.stop(this);
}

private void requestAuthorization(Intent vpnIntent, VpnConfiguration config) {
this.config = config;
startActivityForResult(vpnIntent, VPN_REQUEST_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == VPN_REQUEST_CODE && resultCode == RESULT_OK) {
GnirehtetService.start(this, config);
}
config = null;
finish();
}
}

This file was deleted.

8 changes: 4 additions & 4 deletions relay-java/src/main/java/com/genymobile/gnirehtet/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ private static void cmdStart(String serial, String dnsServers, String routes) th
cmdTunnel(serial);

List<String> cmd = new ArrayList<>();
Collections.addAll(cmd, "shell", "am", "broadcast", "-a", "com.genymobile.gnirehtet.START", "-n",
"com.genymobile.gnirehtet/.GnirehtetControlReceiver");
Collections.addAll(cmd, "shell", "am", "start", "-a", "com.genymobile.gnirehtet.START", "-n",
"com.genymobile.gnirehtet/.GnirehtetActivity");
if (dnsServers != null) {
Collections.addAll(cmd, "--esa", "dnsServers", dnsServers);
}
Expand All @@ -277,8 +277,8 @@ private static void cmdAutostart(final String dnsServers, final String routes) {

private static void cmdStop(String serial) throws InterruptedException, IOException, CommandExecutionException {
Log.i(TAG, "Stopping client...");
execAdb(serial, "shell", "am", "broadcast", "-a", "com.genymobile.gnirehtet.STOP", "-n",
"com.genymobile.gnirehtet/.GnirehtetControlReceiver");
execAdb(serial, "shell", "am", "start", "-a", "com.genymobile.gnirehtet.STOP", "-n",
"com.genymobile.gnirehtet/.GnirehtetActivity");
}

private static void cmdRestart(String serial, String dnsServers, String routes) throws InterruptedException, IOException,
Expand Down
8 changes: 4 additions & 4 deletions relay-rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,11 @@ fn cmd_start(
let mut adb_args = vec![
"shell",
"am",
"broadcast",
"start",
"-a",
"com.genymobile.gnirehtet.START",
"-n",
"com.genymobile.gnirehtet/.GnirehtetControlReceiver",
"com.genymobile.gnirehtet/.GnirehtetActivity",
];
if let Some(dns_servers) = dns_servers {
adb_args.append(&mut vec!["--esa", "dnsServers", dns_servers]);
Expand Down Expand Up @@ -411,11 +411,11 @@ fn cmd_stop(serial: Option<&str>) -> Result<(), CommandExecutionError> {
vec![
"shell",
"am",
"broadcast",
"start",
"-a",
"com.genymobile.gnirehtet.STOP",
"-n",
"com.genymobile.gnirehtet/.GnirehtetControlReceiver",
"com.genymobile.gnirehtet/.GnirehtetActivity",
],
)
}
Expand Down

0 comments on commit f868180

Please sign in to comment.