From ae412cc151f9cac7a7b963c6d488f365438b729c Mon Sep 17 00:00:00 2001 From: Prateek Srivastava Date: Sun, 19 Jun 2016 08:01:43 +0530 Subject: [PATCH 1/6] Throw EOF if attempted to grow QueueFile beyond 1073741824 bytes --- .../com/segment/analytics/QueueFileTest.java | 24 +++++++++++++++++-- .../java/com/segment/analytics/QueueFile.java | 4 ++++ 2 files changed, 26 insertions(+), 2 deletions(-) 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..67bc357b3 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,26 @@ 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. diff --git a/analytics/src/main/java/com/segment/analytics/QueueFile.java b/analytics/src/main/java/com/segment/analytics/QueueFile.java index adb8c0911..4990bf32a 100644 --- a/analytics/src/main/java/com/segment/analytics/QueueFile.java +++ b/analytics/src/main/java/com/segment/analytics/QueueFile.java @@ -16,6 +16,7 @@ package com.segment.analytics; import java.io.Closeable; +import java.io.EOFException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -354,6 +355,9 @@ private void expandIfNecessary(int dataLength) throws IOException { do { remainingBytes += previousLength; newLength = previousLength << 1; + if (newLength < previousLength) { + throw new EOFException("Cannot grow file beyond " + previousLength + " bytes"); + } previousLength = newLength; } while (remainingBytes < elementLength); From 820d9aa79ac0dae89058208637788005ff3ebc84 Mon Sep 17 00:00:00 2001 From: Prateek Srivastava Date: Fri, 24 Jun 2016 01:14:08 +0530 Subject: [PATCH 2/6] suppress long test --- .../src/test/java/com/segment/analytics/QueueFileTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 67bc357b3..39e6e4a5d 100644 --- a/analytics-tests/src/test/java/com/segment/analytics/QueueFileTest.java +++ b/analytics-tests/src/test/java/com/segment/analytics/QueueFileTest.java @@ -766,6 +766,7 @@ assertThat(queueFile2.size()).isEqualTo(queueSize); } + /* @Test public void testOverflow() throws IOException { QueueFile queueFile = new QueueFile(file); @@ -785,6 +786,7 @@ assertThat(e).hasMessage("Cannot grow file beyond 1073741824 bytes"); } } + */ /** * A RandomAccessFile that can break when you go to write the COMMITTED @@ -804,4 +806,4 @@ static class BrokenRandomAccessFile extends RandomAccessFile { super.write(buffer); } } -} \ No newline at end of file +} From 01926a500faf2fde52c13e233dc873b13e6c1519 Mon Sep 17 00:00:00 2001 From: Prateek Srivastava Date: Sun, 10 Jul 2016 15:39:23 -0600 Subject: [PATCH 3/6] Prepare for release 4.1.5. --- CHANGELOG.md | 6 ++++++ gradle.properties | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) 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/gradle.properties b/gradle.properties index fc3e37dc6..448fa2d1c 100755 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ GROUP=com.segment.analytics.android VERSION_CODE=415 -VERSION_NAME=4.1.5-SNAPSHOT +VERSION_NAME=4.1.5 POM_NAME=Segment for Android POM_DESCRIPTION=The hassle-free way to add analytics to your Android app. From 61adfaf1b527487de41900580735c5614bd29762 Mon Sep 17 00:00:00 2001 From: Prateek Srivastava Date: Sun, 10 Jul 2016 15:41:26 -0600 Subject: [PATCH 4/6] Prepare next development version. --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 448fa2d1c..9427ecd7f 100755 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ GROUP=com.segment.analytics.android -VERSION_CODE=415 -VERSION_NAME=4.1.5 +VERSION_CODE=416 +VERSION_NAME=4.1.6-SNAPSHOT POM_NAME=Segment for Android POM_DESCRIPTION=The hassle-free way to add analytics to your Android app. From 878a60fce679d1d2016a4a2e28cbdf57fe4281f3 Mon Sep 17 00:00:00 2001 From: Prateek Srivastava Date: Sat, 25 Jun 2016 16:13:05 +0530 Subject: [PATCH 5/6] Update contributing docs --- CONTRIBUTING.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 CONTRIBUTING.md 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`. From 8455b09137aae5ee2935020acbe623ab269cc51b Mon Sep 17 00:00:00 2001 From: Prateek Srivastava Date: Fri, 1 Jul 2016 12:12:16 -0600 Subject: [PATCH 6/6] Add more logging for collecting advertising ID --- .../java/com/segment/analytics/Analytics.java | 18 ++++++++++++------ .../segment/analytics/AnalyticsContext.java | 12 ++++++++---- .../analytics/GetAdvertisingIdTask.java | 12 +++++++++--- 3 files changed, 29 insertions(+), 13 deletions(-) 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