Bug Fixes

Bug Fixes
master
Abdul Mannan Saeed 2022-08-25 17:37:33 +05:00
parent 8dd19543ca
commit e9451e9923
34 changed files with 685 additions and 89 deletions

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\msman\.android\avd\Pixel_2_API_33.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2022-08-21T18:03:56.258272500Z" />
</component>
</project>

View File

@ -78,6 +78,7 @@
<entry key="..\:/Workspace/Genesis-Android/app/src/main/res/layouts/tab/layout/tab_menu.xml" value="0.16875" /> <entry key="..\:/Workspace/Genesis-Android/app/src/main/res/layouts/tab/layout/tab_menu.xml" value="0.16875" />
<entry key="..\:/Workspace/Genesis-Android/app/src/main/res/layouts/tab/layout/tab_row_view.xml" value="0.5" /> <entry key="..\:/Workspace/Genesis-Android/app/src/main/res/layouts/tab/layout/tab_row_view.xml" value="0.5" />
<entry key="..\:/Workspace/Genesis-Android/app/src/main/res/layouts/tab/layout/tab_view.xml" value="0.203125" /> <entry key="..\:/Workspace/Genesis-Android/app/src/main/res/layouts/tab/layout/tab_view.xml" value="0.203125" />
<entry key="..\:/Workspace/Genesis-Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.1935" />
<entry key="..\:/workspace/Genesis-Android/app/src/main/res/layouts/alert/layout/certificate_info.xml" value="0.18541666666666667" /> <entry key="..\:/workspace/Genesis-Android/app/src/main/res/layouts/alert/layout/certificate_info.xml" value="0.18541666666666667" />
<entry key="..\:/workspace/Genesis-Android/app/src/main/res/layouts/alert/layout/popup_bridge_mail.xml" value="0.5" /> <entry key="..\:/workspace/Genesis-Android/app/src/main/res/layouts/alert/layout/popup_bridge_mail.xml" value="0.5" />
<entry key="..\:/workspace/Genesis-Android/app/src/main/res/layouts/alert/layout/popup_bridge_setting_custom.xml" value="0.5" /> <entry key="..\:/workspace/Genesis-Android/app/src/main/res/layouts/alert/layout/popup_bridge_setting_custom.xml" value="0.5" />

View File

@ -1,4 +1,4 @@
import com.android.build.OutputFile //import com.android.build.OutputFile
plugins { plugins {
id "com.jetbrains.python.envs" version "0.0.26" id "com.jetbrains.python.envs" version "0.0.26"
@ -110,14 +110,18 @@ dependencies {
implementation 'com.applovin:applovin-sdk:+' implementation 'com.applovin:applovin-sdk:+'
implementation 'com.applovin.mediation:mytarget-adapter:+' implementation 'com.applovin.mediation:mytarget-adapter:+'
implementation 'com.applovin.mediation:adcolony-adapter:4.8.0.2'
implementation 'com.adcolony:sdk:4.8.0' implementation 'com.adcolony:sdk:4.8.0'
implementation 'com.facebook.android:audience-network-sdk:6.8.0'
implementation 'com.applovin.mediation:facebook-adapter:6.8.0.12'
/* Orbot Service */ /* Orbot Service */
implementation project(path: ':orbotmanager') implementation project(path: ':orbotmanager')
/* Helper Libraries */ /* Helper Libraries */
implementation "android.arch.lifecycle:extensions:1.1.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
implementation 'com.coolerfall:android-http-download-manager:1.6.3' implementation 'com.coolerfall:android-http-download-manager:1.6.3'
implementation 'com.android.volley:volley:1.2.1' implementation 'com.android.volley:volley:1.2.1'
implementation "net.zetetic:android-database-sqlcipher:4.4.3" implementation "net.zetetic:android-database-sqlcipher:4.4.3"
@ -129,7 +133,7 @@ dependencies {
/* Automated APK Generation */ /* Automated APK Generation */
android.applicationVariants.all { variant -> /*android.applicationVariants.all { variant ->
def buildType = variant.buildType.name def buildType = variant.buildType.name
@ -153,7 +157,7 @@ android.applicationVariants.all { variant ->
output.versionCodeOverride = versionCodeOverride output.versionCodeOverride = versionCodeOverride
} }
} }
} }*/

View File

@ -16,7 +16,7 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:extractNativeLibs="true" android:extractNativeLibs="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:largeHeap="false" android:largeHeap="false"
@ -25,7 +25,7 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="false"
tools:targetApi="n"> tools:targetApi="n">
<activity <activity

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -49,6 +49,8 @@ import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.widget.NestedScrollView; import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.FragmentContainerView; import androidx.fragment.app.FragmentContainerView;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -1096,7 +1098,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
msearchstatuscopy = true; msearchstatuscopy = true;
mSearchBarWasBackButtonPressed = false; mSearchBarWasBackButtonPressed = false;
if (!isFocusChanging) { if (!isFocusChanging) {
if (!status.mThemeApplying) { if (!status.mThemeApplying && mGeckoClient!=null && mGeckoClient.getSession()!=null) {
mHomeViewController.initSearchBarFocus(true, isKeyboardOpened); mHomeViewController.initSearchBarFocus(true, isKeyboardOpened);
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(), true, true, false); mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(), true, true, false);
} }
@ -1740,6 +1742,17 @@ public class homeController extends AppCompatActivity implements ComponentCallba
static boolean mStateService = false; static boolean mStateService = false;
static boolean mBackground = false;
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppBackgrounded() {
mBackground = true;
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onAppForegrounded() {
mBackground = false;
}
public void onStartApplication(View view) { public void onStartApplication(View view) {
if (!mStateService) { if (!mStateService) {
mStateService = true; mStateService = true;
@ -1747,7 +1760,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
if (!isMyServiceRunning(activityStateManager.class)) { if (!isMyServiceRunning(activityStateManager.class)) {
new Handler().postDelayed(() -> new Handler().postDelayed(() ->
{ {
if(!mBackground){
startService(new Intent(this, activityStateManager.class)); startService(new Intent(this, activityStateManager.class));
}
}, 500); }, 500);
} }
}catch (Exception ex){ }catch (Exception ex){

View File

@ -243,6 +243,9 @@ public class tabController extends Fragment {
return; return;
} }
int orientation = activityContextManager.getInstance().getHomeController().getResources().getConfiguration().orientation; int orientation = activityContextManager.getInstance().getHomeController().getResources().getConfiguration().orientation;
if (mRecycleView == null){
return;
}
if (orientation == Configuration.ORIENTATION_PORTRAIT) { if (orientation == Configuration.ORIENTATION_PORTRAIT) {
maxScroll = mRecycleView.computeVerticalScrollRange() - mScreenHeight * 0.350f + helperMethod.pxFromDp(helperMethod.getNavigationBarSize(getContext()).y); maxScroll = mRecycleView.computeVerticalScrollRange() - mScreenHeight * 0.350f + helperMethod.pxFromDp(helperMethod.getNavigationBarSize(getContext()).y);
} else { } else {
@ -258,7 +261,6 @@ public class tabController extends Fragment {
mScrolled = false; mScrolled = false;
if (mRecycleView.getChildAt(mRecycleView.getChildCount() - 1) != null) { if (mRecycleView.getChildAt(mRecycleView.getChildCount() - 1) != null) {
if ((scrollY >= (mRecycleView.getChildAt(mRecycleView.getChildCount() - 1).getMeasuredHeight() - mRecycleView.getMeasuredHeight())) && scrollY > oldScrollY) { if ((scrollY >= (mRecycleView.getChildAt(mRecycleView.getChildCount() - 1).getMeasuredHeight() - mRecycleView.getMeasuredHeight())) && scrollY > oldScrollY) {
Log.i("FUCK2:::::::", scrollY + "");
onSwipeBounce(0); onSwipeBounce(0);
} }
} }

View File

@ -2,20 +2,20 @@ package com.hiddenservices.onionservices.pluginManager.adPluginManager;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.util.Log;
import com.adcolony.sdk.AdColony; import com.adcolony.sdk.AdColony;
import com.adcolony.sdk.AdColonyAppOptions; import com.adcolony.sdk.AdColonyAppOptions;
import com.applovin.mediation.MaxAd; import com.applovin.mediation.MaxAd;
import com.applovin.mediation.MaxAdViewAdListener; import com.applovin.mediation.MaxAdViewAdListener;
import com.applovin.mediation.MaxError; import com.applovin.mediation.MaxError;
import com.applovin.mediation.adapters.AdColonyMediationAdapter;
import com.applovin.mediation.ads.MaxAdView; import com.applovin.mediation.ads.MaxAdView;
import com.applovin.sdk.AppLovinSdk; import com.applovin.sdk.AppLovinSdk;
import com.facebook.ads.AdSettings;
import com.hiddenservices.onionservices.appManager.activityContextManager; import com.hiddenservices.onionservices.appManager.activityContextManager;
import com.hiddenservices.onionservices.eventObserver; import com.hiddenservices.onionservices.eventObserver;
import com.hiddenservices.onionservices.pluginManager.pluginEnums; import com.hiddenservices.onionservices.pluginManager.pluginEnums;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eAdManagerCallbacks.M_ON_AD_LOAD; import static com.hiddenservices.onionservices.pluginManager.pluginEnums.eAdManagerCallbacks.M_ON_AD_LOAD;
public class appLovinManager implements MaxAdViewAdListener { public class appLovinManager implements MaxAdViewAdListener {
@ -26,6 +26,7 @@ public class appLovinManager implements MaxAdViewAdListener {
private int mRequestCount = 0; private int mRequestCount = 0;
private boolean bannerAdRequested = false; private boolean bannerAdRequested = false;
private boolean bannerAdsLoaded = false;
/*Initializations*/ /*Initializations*/
@ -36,7 +37,10 @@ public class appLovinManager implements MaxAdViewAdListener {
} }
private void initializeBannerAds(Context pContext) { private void initializeBannerAds(Context pContext) {
AdSettings.setDataProcessingOptions(new String[]{});
AdColonyAppOptions appOptions = new AdColonyAppOptions(); AdColonyAppOptions appOptions = new AdColonyAppOptions();
appOptions.setPrivacyFrameworkRequired(AdColonyAppOptions.GDPR, true);
appOptions.setPrivacyConsentString(AdColonyAppOptions.GDPR, "1");
AdColony.configure(activityContextManager.getInstance().getHomeController(), appOptions,"app3b56c67c45544c5c89"); AdColony.configure(activityContextManager.getInstance().getHomeController(), appOptions,"app3b56c67c45544c5c89");
AppLovinSdk.getInstance(pContext).setMediationProvider("max"); AppLovinSdk.getInstance(pContext).setMediationProvider("max");
@ -55,7 +59,7 @@ public class appLovinManager implements MaxAdViewAdListener {
} }
private boolean isAdvertLoaded() { private boolean isAdvertLoaded() {
return false; return bannerAdsLoaded;
} }
/* Overriden Methods */ /* Overriden Methods */
@ -72,12 +76,13 @@ public class appLovinManager implements MaxAdViewAdListener {
@Override @Override
public void onAdLoaded(MaxAd ad) { public void onAdLoaded(MaxAd ad) {
bannerAdsLoaded = true;
mEvent.invokeObserver(null, M_ON_AD_LOAD); mEvent.invokeObserver(null, M_ON_AD_LOAD);
} }
@Override @Override
public void onAdDisplayed(MaxAd ad) { public void onAdDisplayed(MaxAd ad) {
Log.i("ads load", "ad has been loaded");
} }
@Override @Override

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="ic_launcher_background">#3DDC84</color> <color name="ic_launcher_background">#FF6A47</color>
</resources> </resources>

View File

@ -1,6 +1,6 @@
/* Version */ /* Version */
project.ext.vname = 'Build | Dark-Origin 1.0.5.6' project.ext.vname = 'Build | Dark-Origin 1.0.5.7'
project.ext.vcode = 405 project.ext.vcode = 410
project.ext.buildType = 'release' project.ext.buildType = 'release'
/* dimension */ /* dimension */

View File

@ -76,6 +76,7 @@ public class OrbotRawEventListener implements RawEventListener {
} }
private void handleBandwidth(long read, long written) { private void handleBandwidth(long read, long written) {
try {
String message = OrbotService.formatBandwidthCount(mService, read) + " \u2193" + " / " + String message = OrbotService.formatBandwidthCount(mService, read) + " \u2193" + " / " +
OrbotService.formatBandwidthCount(mService, written) + " \u2191"; OrbotService.formatBandwidthCount(mService, written) + " \u2191";
@ -86,7 +87,7 @@ public class OrbotRawEventListener implements RawEventListener {
mTotalBandwidthRead += read; mTotalBandwidthRead += read;
mService.sendCallbackBandwidth(written, read, mTotalBandwidthWritten, mTotalBandwidthRead); mService.sendCallbackBandwidth(written, read, mTotalBandwidthWritten, mTotalBandwidthRead);
}catch (Exception ex){}
} }
private void handleNewDescriptors(String[] descriptors) { private void handleNewDescriptors(String[] descriptors) {

View File

@ -746,9 +746,13 @@ public class OrbotService extends VpnService implements OrbotConstants {
debug("torrc.custom=" + extraLines); debug("torrc.custom=" + extraLines);
try {
File fileTorRcCustom = TorService.getTorrc(this); File fileTorRcCustom = TorService.getTorrc(this);
updateTorConfigCustom(fileTorRcCustom, extraLines.toString()); updateTorConfigCustom(fileTorRcCustom, extraLines.toString());
return fileTorRcCustom; return fileTorRcCustom;
}catch (Exception ex){}
return null;
} }
private String checkPortOrAuto(String portString) { private String checkPortOrAuto(String portString) {
@ -875,10 +879,12 @@ public class OrbotService extends VpnService implements OrbotConstants {
} }
private synchronized void startTorService() throws Exception { private synchronized void startTorService() throws Exception {
try {
updateTorConfigCustom(TorService.getDefaultsTorrc(this), updateTorConfigCustom(TorService.getDefaultsTorrc(this),
"DNSPort 0\n" + "DNSPort 0\n" +
"TransPort 0\n" + "TransPort 0\n" +
"DisableNetwork 1\n"); "DisableNetwork 1\n");
}catch (Exception ex){}
var fileTorrcCustom = updateTorrcCustomFile(); var fileTorrcCustom = updateTorrcCustomFile();
if ((!fileTorrcCustom.exists()) || (!fileTorrcCustom.canRead())) if ((!fileTorrcCustom.exists()) || (!fileTorrcCustom.canRead()))
@ -892,6 +898,7 @@ public class OrbotService extends VpnService implements OrbotConstants {
new Thread(){ new Thread(){
public void run(){ public void run(){
try {
TorService torService = ((TorService.LocalBinder) iBinder).getService(); TorService torService = ((TorService.LocalBinder) iBinder).getService();
while ((conn = torService.getTorControlConnection())==null) while ((conn = torService.getTorControlConnection())==null)
@ -936,6 +943,7 @@ public class OrbotService extends VpnService implements OrbotConstants {
initControlConnection(); initControlConnection();
} }
}catch (Exception ex){}
} }
}.start(); }.start();
//moved torService to a local variable, since we only need it once //moved torService to a local variable, since we only need it once
@ -960,12 +968,14 @@ public class OrbotService extends VpnService implements OrbotConstants {
} }
}; };
try {
Intent serviceIntent = new Intent(this, TorService.class); Intent serviceIntent = new Intent(this, TorService.class);
if (Build.VERSION.SDK_INT < 29) { if (Build.VERSION.SDK_INT < 29) {
shouldUnbindTorService = bindService(serviceIntent, torServiceConnection, BIND_AUTO_CREATE); shouldUnbindTorService = bindService(serviceIntent, torServiceConnection, BIND_AUTO_CREATE);
} else { } else {
shouldUnbindTorService = bindService(serviceIntent, BIND_AUTO_CREATE, mExecutor, torServiceConnection); shouldUnbindTorService = bindService(serviceIntent, BIND_AUTO_CREATE, mExecutor, torServiceConnection);
} }
}catch (Exception ex){}
} }
private void sendLocalStatusOffBroadcast() { private void sendLocalStatusOffBroadcast() {

View File

@ -0,0 +1,501 @@
package org.torproject.android.service;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.FileObserver;
import android.os.IBinder;
import android.os.Process;
import android.util.Log;
import net.freehaven.tor.control.RawEventListener;
import net.freehaven.tor.control.TorControlCommands;
import net.freehaven.tor.control.TorControlConnection;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
/**
* A {@link Service} that runs Tor. To control Tor via the {@code ControlPort},
* first bind to this using {@link #bindService(Intent, android.content.ServiceConnection, int)},
* then use {@link #getTorControlConnection()} to get an instance of
* {@link TorControlConnection} from {@code jtorctl}. If
* {@link TorControlCommands#EVENT_CIRCUIT_STATUS} is not included in
* {@link TorControlConnection#setEvents(java.util.List)}, then this service
* will not be able to function properly since it relies on those events to
* detect the state of Tor.
*/
public class TorServiceCustom extends Service {
public static final String TAG = "TorService";
public static final String VERSION_NAME = org.torproject.jni.BuildConfig.VERSION_NAME;
/**
* Request to transparently start Tor services.
*/
public static final String ACTION_START = "org.torproject.android.intent.action.START";
/**
* Internal request to stop Tor services.
*/
private static final String ACTION_STOP = "org.torproject.android.intent.action.STOP";
/**
* {@link Intent} sent by this app with {@code ON/OFF/STARTING/STOPPING} status
* included as an {@link #EXTRA_STATUS} {@code String}. Your app should
* always receive {@code ACTION_STATUS Intent}s since any other app could
* start Orbot. Also, user-triggered starts and stops will also cause
* {@code ACTION_STATUS Intent}s to be broadcast.
*/
public static final String ACTION_STATUS = "org.torproject.android.intent.action.STATUS";
public static final String ACTION_ERROR = "org.torproject.android.intent.action.ERROR";
/**
* {@code String} that contains a status constant: {@link #STATUS_ON},
* {@link #STATUS_OFF}, {@link #STATUS_STARTING}, or
* {@link #STATUS_STOPPING}
*/
public static final String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS";
/**
* A {@link String} {@code packageName} for {@code TorService} to direct its
* status reply to, after receiving an {@link #ACTION_START},
* {@link #ACTION_STOP}, or {@link #ACTION_STATUS} {@link Intent}. This allows
* {@code TorService} to send redundant replies to that single app, rather than
* broadcasting to all apps after every request.
*/
public final static String EXTRA_PACKAGE_NAME = "org.torproject.android.intent.extra.PACKAGE_NAME";
/**
* The {@link String} {@code packageName} of the app to which this {@code TorService} belongs.
* This allows broadcast receivers to distinguish between broadcasts from different apps that
* use {@code TorService}.
*/
public final static String EXTRA_SERVICE_PACKAGE_NAME = "org.torproject.android.intent.extra.SERVICE_PACKAGE_NAME";
/**
* All tor-related services and daemons are stopped
*/
public static final String STATUS_OFF = "OFF";
/**
* All tor-related services and daemons have completed starting
*/
public static final String STATUS_ON = "ON";
public static final String STATUS_STARTING = "STARTING";
public static final String STATUS_STOPPING = "STOPPING";
/**
* @return a {@link File} pointing to the location of the optional
* {@code torrc} file.
* @see <a href="https://www.torproject.org/docs/tor-manual.html#_the_configuration_file_format">Tor configuration file format</a>
*/
public static File getTorrc(Context context) {
return new File(getAppTorServiceDir(context), "torrc");
}
/**
* @return a {@link File} pointing to the location of the optional
* {@code torrc-defaults} file.
* @see <a href="https://www.torproject.org/docs/tor-manual.html#_the_configuration_file_format">Tor configuration file format</a>
*/
public static File getDefaultsTorrc(Context context) {
return new File(getAppTorServiceDir(context), "torrc-defaults");
}
private static File getControlSocket(Context context) {
if (controlSocket == null) {
controlSocket = new File(getAppTorServiceDataDir(context), CONTROL_SOCKET_NAME);
}
return controlSocket;
}
/**
* Get the directory that {@link TorServiceCustom} uses for:
* <ul>
* <li>writing {@code ControlPort.txt} // TODO
* <li>reading {@code torrc} and {@code torrc-defaults}
* <li>{@code DataDirectory} and {@code CacheDirectory}
* <li>the debug log file
* </ul>
*/
private static File getAppTorServiceDir(Context context) {
if (appTorServiceDir == null) {
appTorServiceDir = context.getDir(TorServiceCustom.class.getSimpleName(), MODE_PRIVATE);
}
return appTorServiceDir;
}
/**
* Tor stores private, internal data in this directory.
*/
private static File getAppTorServiceDataDir(Context context) {
File dir = new File(getAppTorServiceDir(context), "data");
dir.mkdir();
if (!(dir.setReadable(true, true) && dir.setWritable(true, true) && dir.setExecutable(true, true))) {
throw new IllegalStateException("Cannot create " + dir);
}
return dir;
}
static {
System.loadLibrary("tor");
}
volatile static String currentStatus = STATUS_OFF;
private static File appTorServiceDir = null;
private static File controlSocket = null;
private static final String CONTROL_SOCKET_NAME = "ControlSocket";
public static int socksPort = -1;
public static int httpTunnelPort = -1;
// Store the opaque reference as a long (pointer) for the native code
private long torConfiguration = -1;
private int torControlFd = -1;
private TorControlConnection torControlConnection;
/**
* This lock must be acquired before calling createTorConfiguration() and
* held until mainConfigurationFree() has been called.
*/
private static final ReentrantLock runLock = new ReentrantLock();
private native String apiGetProviderVersion();
private native boolean createTorConfiguration();
private native void mainConfigurationFree();
private native static FileDescriptor prepareFileDescriptor(String path);
private native boolean mainConfigurationSetCommandLine(String[] args);
private native boolean mainConfigurationSetupControlSocket();
private native int runMain();
public class LocalBinder extends Binder {
public TorServiceCustom getService() {
return TorServiceCustom.this;
}
}
private final IBinder binder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
// TODO send broadcastStatus() here?
return binder;
}
@Override
public void onCreate() {
super.onCreate();
broadcastStatus(this, STATUS_STARTING);
startTorServiceThread();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
sendBroadcastStatusIntent(this);
return super.onStartCommand(intent, flags, startId);
}
/**
* Announce Tor is available for connections once the first circuit is complete
*/
private final RawEventListener startedEventListener = new RawEventListener() {
@Override
public void onEvent(String keyword, String data) {
if (TorServiceCustom.STATUS_STARTING.equals(TorServiceCustom.currentStatus)
&& TorControlCommands.EVENT_CIRCUIT_STATUS.equals(keyword)
&& data != null && data.length() > 0) {
String[] tokenArray = data.split(" ");
if (tokenArray.length > 1 && TorControlCommands.CIRC_EVENT_BUILT.equals(tokenArray[1])) {
TorServiceCustom.broadcastStatus(TorServiceCustom.this, TorServiceCustom.STATUS_ON);
}
}
}
};
/**
* This waits for {@link #CONTROL_SOCKET_NAME} to be created by {@code tor},
* then continues on to connect to the {@code ControlSocket} as described in
* {@link #getControlSocket(Context)}. As a failsafe, this will only wait
* 10 seconds, after that it will check whether the {@code ControlSocket}
* file exists, and if not, throw a {@link IllegalStateException}.
*/
private Thread controlPortThread = new Thread(CONTROL_SOCKET_NAME) {
@Override
public void run() {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
final String observeDir = getAppTorServiceDataDir(TorServiceCustom.this).getAbsolutePath();
FileObserver controlPortFileObserver = new FileObserver(observeDir) {
@Override
public void onEvent(int event, @Nullable String name) {
if ((event & FileObserver.CREATE) > 0 && CONTROL_SOCKET_NAME.equals(name)) {
countDownLatch.countDown();
}
}
};
controlPortFileObserver.startWatching();
controlPortThreadStarted.countDown();
countDownLatch.await(10, TimeUnit.SECONDS);
controlPortFileObserver.stopWatching();
File controlSocket = new File(observeDir, CONTROL_SOCKET_NAME);
if (!controlSocket.canRead()) {
return;
}
FileDescriptor controlSocketFd = prepareFileDescriptor(getControlSocket(TorServiceCustom.this).getAbsolutePath());
InputStream is = new FileInputStream(controlSocketFd);
OutputStream os = new FileOutputStream(controlSocketFd);
torControlConnection = new TorControlConnection(is, os);
torControlConnection.launchThread(true);
torControlConnection.authenticate(new byte[0]);
torControlConnection.addRawEventListener(startedEventListener);
torControlConnection.setEvents(Arrays.asList(TorControlCommands.EVENT_CIRCUIT_STATUS));
socksPort = getPortFromGetInfo("net/listeners/socks");
httpTunnelPort = getPortFromGetInfo("net/listeners/httptunnel");
} catch (IOException | ArrayIndexOutOfBoundsException | InterruptedException e) {
e.printStackTrace();
broadcastStatus(TorServiceCustom.this, STATUS_STOPPING);
TorServiceCustom.this.stopSelf();
}
}
};
private CountDownLatch controlPortThreadStarted;
private int getPortFromGetInfo(String key) {
final String value = getInfo(key);
return Integer.parseInt(value.substring(value.lastIndexOf(':') + 1, value.length() - 1));
}
/**
* Start Tor in a {@link Thread} with the minimum required config. The
* rest of the config should happen via the Control Port. First Tor
* runs with {@code --verify-config} to check the command line flags and
* any {@code torrc} config. If they are correct, then this waits for the
* {@link #controlPortThread} to start so it is running before Tor could
* potentially create the {@code ControlSocket}. Then finally Tor is
* started in its own {@code Thread}.
* <p>
* Tor daemon does not output early debug messages to logcat, only after it
* tries to connect to the ports. So it is important that Tor does not run
* into port conflicts when first starting.
*
* @see <a href="https://trac.torproject.org/projects/tor/ticket/32036">#32036 output debug logs to logcat as early as possible on Android</a>
* @see <a href="https://github.com/torproject/tor/blob/40be20d542a83359ea480bbaa28380b4137c88b2/src/app/config/config.c#L4730">options that must be on the command line</a>
*/
private void startTorServiceThread() {
final Context context = this.getApplicationContext();
new Thread("tor") {
@Override
public void run() {
try {
String socksPort = "auto";
if (isPortAvailable(9050)) {
socksPort = Integer.toString(9050);
}
String httpTunnelPort = "auto";
if (isPortAvailable(8118)) {
httpTunnelPort = Integer.toString(8118);
}
if (runLock.isLocked()) {
Log.i(TAG, "Waiting for lock");
}
runLock.lock();
Log.i(TAG, "Acquired lock");
createTorConfiguration();
ArrayList<String> lines = new ArrayList<>(Arrays.asList("tor", "--verify-config", // must always be here
"--RunAsDaemon", "0",
"-f", getTorrc(context).getAbsolutePath(),
"--defaults-torrc", getDefaultsTorrc(context).getAbsolutePath(),
"--ignore-missing-torrc",
"--SyslogIdentityTag", TAG,
"--CacheDirectory", new File(getCacheDir(), TAG).getAbsolutePath(),
"--DataDirectory", getAppTorServiceDataDir(context).getAbsolutePath(),
"--ControlSocket", getControlSocket(context).getAbsolutePath(),
"--CookieAuthentication", "0",
"--SOCKSPort", socksPort,
"--HTTPTunnelPort", httpTunnelPort,
// can be moved to ControlPort messages
"--LogMessageDomains", "1",
"--TruncateLogFile", "1"
));
String[] verifyLines = lines.toArray(new String[0]);
if (!mainConfigurationSetCommandLine(verifyLines)) {
throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(verifyLines));
}
int result = runMain(); // run verify
if (result != 0) {
throw new IllegalArgumentException("Bad command flags: " + Arrays.toString(verifyLines));
}
controlPortThreadStarted = new CountDownLatch(1);
controlPortThread.start();
controlPortThreadStarted.await();
String[] runLines = new String[lines.size() - 1];
runLines[0] = "tor";
for (int i = 2; i < lines.size(); i++) {
runLines[i - 1] = lines.get(i);
}
if (!mainConfigurationSetCommandLine(runLines)) {
throw new IllegalArgumentException("Setting command line failed: " + Arrays.toString(runLines));
}
if (!mainConfigurationSetupControlSocket()) {
throw new IllegalStateException("Setting up ControlPort failed!");
}
if (runMain() != 0) {
throw new IllegalStateException("Tor could not start!");
}
} catch (IllegalStateException | IllegalArgumentException | InterruptedException e) {
e.printStackTrace();
broadcastError(context, e);
} finally {
broadcastStatus(context, STATUS_STOPPING);
mainConfigurationFree();
Log.i(TAG, "Releasing lock");
runLock.unlock();
TorServiceCustom.this.stopSelf();
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
if (torControlConnection != null) {
torControlConnection.removeRawEventListener(startedEventListener);
}
shutdownTor(TorControlCommands.SIGNAL_SHUTDOWN);
broadcastStatus(TorServiceCustom.this, STATUS_OFF);
}
public int getSocksPort() {
return socksPort;
}
public int getHttpTunnelPort() {
return httpTunnelPort;
}
/**
* @return the value or null on error
* @see <a href="https://gitweb.torproject.org/torspec.git/tree/control-spec.txt?id=bf318ccb042757cc47e47e19a63d1d825dcf222b#n527">control-spec GETINFO</a>
*/
public String getInfo(String key) {
try {
return torControlConnection.getInfo(key);
} catch (IOException | NullPointerException e) {
e.printStackTrace();
}
return null;
}
/**
* Send a signal to the Tor process to shut it down or halt it.
* Does not wait for a response, or report errors.
*
* @see TorControlConnection#shutdownTor(String)
*/
private void shutdownTor(String signal) {
try {
if (torControlConnection != null) {
torControlConnection.shutdownTor(signal);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Get an instance of {@link TorControlConnection} to control this instance
* of Tor, and configure it to set events.
*
* @see TorControlConnection#setEvents(java.util.List)
*/
public TorControlConnection getTorControlConnection() {
return torControlConnection;
}
/**
* Broadcasts the current status to any apps following the status of TorService.
*/
static void sendBroadcastStatusIntent(Context context) {
Intent intent = getBroadcastIntent(ACTION_STATUS, currentStatus);
intent.putExtra(EXTRA_SERVICE_PACKAGE_NAME, context.getPackageName());
context.sendBroadcast(intent);
}
/**
* Sends the current status both internally and for any apps that need to
* follow the status of TorService.
*/
static void broadcastStatus(Context context, String currentStatus) {
TorServiceCustom.currentStatus = currentStatus;
Intent intent = getBroadcastIntent(ACTION_STATUS, currentStatus);
intent.putExtra(EXTRA_SERVICE_PACKAGE_NAME, context.getPackageName());
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
context.sendBroadcast(intent);
}
/**
* This might be better handled by {@link android.content.ServiceConnection}
* but there is no way to write tests for {@code ServiceConnection}.
*/
static void broadcastError(Context context, Throwable e) {
Intent intent = new Intent(ACTION_ERROR);
if (e != null) {
intent.putExtra(Intent.EXTRA_TEXT, e.getLocalizedMessage());
}
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
context.sendBroadcast(intent);
}
private static Intent getBroadcastIntent(String action, String currentStatus) {
Intent intent = new Intent(action);
intent.putExtra(EXTRA_STATUS, currentStatus);
return intent;
}
private static boolean isPortAvailable(int port) {
try {
(new ServerSocket(port)).close();
return true;
} catch (IOException e) {
// Could not connect.
return false;
}
}
}