Skip to content
Permalink
Browse files

Merge pull request #175 from Jigsaw-Code/bemasc-crashlytics

Switch to Firebase Crashlytics
  • Loading branch information...
bemasc committed May 10, 2019
2 parents 6b416e1 + 765a4a8 commit 819af3f01f96246edd77bab4df66d4865fc3ffcb
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

// See https://developer.android.com/studio/publish/app-signing#secure-shared-keystore
def keystorePropertiesFile = rootProject.file("keystore.properties")
@@ -107,7 +108,7 @@ dependencies {
// For Firebase Analytics, etc.
implementation 'com.google.firebase:firebase-core:16.0.9'
implementation 'com.google.firebase:firebase-perf:16.2.5' // Last version to support API <17
implementation 'com.google.firebase:firebase-crash:16.2.1'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.0'
// For Sockslib
implementation 'org.slf4j:slf4j-api:1.7.25'
implementation 'org.slf4j:slf4j-android:1.7.25'
@@ -40,7 +40,7 @@
</receiver>

<meta-data
android:name="firebase_crash_collection_enabled"
android:name="firebase_crashlytics_collection_enabled"
android:value="@bool/FIREBASE_ENABLED"/>
<meta-data
android:name="firebase_analytics_collection_enabled"
@@ -18,7 +18,7 @@
import android.os.SystemClock;
import android.util.Log;
import app.intra.sys.LogWrapper;
import com.google.firebase.crash.FirebaseCrash;
import com.crashlytics.android.Crashlytics;
import java.net.InetAddress;
import java.net.ProtocolException;

@@ -49,14 +49,14 @@ public static DnsUdpQuery fromUdpBody(byte[] dnsPacketData) {
return null;
}
if (!dnsPacket.isNormalQuery() && !dnsPacket.isResponse()) {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "Dropping strange DNS query");
Crashlytics.log(Log.INFO, LOG_TAG, "Dropping strange DNS query");
return null;
}

dnsUdpQuery.type = dnsPacket.getQueryType();
dnsUdpQuery.name = dnsPacket.getQueryName();
if (dnsUdpQuery.name == null || dnsUdpQuery.type == 0) {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "No question in DNS packet");
Crashlytics.log(Log.INFO, LOG_TAG, "No question in DNS packet");
return null;
}
dnsUdpQuery.requestId = dnsPacket.getId();
@@ -18,7 +18,7 @@
import android.util.Log;
import app.intra.net.dns.DnsUdpQuery;
import app.intra.sys.LogWrapper;
import com.google.firebase.crash.FirebaseCrash;
import com.crashlytics.android.Crashlytics;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.BufferOverflowException;
@@ -95,11 +95,11 @@ public void onFailure(Call call, IOException e) {
Transaction.Status.CANCELED : Transaction.Status.SEND_FAIL;
LogWrapper.logcat(Log.WARN, LOG_TAG, "Failed to read HTTPS response: " + e.toString());
if (e instanceof SocketTimeoutException) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "Workaround for OkHttp3 #3146: resetting");
Crashlytics.log(Log.WARN, LOG_TAG, "Workaround for OkHttp3 #3146: resetting");
try {
serverConnection.reset();
} catch (NullPointerException npe) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG,
Crashlytics.log(Log.WARN, LOG_TAG,
"Unlikely race: Null server connection at reset.");
}
}
@@ -123,15 +123,15 @@ private void processResponse(Response response) {
try {
writeRequestIdToDnsResponse(dnsResponse, dnsUdpQuery.requestId);
} catch (BufferOverflowException e) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "ID replacement failed");
Crashlytics.log(Log.WARN, LOG_TAG, "ID replacement failed");
transaction.status = Transaction.Status.BAD_RESPONSE;
return;
}
DnsUdpQuery parsedDnsResponse = DnsUdpQuery.fromUdpBody(dnsResponse);
if (parsedDnsResponse != null) {
Log.d(LOG_TAG, "RNAME: " + parsedDnsResponse.name + " NAME: " + dnsUdpQuery.name);
if (!dnsUdpQuery.name.equals(parsedDnsResponse.name)) {
FirebaseCrash.logcat(Log.ERROR, LOG_TAG, "Mismatch in request and response names.");
Crashlytics.log(Log.ERROR, LOG_TAG, "Mismatch in request and response names.");
transaction.status = Transaction.Status.BAD_RESPONSE;
return;
}
@@ -23,7 +23,7 @@
import app.intra.net.VpnAdapter;
import app.intra.sys.IntraVpnService;
import app.intra.sys.LogWrapper;
import com.google.firebase.crash.FirebaseCrash;
import com.crashlytics.android.Crashlytics;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
@@ -169,7 +169,7 @@ private static ParcelFileDescriptor establishVpn(IntraVpnService vpnService) {
.addDisallowedApplication(vpnService.getPackageName())
.establish();
} catch (Exception e) {
FirebaseCrash.report(e);
Crashlytics.logException(e);
return null;
}
}
@@ -26,7 +26,7 @@
import app.intra.net.doh.ResponseWriter;
import app.intra.net.doh.Transaction;
import app.intra.sys.IntraVpnService;
import com.google.firebase.crash.FirebaseCrash;
import com.crashlytics.android.Crashlytics;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -96,7 +96,7 @@ private static ParcelFileDescriptor establishVpn(IntraVpnService vpnService) {
PrivateAddress privateIpv6Address = new PrivateAddress(IPV6_SUBNET, 120);
PrivateAddress privateIpv4Address = selectPrivateAddress();
if (privateIpv4Address == null) {
FirebaseCrash.logcat(
Crashlytics.log(
Log.ERROR, LOG_TAG, "Unable to find a private address on which to establish a VPN.");
return null;
}
@@ -122,13 +122,13 @@ private static ParcelFileDescriptor establishVpn(IntraVpnService vpnService) {
}
tunFd = builder.establish();
} catch (IllegalArgumentException e) {
FirebaseCrash.report(e);
Crashlytics.logException(e);
Log.e(LOG_TAG, establishVpnErrorMsg, e);
} catch (SecurityException e) {
FirebaseCrash.report(e);
Crashlytics.logException(e);
Log.e(LOG_TAG, establishVpnErrorMsg, e);
} catch (IllegalStateException e) {
FirebaseCrash.report(e);
Crashlytics.logException(e);
Log.e(LOG_TAG, establishVpnErrorMsg, e);
}

@@ -167,7 +167,7 @@ private static PrivateAddress selectPrivateAddress() {
try {
netInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) {
FirebaseCrash.report(e);
Crashlytics.logException(e);
e.printStackTrace();
return null;
}
@@ -199,12 +199,12 @@ private static PrivateAddress selectPrivateAddress() {
@Override
// This thread reads DNS requests from the VPN interface and forwards them via |serverConnection|.
public void run() {
FirebaseCrash.logcat(Log.DEBUG, LOG_TAG, "Query thread starting");
Crashlytics.log(Log.DEBUG, LOG_TAG, "Query thread starting");
if (tunFd == null) {
// This check is necessary due to a race, where the VPN has been closed and the device regains
// network connectivity before the service stops. As a result the TUN file descriptor is null
// at the time the resolver is created.
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "VPN/TUN file descriptor is null");
Crashlytics.log(Log.WARN, LOG_TAG, "VPN/TUN file descriptor is null");
return;
}

@@ -218,8 +218,8 @@ public void run() {
length = in.read(buffer.array());
} catch (IOException e) {
if (!isInterrupted()) {
FirebaseCrash.logcat(Log.ERROR, LOG_TAG, "Failed to read from tun interface.");
FirebaseCrash.report(e);
Crashlytics.log(Log.ERROR, LOG_TAG, "Failed to read from tun interface.");
Crashlytics.logException(e);
}
return;
}
@@ -233,7 +233,7 @@ public void run() {
continue;
}
if (length < IP_MIN_HEADER_LENGTH) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "Received malformed IP packet.");
Crashlytics.log(Log.WARN, LOG_TAG, "Received malformed IP packet.");
continue;
}
buffer.limit(length);
@@ -248,30 +248,29 @@ public void run() {
ipPacket = new Ipv6Packet(buffer);
}
} catch (IllegalArgumentException e) {
FirebaseCrash
.logcat(Log.WARN, LOG_TAG, "Received malformed IP packet: " + e.getMessage());
Crashlytics.log(Log.WARN, LOG_TAG, "Received malformed IP packet: " + e.getMessage());
continue;
}
byte protocol = ipPacket.getProtocol();
if (protocol != UDP_PROTOCOL) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, getProtocolErrorMessage(protocol));
Crashlytics.log(Log.WARN, LOG_TAG, getProtocolErrorMessage(protocol));
continue;
}

UdpPacket udpPacket = new UdpPacket(ByteBuffer.wrap(ipPacket.getPayload()));
if (udpPacket.destPort != DNS_DEFAULT_PORT) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "Received non-DNS UDP packet");
Crashlytics.log(Log.WARN, LOG_TAG, "Received non-DNS UDP packet");
continue;
}

if (udpPacket.length == 0) {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "Received interrupt UDP packet.");
Crashlytics.log(Log.INFO, LOG_TAG, "Received interrupt UDP packet.");
continue;
}

DnsUdpQuery dnsRequest = DnsUdpQuery.fromUdpBody(udpPacket.data);
if (dnsRequest == null) {
FirebaseCrash.logcat(Log.ERROR, LOG_TAG, "Failed to parse DNS request");
Crashlytics.log(Log.ERROR, LOG_TAG, "Failed to parse DNS request");
continue;
}
Log.d(
@@ -292,8 +291,8 @@ public void run() {
dnsRequest, udpPacket.data, this);
} catch (Exception e) {
if (!isInterrupted()) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "Unexpected exception in UDP loop.");
FirebaseCrash.report(e);
Crashlytics.log(Log.WARN, LOG_TAG, "Unexpected exception in UDP loop.");
Crashlytics.logException(e);
}
}
}
@@ -345,8 +344,8 @@ public void sendResult(DnsUdpQuery dnsUdpQuery, Transaction transaction) {
try {
out.write(rawIpResponse);
} catch (IOException e) {
FirebaseCrash.logcat(Log.ERROR, LOG_TAG, "Failed to write to VPN/TUN interface.");
FirebaseCrash.report(e);
Crashlytics.log(Log.ERROR, LOG_TAG, "Failed to write to VPN/TUN interface.");
Crashlytics.logException(e);
transaction.status = Transaction.Status.INTERNAL_ERROR;
}
}
@@ -359,7 +358,7 @@ public void close() {
try {
tunFd.close();
} catch (IOException e) {
FirebaseCrash.report(e);
Crashlytics.logException(e);
}
}
}
@@ -21,7 +21,7 @@
import android.net.VpnService;
import android.util.Log;
import app.intra.ui.MainActivity;
import com.google.firebase.crash.FirebaseCrash;
import com.crashlytics.android.Crashlytics;

/**
* Broadcast receiver that runs on boot, and also when the app is restarted due to an update.
@@ -31,14 +31,14 @@

@Override
public void onReceive(Context context, Intent intent) {
FirebaseCrash.logcat(Log.DEBUG, LOG_TAG, "Boot event");
Crashlytics.log(Log.DEBUG, LOG_TAG, "Boot event");
VpnController controller = VpnController.getInstance();
VpnState state = controller.getState(context);
if (state.activationRequested && !state.on) {
FirebaseCrash.logcat(Log.DEBUG, LOG_TAG, "Autostart enabled");
Crashlytics.log(Log.DEBUG, LOG_TAG, "Autostart enabled");
if (VpnService.prepare(context) != null) {
// prepare() returns a non-null intent if VPN permission has not been granted.
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "VPN permission not granted. Starting UI.");
Crashlytics.log(Log.WARN, LOG_TAG, "VPN permission not granted. Starting UI.");
Intent startIntent = new Intent(context, MainActivity.class);
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startIntent);
@@ -46,8 +46,8 @@
import app.intra.net.split.SplitVpnAdapter;
import app.intra.sys.NetworkManager.NetworkListener;
import app.intra.ui.MainActivity;
import com.crashlytics.android.Crashlytics;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.google.firebase.crash.FirebaseCrash;
import java.util.Calendar;

public class IntraVpnService extends VpnService implements NetworkListener,
@@ -292,7 +292,7 @@ private synchronized void startVpn() {

VpnController.getInstance().onStartComplete(this, vpnAdapter != null);
if (vpnAdapter == null) {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "Failed to startVpn VPN adapter");
Crashlytics.log(Log.WARN, LOG_TAG, "Failed to startVpn VPN adapter");
stopSelf();
}
}
@@ -310,13 +310,13 @@ private synchronized void restartVpn() {
if (vpnAdapter != null) {
vpnAdapter.start();
} else {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "Restart failed");
Crashlytics.log(Log.WARN, LOG_TAG, "Restart failed");
}
}

@Override
public void onCreate() {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "Creating DNS VPN service");
Crashlytics.log(Log.INFO, LOG_TAG, "Creating DNS VPN service");
VpnController.getInstance().setIntraVpnService(this);

firebaseAnalytics = FirebaseAnalytics.getInstance(this);
@@ -326,7 +326,7 @@ public void onCreate() {

public void signalStopService(boolean userInitiated) {
// TODO(alalama): display alert if not user initiated
FirebaseCrash.logcat(
Crashlytics.log(
Log.INFO,
LOG_TAG,
String.format("Received stop signal. User initiated: %b", userInitiated));
@@ -353,12 +353,12 @@ private VpnAdapter makeVpnAdapter() {

private synchronized void startVpnAdapter() {
if (vpnAdapter == null) {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "Starting DNS resolver");
Crashlytics.log(Log.INFO, LOG_TAG, "Starting DNS resolver");
vpnAdapter = makeVpnAdapter();
if (vpnAdapter != null) {
vpnAdapter.start();
} else {
FirebaseCrash.logcat(Log.ERROR, LOG_TAG, "Failed to start VPN adapter!");
Crashlytics.log(Log.ERROR, LOG_TAG, "Failed to start VPN adapter!");
}
}
}
@@ -373,7 +373,7 @@ private synchronized void stopVpnAdapter() {

@Override
public synchronized void onDestroy() {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "Destroying DNS VPN service");
Crashlytics.log(Log.INFO, LOG_TAG, "Destroying DNS VPN service");

PreferenceManager.getDefaultSharedPreferences(this).
unregisterOnSharedPreferenceChangeListener(this);
@@ -395,7 +395,7 @@ public synchronized void onDestroy() {

@Override
public void onRevoke() {
FirebaseCrash.logcat(Log.WARN, LOG_TAG, "VPN service revoked.");
Crashlytics.log(Log.WARN, LOG_TAG, "VPN service revoked.");
stopVpnAdapter();
stopSelf();

@@ -450,7 +450,7 @@ public void onRevoke() {
// Play Store incompatibility is a known issue, so always exclude it.
builder = builder.addDisallowedApplication("com.android.vending");
} catch (PackageManager.NameNotFoundException e) {
FirebaseCrash.report(e);
Crashlytics.logException(e);
Log.e(LOG_TAG, "Failed to exclude an app", e);
}
}
@@ -505,7 +505,7 @@ private void setNetworkConnected(boolean connected) {
// NetworkListener interface implementation
@Override
public void onNetworkConnected(NetworkInfo networkInfo) {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "Connected event.");
Crashlytics.log(Log.INFO, LOG_TAG, "Connected event.");
setNetworkConnected(true);
// This code is used to start the VPN for the first time, but startVpn is idempotent, so we can
// call it every time. startVpn performs network activity so it has to run on a separate thread.
@@ -521,7 +521,7 @@ public void run() {

@Override
public void onNetworkDisconnected() {
FirebaseCrash.logcat(Log.INFO, LOG_TAG, "Disconnected event.");
Crashlytics.log(Log.INFO, LOG_TAG, "Disconnected event.");
setNetworkConnected(false);
VpnController.getInstance().onConnectionStateChanged(this, null);
}

0 comments on commit 819af3f

Please sign in to comment.
You can’t perform that action at this time.