[tor-commits] [orbot/master] switch to Briar jtorctl, upgrade to AndroidX, and tor 0.4.1.6

n8fr8 at torproject.org n8fr8 at torproject.org
Tue Apr 28 21:05:01 UTC 2020


commit 0c8e2e7d24ae349db9b34933636b83f6d641e8f1
Author: n8fr8 <nathan at guardianproject.info>
Date:   Fri Nov 15 12:30:57 2019 -0500

    switch to Briar jtorctl, upgrade to AndroidX, and tor 0.4.1.6
---
 app-mini/build.gradle                              |   4 +-
 .../torproject/android/mini/MiniMainActivity.java  |  16 +-
 .../org/torproject/android/mini/OrbotMiniApp.java  |   2 +-
 .../android/mini/ui/AppConfigActivity.java         |   4 +-
 .../android/mini/ui/AppManagerActivity.java        |   2 +-
 .../mini/ui/NoPersonalizedLearningEditText.java    |   2 +-
 .../mini/ui/onboarding/CustomSlideBigText.java     |   4 +-
 .../mini/ui/onboarding/OnboardingActivity.java     |   4 +-
 .../android/mini/vpn/VPNEnableActivity.java        |   2 +-
 .../src/main/res/layout/activity_app_config.xml    |  10 +-
 app-mini/src/main/res/layout/layout_main.xml       |  10 +-
 app/build.gradle                                   |   2 +-
 app/src/main/AndroidManifest.xml                   |   2 +-
 .../main/java/org/torproject/android/OrbotApp.java |   2 +-
 .../org/torproject/android/OrbotMainActivity.java  |  12 +-
 .../torproject/android/ui/AppManagerActivity.java  |   2 +-
 .../android/ui/NoPersonalizedLearningEditText.java |   2 +-
 .../torproject/android/ui/VPNEnableActivity.java   |   2 +-
 .../ui/hiddenservices/ClientCookiesActivity.java   |   6 +-
 .../ui/hiddenservices/HiddenServicesActivity.java  |   8 +-
 .../adapters/ClientCookiesAdapter.java             |   2 +-
 .../hiddenservices/adapters/OnionListAdapter.java  |   2 +-
 .../android/ui/hiddenservices/backup/ZipIt.java    |   4 +-
 .../ui/hiddenservices/dialogs/AddCookieDialog.java |   6 +-
 .../dialogs/CookieActionsDialog.java               |   6 +-
 .../hiddenservices/dialogs/CookieDeleteDialog.java |   6 +-
 .../ui/hiddenservices/dialogs/HSActionsDialog.java |   6 +-
 .../ui/hiddenservices/dialogs/HSCookieDialog.java  |   6 +-
 .../ui/hiddenservices/dialogs/HSDataDialog.java    |   6 +-
 .../ui/hiddenservices/dialogs/HSDeleteDialog.java  |   6 +-
 .../dialogs/SelectCookieBackupDialog.java          |   6 +-
 .../dialogs/SelectHSBackupDialog.java              |   6 +-
 .../permissions/PermissionManager.java             |   6 +-
 .../providers/CookieContentProvider.java           |   4 +-
 .../providers/HSContentProvider.java               |   4 +-
 .../ui/onboarding/BridgeWizardActivity.java        |   4 +-
 .../android/ui/onboarding/CustomSlideBigText.java  |   4 +-
 .../android/ui/onboarding/OnboardingActivity.java  |   4 +-
 app/src/main/res/layout/activity_bridge_wizard.xml |  10 +-
 .../res/layout/layout_activity_client_cookies.xml  |  12 +-
 app/src/main/res/layout/layout_hs_list_view.xml    |  12 +-
 app/src/main/res/layout/layout_main.xml            |  10 +-
 gradle.properties                                  |   2 +
 orbotservice/build.gradle                          |   6 +-
 .../java/org/torproject/android/control/Bytes.java | 114 ----
 .../torproject/android/control/ConfigEntry.java    |  20 -
 .../torproject/android/control/EventHandler.java   |  75 ---
 .../torproject/android/control/PasswordDigest.java |  98 ---
 .../android/control/TorControlCommands.java        | 148 -----
 .../android/control/TorControlConnection.java      | 730 ---------------------
 .../android/control/TorControlError.java           |  39 --
 .../android/control/TorControlSyntaxError.java     |  16 -
 .../android/service/TorEventHandler.java           |   4 +-
 .../org/torproject/android/service/TorService.java |  18 +-
 .../android/service/util/CustomShell.java          |   6 +-
 .../android/service/vpn/TorVpnService.java         |   2 +-
 56 files changed, 138 insertions(+), 1370 deletions(-)

diff --git a/app-mini/build.gradle b/app-mini/build.gradle
index e48340e8..76f2a0ce 100644
--- a/app-mini/build.gradle
+++ b/app-mini/build.gradle
@@ -102,9 +102,9 @@ android {
 dependencies {
     implementation project(':orbotservice')
     implementation 'com.github.apl-devs:appintro:v4.2.2'
-    implementation 'com.android.support:palette-v7:28.0.0'
+    implementation 'androidx.palette:palette:1.0.0'
     implementation 'com.github.javiersantos:AppUpdater:2.7'
-    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
     androidTestImplementation "tools.fastlane:screengrab:1.2.0"
 }
 
diff --git a/app-mini/src/main/java/org/torproject/android/mini/MiniMainActivity.java b/app-mini/src/main/java/org/torproject/android/mini/MiniMainActivity.java
index d43cec81..bc46b251 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/MiniMainActivity.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/MiniMainActivity.java
@@ -23,14 +23,14 @@ import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.support.v4.content.LocalBroadcastManager;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.graphics.Palette;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.SwitchCompat;
-import android.support.v7.widget.Toolbar;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.drawerlayout.widget.DrawerLayout;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.palette.graphics.Palette;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.appcompat.widget.SwitchCompat;
+import androidx.appcompat.widget.Toolbar;
 import android.text.Html;
 import android.text.TextUtils;
 import android.util.Log;
diff --git a/app-mini/src/main/java/org/torproject/android/mini/OrbotMiniApp.java b/app-mini/src/main/java/org/torproject/android/mini/OrbotMiniApp.java
index 80b34d6d..41bd0697 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/OrbotMiniApp.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/OrbotMiniApp.java
@@ -11,7 +11,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.support.v4.app.NotificationCompat;
+import androidx.core.app.NotificationCompat;
 import com.github.javiersantos.appupdater.AppUpdater;
 import com.github.javiersantos.appupdater.enums.Display;
 import com.github.javiersantos.appupdater.enums.UpdateFrom;
diff --git a/app-mini/src/main/java/org/torproject/android/mini/ui/AppConfigActivity.java b/app-mini/src/main/java/org/torproject/android/mini/ui/AppConfigActivity.java
index a731ef29..03b56bfa 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/ui/AppConfigActivity.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/ui/AppConfigActivity.java
@@ -4,8 +4,8 @@ import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
 import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
diff --git a/app-mini/src/main/java/org/torproject/android/mini/ui/AppManagerActivity.java b/app-mini/src/main/java/org/torproject/android/mini/ui/AppManagerActivity.java
index 489aba4c..1af635d0 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/ui/AppManagerActivity.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/ui/AppManagerActivity.java
@@ -12,7 +12,7 @@ import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
+import androidx.appcompat.app.AppCompatActivity;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
diff --git a/app-mini/src/main/java/org/torproject/android/mini/ui/NoPersonalizedLearningEditText.java b/app-mini/src/main/java/org/torproject/android/mini/ui/NoPersonalizedLearningEditText.java
index a5d67d79..07d91429 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/ui/NoPersonalizedLearningEditText.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/ui/NoPersonalizedLearningEditText.java
@@ -1,7 +1,7 @@
 package org.torproject.android.mini.ui;
 
 import android.content.Context;
-import android.support.v7.widget.AppCompatEditText;
+import androidx.appcompat.widget.AppCompatEditText;
 import android.util.AttributeSet;
 import android.view.inputmethod.EditorInfo;
 
diff --git a/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/CustomSlideBigText.java b/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/CustomSlideBigText.java
index a370c6f1..a4512639 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/CustomSlideBigText.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/CustomSlideBigText.java
@@ -1,8 +1,8 @@
 package org.torproject.android.mini.ui.onboarding;
 
 import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/OnboardingActivity.java b/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/OnboardingActivity.java
index 5e661999..bce4585a 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/OnboardingActivity.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/ui/onboarding/OnboardingActivity.java
@@ -2,8 +2,8 @@ package org.torproject.android.mini.ui.onboarding;
 
 import android.content.Context;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
 import com.github.paolorotolo.appintro.AppIntro;
 import org.torproject.android.mini.R;
 import org.torproject.android.mini.settings.LocaleHelper;
diff --git a/app-mini/src/main/java/org/torproject/android/mini/vpn/VPNEnableActivity.java b/app-mini/src/main/java/org/torproject/android/mini/vpn/VPNEnableActivity.java
index bb263372..d65913b5 100644
--- a/app-mini/src/main/java/org/torproject/android/mini/vpn/VPNEnableActivity.java
+++ b/app-mini/src/main/java/org/torproject/android/mini/vpn/VPNEnableActivity.java
@@ -5,7 +5,7 @@ import android.net.VpnService;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
-import android.support.v7.app.AppCompatActivity;
+import androidx.appcompat.app.AppCompatActivity;
 import android.util.Log;
 import android.view.Window;
 import org.torproject.android.service.TorService;
diff --git a/app-mini/src/main/res/layout/activity_app_config.xml b/app-mini/src/main/res/layout/activity_app_config.xml
index accb290b..e2b12feb 100644
--- a/app-mini/src/main/res/layout/activity_app_config.xml
+++ b/app-mini/src/main/res/layout/activity_app_config.xml
@@ -1,26 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
-<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".ui.AppConfigActivity">
 
-    <android.support.design.widget.AppBarLayout
+    <com.google.android.material.appbar.AppBarLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:theme="@style/DefaultTheme.AppBarOverlay">
 
-        <android.support.v7.widget.Toolbar
+        <androidx.appcompat.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
             android:background="@color/dark_green"
             app:popupTheme="@style/DefaultTheme.PopupOverlay" />
 
-    </android.support.design.widget.AppBarLayout>
+    </com.google.android.material.appbar.AppBarLayout>
 
 
     <include layout="@layout/content_app_config" />
 
-</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app-mini/src/main/res/layout/layout_main.xml b/app-mini/src/main/res/layout/layout_main.xml
index d8fbfce6..9fff25b8 100644
--- a/app-mini/src/main/res/layout/layout_main.xml
+++ b/app-mini/src/main/res/layout/layout_main.xml
@@ -8,12 +8,12 @@
     android:background="@color/light_gray"
 	xmlns:app="http://schemas.android.com/apk/res-auto">
     
-     <android.support.v7.widget.Toolbar
+     <androidx.appcompat.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:minHeight="?attr/actionBarSize" />
-    <android.support.v4.widget.DrawerLayout
+    <androidx.drawerlayout.widget.DrawerLayout
     android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -23,7 +23,7 @@
     android:layout_height="match_parent">
 
 
-<android.support.v7.widget.RecyclerView
+<androidx.recyclerview.widget.RecyclerView
 	android:layout_width="match_parent"
 	android:layout_height="wrap_content"
 	android:id="@+id/rv"
@@ -62,7 +62,7 @@
 			android:layout_margin="0dp"
 			android:src="@drawable/toroff" />
 
-		<android.support.v7.widget.SwitchCompat
+		<androidx.appcompat.widget.SwitchCompat
             android:id="@+id/btnVPN"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -139,7 +139,7 @@
 			 />
     </LinearLayout>
 	
-	</android.support.v4.widget.DrawerLayout>
+	</androidx.drawerlayout.widget.DrawerLayout>
 
 </LinearLayout>
 
diff --git a/app/build.gradle b/app/build.gradle
index 1c89e568..3c5d265f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -117,7 +117,7 @@ android {
 
 dependencies {
     implementation project(':orbotservice')
-    implementation 'com.android.support:design:28.0.0'
+    implementation 'com.google.android.material:material:1.0.0'
     implementation 'pl.bclogic:pulsator4droid:1.0.3'
     implementation 'com.github.apl-devs:appintro:v4.2.2'
     implementation 'com.github.javiersantos:AppUpdater:2.6.4'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f118253e..184dbdd9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -137,7 +137,7 @@
             android:authorities="org.torproject.android.ui.hiddenservices.providers"
             android:exported="false" />
         <provider
-            android:name="android.support.v4.content.FileProvider"
+            android:name="androidx.core.content.FileProvider"
             android:authorities="org.torproject.android.ui.hiddenservices.storage"
             android:exported="false"
             android:grantUriPermissions="true">
diff --git a/app/src/main/java/org/torproject/android/OrbotApp.java b/app/src/main/java/org/torproject/android/OrbotApp.java
index f022f611..e265bef8 100644
--- a/app/src/main/java/org/torproject/android/OrbotApp.java
+++ b/app/src/main/java/org/torproject/android/OrbotApp.java
@@ -11,7 +11,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.support.v4.app.NotificationCompat;
+import androidx.core.app.NotificationCompat;
 import com.github.javiersantos.appupdater.AppUpdater;
 import com.github.javiersantos.appupdater.enums.Display;
 import com.github.javiersantos.appupdater.enums.UpdateFrom;
diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 4ff3e850..64f1ee42 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -24,11 +24,11 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
-import android.support.v4.content.LocalBroadcastManager;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.SwitchCompat;
-import android.support.v7.widget.Toolbar;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.drawerlayout.widget.DrawerLayout;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SwitchCompat;
+import androidx.appcompat.widget.Toolbar;
 import android.text.Html;
 import android.text.TextUtils;
 import android.util.Log;
@@ -87,7 +87,7 @@ import java.util.ArrayList;
 import java.util.Locale;
 import java.util.StringTokenizer;
 
-import static android.support.v4.content.FileProvider.getUriForFile;
+import static androidx.core.content.FileProvider.getUriForFile;
 import static org.torproject.android.MainConstants.COUNTRY_CODES;
 import static org.torproject.android.MainConstants.RESULT_CLOSE_ALL;
 import static org.torproject.android.MainConstants.URL_TOR_CHECK;
diff --git a/app/src/main/java/org/torproject/android/ui/AppManagerActivity.java b/app/src/main/java/org/torproject/android/ui/AppManagerActivity.java
index 111dda5f..98e62a1f 100644
--- a/app/src/main/java/org/torproject/android/ui/AppManagerActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/AppManagerActivity.java
@@ -12,7 +12,7 @@ import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
+import androidx.appcompat.app.AppCompatActivity;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
diff --git a/app/src/main/java/org/torproject/android/ui/NoPersonalizedLearningEditText.java b/app/src/main/java/org/torproject/android/ui/NoPersonalizedLearningEditText.java
index 15d8d023..7a21c7c5 100644
--- a/app/src/main/java/org/torproject/android/ui/NoPersonalizedLearningEditText.java
+++ b/app/src/main/java/org/torproject/android/ui/NoPersonalizedLearningEditText.java
@@ -1,7 +1,7 @@
 package org.torproject.android.ui;
 
 import android.content.Context;
-import android.support.v7.widget.AppCompatEditText;
+import androidx.appcompat.widget.AppCompatEditText;
 import android.util.AttributeSet;
 import android.view.inputmethod.EditorInfo;
 
diff --git a/app/src/main/java/org/torproject/android/ui/VPNEnableActivity.java b/app/src/main/java/org/torproject/android/ui/VPNEnableActivity.java
index e910be32..be26e315 100644
--- a/app/src/main/java/org/torproject/android/ui/VPNEnableActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/VPNEnableActivity.java
@@ -5,7 +5,7 @@ import android.net.VpnService;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
-import android.support.v7.app.AppCompatActivity;
+import androidx.appcompat.app.AppCompatActivity;
 import android.util.Log;
 import android.view.Window;
 import org.torproject.android.service.TorService;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
index 8ff14fbb..4b76e1e7 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/ClientCookiesActivity.java
@@ -9,9 +9,9 @@ import android.database.ContentObserver;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.Handler;
-import android.support.design.widget.FloatingActionButton;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
index f41babdf..04404df2 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
@@ -8,10 +8,10 @@ import android.database.ContentObserver;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.Handler;
-import android.support.design.widget.FloatingActionButton;
-import android.support.v4.view.MenuItemCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import androidx.core.view.MenuItemCompat;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClientCookiesAdapter.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClientCookiesAdapter.java
index 10108ba8..e0db9528 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClientCookiesAdapter.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/ClientCookiesAdapter.java
@@ -4,7 +4,7 @@ import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
-import android.support.v4.widget.CursorAdapter;
+import androidx.cursoradapter.widget.CursorAdapter;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
index a41befdf..485afe09 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/adapters/OnionListAdapter.java
@@ -4,7 +4,7 @@ import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
-import android.support.v4.widget.CursorAdapter;
+import androidx.cursoradapter.widget.CursorAdapter;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipIt.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipIt.java
index 130b56bb..4a42df1f 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipIt.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/ZipIt.java
@@ -1,8 +1,8 @@
 package org.torproject.android.ui.hiddenservices.backup;
 
 
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/AddCookieDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/AddCookieDialog.java
index af8922d6..c47d9ae8 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/AddCookieDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/AddCookieDialog.java
@@ -5,9 +5,9 @@ import android.app.Dialog;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java
index 03dddbd6..a060453d 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieActionsDialog.java
@@ -6,9 +6,9 @@ import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import android.view.View;
 import android.widget.Button;
 import android.widget.Toast;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieDeleteDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieDeleteDialog.java
index d2b1220d..ed847cdc 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieDeleteDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/CookieDeleteDialog.java
@@ -5,9 +5,9 @@ import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import org.torproject.android.R;
 import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
 
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
index ce77fd2a..31ae2bee 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
@@ -8,9 +8,9 @@ import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import android.view.View;
 import android.widget.Button;
 import android.widget.Toast;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
index eb9ee9ce..054516fb 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSCookieDialog.java
@@ -5,9 +5,9 @@ import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
index d7ba35e3..bfae0ca3 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
@@ -5,9 +5,9 @@ import android.app.Dialog;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import android.view.View;
 import android.widget.Button;
 import android.widget.CheckBox;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java
index cf38ffab..a0951d35 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDeleteDialog.java
@@ -5,9 +5,9 @@ import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import org.torproject.android.R;
 import org.torproject.android.service.TorServiceConstants;
 import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectCookieBackupDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectCookieBackupDialog.java
index af362358..a8e380d9 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectCookieBackupDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectCookieBackupDialog.java
@@ -3,9 +3,9 @@ package org.torproject.android.ui.hiddenservices.dialogs;
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.ListView;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectHSBackupDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectHSBackupDialog.java
index cb0c2bfe..ae15ae49 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectHSBackupDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/SelectHSBackupDialog.java
@@ -3,9 +3,9 @@ package org.torproject.android.ui.hiddenservices.dialogs;
 import android.app.Dialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
+import androidx.appcompat.app.AlertDialog;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.ListView;
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java
index 3ee11ec8..eb1a40b4 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/permissions/PermissionManager.java
@@ -11,9 +11,9 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.PowerManager;
 import android.provider.Settings;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.app.FragmentActivity;
+import com.google.android.material.snackbar.Snackbar;
+import androidx.core.app.ActivityCompat;
+import androidx.fragment.app.FragmentActivity;
 import android.view.View;
 import org.torproject.android.R;
 
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/CookieContentProvider.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/CookieContentProvider.java
index 1f31b9cb..318e37af 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/CookieContentProvider.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/CookieContentProvider.java
@@ -9,8 +9,8 @@ import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.net.Uri;
 import android.provider.BaseColumns;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import org.torproject.android.ui.hiddenservices.database.HSDatabase;
 
 
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
index 07641ea0..5cf20f8e 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
@@ -9,8 +9,8 @@ import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.net.Uri;
 import android.provider.BaseColumns;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import org.torproject.android.ui.hiddenservices.database.HSDatabase;
 
 
diff --git a/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java b/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java
index 15216333..6e54e103 100644
--- a/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/onboarding/BridgeWizardActivity.java
@@ -8,8 +8,8 @@ import android.content.Intent;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
 import android.text.TextUtils;
 import android.view.MenuItem;
 import android.view.View;
diff --git a/app/src/main/java/org/torproject/android/ui/onboarding/CustomSlideBigText.java b/app/src/main/java/org/torproject/android/ui/onboarding/CustomSlideBigText.java
index 2ed1c01c..b4f319b2 100644
--- a/app/src/main/java/org/torproject/android/ui/onboarding/CustomSlideBigText.java
+++ b/app/src/main/java/org/torproject/android/ui/onboarding/CustomSlideBigText.java
@@ -1,8 +1,8 @@
 package org.torproject.android.ui.onboarding;
 
 import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/app/src/main/java/org/torproject/android/ui/onboarding/OnboardingActivity.java b/app/src/main/java/org/torproject/android/ui/onboarding/OnboardingActivity.java
index 88359434..e73a88b8 100644
--- a/app/src/main/java/org/torproject/android/ui/onboarding/OnboardingActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/onboarding/OnboardingActivity.java
@@ -3,8 +3,8 @@ package org.torproject.android.ui.onboarding;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
 import android.view.View;
 import com.github.paolorotolo.appintro.AppIntro;
 import org.torproject.android.R;
diff --git a/app/src/main/res/layout/activity_bridge_wizard.xml b/app/src/main/res/layout/activity_bridge_wizard.xml
index 7ff470c9..d5b88c0d 100644
--- a/app/src/main/res/layout/activity_bridge_wizard.xml
+++ b/app/src/main/res/layout/activity_bridge_wizard.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
@@ -8,20 +8,20 @@
 
     tools:context="org.torproject.android.ui.onboarding.BridgeWizardActivity">
 
-    <android.support.design.widget.AppBarLayout
+    <com.google.android.material.appbar.AppBarLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:theme="@style/DefaultTheme.AppBarOverlay">
 
-        <android.support.v7.widget.Toolbar
+        <androidx.appcompat.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
             android:background="?attr/colorPrimary"
             app:popupTheme="@style/DefaultTheme.PopupOverlay" />
 
-    </android.support.design.widget.AppBarLayout>
+    </com.google.android.material.appbar.AppBarLayout>
 
     <include layout="@layout/content_bridge_wizard" />
 
-</android.support.design.widget.CoordinatorLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout/layout_activity_client_cookies.xml b/app/src/main/res/layout/layout_activity_client_cookies.xml
index b8f0626e..9314255d 100644
--- a/app/src/main/res/layout/layout_activity_client_cookies.xml
+++ b/app/src/main/res/layout/layout_activity_client_cookies.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
@@ -7,23 +7,23 @@
     android:fitsSystemWindows="true"
     tools:context="org.torproject.android.ui.hiddenservices.ClientCookiesActivity">
 
-    <android.support.design.widget.AppBarLayout
+    <com.google.android.material.appbar.AppBarLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:theme="@style/DefaultTheme.AppBarOverlay">
 
-        <android.support.v7.widget.Toolbar
+        <androidx.appcompat.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
             android:background="?attr/colorPrimary"
             app:popupTheme="@style/DefaultTheme.PopupOverlay" />
 
-    </android.support.design.widget.AppBarLayout>
+    </com.google.android.material.appbar.AppBarLayout>
 
     <include layout="@layout/layout_content_client_cookies" />
 
-    <android.support.design.widget.FloatingActionButton
+    <com.google.android.material.floatingactionbutton.FloatingActionButton
         android:id="@+id/fab"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -32,4 +32,4 @@
         app:srcCompat="@android:drawable/stat_notify_more"
         app:backgroundTint="@android:color/darker_gray" />
 
-</android.support.design.widget.CoordinatorLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout/layout_hs_list_view.xml b/app/src/main/res/layout/layout_hs_list_view.xml
index 4981877d..e4171949 100644
--- a/app/src/main/res/layout/layout_hs_list_view.xml
+++ b/app/src/main/res/layout/layout_hs_list_view.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
@@ -7,21 +7,21 @@
     android:fitsSystemWindows="true"
     tools:context="org.torproject.android.ui.hiddenservices.HiddenServicesActivity">
 
-    <android.support.design.widget.AppBarLayout
+    <com.google.android.material.appbar.AppBarLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
-        <android.support.v7.widget.Toolbar
+        <androidx.appcompat.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
             android:background="?attr/colorPrimary" />
 
-    </android.support.design.widget.AppBarLayout>
+    </com.google.android.material.appbar.AppBarLayout>
 
     <include layout="@layout/layout_hs_list_view_main" />
 
-    <android.support.design.widget.FloatingActionButton
+    <com.google.android.material.floatingactionbutton.FloatingActionButton
         android:id="@+id/fab"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
@@ -30,4 +30,4 @@
         app:srcCompat="@android:drawable/stat_notify_more"
         app:backgroundTint="@android:color/darker_gray" />
 
-</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_main.xml b/app/src/main/res/layout/layout_main.xml
index 42e6691f..106cf921 100644
--- a/app/src/main/res/layout/layout_main.xml
+++ b/app/src/main/res/layout/layout_main.xml
@@ -9,12 +9,12 @@
 	android:background="@color/dark_purple"
 	xmlns:app="http://schemas.android.com/apk/res-auto">
     
-     <android.support.v7.widget.Toolbar
+     <androidx.appcompat.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:minHeight="?attr/actionBarSize" />
-    <android.support.v4.widget.DrawerLayout
+    <androidx.drawerlayout.widget.DrawerLayout
     android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -147,7 +147,7 @@
         android:layout_weight="1"
 
         >
-        <android.support.v7.widget.SwitchCompat
+        <androidx.appcompat.widget.SwitchCompat
             android:id="@+id/btnVPN"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -261,7 +261,7 @@
             android:lines="1"
 
             />
-        <android.support.v7.widget.SwitchCompat
+        <androidx.appcompat.widget.SwitchCompat
             android:id="@+id/btnBridges"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -336,7 +336,7 @@
 			 />
     </LinearLayout>
 	
-	</android.support.v4.widget.DrawerLayout>
+	</androidx.drawerlayout.widget.DrawerLayout>
 
 </LinearLayout>
 
diff --git a/gradle.properties b/gradle.properties
index d5f3dfc4..1cf3bf02 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,6 +6,8 @@
 # Specifies the JVM arguments used for the daemon process.
 # The setting is particularly useful for tweaking memory settings.
 # Default value: -Xmx10248m -XX:MaxPermSize=256m
+android.enableJetifier=true
+android.useAndroidX=true
 org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
 #
 # When configured, Gradle will run in incubating parallel mode.
diff --git a/orbotservice/build.gradle b/orbotservice/build.gradle
index 13987ab9..5f8cadba 100644
--- a/orbotservice/build.gradle
+++ b/orbotservice/build.gradle
@@ -41,9 +41,9 @@ android {
 
 dependencies {
 
-    implementation 'com.android.support:support-v4:28.0.0'
+    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
 
-    implementation 'org.torproject:tor-android-binary:0.4.1.5'
+    implementation 'org.torproject:tor-android-binary:0.4.1.6-dev'
     implementation 'info.pluggabletransports.aptds:apt-dispatch-library:1.0.7'
     implementation 'info.pluggabletransports.aptds:apt-meek-obfs4-legacy:1.0.7'
     implementation 'info.pluggabletransports.aptds:jsocksAndroid:1.0.4'
@@ -53,4 +53,6 @@ dependencies {
     testImplementation 'junit:junit:4.12'
 
     implementation 'com.offbynull.portmapper:portmapper:2.0.5'
+
+    implementation 'org.briarproject:jtorctl:0.3'
 }
diff --git a/orbotservice/src/main/java/org/torproject/android/control/Bytes.java b/orbotservice/src/main/java/org/torproject/android/control/Bytes.java
deleted file mode 100644
index e754d907..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/Bytes.java
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Static class to do bytewise structure manipulation in Java.
- */
-/* XXXX There must be a better way to do most of this.
- * XXXX The string logic here uses default encoding, which is stupid.
- */
-final class Bytes {
-
-    /** Write the two-byte value in 's' into the byte array 'ba', starting at
-     * the index 'pos'. */
-    public static void setU16(byte[] ba, int pos, short s) {
-        ba[pos]   = (byte)((s >> 8) & 0xff);
-        ba[pos+1] = (byte)((s     ) & 0xff);
-    }
-
-    /** Write the four-byte value in 'i' into the byte array 'ba', starting at
-     * the index 'pos'. */
-    public static void setU32(byte[] ba, int pos, int i) {
-        ba[pos]   = (byte)((i >> 24) & 0xff);
-        ba[pos+1] = (byte)((i >> 16) & 0xff);
-        ba[pos+2] = (byte)((i >>  8) & 0xff);
-        ba[pos+3] = (byte)((i      ) & 0xff);
-    }
-
-    /** Return the four-byte value starting at index 'pos' within 'ba' */
-    public static int getU32(byte[] ba, int pos) {
-        return
-            ((ba[pos  ]&0xff)<<24) |
-            ((ba[pos+1]&0xff)<<16) |
-            ((ba[pos+2]&0xff)<< 8)  |
-            ((ba[pos+3]&0xff));
-    }
-
-    public static String getU32S(byte[] ba, int pos) {
-        return String.valueOf( (getU32(ba,pos))&0xffffffffL );
-    }
-
-    /** Return the two-byte value starting at index 'pos' within 'ba' */
-    public static int getU16(byte[] ba, int pos) {
-        return
-            ((ba[pos  ]&0xff)<<8) |
-            ((ba[pos+1]&0xff));
-    }
-
-    /** Return the string starting at position 'pos' of ba and extending
-     * until a zero byte or the end of the string. */
-    public static String getNulTerminatedStr(byte[] ba, int pos) {
-        int len, maxlen = ba.length-pos;
-        for (len=0; len<maxlen; ++len) {
-            if (ba[pos+len] == 0)
-                break;
-        }
-        return new String(ba, pos, len);
-    }
-
-    /**
-     * Read bytes from 'ba' starting at 'pos', dividing them into strings
-     * along the character in 'split' and writing them into 'lst'
-     */
-    public static void splitStr(List<String> lst, byte[] ba, int pos, byte split) {
-        while (pos < ba.length && ba[pos] != 0) {
-            int len;
-            for (len=0; pos+len < ba.length; ++len) {
-                if (ba[pos+len] == 0 || ba[pos+len] == split)
-                    break;
-            }
-            if (len>0)
-                lst.add(new String(ba, pos, len));
-            pos += len;
-            if (ba[pos] == split)
-                ++pos;
-        }
-    }
-
-    /**
-     * Read bytes from 'ba' starting at 'pos', dividing them into strings
-     * along the character in 'split' and writing them into 'lst'
-     */
-    public static List<String> splitStr(List<String> lst, String str) {
-        // split string on spaces, include trailing/leading
-        String[] tokenArray = str.split(" ", -1);
-        if (lst == null) {
-            lst = Arrays.asList( tokenArray );
-        } else {
-            lst.addAll( Arrays.asList( tokenArray ) );
-        }
-        return lst;
-    }
-
-    private static final char[] NYBBLES = {
-        '0', '1', '2', '3', '4', '5', '6', '7',
-        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-    };
-
-    public static final String hex(byte[] ba) {
-        StringBuffer buf = new StringBuffer();
-        for (int i = 0; i < ba.length; ++i) {
-            int b = (ba[i]) & 0xff;
-            buf.append(NYBBLES[b >> 4]);
-            buf.append(NYBBLES[b&0x0f]);
-        }
-        return buf.toString();
-    }
-
-    private Bytes() {};
-}
-
diff --git a/orbotservice/src/main/java/org/torproject/android/control/ConfigEntry.java b/orbotservice/src/main/java/org/torproject/android/control/ConfigEntry.java
deleted file mode 100644
index 31eb4b8e..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/ConfigEntry.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-/** A single key-value pair from Tor's configuration. */
-public class ConfigEntry {
-    public ConfigEntry(String k, String v) {
-        key = k;
-        value = v;
-        is_default = false;
-    }
-    public ConfigEntry(String k) {
-        key = k;
-        value = "";
-        is_default = true;
-    }
-    public final String key;
-    public final String value;
-    public final boolean is_default;
-}
diff --git a/orbotservice/src/main/java/org/torproject/android/control/EventHandler.java b/orbotservice/src/main/java/org/torproject/android/control/EventHandler.java
deleted file mode 100644
index de06bf0f..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/EventHandler.java
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-/**
- * Abstract interface whose methods are invoked when Tor sends us an event.
- *
- * @see TorControlConnection#setEventHandler
- * @see TorControlConnection#setEvents
- */
-public interface EventHandler {
-    /**
-     * Invoked when a circuit's status has changed.
-     * Possible values for <b>status</b> are:
-     * <ul>
-     *   <li>"LAUNCHED" :  circuit ID assigned to new circuit</li>
-     *   <li>"BUILT"    :  all hops finished, can now accept streams</li>
-     *   <li>"EXTENDED" :  one more hop has been completed</li>
-     *   <li>"FAILED"   :  circuit closed (was not built)</li>
-     *   <li>"CLOSED"   :  circuit closed (was built)</li>
-     *	</ul>
-     *
-     * <b>circID</b> is the alphanumeric identifier of the affected circuit,
-     * and <b>path</b> is a comma-separated list of alphanumeric ServerIDs.
-     */
-    public void circuitStatus(String status, String circID, String path);
-    /**
-     * Invoked when a stream's status has changed.
-     * Possible values for <b>status</b> are:
-     * <ul>
-     *   <li>"NEW"         :  New request to connect</li>
-     *   <li>"NEWRESOLVE"  :  New request to resolve an address</li>
-     *   <li>"SENTCONNECT" :  Sent a connect cell along a circuit</li>
-     *   <li>"SENTRESOLVE" :  Sent a resolve cell along a circuit</li>
-     *   <li>"SUCCEEDED"   :  Received a reply; stream established</li>
-     *   <li>"FAILED"      :  Stream failed and not retriable.</li>
-     *   <li>"CLOSED"      :  Stream closed</li>
-     *   <li>"DETACHED"    :  Detached from circuit; still retriable.</li>
-     *	</ul>
-     *
-     * <b>streamID</b> is the alphanumeric identifier of the affected stream,
-     * and its <b>target</b> is specified as address:port.
-     */
-    public void streamStatus(String status, String streamID, String target);
-    /**
-     * Invoked when the status of a connection to an OR has changed.
-     * Possible values for <b>status</b> are ["LAUNCHED" | "CONNECTED" | "FAILED" | "CLOSED"].
-     * <b>orName</b> is the alphanumeric identifier of the OR affected.
-     */
-    public void orConnStatus(String status, String orName);
-    /**
-     * Invoked once per second. <b>read</b> and <b>written</b> are
-     * the number of bytes read and written, respectively, in
-     * the last second.
-     */
-    public void bandwidthUsed(long read, long written);
-    /**
-     * Invoked whenever Tor learns about new ORs.  The <b>orList</b> object
-     * contains the alphanumeric ServerIDs associated with the new ORs.
-     */
-    public void newDescriptors(java.util.List<String> orList);
-    /**
-     * Invoked when Tor logs a message.
-     * <b>severity</b> is one of ["DEBUG" | "INFO" | "NOTICE" | "WARN" | "ERR"],
-     * and <b>msg</b> is the message string.
-     */
-    public void message(String severity, String msg);
-    /**
-     * Invoked when an unspecified message is received.
-     * <type> is the message type, and <msg> is the message string.
-     */
-    public void unrecognized(String type, String msg);
-
-}
-
diff --git a/orbotservice/src/main/java/org/torproject/android/control/PasswordDigest.java b/orbotservice/src/main/java/org/torproject/android/control/PasswordDigest.java
deleted file mode 100644
index 03d0a98e..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/PasswordDigest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-
-/**
- * A hashed digest of a secret password (used to set control connection
- * security.)
- *
- * For the actual hashing algorithm, see RFC2440's secret-to-key conversion.
- */
-public class PasswordDigest {
-
-    private final byte[] secret;
-    private final String hashedKey;
-
-    /** Return a new password digest with a random secret and salt. */
-    public static PasswordDigest generateDigest() {
-        byte[] secret = new byte[20];
-        SecureRandom rng = new SecureRandom();
-        rng.nextBytes(secret);
-        return new PasswordDigest(secret);
-    }
-
-    /** Construct a new password digest with a given secret and random salt */
-    public PasswordDigest(byte[] secret) {
-        this(secret, null);
-    }
-
-    /** Construct a new password digest with a given secret and random salt.
-     * Note that the 9th byte of the specifier determines the number of hash
-     * iterations as in RFC2440.
-     */
-    public PasswordDigest(byte[] secret, byte[] specifier) {
-        this.secret = secret.clone();
-        if (specifier == null) {
-            specifier = new byte[9];
-            SecureRandom rng = new SecureRandom();
-            rng.nextBytes(specifier);
-            specifier[8] = 96;
-        }
-        hashedKey = "16:"+encodeBytes(secretToKey(secret, specifier));
-    }
-
-    /** Return the secret used to generate this password hash.
-     */
-    public byte[] getSecret() {
-        return secret.clone();
-    }
-
-    /** Return the hashed password in the format used by Tor. */
-    public String getHashedPassword() {
-        return hashedKey;
-    }
-
-    /** Parameter used by RFC2440's s2k algorithm. */
-    private static final int EXPBIAS = 6;
-
-    /** Implement rfc2440 s2k */
-    public static byte[] secretToKey(byte[] secret, byte[] specifier) {
-        MessageDigest d;
-        try {
-            d = MessageDigest.getInstance("SHA-1");
-        } catch (NoSuchAlgorithmException ex) {
-            throw new RuntimeException("Can't run without sha-1.");
-        }
-        int c = (specifier[8])&0xff;
-        int count = (16 + (c&15)) << ((c>>4) + EXPBIAS);
-
-        byte[] tmp = new byte[8+secret.length];
-        System.arraycopy(specifier, 0, tmp, 0, 8);
-        System.arraycopy(secret, 0, tmp, 8, secret.length);
-        while (count > 0) {
-            if (count >= tmp.length) {
-                d.update(tmp);
-                count -= tmp.length;
-            } else {
-                d.update(tmp, 0, count);
-                count = 0;
-            }
-        }
-        byte[] key = new byte[20+9];
-        System.arraycopy(d.digest(), 0, key, 9, 20);
-        System.arraycopy(specifier, 0, key, 0, 9);
-        return key;
-    }
-
-    /** Return a hexadecimal encoding of a byte array. */
-    // XXX There must be a better way to do this in Java.
-    private static final String encodeBytes(byte[] ba) {
-        return Bytes.hex(ba);
-    }
-
-}
-
diff --git a/orbotservice/src/main/java/org/torproject/android/control/TorControlCommands.java b/orbotservice/src/main/java/org/torproject/android/control/TorControlCommands.java
deleted file mode 100644
index c98a1c48..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/TorControlCommands.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-/** Interface defining constants used by the Tor controller protocol.
- */
-// XXXX Take documentation for these from control-spec.txt
-public interface TorControlCommands {
-
-    public static final short CMD_ERROR = 0x0000;
-    public static final short CMD_DONE = 0x0001;
-    public static final short CMD_SETCONF = 0x0002;
-    public static final short CMD_GETCONF = 0x0003;
-    public static final short CMD_CONFVALUE = 0x0004;
-    public static final short CMD_SETEVENTS = 0x0005;
-    public static final short CMD_EVENT = 0x0006;
-    public static final short CMD_AUTH = 0x0007;
-    public static final short CMD_SAVECONF = 0x0008;
-    public static final short CMD_SIGNAL = 0x0009;
-    public static final short CMD_MAPADDRESS = 0x000A;
-    public static final short CMD_GETINFO = 0x000B;
-    public static final short CMD_INFOVALUE = 0x000C;
-    public static final short CMD_EXTENDCIRCUIT = 0x000D;
-    public static final short CMD_ATTACHSTREAM = 0x000E;
-    public static final short CMD_POSTDESCRIPTOR = 0x000F;
-    public static final short CMD_FRAGMENTHEADER = 0x0010;
-    public static final short CMD_FRAGMENT = 0x0011;
-    public static final short CMD_REDIRECTSTREAM = 0x0012;
-    public static final short CMD_CLOSESTREAM = 0x0013;
-    public static final short CMD_CLOSECIRCUIT = 0x0014;
-
-    public static final String[] CMD_NAMES = {
-        "ERROR",
-        "DONE",
-        "SETCONF",
-        "GETCONF",
-        "CONFVALUE",
-        "SETEVENTS",
-        "EVENT",
-        "AUTH",
-        "SAVECONF",
-        "SIGNAL",
-        "MAPADDRESS",
-        "GETINFO",
-        "INFOVALUE",
-        "EXTENDCIRCUIT",
-        "ATTACHSTREAM",
-        "POSTDESCRIPTOR",
-        "FRAGMENTHEADER",
-        "FRAGMENT",
-        "REDIRECTSTREAM",
-        "CLOSESTREAM",
-        "CLOSECIRCUIT",
-    };
-
-    public static final short EVENT_CIRCSTATUS = 0x0001;
-    public static final short EVENT_STREAMSTATUS = 0x0002;
-    public static final short EVENT_ORCONNSTATUS = 0x0003;
-    public static final short EVENT_BANDWIDTH = 0x0004;
-    public static final short EVENT_NEWDESCRIPTOR = 0x0006;
-    public static final short EVENT_MSG_DEBUG = 0x0007;
-    public static final short EVENT_MSG_INFO = 0x0008;
-    public static final short EVENT_MSG_NOTICE = 0x0009;
-    public static final short EVENT_MSG_WARN = 0x000A;
-    public static final short EVENT_MSG_ERROR = 0x000B;
-
-    public static final String[] EVENT_NAMES = {
-        "(0)",
-        "CIRC",
-        "STREAM",
-        "ORCONN",
-        "BW",
-        "OLDLOG",
-        "NEWDESC",
-        "DEBUG",
-        "INFO",
-        "NOTICE",
-        "WARN",
-        "ERR",
-    };
-
-    public static final byte CIRC_STATUS_LAUNCHED = 0x01;
-    public static final byte CIRC_STATUS_BUILT = 0x02;
-    public static final byte CIRC_STATUS_EXTENDED = 0x03;
-    public static final byte CIRC_STATUS_FAILED = 0x04;
-    public static final byte CIRC_STATUS_CLOSED = 0x05;
-
-    public static final String[] CIRC_STATUS_NAMES = {
-        "LAUNCHED",
-        "BUILT",
-        "EXTENDED",
-        "FAILED",
-        "CLOSED",
-    };
-
-    public static final byte STREAM_STATUS_SENT_CONNECT = 0x00;
-    public static final byte STREAM_STATUS_SENT_RESOLVE = 0x01;
-    public static final byte STREAM_STATUS_SUCCEEDED = 0x02;
-    public static final byte STREAM_STATUS_FAILED = 0x03;
-    public static final byte STREAM_STATUS_CLOSED = 0x04;
-    public static final byte STREAM_STATUS_NEW_CONNECT = 0x05;
-    public static final byte STREAM_STATUS_NEW_RESOLVE = 0x06;
-    public static final byte STREAM_STATUS_DETACHED = 0x07;
-
-    public static final String[] STREAM_STATUS_NAMES = {
-        "SENT_CONNECT",
-        "SENT_RESOLVE",
-        "SUCCEEDED",
-        "FAILED",
-        "CLOSED",
-        "NEW_CONNECT",
-        "NEW_RESOLVE",
-        "DETACHED"
-    };
-
-    public static final byte OR_CONN_STATUS_LAUNCHED = 0x00;
-    public static final byte OR_CONN_STATUS_CONNECTED = 0x01;
-    public static final byte OR_CONN_STATUS_FAILED = 0x02;
-    public static final byte OR_CONN_STATUS_CLOSED = 0x03;
-
-    public static final String[] OR_CONN_STATUS_NAMES = {
-        "LAUNCHED","CONNECTED","FAILED","CLOSED"
-    };
-
-    public static final byte SIGNAL_HUP = 0x01;
-    public static final byte SIGNAL_INT = 0x02;
-    public static final byte SIGNAL_USR1 = 0x0A;
-    public static final byte SIGNAL_USR2 = 0x0C;
-    public static final byte SIGNAL_TERM = 0x0F;
-
-    public static final String ERROR_MSGS[] = {
-        "Unspecified error",
-        "Internal error",
-        "Unrecognized message type",
-        "Syntax error",
-        "Unrecognized configuration key",
-        "Invalid configuration value",
-        "Unrecognized byte code",
-        "Unauthorized",
-        "Failed authentication attempt",
-        "Resource exhausted",
-        "No such stream",
-        "No such circuit",
-        "No such OR",
-    };
-
-}
-
diff --git a/orbotservice/src/main/java/org/torproject/android/control/TorControlConnection.java b/orbotservice/src/main/java/org/torproject/android/control/TorControlConnection.java
deleted file mode 100644
index bed62128..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/TorControlConnection.java
+++ /dev/null
@@ -1,730 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-/** A connection to a running Tor process as specified in control-spec.txt. */
-public class TorControlConnection implements TorControlCommands {
-
-    private final LinkedList<Waiter> waiters;
-    private final BufferedReader input;
-    private final Writer output;
-
-    private ControlParseThread thread; // Locking: this
-
-    private volatile EventHandler handler;
-    private volatile PrintWriter debugOutput;
-    private volatile IOException parseThreadException;
-
-    static class Waiter {
-
-        List<ReplyLine> response; // Locking: this
-
-        synchronized List<ReplyLine> getResponse() throws InterruptedException {
-                while (response == null) {
-                    wait();
-                }
-            return response;
-        }
-
-        synchronized void setResponse(List<ReplyLine> response) {
-            this.response = response;
-            notifyAll();
-        }
-    }
-
-    static class ReplyLine {
-
-        final String status;
-        final String msg;
-        final String rest;
-
-        ReplyLine(String status, String msg, String rest) {
-            this.status = status; this.msg = msg; this.rest = rest;
-        }
-    }
-
-    /** Create a new TorControlConnection to communicate with Tor over
-     * a given socket.  After calling this constructor, it is typical to
-     * call launchThread and authenticate. */
-    public TorControlConnection(Socket connection) throws IOException {
-        this(connection.getInputStream(), connection.getOutputStream());
-    }
-
-    /** Create a new TorControlConnection to communicate with Tor over
-     * an arbitrary pair of data streams.
-     */
-    public TorControlConnection(InputStream i, OutputStream o) {
-        this(new InputStreamReader(i), new OutputStreamWriter(o));
-    }
-
-    public TorControlConnection(Reader i, Writer o) {
-        this.output = o;
-        if (i instanceof BufferedReader)
-            this.input = (BufferedReader) i;
-        else
-            this.input = new BufferedReader(i);
-        this.waiters = new LinkedList<Waiter>();
-    }
-
-    protected final void writeEscaped(String s) throws IOException {
-        StringTokenizer st = new StringTokenizer(s, "\n");
-        while (st.hasMoreTokens()) {
-            String line = st.nextToken();
-            if (line.startsWith("."))
-                line = "."+line;
-            if (line.endsWith("\r"))
-                line += "\n";
-            else
-                line += "\r\n";
-            if (debugOutput != null)
-                debugOutput.print(">> "+line);
-            output.write(line);
-        }
-        output.write(".\r\n");
-        if (debugOutput != null)
-            debugOutput.print(">> .\n");
-    }
-
-    protected static final String quote(String s) {
-        StringBuffer sb = new StringBuffer("\"");
-        for (int i = 0; i < s.length(); ++i) {
-            char c = s.charAt(i);
-            switch (c)
-                {
-                case '\r':
-                case '\n':
-                case '\\':
-                case '\"':
-                    sb.append('\\');
-                }
-            sb.append(c);
-        }
-        sb.append('\"');
-        return sb.toString();
-    }
-
-    protected final ArrayList<ReplyLine> readReply() throws IOException {
-        ArrayList<ReplyLine> reply = new ArrayList<ReplyLine>();
-        char c;
-        do {
-            String line = input.readLine();
-            if (line == null) {
-                // if line is null, the end of the stream has been reached, i.e.
-                // the connection to Tor has been closed!
-                if (reply.isEmpty()) {
-                        // nothing received so far, can exit cleanly
-                        return reply;
-                }
-                // received half of a reply before the connection broke down
-                throw new TorControlSyntaxError("Connection to Tor " +
-                     " broke down while receiving reply!");
-            }
-            if (debugOutput != null)
-                debugOutput.println("<< "+line);
-            if (line.length() < 4)
-                throw new TorControlSyntaxError("Line (\""+line+"\") too short");
-            String status = line.substring(0,3);
-            c = line.charAt(3);
-            String msg = line.substring(4);
-            String rest = null;
-            if (c == '+') {
-                StringBuffer data = new StringBuffer();
-                while (true) {
-                    line = input.readLine();
-                    if (debugOutput != null)
-                        debugOutput.print("<< "+line);
-                    if (line.equals("."))
-                        break;
-                    else if (line.startsWith("."))
-                        line = line.substring(1);
-                    data.append(line).append('\n');
-                }
-                rest = data.toString();
-            }
-            reply.add(new ReplyLine(status, msg, rest));
-        } while (c != ' ');
-
-        return reply;
-    }
-
-    protected synchronized List<ReplyLine> sendAndWaitForResponse(String s,
-        String rest) throws IOException {
-        if(parseThreadException != null) throw parseThreadException;
-        checkThread();
-        Waiter w = new Waiter();
-        if (debugOutput != null)
-            debugOutput.print(">> "+s);
-        synchronized (waiters) {
-            output.write(s);
-            if (rest != null)
-                writeEscaped(rest);
-            output.flush();
-            waiters.addLast(w);
-        }
-        List<ReplyLine> lst;
-        try {
-            lst = w.getResponse();
-        } catch (InterruptedException ex) {
-            throw new IOException("Interrupted");
-        }
-        for (Iterator<ReplyLine> i = lst.iterator(); i.hasNext(); ) {
-            ReplyLine c = i.next();
-            if (! c.status.startsWith("2"))
-                throw new TorControlError("Error reply: "+c.msg);
-        }
-        return lst;
-    }
-
-    /** Helper: decode a CMD_EVENT command and dispatch it to our
-     * EventHandler (if any). */
-    protected void handleEvent(ArrayList<ReplyLine> events) {
-        if (handler == null)
-            return;
-
-        for (Iterator<ReplyLine> i = events.iterator(); i.hasNext(); ) {
-            ReplyLine line = i.next();
-            int idx = line.msg.indexOf(' ');
-            String tp = line.msg.substring(0, idx).toUpperCase();
-            String rest = line.msg.substring(idx+1);
-            if (tp.equals("CIRC")) {
-                List<String> lst = Bytes.splitStr(null, rest);
-                handler.circuitStatus(lst.get(1),
-                                      lst.get(0),
-                                      lst.get(1).equals("LAUNCHED")
-                                          || lst.size() < 3 ? ""
-                                          : lst.get(2));
-            } else if (tp.equals("STREAM")) {
-                List<String> lst = Bytes.splitStr(null, rest);
-                handler.streamStatus(lst.get(1),
-                                     lst.get(0),
-                                     lst.get(3));
-                // XXXX circID.
-            } else if (tp.equals("ORCONN")) {
-                List<String> lst = Bytes.splitStr(null, rest);
-                handler.orConnStatus(lst.get(1), lst.get(0));
-            } else if (tp.equals("BW")) {
-                List<String> lst = Bytes.splitStr(null, rest);
-                handler.bandwidthUsed(Integer.parseInt(lst.get(0)),
-                                      Integer.parseInt(lst.get(1)));
-            } else if (tp.equals("NEWDESC")) {
-                List<String> lst = Bytes.splitStr(null, rest);
-                handler.newDescriptors(lst);
-            } else if (tp.equals("DEBUG") ||
-                       tp.equals("INFO") ||
-                       tp.equals("NOTICE") ||
-                       tp.equals("WARN") ||
-                       tp.equals("ERR")) {
-                handler.message(tp, rest);
-            } else {
-                handler.unrecognized(tp, rest);
-            }
-        }
-    }
-
-
-    /** Sets <b>w</b> as the PrintWriter for debugging output,
-    * which writes out all messages passed between Tor and the controller.
-    * Outgoing messages are preceded by "\>\>" and incoming messages are preceded
-    * by "\<\<"
-    */
-    public void setDebugging(PrintWriter w) {
-        debugOutput = w;
-    }
-
-    /** Sets <b>s</b> as the PrintStream for debugging output,
-    * which writes out all messages passed between Tor and the controller.
-    * Outgoing messages are preceded by "\>\>" and incoming messages are preceded
-    * by "\<\<"
-    */
-    public void setDebugging(PrintStream s) {
-        debugOutput = new PrintWriter(s, true);
-    }
-
-    /** Set the EventHandler object that will be notified of any
-     * events Tor delivers to this connection.  To make Tor send us
-     * events, call setEvents(). */
-    public void setEventHandler(EventHandler handler) {
-        this.handler = handler;
-    }
-
-    /**
-     * Start a thread to react to Tor's responses in the background.
-     * This is necessary to handle asynchronous events and synchronous
-     * responses that arrive independantly over the same socket.
-     */
-    public synchronized Thread launchThread(boolean daemon) {
-    	ControlParseThread th = new ControlParseThread();
-        if (daemon)
-            th.setDaemon(true);
-        th.start();
-        this.thread = th;
-        return th;
-    }
-
-    protected class ControlParseThread extends Thread {
-
-        @Override
-    	public void run() {
-            try {
-                react();
-            } catch (IOException ex) {
-                parseThreadException = ex;
-            }
-        }
-    }
-
-    protected synchronized void checkThread() {
-        if (thread == null)
-            launchThread(true);
-    }
-
-    /** helper: implement the main background loop. */
-    protected void react() throws IOException {
-        while (true) {
-            ArrayList<ReplyLine> lst = readReply();
-            if (lst.isEmpty()) {
-                // connection has been closed remotely! end the loop!
-                return;
-            }
-            if ((lst.get(0)).status.startsWith("6"))
-                handleEvent(lst);
-            else {
-                synchronized (waiters) {
-                    if (!waiters.isEmpty())
-                    {
-                                Waiter w;
-                                w = waiters.removeFirst();
-                                w.setResponse(lst);
-                    }
-                }
-
-            }
-        }
-    }
-
-    /** Change the value of the configuration option 'key' to 'val'.
-     */
-    public void setConf(String key, String value) throws IOException {
-        List<String> lst = new ArrayList<String>();
-        lst.add(key+" "+value);
-        setConf(lst);
-    }
-
-    /** Change the values of the configuration options stored in kvMap. */
-    public void setConf(Map<String, String> kvMap) throws IOException {
-        List<String> lst = new ArrayList<String>();
-        for (Iterator<Map.Entry<String,String>> it = kvMap.entrySet().iterator(); it.hasNext(); ) {
-            Map.Entry<String,String> ent = it.next();
-            lst.add(ent.getKey()+" "+ent.getValue()+"\n");
-        }
-        setConf(lst);
-    }
-
-    /** Changes the values of the configuration options stored in
-     * <b>kvList</b>.  Each list element in <b>kvList</b> is expected to be
-     * String of the format "key value".
-     *
-     * Tor behaves as though it had just read each of the key-value pairs
-     * from its configuration file.  Keywords with no corresponding values have
-     * their configuration values reset to their defaults.  setConf is
-     * all-or-nothing: if there is an error in any of the configuration settings,
-     * Tor sets none of them.
-     *
-     * When a configuration option takes multiple values, or when multiple
-     * configuration keys form a context-sensitive group (see getConf below), then
-     * setting any of the options in a setConf command is taken to reset all of
-     * the others.  For example, if two ORBindAddress values are configured, and a
-     * command arrives containing a single ORBindAddress value, the new
-     * command's value replaces the two old values.
-     *
-     * To remove all settings for a given option entirely (and go back to its
-     * default value), include a String in <b>kvList</b> containing the key and no value.
-     */
-    public void setConf(Collection<String> kvList) throws IOException {
-        if (kvList.size() == 0)
-            return;
-        StringBuffer b = new StringBuffer("SETCONF");
-        for (Iterator<String> it = kvList.iterator(); it.hasNext(); ) {
-            String kv = it.next();
-            int i = kv.indexOf(' ');
-            if (i == -1)
-                b.append(" ").append(kv);
-            b.append(" ").append(kv.substring(0,i)).append("=")
-                .append(quote(kv.substring(i+1)));
-        }
-        b.append("\r\n");
-        sendAndWaitForResponse(b.toString(), null);
-    }
-
-    /** Try to reset the values listed in the collection 'keys' to their
-     * default values.
-     **/
-    public void resetConf(Collection<String> keys) throws IOException {
-        if (keys.size() == 0)
-            return;
-        StringBuffer b = new StringBuffer("RESETCONF");
-        for (Iterator<String> it = keys.iterator(); it.hasNext(); ) {
-            String key = it.next();
-            b.append(" ").append(key);
-        }
-        b.append("\r\n");
-        sendAndWaitForResponse(b.toString(), null);
-    }
-
-    /** Return the value of the configuration option 'key' */
-    public List<ConfigEntry> getConf(String key) throws IOException {
-        List<String> lst = new ArrayList<String>();
-        lst.add(key);
-        return getConf(lst);
-    }
-
-    /** Requests the values of the configuration variables listed in <b>keys</b>.
-     * Results are returned as a list of ConfigEntry objects.
-     *
-     * If an option appears multiple times in the configuration, all of its
-     * key-value pairs are returned in order.
-     *
-     * Some options are context-sensitive, and depend on other options with
-     * different keywords.  These cannot be fetched directly.  Currently there
-     * is only one such option: clients should use the "HiddenServiceOptions"
-     * virtual keyword to get all HiddenServiceDir, HiddenServicePort,
-     * HiddenServiceNodes, and HiddenServiceExcludeNodes option settings.
-     */
-    public List<ConfigEntry> getConf(Collection<String> keys) throws IOException {
-        StringBuffer sb = new StringBuffer("GETCONF");
-        for (Iterator<String> it = keys.iterator(); it.hasNext(); ) {
-            String key = it.next();
-            sb.append(" ").append(key);
-        }
-        sb.append("\r\n");
-        List<ReplyLine> lst = sendAndWaitForResponse(sb.toString(), null);
-        List<ConfigEntry> result = new ArrayList<ConfigEntry>();
-        for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) {
-            String kv = (it.next()).msg;
-            int idx = kv.indexOf('=');
-            if (idx >= 0)
-                result.add(new ConfigEntry(kv.substring(0, idx),
-                                           kv.substring(idx+1)));
-            else
-                result.add(new ConfigEntry(kv));
-        }
-        return result;
-    }
-
-    /** Request that the server inform the client about interesting events.
-     * Each element of <b>events</b> is one of the following Strings:
-     * ["CIRC" | "STREAM" | "ORCONN" | "BW" | "DEBUG" |
-     *  "INFO" | "NOTICE" | "WARN" | "ERR" | "NEWDESC" | "ADDRMAP"] .
-     *
-     * Any events not listed in the <b>events</b> are turned off; thus, calling
-     * setEvents with an empty <b>events</b> argument turns off all event reporting.
-     */
-    public void setEvents(List<String> events) throws IOException {
-        StringBuffer sb = new StringBuffer("SETEVENTS");
-        for (Iterator<String> it = events.iterator(); it.hasNext(); ) {
-            sb.append(" ").append(it.next());
-        }
-        sb.append("\r\n");
-        sendAndWaitForResponse(sb.toString(), null);
-    }
-
-    /** Authenticates the controller to the Tor server.
-     *
-     * By default, the current Tor implementation trusts all local users, and
-     * the controller can authenticate itself by calling authenticate(new byte[0]).
-     *
-     * If the 'CookieAuthentication' option is true, Tor writes a "magic cookie"
-     * file named "control_auth_cookie" into its data directory.  To authenticate,
-     * the controller must send the contents of this file in <b>auth</b>.
-     *
-     * If the 'HashedControlPassword' option is set, <b>auth</b> must contain the salted
-     * hash of a secret password.  The salted hash is computed according to the
-     * S2K algorithm in RFC 2440 (OpenPGP), and prefixed with the s2k specifier.
-     * This is then encoded in hexadecimal, prefixed by the indicator sequence
-     * "16:".
-     *
-     * You can generate the salt of a password by calling
-     *       'tor --hash-password <password>'
-     * or by using the provided PasswordDigest class.
-     * To authenticate under this scheme, the controller sends Tor the original
-     * secret that was used to generate the password.
-     */
-    public void authenticate(byte[] auth) throws IOException {
-        String cmd = "AUTHENTICATE " + Bytes.hex(auth) + "\r\n";
-        sendAndWaitForResponse(cmd, null);
-    }
-
-    /** Instructs the server to write out its configuration options into its torrc.
-     */
-    public void saveConf() throws IOException {
-        sendAndWaitForResponse("SAVECONF\r\n", null);
-    }
-
-    /** Sends a signal from the controller to the Tor server.
-     * <b>signal</b> is one of the following Strings:
-     * <ul>
-     * <li>"RELOAD" or "HUP" :  Reload config items, refetch directory</li>
-     * <li>"SHUTDOWN" or "INT" : Controlled shutdown: if server is an OP, exit immediately.
-     *     If it's an OR, close listeners and exit after 30 seconds</li>
-     * <li>"DUMP" or "USR1" : Dump stats: log information about open connections and circuits</li>
-     * <li>"DEBUG" or "USR2" : Debug: switch all open logs to loglevel debug</li>
-     * <li>"HALT" or "TERM" : Immediate shutdown: clean up and exit now</li>
-     * </ul>
-     */
-    public void signal(String signal) throws IOException {
-        String cmd = "SIGNAL " + signal + "\r\n";
-        sendAndWaitForResponse(cmd, null);
-    }
-
-    /** Send a signal to the Tor process to shut it down or halt it.
-     * Does not wait for a response. */
-    public void shutdownTor(String signal) throws IOException {
-        String s = "SIGNAL " + signal + "\r\n";
-        Waiter w = new Waiter();
-        if (debugOutput != null)
-            debugOutput.print(">> "+s);
-        synchronized (waiters) {
-            output.write(s);
-            output.flush();
-        }
-    }
-
-    /** Tells the Tor server that future SOCKS requests for connections to a set of original
-     * addresses should be replaced with connections to the specified replacement
-     * addresses.  Each element of <b>kvLines</b> is a String of the form
-     * "old-address new-address".  This function returns the new address mapping.
-     *
-     * The client may decline to provide a body for the original address, and
-     * instead send a special null address ("0.0.0.0" for IPv4, "::0" for IPv6, or
-     * "." for hostname), signifying that the server should choose the original
-     * address itself, and return that address in the reply.  The server
-     * should ensure that it returns an element of address space that is unlikely
-     * to be in actual use.  If there is already an address mapped to the
-     * destination address, the server may reuse that mapping.
-     *
-     * If the original address is already mapped to a different address, the old
-     * mapping is removed.  If the original address and the destination address
-     * are the same, the server removes any mapping in place for the original
-     * address.
-     *
-     * Mappings set by the controller last until the Tor process exits:
-     * they never expire. If the controller wants the mapping to last only
-     * a certain time, then it must explicitly un-map the address when that
-     * time has elapsed.
-     */
-    public Map<String,String> mapAddresses(Collection<String> kvLines) throws IOException {
-        StringBuffer sb = new StringBuffer("MAPADDRESS");
-        for (Iterator<String> it = kvLines.iterator(); it.hasNext(); ) {
-            String kv = it.next();
-            int i = kv.indexOf(' ');
-            sb.append(" ").append(kv.substring(0,i)).append("=")
-                .append(quote(kv.substring(i+1)));
-        }
-        sb.append("\r\n");
-        List<ReplyLine> lst = sendAndWaitForResponse(sb.toString(), null);
-        Map<String,String> result = new HashMap<String,String>();
-        for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) {
-            String kv = (it.next()).msg;
-            int idx = kv.indexOf('=');
-            result.put(kv.substring(0, idx),
-                       kv.substring(idx+1));
-        }
-        return result;
-    }
-
-    public Map<String,String> mapAddresses(Map<String,String> addresses) throws IOException {
-        List<String> kvList = new ArrayList<String>();
-        for (Iterator<Map.Entry<String, String>> it = addresses.entrySet().iterator(); it.hasNext(); ) {
-            Map.Entry<String,String> e = it.next();
-            kvList.add(e.getKey()+" "+e.getValue());
-        }
-        return mapAddresses(kvList);
-    }
-
-    public String mapAddress(String fromAddr, String toAddr) throws IOException {
-        List<String> lst = new ArrayList<String>();
-        lst.add(fromAddr+" "+toAddr+"\n");
-        Map<String,String> m = mapAddresses(lst);
-        return m.get(fromAddr);
-    }
-
-    /** Queries the Tor server for keyed values that are not stored in the torrc
-     * configuration file.  Returns a map of keys to values.
-     *
-     * Recognized keys include:
-     * <ul>
-     * <li>"version" : The version of the server's software, including the name
-     *  of the software. (example: "Tor 0.0.9.4")</li>
-     * <li>"desc/id/<OR identity>" or "desc/name/<OR nickname>" : the latest server
-     * descriptor for a given OR, NUL-terminated.  If no such OR is known, the
-     * corresponding value is an empty string.</li>
-     * <li>"network-status" : a space-separated list of all known OR identities.
-     * This is in the same format as the router-status line in directories;
-     * see tor-spec.txt for details.</li>
-     * <li>"addr-mappings/all"</li>
-     * <li>"addr-mappings/config"</li>
-     * <li>"addr-mappings/cache"</li>
-     * <li>"addr-mappings/control" : a space-separated list of address mappings, each
-     * in the form of "from-address=to-address".  The 'config' key
-     * returns those address mappings set in the configuration; the 'cache'
-     * key returns the mappings in the client-side DNS cache; the 'control'
-     * key returns the mappings set via the control interface; the 'all'
-     * target returns the mappings set through any mechanism.</li>
-     * <li>"circuit-status" : A series of lines as for a circuit status event. Each line is of the form:
-     * "CircuitID CircStatus Path"</li>
-     * <li>"stream-status" : A series of lines as for a stream status event.  Each is of the form:
-     * "StreamID StreamStatus CircID Target"</li>
-     * <li>"orconn-status" : A series of lines as for an OR connection status event.  Each is of the
-     * form: "ServerID ORStatus"</li>
-     * </ul>
-     */
-    public Map<String,String> getInfo(Collection<String> keys) throws IOException {
-        StringBuffer sb = new StringBuffer("GETINFO");
-        for (Iterator<String> it = keys.iterator(); it.hasNext(); ) {
-            sb.append(" ").append(it.next());
-        }
-        sb.append("\r\n");
-        List<ReplyLine> lst = sendAndWaitForResponse(sb.toString(), null);
-        Map<String,String> m = new HashMap<String,String>();
-        for (Iterator<ReplyLine> it = lst.iterator(); it.hasNext(); ) {
-            ReplyLine line = it.next();
-            int idx = line.msg.indexOf('=');
-            if (idx<0)
-                break;
-            String k = line.msg.substring(0,idx);
-            String v;
-            if (line.rest != null) {
-                v = line.rest;
-            } else {
-                v = line.msg.substring(idx+1);
-            }
-            m.put(k, v);
-        }
-        return m;
-    }
-
-
-
-    /** Return the value of the information field 'key' */
-    public String getInfo(String key) throws IOException {
-        List<String> lst = new ArrayList<String>();
-        lst.add(key);
-        Map<String,String> m = getInfo(lst);
-        return  m.get(key);
-    }
-
-    /** An extendCircuit request takes one of two forms: either the <b>circID</b> is zero, in
-     * which case it is a request for the server to build a new circuit according
-     * to the specified path, or the <b>circID</b> is nonzero, in which case it is a
-     * request for the server to extend an existing circuit with that ID according
-     * to the specified <b>path</b>.
-     *
-     * If successful, returns the Circuit ID of the (maybe newly created) circuit.
-     */
-    public String extendCircuit(String circID, String path) throws IOException {
-        List<ReplyLine> lst = sendAndWaitForResponse(
-                          "EXTENDCIRCUIT "+circID+" "+path+"\r\n", null);
-        return (lst.get(0)).msg;
-    }
-
-    /** Informs the Tor server that the stream specified by <b>streamID</b> should be
-     * associated with the circuit specified by <b>circID</b>.
-     *
-     * Each stream may be associated with
-     * at most one circuit, and multiple streams may share the same circuit.
-     * Streams can only be attached to completed circuits (that is, circuits that
-     * have sent a circuit status "BUILT" event or are listed as built in a
-     * getInfo circuit-status request).
-     *
-     * If <b>circID</b> is 0, responsibility for attaching the given stream is
-     * returned to Tor.
-     *
-     * By default, Tor automatically attaches streams to
-     * circuits itself, unless the configuration variable
-     * "__LeaveStreamsUnattached" is set to "1".  Attempting to attach streams
-     * via TC when "__LeaveStreamsUnattached" is false may cause a race between
-     * Tor and the controller, as both attempt to attach streams to circuits.
-     */
-    public void attachStream(String streamID, String circID)
-        throws IOException {
-        sendAndWaitForResponse("ATTACHSTREAM "+streamID+" "+circID+"\r\n", null);
-    }
-
-    /** Tells Tor about the server descriptor in <b>desc</b>.
-     *
-     * The descriptor, when parsed, must contain a number of well-specified
-     * fields, including fields for its nickname and identity.
-     */
-    // More documentation here on format of desc?
-    // No need for return value?  control-spec.txt says reply is merely "250 OK" on success...
-    public String postDescriptor(String desc) throws IOException {
-        List<ReplyLine> lst = sendAndWaitForResponse("+POSTDESCRIPTOR\r\n", desc);
-        return (lst.get(0)).msg;
-    }
-
-    /** Tells Tor to change the exit address of the stream identified by <b>streamID</b>
-     * to <b>address</b>. No remapping is performed on the new provided address.
-     *
-     * To be sure that the modified address will be used, this event must be sent
-     * after a new stream event is received, and before attaching this stream to
-     * a circuit.
-     */
-    public void redirectStream(String streamID, String address) throws IOException {
-        sendAndWaitForResponse("REDIRECTSTREAM "+streamID+" "+address+"\r\n",
-                               null);
-    }
-
-    /** Tells Tor to close the stream identified by <b>streamID</b>.
-     * <b>reason</b> should be one of the Tor RELAY_END reasons given in tor-spec.txt, as a decimal:
-     * <ul>
-     * <li>1 -- REASON_MISC           (catch-all for unlisted reasons)</li>
-     * <li>2 -- REASON_RESOLVEFAILED  (couldn't look up hostname)</li>
-     * <li>3 -- REASON_CONNECTREFUSED (remote host refused connection)</li>
-     * <li>4 -- REASON_EXITPOLICY     (OR refuses to connect to host or port)</li>
-     * <li>5 -- REASON_DESTROY        (Circuit is being destroyed)</li>
-     * <li>6 -- REASON_DONE           (Anonymized TCP connection was closed)</li>
-     * <li>7 -- REASON_TIMEOUT        (Connection timed out, or OR timed out while connecting)</li>
-     * <li>8 -- (unallocated)</li>
-     * <li>9 -- REASON_HIBERNATING    (OR is temporarily hibernating)</li>
-     * <li>10 -- REASON_INTERNAL       (Internal error at the OR)</li>
-     * <li>11 -- REASON_RESOURCELIMIT  (OR has no resources to fulfill request)</li>
-     * <li>12 -- REASON_CONNRESET      (Connection was unexpectedly reset)</li>
-     * <li>13 -- REASON_TORPROTOCOL    (Sent when closing connection because of Tor protocol violations)</li>
-     * </ul>
-     *
-     * Tor may hold the stream open for a while to flush any data that is pending.
-     */
-    public void closeStream(String streamID, byte reason)
-        throws IOException {
-        sendAndWaitForResponse("CLOSESTREAM "+streamID+" "+reason+"\r\n",null);
-    }
-
-    /** Tells Tor to close the circuit identified by <b>circID</b>.
-     * If <b>ifUnused</b> is true, do not close the circuit unless it is unused.
-     */
-    public void closeCircuit(String circID, boolean ifUnused) throws IOException {
-        sendAndWaitForResponse("CLOSECIRCUIT "+circID+
-                               (ifUnused?" IFUNUSED":"")+"\r\n", null);
-    }
-}
-
diff --git a/orbotservice/src/main/java/org/torproject/android/control/TorControlError.java b/orbotservice/src/main/java/org/torproject/android/control/TorControlError.java
deleted file mode 100644
index d07ee514..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/TorControlError.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-import java.io.IOException;
-
-/**
- * An exception raised when Tor tells us about an error.
- */
-public class TorControlError extends IOException {
-
-    static final long serialVersionUID = 3;
-
-    private final int errorType;
-
-    public TorControlError(int type, String s) {
-        super(s);
-        errorType = type;
-    }
-
-    public TorControlError(String s) {
-        this(-1, s);
-    }
-
-    public int getErrorType() {
-        return errorType;
-    }
-
-    public String getErrorMsg() {
-        try {
-            if (errorType == -1)
-                return null;
-            return TorControlCommands.ERROR_MSGS[errorType];
-        } catch (ArrayIndexOutOfBoundsException ex) {
-            return "Unrecongized error #"+errorType;
-        }
-    }
-}
-
diff --git a/orbotservice/src/main/java/org/torproject/android/control/TorControlSyntaxError.java b/orbotservice/src/main/java/org/torproject/android/control/TorControlSyntaxError.java
deleted file mode 100644
index dba4f44b..00000000
--- a/orbotservice/src/main/java/org/torproject/android/control/TorControlSyntaxError.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2005 Nick Mathewson, Roger Dingledine
-// See LICENSE file for copying information
-package org.torproject.android.control;
-
-import java.io.IOException;
-
-/**
- * An exception raised when Tor behaves in an unexpected way.
- */
-public class TorControlSyntaxError extends IOException {
-
-    static final long serialVersionUID = 3;
-
-    public TorControlSyntaxError(String s) { super(s); }
-}
-
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java b/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java
index 62f14308..c67afff4 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorEventHandler.java
@@ -1,7 +1,9 @@
 package org.torproject.android.service;
 
 import android.text.TextUtils;
-import org.torproject.android.control.EventHandler;
+
+import net.freehaven.tor.control.EventHandler;
+
 import org.torproject.android.service.util.Prefs;
 
 import java.text.NumberFormat;
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorService.java b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
index e5a8c216..5e9e9168 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
@@ -29,20 +29,19 @@ import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.os.Build;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.provider.BaseColumns;
-import android.support.annotation.RequiresApi;
-import android.support.v4.app.NotificationCompat;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.annotation.RequiresApi;
+import androidx.core.app.NotificationCompat;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 import android.text.TextUtils;
 import android.util.Log;
 import com.jaredrummler.android.shell.CommandResult;
-import info.pluggabletransports.dispatch.util.TransportListener;
-import info.pluggabletransports.dispatch.util.TransportManager;
-import org.torproject.android.control.ConfigEntry;
-import org.torproject.android.control.TorControlConnection;
+
+import net.freehaven.tor.control.ConfigEntry;
+import net.freehaven.tor.control.TorControlConnection;
+
 import org.torproject.android.service.util.CustomShell;
 import org.torproject.android.service.util.CustomTorResourceInstaller;
 import org.torproject.android.service.util.DummyActivity;
@@ -52,6 +51,9 @@ import org.torproject.android.service.util.Utils;
 import org.torproject.android.service.vpn.OrbotVpnManager;
 import org.torproject.android.service.vpn.VpnPrefs;
 
+import info.pluggabletransports.dispatch.util.TransportListener;
+import info.pluggabletransports.dispatch.util.TransportManager;
+
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
diff --git a/orbotservice/src/main/java/org/torproject/android/service/util/CustomShell.java b/orbotservice/src/main/java/org/torproject/android/service/util/CustomShell.java
index db1a08e2..8007d047 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/util/CustomShell.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/util/CustomShell.java
@@ -1,8 +1,8 @@
 package org.torproject.android.service.util;
 
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.WorkerThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
 import com.jaredrummler.android.shell.CommandResult;
 import com.jaredrummler.android.shell.Shell;
 import com.jaredrummler.android.shell.ShellExitCode;
diff --git a/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java b/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java
index 13ff2c49..d394b5c8 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/vpn/TorVpnService.java
@@ -6,7 +6,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.VpnService;
-import android.support.v4.content.LocalBroadcastManager;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 import android.util.Log;
 import org.torproject.android.service.TorService;
 import org.torproject.android.service.TorServiceConstants;





More information about the tor-commits mailing list