diff --git a/CHANGELOG.md b/CHANGELOG.md index b39a713ad..4b8e8b0d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ +Version 4.1.5 (July 10th, 2016) +============================== + + * Improvement: Add more protection against growing disk queue to over 2GB. + + Version 4.1.4 (Jun 6th, 2016) ============================== diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..2236c4bfc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,17 @@ +Contributing +============ + +If you would like to contribute code to `analytics-android` you can do so through +GitHub by forking the repository and sending a pull request. + +Development occurs on the `dev` branch, and pull requests must be opened against +the `dev` branch. Every second Wednesday, `master` is taggged and released, and +`dev` is merged into `master`. In general, code will be available on `master` +for two weeks before being tagged as a stable release. + +Critical bug fixes will be cherry picked into `master` after being merged into +`dev` and released immediately. + +When submitting code, please make every effort to follow existing conventions +and style in order to keep the code as readable as possible. Please also make +sure your code compiles by running `make build test`. diff --git a/analytics-tests/src/test/java/com/segment/analytics/QueueFileTest.java b/analytics-tests/src/test/java/com/segment/analytics/QueueFileTest.java index 384898f06..39e6e4a5d 100644 --- a/analytics-tests/src/test/java/com/segment/analytics/QueueFileTest.java +++ b/analytics-tests/src/test/java/com/segment/analytics/QueueFileTest.java @@ -4,6 +4,7 @@ import com.segment.analytics.QueueFile.Element; import java.io.ByteArrayOutputStream; +import java.io.EOFException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -33,8 +34,7 @@ /** * Takes up 33401 bytes in the queue (N*(N+1)/2+4*N). Picked 254 instead of 255 so that the - * number - * of bytes isn't a multiple of 4. + * number of bytes isn't a multiple of 4. */ private static int N = 254; private static byte[][] values = new byte[N][]; @@ -766,6 +766,28 @@ assertThat(queueFile2.size()).isEqualTo(queueSize); } + /* + @Test public void testOverflow() throws IOException { + QueueFile queueFile = new QueueFile(file); + + // Create a 32k block of test data. + byte[] value = new byte[32768]; + + // Run 32764 iterations = (32768 + 4) * 32764 = 1073741808 bytes. + for (int i = 0; i < 32764; i++) { + queueFile.add(value); + } + + // Grow the file to 1073741808 + (32768 + 4) = 1073774580 bytes. + try { + queueFile.add(value); + fail("QueueFile should throw error if attempted to grow beyond 1073741824 bytes"); + } catch (EOFException e) { + assertThat(e).hasMessage("Cannot grow file beyond 1073741824 bytes"); + } + } + */ + /** * A RandomAccessFile that can break when you go to write the COMMITTED * status. @@ -784,4 +806,4 @@ static class BrokenRandomAccessFile extends RandomAccessFile { super.write(buffer); } } -} \ No newline at end of file +} diff --git a/analytics/src/main/java/com/segment/analytics/Analytics.java b/analytics/src/main/java/com/segment/analytics/Analytics.java index 737b133f7..80c692248 100644 --- a/analytics/src/main/java/com/segment/analytics/Analytics.java +++ b/analytics/src/main/java/com/segment/analytics/Analytics.java @@ -653,7 +653,12 @@ public void alias(final String newId, final Options options) { void waitForAdvertisingId() { try { advertisingIdLatch.await(15, TimeUnit.SECONDS); - } catch (InterruptedException ignored) { + } catch (InterruptedException e) { + logger.error(e, "Thread interrupted while waiting for advertising ID."); + } + if (advertisingIdLatch.getCount() == 1) { + logger.debug("Advertising ID may not be collected because the Advertising ID API did not " + + "respond within 15 seconds."); } } @@ -1133,20 +1138,21 @@ public Analytics build() { Traits traits = Traits.create(); traitsCache.set(traits); } + + Logger logger = Logger.with(logLevel); AnalyticsContext analyticsContext = AnalyticsContext.create(application, traitsCache.get(), collectDeviceID); CountDownLatch advertisingIdLatch = new CountDownLatch(1); - analyticsContext.attachAdvertisingId(application, advertisingIdLatch); + analyticsContext.attachAdvertisingId(application, advertisingIdLatch, logger); List factories = new ArrayList<>(1 + this.factories.size()); factories.add(SegmentIntegration.FACTORY); factories.addAll(this.factories); return new Analytics(application, networkExecutor, stats, traitsCache, analyticsContext, - defaultOptions, Logger.with(logLevel), tag, factories, client, cartographer, - projectSettingsCache, writeKey, flushQueueSize, flushIntervalInMillis, - Executors.newSingleThreadExecutor(), trackApplicationLifecycleEvents, advertisingIdLatch, - recordScreenViews, optOut); + defaultOptions, logger, tag, factories, client, cartographer, projectSettingsCache, + writeKey, flushQueueSize, flushIntervalInMillis, Executors.newSingleThreadExecutor(), + trackApplicationLifecycleEvents, advertisingIdLatch, recordScreenViews, optOut); } } diff --git a/analytics/src/main/java/com/segment/analytics/AnalyticsContext.java b/analytics/src/main/java/com/segment/analytics/AnalyticsContext.java index 05a79338f..0fe535c23 100644 --- a/analytics/src/main/java/com/segment/analytics/AnalyticsContext.java +++ b/analytics/src/main/java/com/segment/analytics/AnalyticsContext.java @@ -35,6 +35,7 @@ import android.view.Display; import android.view.WindowManager; import com.segment.analytics.core.BuildConfig; +import com.segment.analytics.integrations.Logger; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; @@ -147,13 +148,16 @@ static void putUndefinedIfNull(Map target, String key, CharSeque super(delegate); } - void attachAdvertisingId(Context context, CountDownLatch latch) { + void attachAdvertisingId(Context context, CountDownLatch latch, Logger logger) { // This is done as an extra step so we don't run into errors like this for testing - // http://pastebin.com/gyWJKWiu + // http://pastebin.com/gyWJKWiu. if (isOnClassPath("com.google.android.gms.ads.identifier.AdvertisingIdClient")) { - // this needs to be done each time since the settings may have been updated - new GetAdvertisingIdTask(this, latch).execute(context); + // This needs to be done each time since the settings may have been updated. + new GetAdvertisingIdTask(this, latch, logger).execute(context); } else { + logger.debug("Not collecting advertising ID because " + + "com.google.android.gms.ads.identifier.AdvertisingIdClient " + + "was not found on the classpath."); latch.countDown(); } } diff --git a/analytics/src/main/java/com/segment/analytics/GetAdvertisingIdTask.java b/analytics/src/main/java/com/segment/analytics/GetAdvertisingIdTask.java index a65525d5c..ab30f64e1 100644 --- a/analytics/src/main/java/com/segment/analytics/GetAdvertisingIdTask.java +++ b/analytics/src/main/java/com/segment/analytics/GetAdvertisingIdTask.java @@ -3,6 +3,7 @@ import android.content.Context; import android.os.AsyncTask; import android.util.Pair; +import com.segment.analytics.integrations.Logger; import java.util.concurrent.CountDownLatch; /** @@ -13,10 +14,12 @@ class GetAdvertisingIdTask extends AsyncTask doInBackground(Context... contexts) { @@ -31,15 +34,17 @@ class GetAdvertisingIdTask extends AsyncTask info) { @@ -51,6 +56,7 @@ class GetAdvertisingIdTask extends AsyncTask