diff --git a/ndk/src/main/java/com/bugsnag/android/ndk/NativeBridge.java b/ndk/src/main/java/com/bugsnag/android/ndk/NativeBridge.java index b2370b3397..5828ecde88 100644 --- a/ndk/src/main/java/com/bugsnag/android/ndk/NativeBridge.java +++ b/ndk/src/main/java/com/bugsnag/android/ndk/NativeBridge.java @@ -1,8 +1,5 @@ package com.bugsnag.android.ndk; -import com.bugsnag.android.Breadcrumb; -import com.bugsnag.android.NativeInterface; - import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -206,22 +203,8 @@ public static native void startedSession(String sessionID, String key, public static native void updateUserName(String newValue); - private boolean loggingEnabled = true; - private final String reportDirectory; - - /** - * Creates a new native bridge for interacting with native components. - * Configures logging and ensures that the reporting directory exists - * immediately. - */ - public NativeBridge() { - loggingEnabled = NativeInterface.getLoggingEnabled(); - reportDirectory = NativeInterface.getNativeReportPath(); - File outFile = new File(reportDirectory); - if (!outFile.exists() && !outFile.mkdirs()) { - warn("The native reporting directory cannot be created."); - } - } + private volatile boolean loggingEnabled = true; + private volatile String reportDirectory; @Override public void update(Observable observable, Object rawMessage) { @@ -343,6 +326,11 @@ private void deliverPendingReports() { } } + /** + * Creates a new native bridge for interacting with native components. + * Configures logging and ensures that the reporting directory exists + * immediately. + */ private void handleInstallMessage(Object arg) { lock.lock(); try { @@ -350,35 +338,53 @@ private void handleInstallMessage(Object arg) { warn("Received duplicate setup message with arg: " + arg); return; } - String reportPath = reportDirectory + UUID.randomUUID().toString() + ".crash"; - install(reportPath, true, Build.VERSION.SDK_INT, is32bit()); - installed.set(true); - } finally { - lock.unlock(); - } - } - private boolean is32bit() { - String[] abis = NativeInterface.getCpuAbi(); + boolean is32bit; - boolean is32bit = true; - for (String abi : abis) { - if (abi.contains("64")) { - is32bit = false; - break; + if (arg instanceof List) { + @SuppressWarnings("unchecked") + List values = (List) arg; + if (values.size() == 4 + && values.get(1) instanceof Boolean + && values.get(2) instanceof Boolean + && values.get(3) instanceof String) { + + is32bit = loggingEnabled = (boolean) values.get(1); + loggingEnabled = (boolean) values.get(2); + reportDirectory = (String) values.get(3); + + File outFile = new File(reportDirectory); + if (!outFile.exists() && !outFile.mkdirs()) { + warn("The native reporting directory cannot be created."); + } + + String reportPath = reportDirectory + UUID.randomUUID().toString() + ".crash"; + install(reportPath, true, Build.VERSION.SDK_INT, is32bit); + installed.set(true); + } else { + warn("Received malformed NDK install message."); + } + } else { + warn("Received malformed NDK install message."); } + + } finally { + lock.unlock(); } - return is32bit; } private void handleAddBreadcrumb(Object arg) { - if (arg instanceof Breadcrumb) { - Breadcrumb crumb = (Breadcrumb) arg; - addBreadcrumb(crumb.getName(), crumb.getType().toString(), - crumb.getTimestamp(), crumb.getMetadata()); - } else { - warn("Attempted to add non-breadcrumb: " + arg); + if (arg instanceof List) { + @SuppressWarnings("unchecked") + List values = (List) arg; + + if (values.size() == 4) { + addBreadcrumb((String) values.get(0), (String) values.get(1), + (String) values.get(2), values.get(3)); + return; + } } + warn("Attempted to add non-breadcrumb: " + arg); } private void handleAddMetadata(Object arg) { diff --git a/sdk/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java b/sdk/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java index e9b5bed8e4..283647bfd1 100644 --- a/sdk/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java +++ b/sdk/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Observable; import java.util.Observer; @@ -255,23 +256,27 @@ public void testClientClearUserSendsMessage() { @Test public void testLeaveStringBreadcrumbSendsMessage() { client.leaveBreadcrumb("Drift 4 units left"); - Breadcrumb crumb = (Breadcrumb)findMessageInQueue( - NativeBridge.MessageType.ADD_BREADCRUMB, Breadcrumb.class); - assertEquals(BreadcrumbType.MANUAL, crumb.getType()); - assertEquals("manual", crumb.getName()); - assertEquals(1, crumb.getMetadata().size()); - assertEquals("Drift 4 units left", crumb.getMetadata().get("message")); + List crumb = (List)findMessageInQueue( + NativeBridge.MessageType.ADD_BREADCRUMB, List.class); + assertEquals("manual", crumb.get(0)); + assertEquals(BreadcrumbType.MANUAL.toString(), crumb.get(1)); + + Map metaData = ((Map)crumb.get(3)); + assertEquals(1, metaData.size()); + assertEquals("Drift 4 units left", metaData.get("message")); } @Test public void testLeaveStringBreadcrumbDirectlySendsMessage() { client.breadcrumbs.add(new Breadcrumb("Drift 4 units left")); - Breadcrumb crumb = (Breadcrumb)findMessageInQueue( - NativeBridge.MessageType.ADD_BREADCRUMB, Breadcrumb.class); - assertEquals(BreadcrumbType.MANUAL, crumb.getType()); - assertEquals("manual", crumb.getName()); - assertEquals(1, crumb.getMetadata().size()); - assertEquals("Drift 4 units left", crumb.getMetadata().get("message")); + List crumb = (List)findMessageInQueue( + NativeBridge.MessageType.ADD_BREADCRUMB, List.class); + assertEquals("manual", crumb.get(0)); + assertEquals(BreadcrumbType.MANUAL.toString(), crumb.get(1)); + + Map metaData = ((Map)crumb.get(3)); + assertEquals(1, metaData.size()); + assertEquals("Drift 4 units left", metaData.get("message")); } @Test @@ -289,11 +294,12 @@ public void testClearBreadcrumbsDirectlySendsMessage() { @Test public void testLeaveBreadcrumbSendsMessage() { client.leaveBreadcrumb("Rollback", BreadcrumbType.LOG, new HashMap()); - Breadcrumb crumb = (Breadcrumb)findMessageInQueue( - NativeBridge.MessageType.ADD_BREADCRUMB, Breadcrumb.class); - assertEquals(BreadcrumbType.LOG, crumb.getType()); - assertEquals("Rollback", crumb.getName()); - assertEquals(0, crumb.getMetadata().size()); + List crumb = (List)findMessageInQueue( + NativeBridge.MessageType.ADD_BREADCRUMB, List.class); + + assertEquals("Rollback", crumb.get(0)); + assertEquals(BreadcrumbType.LOG.toString(), crumb.get(1)); + assertEquals(0, ((Map)crumb.get(3)).size()); } private Object findMessageInQueue(NativeBridge.MessageType type, Class argClass) { diff --git a/sdk/src/main/java/com/bugsnag/android/Breadcrumbs.java b/sdk/src/main/java/com/bugsnag/android/Breadcrumbs.java index 5f67bf5a47..67349adc31 100644 --- a/sdk/src/main/java/com/bugsnag/android/Breadcrumbs.java +++ b/sdk/src/main/java/com/bugsnag/android/Breadcrumbs.java @@ -5,6 +5,8 @@ import android.support.annotation.NonNull; import java.io.IOException; +import java.util.Arrays; +import java.util.List; import java.util.Observable; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -53,8 +55,16 @@ private void addToStore(@NonNull Breadcrumb breadcrumb) { store.add(breadcrumb); pruneBreadcrumbs(); setChanged(); + + List breadcrumbValues = Arrays.asList( + breadcrumb.getName(), + breadcrumb.getType().toString(), + breadcrumb.getTimestamp(), + breadcrumb.getMetadata() + ); + notifyObservers(new NativeBridge.Message( - NativeBridge.MessageType.ADD_BREADCRUMB, breadcrumb)); + NativeBridge.MessageType.ADD_BREADCRUMB, breadcrumbValues)); } catch (IOException ex) { Logger.warn("Dropping breadcrumb because it could not be serialized", ex); } diff --git a/sdk/src/main/java/com/bugsnag/android/Client.java b/sdk/src/main/java/com/bugsnag/android/Client.java index 42aeefe5c6..f7f9bb7cc7 100644 --- a/sdk/src/main/java/com/bugsnag/android/Client.java +++ b/sdk/src/main/java/com/bugsnag/android/Client.java @@ -24,8 +24,10 @@ import android.view.OrientationEventListener; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Observable; import java.util.Observer; @@ -284,7 +286,14 @@ public void onReceive(Context context, Intent intent) { void sendNativeSetupNotification() { setChanged(); - super.notifyObservers(new NativeBridge.Message(NativeBridge.MessageType.INSTALL, config)); + List obj = Arrays.asList( + config, + NativeInterface.is32bit(), + NativeInterface.getLoggingEnabled(), + NativeInterface.getNativeReportPath() + ); + + super.notifyObservers(new NativeBridge.Message(NativeBridge.MessageType.INSTALL, obj)); try { Async.run(new Runnable() { @Override diff --git a/sdk/src/main/java/com/bugsnag/android/NativeInterface.java b/sdk/src/main/java/com/bugsnag/android/NativeInterface.java index c80809aeef..a5b54f9f8d 100644 --- a/sdk/src/main/java/com/bugsnag/android/NativeInterface.java +++ b/sdk/src/main/java/com/bugsnag/android/NativeInterface.java @@ -339,4 +339,17 @@ public void beforeNotify(@NonNull Report report) { } }); } + + static boolean is32bit() { + String[] abis = NativeInterface.getCpuAbi(); + + boolean is32bit = true; + for (String abi : abis) { + if (abi.contains("64")) { + is32bit = false; + break; + } + } + return is32bit; + } }