summaryrefslogtreecommitdiffstats
path: root/mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java')
-rw-r--r--mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java781
1 files changed, 0 insertions, 781 deletions
diff --git a/mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java b/mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java
deleted file mode 100644
index 8c7858b97..000000000
--- a/mobile/android/thirdparty/com/adjust/sdk/ActivityHandler.java
+++ /dev/null
@@ -1,781 +0,0 @@
-//
-// ActivityHandler.java
-// Adjust
-//
-// Created by Christian Wellenbrock on 2013-06-25.
-// Copyright (c) 2013 adjust GmbH. All rights reserved.
-// See the file MIT-LICENSE for copying permission.
-//
-
-package com.adjust.sdk;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-
-import org.json.JSONObject;
-
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import static com.adjust.sdk.Constants.ACTIVITY_STATE_FILENAME;
-import static com.adjust.sdk.Constants.ATTRIBUTION_FILENAME;
-import static com.adjust.sdk.Constants.LOGTAG;
-
-public class ActivityHandler extends HandlerThread implements IActivityHandler {
-
- private static long TIMER_INTERVAL;
- private static long TIMER_START;
- private static long SESSION_INTERVAL;
- private static long SUBSESSION_INTERVAL;
- private static final String TIME_TRAVEL = "Time travel!";
- private static final String ADJUST_PREFIX = "adjust_";
- private static final String ACTIVITY_STATE_NAME = "Activity state";
- private static final String ATTRIBUTION_NAME = "Attribution";
-
- private SessionHandler sessionHandler;
- private IPackageHandler packageHandler;
- private ActivityState activityState;
- private ILogger logger;
- private static ScheduledExecutorService timer;
- private boolean enabled;
- private boolean offline;
-
- private DeviceInfo deviceInfo;
- private AdjustConfig adjustConfig; // always valid after construction
- private AdjustAttribution attribution;
- private IAttributionHandler attributionHandler;
-
- private ActivityHandler(AdjustConfig adjustConfig) {
- super(LOGTAG, MIN_PRIORITY);
- setDaemon(true);
- start();
-
- logger = AdjustFactory.getLogger();
- sessionHandler = new SessionHandler(getLooper(), this);
- enabled = true;
- init(adjustConfig);
-
- Message message = Message.obtain();
- message.arg1 = SessionHandler.INIT;
- sessionHandler.sendMessage(message);
- }
-
- @Override
- public void init(AdjustConfig adjustConfig) {
- this.adjustConfig = adjustConfig;
- }
-
- public static ActivityHandler getInstance(AdjustConfig adjustConfig) {
- if (adjustConfig == null) {
- AdjustFactory.getLogger().error("AdjustConfig missing");
- return null;
- }
-
- if (!adjustConfig.isValid()) {
- AdjustFactory.getLogger().error("AdjustConfig not initialized correctly");
- return null;
- }
-
- ActivityHandler activityHandler = new ActivityHandler(adjustConfig);
- return activityHandler;
- }
-
- @Override
- public void trackSubsessionStart() {
- Message message = Message.obtain();
- message.arg1 = SessionHandler.START;
- sessionHandler.sendMessage(message);
- }
-
- @Override
- public void trackSubsessionEnd() {
- Message message = Message.obtain();
- message.arg1 = SessionHandler.END;
- sessionHandler.sendMessage(message);
- }
-
- @Override
- public void trackEvent(AdjustEvent event) {
- Message message = Message.obtain();
- message.arg1 = SessionHandler.EVENT;
- message.obj = event;
- sessionHandler.sendMessage(message);
- }
-
- @Override
- public void finishedTrackingActivity(JSONObject jsonResponse) {
- if (jsonResponse == null) {
- return;
- }
-
- Message message = Message.obtain();
- message.arg1 = SessionHandler.FINISH_TRACKING;
- message.obj = jsonResponse;
- sessionHandler.sendMessage(message);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- if (enabled == this.enabled) {
- if (enabled) {
- logger.debug("Adjust already enabled");
- } else {
- logger.debug("Adjust already disabled");
- }
- return;
- }
- this.enabled = enabled;
- if (activityState != null) {
- activityState.enabled = enabled;
- }
- if (enabled) {
- if (toPause()) {
- logger.info("Package and attribution handler remain paused due to the SDK is offline");
- } else {
- logger.info("Resuming package handler and attribution handler to enabled the SDK");
- }
- trackSubsessionStart();
- } else {
- logger.info("Pausing package handler and attribution handler to disable the SDK");
- trackSubsessionEnd();
- }
- }
-
- @Override
- public void setOfflineMode(boolean offline) {
- if (offline == this.offline) {
- if (offline) {
- logger.debug("Adjust already in offline mode");
- } else {
- logger.debug("Adjust already in online mode");
- }
- return;
- }
- this.offline = offline;
- if (offline) {
- logger.info("Pausing package and attribution handler to put in offline mode");
- } else {
- if (toPause()) {
- logger.info("Package and attribution handler remain paused because the SDK is disabled");
- } else {
- logger.info("Resuming package handler and attribution handler to put in online mode");
- }
- }
- updateStatus();
- }
-
- @Override
- public boolean isEnabled() {
- if (activityState != null) {
- return activityState.enabled;
- } else {
- return enabled;
- }
- }
-
- @Override
- public void readOpenUrl(Uri url, long clickTime) {
- Message message = Message.obtain();
- message.arg1 = SessionHandler.DEEP_LINK;
- UrlClickTime urlClickTime = new UrlClickTime(url, clickTime);
- message.obj = urlClickTime;
- sessionHandler.sendMessage(message);
- }
-
- @Override
- public boolean tryUpdateAttribution(AdjustAttribution attribution) {
- if (attribution == null) return false;
-
- if (attribution.equals(this.attribution)) {
- return false;
- }
-
- saveAttribution(attribution);
- launchAttributionListener();
- return true;
- }
-
- private void saveAttribution(AdjustAttribution attribution) {
- this.attribution = attribution;
- writeAttribution();
- }
-
- private void launchAttributionListener() {
- if (adjustConfig.onAttributionChangedListener == null) {
- return;
- }
- Handler handler = new Handler(adjustConfig.context.getMainLooper());
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- adjustConfig.onAttributionChangedListener.onAttributionChanged(attribution);
- }
- };
- handler.post(runnable);
- }
-
- @Override
- public void setAskingAttribution(boolean askingAttribution) {
- activityState.askingAttribution = askingAttribution;
- writeActivityState();
- }
-
- @Override
- public ActivityPackage getAttributionPackage() {
- long now = System.currentTimeMillis();
- PackageBuilder attributionBuilder = new PackageBuilder(adjustConfig,
- deviceInfo,
- activityState,
- now);
- return attributionBuilder.buildAttributionPackage();
- }
-
- @Override
- public void sendReferrer(String referrer, long clickTime) {
- Message message = Message.obtain();
- message.arg1 = SessionHandler.SEND_REFERRER;
- ReferrerClickTime referrerClickTime = new ReferrerClickTime(referrer, clickTime);
- message.obj = referrerClickTime;
- sessionHandler.sendMessage(message);
- }
-
- private class UrlClickTime {
- Uri url;
- long clickTime;
-
- UrlClickTime(Uri url, long clickTime) {
- this.url = url;
- this.clickTime = clickTime;
- }
- }
-
- private class ReferrerClickTime {
- String referrer;
- long clickTime;
-
- ReferrerClickTime(String referrer, long clickTime) {
- this.referrer = referrer;
- this.clickTime = clickTime;
- }
- }
-
- private void updateStatus() {
- Message message = Message.obtain();
- message.arg1 = SessionHandler.UPDATE_STATUS;
- sessionHandler.sendMessage(message);
- }
-
- private static final class SessionHandler extends Handler {
- private static final int BASE_ADDRESS = 72630;
- private static final int INIT = BASE_ADDRESS + 1;
- private static final int START = BASE_ADDRESS + 2;
- private static final int END = BASE_ADDRESS + 3;
- private static final int EVENT = BASE_ADDRESS + 4;
- private static final int FINISH_TRACKING = BASE_ADDRESS + 5;
- private static final int DEEP_LINK = BASE_ADDRESS + 6;
- private static final int SEND_REFERRER = BASE_ADDRESS + 7;
- private static final int UPDATE_STATUS = BASE_ADDRESS + 8;
-
- private final WeakReference<ActivityHandler> sessionHandlerReference;
-
- protected SessionHandler(Looper looper, ActivityHandler sessionHandler) {
- super(looper);
- this.sessionHandlerReference = new WeakReference<ActivityHandler>(sessionHandler);
- }
-
- @Override
- public void handleMessage(Message message) {
- super.handleMessage(message);
-
- ActivityHandler sessionHandler = sessionHandlerReference.get();
- if (sessionHandler == null) {
- return;
- }
-
- switch (message.arg1) {
- case INIT:
- sessionHandler.initInternal();
- break;
- case START:
- sessionHandler.startInternal();
- break;
- case END:
- sessionHandler.endInternal();
- break;
- case EVENT:
- AdjustEvent event = (AdjustEvent) message.obj;
- sessionHandler.trackEventInternal(event);
- break;
- case FINISH_TRACKING:
- JSONObject jsonResponse = (JSONObject) message.obj;
- sessionHandler.finishedTrackingActivityInternal(jsonResponse);
- break;
- case DEEP_LINK:
- UrlClickTime urlClickTime = (UrlClickTime) message.obj;
- sessionHandler.readOpenUrlInternal(urlClickTime.url, urlClickTime.clickTime);
- break;
- case SEND_REFERRER:
- ReferrerClickTime referrerClickTime = (ReferrerClickTime) message.obj;
- sessionHandler.sendReferrerInternal(referrerClickTime.referrer, referrerClickTime.clickTime);
- break;
- case UPDATE_STATUS:
- sessionHandler.updateStatusInternal();
- break;
- }
- }
- }
-
- private void initInternal() {
- TIMER_INTERVAL = AdjustFactory.getTimerInterval();
- TIMER_START = AdjustFactory.getTimerStart();
- SESSION_INTERVAL = AdjustFactory.getSessionInterval();
- SUBSESSION_INTERVAL = AdjustFactory.getSubsessionInterval();
-
- deviceInfo = new DeviceInfo(adjustConfig.context, adjustConfig.sdkPrefix);
-
- if (adjustConfig.environment == AdjustConfig.ENVIRONMENT_PRODUCTION) {
- logger.setLogLevel(LogLevel.ASSERT);
- } else {
- logger.setLogLevel(adjustConfig.logLevel);
- }
-
- if (adjustConfig.eventBufferingEnabled) {
- logger.info("Event buffering is enabled");
- }
-
- String playAdId = Util.getPlayAdId(adjustConfig.context);
- if (playAdId == null) {
- logger.info("Unable to get Google Play Services Advertising ID at start time");
- }
-
- if (adjustConfig.defaultTracker != null) {
- logger.info("Default tracker: '%s'", adjustConfig.defaultTracker);
- }
-
- if (adjustConfig.referrer != null) {
- sendReferrer(adjustConfig.referrer, adjustConfig.referrerClickTime); // send to background queue to make sure that activityState is valid
- }
-
- readAttribution();
- readActivityState();
-
- packageHandler = AdjustFactory.getPackageHandler(this, adjustConfig.context, toPause());
-
- startInternal();
- }
-
- private void startInternal() {
- // it shouldn't start if it was disabled after a first session
- if (activityState != null
- && !activityState.enabled) {
- return;
- }
-
- updateStatusInternal();
-
- processSession();
-
- checkAttributionState();
-
- startTimer();
- }
-
- private void processSession() {
- long now = System.currentTimeMillis();
-
- // very first session
- if (activityState == null) {
- activityState = new ActivityState();
- activityState.sessionCount = 1; // this is the first session
-
- transferSessionPackage(now);
- activityState.resetSessionAttributes(now);
- activityState.enabled = this.enabled;
- writeActivityState();
- return;
- }
-
- long lastInterval = now - activityState.lastActivity;
-
- if (lastInterval < 0) {
- logger.error(TIME_TRAVEL);
- activityState.lastActivity = now;
- writeActivityState();
- return;
- }
-
- // new session
- if (lastInterval > SESSION_INTERVAL) {
- activityState.sessionCount++;
- activityState.lastInterval = lastInterval;
-
- transferSessionPackage(now);
- activityState.resetSessionAttributes(now);
- writeActivityState();
- return;
- }
-
- // new subsession
- if (lastInterval > SUBSESSION_INTERVAL) {
- activityState.subsessionCount++;
- activityState.sessionLength += lastInterval;
- activityState.lastActivity = now;
- writeActivityState();
- logger.info("Started subsession %d of session %d",
- activityState.subsessionCount,
- activityState.sessionCount);
- }
- }
-
- private void checkAttributionState() {
- // if there is no attribution saved, or there is one being asked
- if (attribution == null || activityState.askingAttribution) {
- getAttributionHandler().getAttribution();
- }
- }
-
- private void endInternal() {
- packageHandler.pauseSending();
- getAttributionHandler().pauseSending();
- stopTimer();
- if (updateActivityState(System.currentTimeMillis())) {
- writeActivityState();
- }
- }
-
- private void trackEventInternal(AdjustEvent event) {
- if (!checkEvent(event)) return;
- if (!activityState.enabled) return;
-
- long now = System.currentTimeMillis();
-
- activityState.eventCount++;
- updateActivityState(now);
-
- PackageBuilder eventBuilder = new PackageBuilder(adjustConfig, deviceInfo, activityState, now);
- ActivityPackage eventPackage = eventBuilder.buildEventPackage(event);
- packageHandler.addPackage(eventPackage);
-
- if (adjustConfig.eventBufferingEnabled) {
- logger.info("Buffered event %s", eventPackage.getSuffix());
- } else {
- packageHandler.sendFirstPackage();
- }
-
- writeActivityState();
- }
-
- private void finishedTrackingActivityInternal(JSONObject jsonResponse) {
- if (jsonResponse == null) {
- return;
- }
-
- String deeplink = jsonResponse.optString("deeplink", null);
- launchDeeplinkMain(deeplink);
- getAttributionHandler().checkAttribution(jsonResponse);
- }
-
- private void sendReferrerInternal(String referrer, long clickTime) {
- ActivityPackage clickPackage = buildQueryStringClickPackage(referrer,
- "reftag",
- clickTime);
- if (clickPackage == null) {
- return;
- }
-
- getAttributionHandler().getAttribution();
-
- packageHandler.sendClickPackage(clickPackage);
- }
-
- private void readOpenUrlInternal(Uri url, long clickTime) {
- if (url == null) {
- return;
- }
-
- String queryString = url.getQuery();
-
- ActivityPackage clickPackage = buildQueryStringClickPackage(queryString, "deeplink", clickTime);
- if (clickPackage == null) {
- return;
- }
-
- getAttributionHandler().getAttribution();
-
- packageHandler.sendClickPackage(clickPackage);
- }
-
- private ActivityPackage buildQueryStringClickPackage(String queryString, String source, long clickTime) {
- if (queryString == null) {
- return null;
- }
-
- long now = System.currentTimeMillis();
- Map<String, String> queryStringParameters = new HashMap<String, String>();
- AdjustAttribution queryStringAttribution = new AdjustAttribution();
- boolean hasAdjustTags = false;
-
- String[] queryPairs = queryString.split("&");
- for (String pair : queryPairs) {
- if (readQueryString(pair, queryStringParameters, queryStringAttribution)) {
- hasAdjustTags = true;
- }
- }
-
- if (!hasAdjustTags) {
- return null;
- }
-
- String reftag = queryStringParameters.remove("reftag");
-
- PackageBuilder builder = new PackageBuilder(adjustConfig, deviceInfo, activityState, now);
- builder.extraParameters = queryStringParameters;
- builder.attribution = queryStringAttribution;
- builder.reftag = reftag;
- ActivityPackage clickPackage = builder.buildClickPackage(source, clickTime);
- return clickPackage;
- }
-
- private boolean readQueryString(String queryString,
- Map<String, String> extraParameters,
- AdjustAttribution queryStringAttribution) {
- String[] pairComponents = queryString.split("=");
- if (pairComponents.length != 2) return false;
-
- String key = pairComponents[0];
- if (!key.startsWith(ADJUST_PREFIX)) return false;
-
- String value = pairComponents[1];
- if (value.length() == 0) return false;
-
- String keyWOutPrefix = key.substring(ADJUST_PREFIX.length());
- if (keyWOutPrefix.length() == 0) return false;
-
- if (!trySetAttribution(queryStringAttribution, keyWOutPrefix, value)) {
- extraParameters.put(keyWOutPrefix, value);
- }
-
- return true;
- }
-
- private boolean trySetAttribution(AdjustAttribution queryStringAttribution,
- String key,
- String value) {
- if (key.equals("tracker")) {
- queryStringAttribution.trackerName = value;
- return true;
- }
-
- if (key.equals("campaign")) {
- queryStringAttribution.campaign = value;
- return true;
- }
-
- if (key.equals("adgroup")) {
- queryStringAttribution.adgroup = value;
- return true;
- }
-
- if (key.equals("creative")) {
- queryStringAttribution.creative = value;
- return true;
- }
-
- return false;
- }
-
- private void updateStatusInternal() {
- updateAttributionHandlerStatus();
- updatePackageHandlerStatus();
- }
-
- private void updateAttributionHandlerStatus() {
- if (attributionHandler == null) {
- return;
- }
- if (toPause()) {
- attributionHandler.pauseSending();
- } else {
- attributionHandler.resumeSending();
- }
- }
-
- private void updatePackageHandlerStatus() {
- if (packageHandler == null) {
- return;
- }
- if (toPause()) {
- packageHandler.pauseSending();
- } else {
- packageHandler.resumeSending();
- }
- }
-
- private void launchDeeplinkMain(String deeplink) {
- if (deeplink == null) return;
-
- Uri location = Uri.parse(deeplink);
- Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
- mapIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- // Verify it resolves
- PackageManager packageManager = adjustConfig.context.getPackageManager();
- List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
- boolean isIntentSafe = activities.size() > 0;
-
- // Start an activity if it's safe
- if (!isIntentSafe) {
- logger.error("Unable to open deep link (%s)", deeplink);
- return;
- }
-
- logger.info("Open deep link (%s)", deeplink);
- adjustConfig.context.startActivity(mapIntent);
- }
-
- private boolean updateActivityState(long now) {
- long lastInterval = now - activityState.lastActivity;
- // ignore late updates
- if (lastInterval > SESSION_INTERVAL) {
- return false;
- }
- activityState.lastActivity = now;
-
- if (lastInterval < 0) {
- logger.error(TIME_TRAVEL);
- } else {
- activityState.sessionLength += lastInterval;
- activityState.timeSpent += lastInterval;
- }
- return true;
- }
-
- public static boolean deleteActivityState(Context context) {
- return context.deleteFile(ACTIVITY_STATE_FILENAME);
- }
-
- public static boolean deleteAttribution(Context context) {
- return context.deleteFile(ATTRIBUTION_FILENAME);
- }
-
- private void transferSessionPackage(long now) {
- PackageBuilder builder = new PackageBuilder(adjustConfig, deviceInfo, activityState, now);
- ActivityPackage sessionPackage = builder.buildSessionPackage();
- packageHandler.addPackage(sessionPackage);
- packageHandler.sendFirstPackage();
- }
-
- private void startTimer() {
- stopTimer();
-
- if (!activityState.enabled) {
- return;
- }
- timer = Executors.newSingleThreadScheduledExecutor();
- timer.scheduleWithFixedDelay(new Runnable() {
- @Override
- public void run() {
- timerFired();
- }
- }, TIMER_START, TIMER_INTERVAL, TimeUnit.MILLISECONDS);
- }
-
- private void stopTimer() {
- if (timer != null) {
- timer.shutdown();
- timer = null;
- }
- }
-
- private void timerFired() {
- if (!activityState.enabled) {
- stopTimer();
- return;
- }
-
- packageHandler.sendFirstPackage();
-
- if (updateActivityState(System.currentTimeMillis())) {
- writeActivityState();
- }
- }
-
- private void readActivityState() {
- try {
- /**
- * Mozilla:
- * readObject is a generic object, and can therefore return arbitrary generic objects
- * that might not match the expected type. Therefore there will be an implicit cast
- * here, which can fail. Therefore we have to add the catch (ClassCastException)
- * Note: this has been fixed in upstream, we only need this for the version we are still shipping.
- */
- activityState = Util.readObject(adjustConfig.context, ACTIVITY_STATE_FILENAME, ACTIVITY_STATE_NAME);
- } catch (ClassCastException e) {
- activityState = null;
- }
- }
-
- private void readAttribution() {
- try {
- /**
- * Mozilla: (same as in readActivityState() )
- * readObject is a generic object, and can therefore return arbitrary generic objects
- * that might not match the expected type. Therefore there will be an implicit cast
- * here, which can fail. Therefore we have to add the catch (ClassCastException)
- * Note: this has been fixed in upstream, we only need this for the version we are still shipping.
- */
- attribution = Util.readObject(adjustConfig.context, ATTRIBUTION_FILENAME, ATTRIBUTION_NAME);
- } catch (ClassCastException e) {
- activityState = null;
- }
- }
-
- private void writeActivityState() {
- Util.writeObject(activityState, adjustConfig.context, ACTIVITY_STATE_FILENAME, ACTIVITY_STATE_NAME);
- }
-
- private void writeAttribution() {
- Util.writeObject(attribution, adjustConfig.context, ATTRIBUTION_FILENAME, ATTRIBUTION_NAME);
- }
-
- private boolean checkEvent(AdjustEvent event) {
- if (event == null) {
- logger.error("Event missing");
- return false;
- }
-
- if (!event.isValid()) {
- logger.error("Event not initialized correctly");
- return false;
- }
-
- return true;
- }
-
- // lazy initialization to prevent null activity state before first session
- private IAttributionHandler getAttributionHandler() {
- if (attributionHandler == null) {
- ActivityPackage attributionPackage = getAttributionPackage();
- attributionHandler = AdjustFactory.getAttributionHandler(this,
- attributionPackage,
- toPause());
- }
- return attributionHandler;
- }
-
- private boolean toPause() {
- return offline || !isEnabled();
- }
-}