diff options
Diffstat (limited to 'mobile/android/thirdparty/com')
73 files changed, 0 insertions, 10057 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(); - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/ActivityKind.java b/mobile/android/thirdparty/com/adjust/sdk/ActivityKind.java deleted file mode 100644 index a255b83a9..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/ActivityKind.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.adjust.sdk; - -public enum ActivityKind { - UNKNOWN, SESSION, EVENT, CLICK, ATTRIBUTION; - - public static ActivityKind fromString(String string) { - if ("session".equals(string)) { - return SESSION; - } else if ("event".equals(string)) { - return EVENT; - } else if ("click".equals(string)) { - return CLICK; - } else if ("attribution".equals(string)) { - return ATTRIBUTION; - } else { - return UNKNOWN; - } - } - - @Override - public String toString() { - switch (this) { - case SESSION: - return "session"; - case EVENT: - return "event"; - case CLICK: - return "click"; - case ATTRIBUTION: - return "attribution"; - default: - return "unknown"; - } - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/ActivityPackage.java b/mobile/android/thirdparty/com/adjust/sdk/ActivityPackage.java deleted file mode 100644 index 27ab969fd..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/ActivityPackage.java +++ /dev/null @@ -1,100 +0,0 @@ -// -// ActivityPackage.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 java.io.Serializable; -import java.util.Map; - -public class ActivityPackage implements Serializable { - private static final long serialVersionUID = -35935556512024097L; - - // data - private String path; - private String clientSdk; - private Map<String, String> parameters; - - // logs - private ActivityKind activityKind; - private String suffix; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getClientSdk() { - return clientSdk; - } - - public void setClientSdk(String clientSdk) { - this.clientSdk = clientSdk; - } - - public Map<String, String> getParameters() { - return parameters; - } - - public void setParameters(Map<String, String> parameters) { - this.parameters = parameters; - } - - public ActivityKind getActivityKind() { - return activityKind; - } - - public void setActivityKind(ActivityKind activityKind) { - this.activityKind = activityKind; - } - - public String getSuffix() { - return suffix; - } - - public void setSuffix(String suffix) { - this.suffix = suffix; - } - - public String toString() { - return String.format("%s%s", activityKind.toString(), suffix); - } - - public String getExtendedString() { - StringBuilder builder = new StringBuilder(); - builder.append(String.format("Path: %s\n", path)); - builder.append(String.format("ClientSdk: %s\n", clientSdk)); - - if (parameters != null) { - builder.append("Parameters:"); - for (Map.Entry<String, String> entry : parameters.entrySet()) { - builder.append(String.format("\n\t%-16s %s", entry.getKey(), entry.getValue())); - } - } - return builder.toString(); - } - - protected String getSuccessMessage() { - try { - return String.format("Tracked %s%s", activityKind.toString(), suffix); - } catch (NullPointerException e) { - return "Tracked ???"; - } - } - - protected String getFailureMessage() { - try { - return String.format("Failed to track %s%s", activityKind.toString(), suffix); - } catch (NullPointerException e) { - return "Failed to track ???"; - } - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/ActivityState.java b/mobile/android/thirdparty/com/adjust/sdk/ActivityState.java deleted file mode 100644 index 41ad2ca3b..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/ActivityState.java +++ /dev/null @@ -1,151 +0,0 @@ -// -// ActivityState.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 java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectInputStream.GetField; -import java.io.Serializable; -import java.util.Calendar; -import java.util.Locale; - -public class ActivityState implements Serializable, Cloneable { - private static final long serialVersionUID = 9039439291143138148L; - private transient String readErrorMessage = "Unable to read '%s' field in migration device with message (%s)"; - private transient ILogger logger; - - // persistent data - protected String uuid; - protected boolean enabled; - protected boolean askingAttribution; - - // global counters - protected int eventCount; - protected int sessionCount; - - // session attributes - protected int subsessionCount; - protected long sessionLength; // all durations in milliseconds - protected long timeSpent; - protected long lastActivity; // all times in milliseconds since 1970 - - protected long lastInterval; - - protected ActivityState() { - logger = AdjustFactory.getLogger(); - // create UUID for new devices - uuid = Util.createUuid(); - enabled = true; - askingAttribution = false; - - eventCount = 0; // no events yet - sessionCount = 0; // the first session just started - subsessionCount = -1; // we don't know how many subsessions this first session will have - sessionLength = -1; // same for session length and time spent - timeSpent = -1; // this information will be collected and attached to the next session - lastActivity = -1; - lastInterval = -1; - } - - protected void resetSessionAttributes(long now) { - subsessionCount = 1; // first subsession - sessionLength = 0; // no session length yet - timeSpent = 0; // no time spent yet - lastActivity = now; - lastInterval = -1; - } - - @Override - public String toString() { - return String.format(Locale.US, - "ec:%d sc:%d ssc:%d sl:%.1f ts:%.1f la:%s uuid:%s", - eventCount, sessionCount, subsessionCount, - sessionLength / 1000.0, timeSpent / 1000.0, - stamp(lastActivity), uuid); - } - - @Override - public ActivityState clone() { - try { - return (ActivityState) super.clone(); - } catch (CloneNotSupportedException e) { - return null; - } - } - - - private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { - GetField fields = stream.readFields(); - - eventCount = readIntField(fields, "eventCount", 0); - sessionCount = readIntField(fields, "sessionCount", 0); - subsessionCount = readIntField(fields, "subsessionCount", -1); - sessionLength = readLongField(fields, "sessionLength", -1l); - timeSpent = readLongField(fields, "timeSpent", -1l); - lastActivity = readLongField(fields, "lastActivity", -1l); - lastInterval = readLongField(fields, "lastInterval", -1l); - - // new fields - uuid = readStringField(fields, "uuid", null); - enabled = readBooleanField(fields, "enabled", true); - askingAttribution = readBooleanField(fields, "askingAttribution", false); - - // create UUID for migrating devices - if (uuid == null) { - uuid = Util.createUuid(); - } - } - - private String readStringField(GetField fields, String name, String defaultValue) { - try { - return (String) fields.get(name, defaultValue); - } catch (Exception e) { - logger.debug(readErrorMessage, name, e.getMessage()); - return defaultValue; - } - } - - private boolean readBooleanField(GetField fields, String name, boolean defaultValue) { - try { - return fields.get(name, defaultValue); - } catch (Exception e) { - logger.debug(readErrorMessage, name, e.getMessage()); - return defaultValue; - } - } - - private int readIntField(GetField fields, String name, int defaultValue) { - try { - return fields.get(name, defaultValue); - } catch (Exception e) { - logger.debug(readErrorMessage, name, e.getMessage()); - return defaultValue; - } - } - - private long readLongField(GetField fields, String name, long defaultValue) { - try { - return fields.get(name, defaultValue); - } catch (Exception e) { - logger.debug(readErrorMessage, name, e.getMessage()); - return defaultValue; - } - } - - private static String stamp(long dateMillis) { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(dateMillis); - return String.format(Locale.US, - "%02d:%02d:%02d", - calendar.HOUR_OF_DAY, - calendar.MINUTE, - calendar.SECOND); - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/Adjust.java b/mobile/android/thirdparty/com/adjust/sdk/Adjust.java deleted file mode 100644 index 3b81a077b..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/Adjust.java +++ /dev/null @@ -1,79 +0,0 @@ -// -// Adjust.java -// Adjust -// -// Created by Christian Wellenbrock on 2012-10-11. -// Copyright (c) 2012-2014 adjust GmbH. All rights reserved. -// See the file MIT-LICENSE for copying permission. -// - -package com.adjust.sdk; - -import android.net.Uri; - -/** - * The main interface to Adjust. - * Use the methods of this class to tell Adjust about the usage of your app. - * See the README for details. - */ -public class Adjust { - - private static AdjustInstance defaultInstance; - - private Adjust() { - } - - public static synchronized AdjustInstance getDefaultInstance() { - if (defaultInstance == null) { - defaultInstance = new AdjustInstance(); - } - return defaultInstance; - } - - public static void onCreate(AdjustConfig adjustConfig) { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.onCreate(adjustConfig); - } - - public static void trackEvent(AdjustEvent event) { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.trackEvent(event); - } - - public static void onResume() { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.onResume(); - } - - public static void onPause() { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.onPause(); - } - - public static void setEnabled(boolean enabled) { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.setEnabled(enabled); - } - - public static boolean isEnabled() { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - return adjustInstance.isEnabled(); - } - - public static void appWillOpenUrl(Uri url) { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.appWillOpenUrl(url); - } - - public static void setReferrer(String referrer) { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.sendReferrer(referrer); - } - - public static void setOfflineMode(boolean enabled) { - AdjustInstance adjustInstance = Adjust.getDefaultInstance(); - adjustInstance.setOfflineMode(enabled); - } -} - - diff --git a/mobile/android/thirdparty/com/adjust/sdk/AdjustAttribution.java b/mobile/android/thirdparty/com/adjust/sdk/AdjustAttribution.java deleted file mode 100644 index 4e3abb017..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/AdjustAttribution.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.adjust.sdk; - -import org.json.JSONObject; - -import java.io.Serializable; - -/** - * Created by pfms on 07/11/14. - */ -public class AdjustAttribution implements Serializable { - private static final long serialVersionUID = 1L; - - public String trackerToken; - public String trackerName; - public String network; - public String campaign; - public String adgroup; - public String creative; - - public static AdjustAttribution fromJson(JSONObject jsonObject) { - if (jsonObject == null) return null; - - AdjustAttribution attribution = new AdjustAttribution(); - - attribution.trackerToken = jsonObject.optString("tracker_token", null); - attribution.trackerName = jsonObject.optString("tracker_name", null); - attribution.network = jsonObject.optString("network", null); - attribution.campaign = jsonObject.optString("campaign", null); - attribution.adgroup = jsonObject.optString("adgroup", null); - attribution.creative = jsonObject.optString("creative", null); - - return attribution; - } - - public boolean equals(Object other) { - if (other == this) return true; - if (other == null) return false; - if (getClass() != other.getClass()) return false; - AdjustAttribution otherAttribution = (AdjustAttribution) other; - - if (!equalString(trackerToken, otherAttribution.trackerToken)) return false; - if (!equalString(trackerName, otherAttribution.trackerName)) return false; - if (!equalString(network, otherAttribution.network)) return false; - if (!equalString(campaign, otherAttribution.campaign)) return false; - if (!equalString(adgroup, otherAttribution.adgroup)) return false; - if (!equalString(creative, otherAttribution.creative)) return false; - return true; - } - - private boolean equalString(String first, String second) { - if (first == null || second == null) { - return first == null && second == null; - } - return first.equals(second); - } - - @Override - public String toString() { - return String.format("tt:%s tn:%s net:%s cam:%s adg:%s cre:%s", - trackerToken, trackerName, network, campaign, adgroup, creative); - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/AdjustConfig.java b/mobile/android/thirdparty/com/adjust/sdk/AdjustConfig.java deleted file mode 100644 index 148a5f670..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/AdjustConfig.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.adjust.sdk; - -import android.content.Context; - -/** - * Created by pfms on 06/11/14. - */ -public class AdjustConfig { - Context context; - String appToken; - String environment; - LogLevel logLevel; - String sdkPrefix; - Boolean eventBufferingEnabled; - String defaultTracker; - OnAttributionChangedListener onAttributionChangedListener; - String referrer; - long referrerClickTime; - Boolean knownDevice; - - public static final String ENVIRONMENT_SANDBOX = "sandbox"; - public static final String ENVIRONMENT_PRODUCTION = "production"; - - public AdjustConfig(Context context, String appToken, String environment) { - if (!isValid(context, appToken, environment)) { - return; - } - - this.context = context.getApplicationContext(); - this.appToken = appToken; - this.environment = environment; - - // default values - this.logLevel = LogLevel.INFO; - this.eventBufferingEnabled = false; - } - - public void setEventBufferingEnabled(Boolean eventBufferingEnabled) { - this.eventBufferingEnabled = eventBufferingEnabled; - } - - public void setLogLevel(LogLevel logLevel) { - this.logLevel = logLevel; - } - - public void setSdkPrefix(String sdkPrefix) { - this.sdkPrefix = sdkPrefix; - } - - public void setDefaultTracker(String defaultTracker) { - this.defaultTracker = defaultTracker; - } - - public void setOnAttributionChangedListener(OnAttributionChangedListener onAttributionChangedListener) { - this.onAttributionChangedListener = onAttributionChangedListener; - } - - public boolean hasListener() { - return onAttributionChangedListener != null; - } - - public boolean isValid() { - return appToken != null; - } - - private boolean isValid(Context context, String appToken, String environment) { - if (!checkAppToken(appToken)) return false; - if (!checkEnvironment(environment)) return false; - if (!checkContext(context)) return false; - - return true; - } - - private static boolean checkContext(Context context) { - ILogger logger = AdjustFactory.getLogger(); - if (context == null) { - logger.error("Missing context"); - return false; - } - - if (!Util.checkPermission(context, android.Manifest.permission.INTERNET)) { - logger.error("Missing permission: INTERNET"); - return false; - } - - return true; - } - - private static boolean checkAppToken(String appToken) { - ILogger logger = AdjustFactory.getLogger(); - if (appToken == null) { - logger.error("Missing App Token."); - return false; - } - - if (appToken.length() != 12) { - logger.error("Malformed App Token '%s'", appToken); - return false; - } - - return true; - } - - private static boolean checkEnvironment(String environment) { - ILogger logger = AdjustFactory.getLogger(); - if (environment == null) { - logger.error("Missing environment"); - return false; - } - - if (environment == AdjustConfig.ENVIRONMENT_SANDBOX) { - logger.Assert("SANDBOX: Adjust is running in Sandbox mode. " + - "Use this setting for testing. " + - "Don't forget to set the environment to `production` before publishing!"); - return true; - } - if (environment == AdjustConfig.ENVIRONMENT_PRODUCTION) { - logger.Assert( - "PRODUCTION: Adjust is running in Production mode. " + - "Use this setting only for the build that you want to publish. " + - "Set the environment to `sandbox` if you want to test your app!"); - return true; - } - - logger.error("Unknown environment '%s'", environment); - return false; - } -}
\ No newline at end of file diff --git a/mobile/android/thirdparty/com/adjust/sdk/AdjustEvent.java b/mobile/android/thirdparty/com/adjust/sdk/AdjustEvent.java deleted file mode 100644 index f03718183..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/AdjustEvent.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.adjust.sdk; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by pfms on 05/11/14. - */ -public class AdjustEvent { - String eventToken; - Double revenue; - String currency; - Map<String, String> callbackParameters; - Map<String, String> partnerParameters; - - private static ILogger logger = AdjustFactory.getLogger(); - - public AdjustEvent(String eventToken) { - if (!checkEventToken(eventToken, logger)) return; - - this.eventToken = eventToken; - } - - public void setRevenue(double revenue, String currency) { - if (!checkRevenue(revenue, currency)) return; - - this.revenue = revenue; - this.currency = currency; - } - - public void addCallbackParameter(String key, String value) { - if (!isValidParameter(key, "key", "Callback")) return; - if (!isValidParameter(value, "value", "Callback")) return; - - if (callbackParameters == null) { - callbackParameters = new HashMap<String, String>(); - } - - String previousValue = callbackParameters.put(key, value); - - if (previousValue != null) { - logger.warn("key %s was overwritten", key); - } - } - - public void addPartnerParameter(String key, String value) { - if (!isValidParameter(key, "key", "Partner")) return; - if (!isValidParameter(value, "value", "Partner")) return; - - if (partnerParameters == null) { - partnerParameters = new HashMap<String, String>(); - } - - String previousValue = partnerParameters.put(key, value); - - if (previousValue != null) { - logger.warn("key %s was overwritten", key); - } - } - - public boolean isValid() { - return eventToken != null; - } - - private static boolean checkEventToken(String eventToken, ILogger logger) { - if (eventToken == null) { - logger.error("Missing Event Token"); - return false; - } - if (eventToken.length() != 6) { - logger.error("Malformed Event Token '%s'", eventToken); - return false; - } - return true; - } - - private boolean checkRevenue(Double revenue, String currency) { - if (revenue != null) { - if (revenue < 0.0) { - logger.error("Invalid amount %.4f", revenue); - return false; - } - - if (currency == null) { - logger.error("Currency must be set with revenue"); - return false; - } - if (currency == "") { - logger.error("Currency is empty"); - return false; - } - - } else if (currency != null) { - logger.error("Revenue must be set with currency"); - return false; - } - return true; - } - - private boolean isValidParameter(String attribute, String attributeType, String parameterName) { - if (attribute == null) { - logger.error("%s parameter %s is missing", parameterName, attributeType); - return false; - } - if (attribute == "") { - logger.error("%s parameter %s is empty", parameterName, attributeType); - return false; - } - - return true; - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/AdjustFactory.java b/mobile/android/thirdparty/com/adjust/sdk/AdjustFactory.java deleted file mode 100644 index 802af6416..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/AdjustFactory.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.adjust.sdk; - -import android.content.Context; - -import ch.boye.httpclientandroidlib.client.HttpClient; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; -import ch.boye.httpclientandroidlib.params.HttpParams; - -public class AdjustFactory { - private static IPackageHandler packageHandler = null; - private static IRequestHandler requestHandler = null; - private static IAttributionHandler attributionHandler = null; - private static IActivityHandler activityHandler = null; - private static ILogger logger = null; - private static HttpClient httpClient = null; - - private static long timerInterval = -1; - private static long timerStart = -1; - private static long sessionInterval = -1; - private static long subsessionInterval = -1; - - public static IPackageHandler getPackageHandler(ActivityHandler activityHandler, - Context context, - boolean startPaused) { - if (packageHandler == null) { - return new PackageHandler(activityHandler, context, startPaused); - } - packageHandler.init(activityHandler, context, startPaused); - return packageHandler; - } - - public static IRequestHandler getRequestHandler(IPackageHandler packageHandler) { - if (requestHandler == null) { - return new RequestHandler(packageHandler); - } - requestHandler.init(packageHandler); - return requestHandler; - } - - public static ILogger getLogger() { - if (logger == null) { - // Logger needs to be "static" to retain the configuration throughout the app - logger = new Logger(); - } - return logger; - } - - public static HttpClient getHttpClient(HttpParams params) { - if (httpClient == null) { - return new DefaultHttpClient(params); - } - return httpClient; - } - - public static long getTimerInterval() { - if (timerInterval == -1) { - return Constants.ONE_MINUTE; - } - return timerInterval; - } - - public static long getTimerStart() { - if (timerStart == -1) { - return 0; - } - return timerStart; - } - - public static long getSessionInterval() { - if (sessionInterval == -1) { - return Constants.THIRTY_MINUTES; - } - return sessionInterval; - } - - public static long getSubsessionInterval() { - if (subsessionInterval == -1) { - return Constants.ONE_SECOND; - } - return subsessionInterval; - } - - public static IActivityHandler getActivityHandler(AdjustConfig config) { - if (activityHandler == null) { - return ActivityHandler.getInstance(config); - } - activityHandler.init(config); - return activityHandler; - } - - public static IAttributionHandler getAttributionHandler(IActivityHandler activityHandler, - ActivityPackage attributionPackage, - boolean startPaused) { - if (attributionHandler == null) { - return new AttributionHandler(activityHandler, attributionPackage, startPaused); - } - attributionHandler.init(activityHandler, attributionPackage, startPaused); - return attributionHandler; - } - - public static void setPackageHandler(IPackageHandler packageHandler) { - AdjustFactory.packageHandler = packageHandler; - } - - public static void setRequestHandler(IRequestHandler requestHandler) { - AdjustFactory.requestHandler = requestHandler; - } - - public static void setLogger(ILogger logger) { - AdjustFactory.logger = logger; - } - - public static void setHttpClient(HttpClient httpClient) { - AdjustFactory.httpClient = httpClient; - } - - public static void setTimerInterval(long timerInterval) { - AdjustFactory.timerInterval = timerInterval; - } - - public static void setTimerStart(long timerStart) { - AdjustFactory.timerStart = timerStart; - } - - public static void setSessionInterval(long sessionInterval) { - AdjustFactory.sessionInterval = sessionInterval; - } - - public static void setSubsessionInterval(long subsessionInterval) { - AdjustFactory.subsessionInterval = subsessionInterval; - } - - public static void setActivityHandler(IActivityHandler activityHandler) { - AdjustFactory.activityHandler = activityHandler; - } - - public static void setAttributionHandler(IAttributionHandler attributionHandler) { - AdjustFactory.attributionHandler = attributionHandler; - } - -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/AdjustInstance.java b/mobile/android/thirdparty/com/adjust/sdk/AdjustInstance.java deleted file mode 100644 index 158fb7ca1..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/AdjustInstance.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.adjust.sdk; - -import android.net.Uri; - -/** - * Created by pfms on 04/12/14. - */ -public class AdjustInstance { - - private String referrer; - private long referrerClickTime; - private ActivityHandler activityHandler; - - private static ILogger getLogger() { - return AdjustFactory.getLogger(); - } - - public void onCreate(AdjustConfig adjustConfig) { - if (activityHandler != null) { - getLogger().error("Adjust already initialized"); - return; - } - - adjustConfig.referrer = this.referrer; - adjustConfig.referrerClickTime = this.referrerClickTime; - - activityHandler = ActivityHandler.getInstance(adjustConfig); - } - - public void trackEvent(AdjustEvent event) { - if (!checkActivityHandler()) return; - activityHandler.trackEvent(event); - } - - public void onResume() { - if (!checkActivityHandler()) return; - activityHandler.trackSubsessionStart(); - } - - public void onPause() { - if (!checkActivityHandler()) return; - activityHandler.trackSubsessionEnd(); - } - - public void setEnabled(boolean enabled) { - if (!checkActivityHandler()) return; - activityHandler.setEnabled(enabled); - } - - public boolean isEnabled() { - if (!checkActivityHandler()) return false; - return activityHandler.isEnabled(); - } - - public void appWillOpenUrl(Uri url) { - if (!checkActivityHandler()) return; - long clickTime = System.currentTimeMillis(); - activityHandler.readOpenUrl(url, clickTime); - } - - public void sendReferrer(String referrer) { - long clickTime = System.currentTimeMillis(); - // sendReferrer might be triggered before Adjust - if (activityHandler == null) { - // save it to inject in the config before launch - this.referrer = referrer; - this.referrerClickTime = clickTime; - } else { - activityHandler.sendReferrer(referrer, clickTime); - } - } - - public void setOfflineMode(boolean enabled) { - if (!checkActivityHandler()) return; - activityHandler.setOfflineMode(enabled); - } - - private boolean checkActivityHandler() { - if (activityHandler == null) { - getLogger().error("Please initialize Adjust by calling 'onCreate' before"); - return false; - } else { - return true; - } - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/AdjustReferrerReceiver.java b/mobile/android/thirdparty/com/adjust/sdk/AdjustReferrerReceiver.java deleted file mode 100644 index cfeecd8d0..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/AdjustReferrerReceiver.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.adjust.sdk; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; - -import static com.adjust.sdk.Constants.ENCODING; -import static com.adjust.sdk.Constants.MALFORMED; -import static com.adjust.sdk.Constants.REFERRER; - -// support multiple BroadcastReceivers for the INSTALL_REFERRER: -// http://blog.appington.com/2012/08/01/giving-credit-for-android-app-installs - -public class AdjustReferrerReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String rawReferrer = intent.getStringExtra(REFERRER); - if (null == rawReferrer) { - return; - } - - String referrer; - try { - referrer = URLDecoder.decode(rawReferrer, ENCODING); - } catch (UnsupportedEncodingException e) { - referrer = MALFORMED; - } - - AdjustInstance adjust = Adjust.getDefaultInstance(); - adjust.sendReferrer(referrer); - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/AttributionHandler.java b/mobile/android/thirdparty/com/adjust/sdk/AttributionHandler.java deleted file mode 100644 index 0d550a83a..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/AttributionHandler.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.adjust.sdk; - -import android.net.Uri; - -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.client.HttpClient; -import ch.boye.httpclientandroidlib.client.methods.HttpGet; -import org.json.JSONObject; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -/** - * Created by pfms on 07/11/14. - */ -public class AttributionHandler implements IAttributionHandler { - private ScheduledExecutorService scheduler; - private IActivityHandler activityHandler; - private ILogger logger; - private ActivityPackage attributionPackage; - private ScheduledFuture waitingTask; - private HttpClient httpClient; - private boolean paused; - - public AttributionHandler(IActivityHandler activityHandler, - ActivityPackage attributionPackage, - boolean startPaused) { - scheduler = Executors.newSingleThreadScheduledExecutor(); - logger = AdjustFactory.getLogger(); - httpClient = Util.getHttpClient(); - init(activityHandler, attributionPackage, startPaused); - } - - @Override - public void init(IActivityHandler activityHandler, - ActivityPackage attributionPackage, - boolean startPaused) { - this.activityHandler = activityHandler; - this.attributionPackage = attributionPackage; - this.paused = startPaused; - } - - @Override - public void getAttribution() { - getAttribution(0); - } - - @Override - public void checkAttribution(final JSONObject jsonResponse) { - scheduler.submit(new Runnable() { - @Override - public void run() { - checkAttributionInternal(jsonResponse); - } - }); - } - - @Override - public void pauseSending() { - paused = true; - } - - @Override - public void resumeSending() { - paused = false; - } - - private void getAttribution(int delayInMilliseconds) { - if (waitingTask != null) { - waitingTask.cancel(false); - } - - if (delayInMilliseconds != 0) { - logger.debug("Waiting to query attribution in %d milliseconds", delayInMilliseconds); - } - - waitingTask = scheduler.schedule(new Runnable() { - @Override - public void run() { - getAttributionInternal(); - } - }, delayInMilliseconds, TimeUnit.MILLISECONDS); - } - - private void checkAttributionInternal(JSONObject jsonResponse) { - if (jsonResponse == null) return; - - JSONObject attributionJson = jsonResponse.optJSONObject("attribution"); - AdjustAttribution attribution = AdjustAttribution.fromJson(attributionJson); - - int timerMilliseconds = jsonResponse.optInt("ask_in", -1); - - // without ask_in attribute - if (timerMilliseconds < 0) { - activityHandler.tryUpdateAttribution(attribution); - - activityHandler.setAskingAttribution(false); - - return; - } - - activityHandler.setAskingAttribution(true); - - getAttribution(timerMilliseconds); - } - - private void getAttributionInternal() { - if (paused) { - logger.debug("Attribution Handler is paused"); - return; - } - logger.verbose("%s", attributionPackage.getExtendedString()); - HttpResponse httpResponse = null; - try { - HttpGet request = getRequest(attributionPackage); - httpResponse = httpClient.execute(request); - } catch (Exception e) { - logger.error("Failed to get attribution (%s)", e.getMessage()); - return; - } - - JSONObject jsonResponse = Util.parseJsonResponse(httpResponse, logger); - - checkAttributionInternal(jsonResponse); - } - - private Uri buildUri(ActivityPackage attributionPackage) { - Uri.Builder uriBuilder = new Uri.Builder(); - - uriBuilder.scheme(Constants.SCHEME); - uriBuilder.authority(Constants.AUTHORITY); - uriBuilder.appendPath(attributionPackage.getPath()); - - for (Map.Entry<String, String> entry : attributionPackage.getParameters().entrySet()) { - uriBuilder.appendQueryParameter(entry.getKey(), entry.getValue()); - } - - return uriBuilder.build(); - } - - private HttpGet getRequest(ActivityPackage attributionPackage) throws URISyntaxException { - HttpGet request = new HttpGet(); - Uri uri = buildUri(attributionPackage); - request.setURI(new URI(uri.toString())); - - request.addHeader("Client-SDK", attributionPackage.getClientSdk()); - - return request; - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/Constants.java b/mobile/android/thirdparty/com/adjust/sdk/Constants.java deleted file mode 100644 index 7a97cb2f4..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/Constants.java +++ /dev/null @@ -1,53 +0,0 @@ -// -// Constants.java -// Adjust -// -// Created by keyboardsurfer on 2013-11-08. -// Copyright (c) 2012-2014 adjust GmbH. All rights reserved. -// See the file MIT-LICENSE for copying permission. -// - -package com.adjust.sdk; - -import java.util.Arrays; -import java.util.List; - -/** - * @author keyboardsurfer - * @since 8.11.13 - */ -public interface Constants { - int ONE_SECOND = 1000; - int ONE_MINUTE = 60 * ONE_SECOND; - int THIRTY_MINUTES = 30 * ONE_MINUTE; - - int CONNECTION_TIMEOUT = Constants.ONE_MINUTE; - int SOCKET_TIMEOUT = Constants.ONE_MINUTE; - - String BASE_URL = "https://app.adjust.com"; - String SCHEME = "https"; - String AUTHORITY = "app.adjust.com"; - String CLIENT_SDK = "android4.0.0"; - String LOGTAG = "Adjust"; - - String ACTIVITY_STATE_FILENAME = "AdjustIoActivityState"; - String ATTRIBUTION_FILENAME = "AdjustAttribution"; - - String MALFORMED = "malformed"; - String SMALL = "small"; - String NORMAL = "normal"; - String LONG = "long"; - String LARGE = "large"; - String XLARGE = "xlarge"; - String LOW = "low"; - String MEDIUM = "medium"; - String HIGH = "high"; - String REFERRER = "referrer"; - - String ENCODING = "UTF-8"; - String MD5 = "MD5"; - String SHA1 = "SHA-1"; - - // List of known plugins, possibly not active - List<String> PLUGINS = Arrays.asList(); -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/DeviceInfo.java b/mobile/android/thirdparty/com/adjust/sdk/DeviceInfo.java deleted file mode 100644 index 5cccb77f4..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/DeviceInfo.java +++ /dev/null @@ -1,290 +0,0 @@ -package com.adjust.sdk; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.util.DisplayMetrics; - -import java.math.BigInteger; -import java.security.MessageDigest; -import java.util.Locale; -import java.util.Map; - -import static com.adjust.sdk.Constants.ENCODING; -import static com.adjust.sdk.Constants.HIGH; -import static com.adjust.sdk.Constants.LARGE; -import static com.adjust.sdk.Constants.LONG; -import static com.adjust.sdk.Constants.LOW; -import static com.adjust.sdk.Constants.MD5; -import static com.adjust.sdk.Constants.MEDIUM; -import static com.adjust.sdk.Constants.NORMAL; -import static com.adjust.sdk.Constants.SHA1; -import static com.adjust.sdk.Constants.SMALL; -import static com.adjust.sdk.Constants.XLARGE; - -/** - * Created by pfms on 06/11/14. - */ -class DeviceInfo { - String macSha1; - String macShortMd5; - String androidId; - String fbAttributionId; - String clientSdk; - String packageName; - String appVersion; - String deviceType; - String deviceName; - String deviceManufacturer; - String osName; - String osVersion; - String language; - String country; - String screenSize; - String screenFormat; - String screenDensity; - String displayWidth; - String displayHeight; - Map<String, String> pluginKeys; - - DeviceInfo(Context context, String sdkPrefix) { - Resources resources = context.getResources(); - DisplayMetrics displayMetrics = resources.getDisplayMetrics(); - Configuration configuration = resources.getConfiguration(); - Locale locale = configuration.locale; - int screenLayout = configuration.screenLayout; - boolean isGooglePlayServicesAvailable = Reflection.isGooglePlayServicesAvailable(context); - String macAddress = getMacAddress(context, isGooglePlayServicesAvailable); - - packageName = getPackageName(context); - appVersion = getAppVersion(context); - deviceType = getDeviceType(screenLayout); - deviceName = getDeviceName(); - deviceManufacturer = getDeviceManufacturer(); - osName = getOsName(); - osVersion = getOsVersion(); - language = getLanguage(locale); - country = getCountry(locale); - screenSize = getScreenSize(screenLayout); - screenFormat = getScreenFormat(screenLayout); - screenDensity = getScreenDensity(displayMetrics); - displayWidth = getDisplayWidth(displayMetrics); - displayHeight = getDisplayHeight(displayMetrics); - clientSdk = getClientSdk(sdkPrefix); - androidId = getAndroidId(context, isGooglePlayServicesAvailable); - fbAttributionId = getFacebookAttributionId(context); - pluginKeys = Reflection.getPluginKeys(context); - macSha1 = getMacSha1(macAddress); - macShortMd5 = getMacShortMd5(macAddress); - } - - private String getMacAddress(Context context, boolean isGooglePlayServicesAvailable) { - if (!isGooglePlayServicesAvailable) { - if (!!Util.checkPermission(context, android.Manifest.permission.ACCESS_WIFI_STATE)) { - AdjustFactory.getLogger().warn("Missing permission: ACCESS_WIFI_STATE"); - } - return Reflection.getMacAddress(context); - } else { - return null; - } - } - - private String getPackageName(Context context) { - return context.getPackageName(); - } - - private String getAppVersion(Context context) { - try { - PackageManager packageManager = context.getPackageManager(); - String name = context.getPackageName(); - PackageInfo info = packageManager.getPackageInfo(name, 0); - return info.versionName; - } catch (PackageManager.NameNotFoundException e) { - return null; - } - } - - private String getDeviceType(int screenLayout) { - int screenSize = screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; - - switch (screenSize) { - case Configuration.SCREENLAYOUT_SIZE_SMALL: - case Configuration.SCREENLAYOUT_SIZE_NORMAL: - return "phone"; - case Configuration.SCREENLAYOUT_SIZE_LARGE: - case 4: - return "tablet"; - default: - return null; - } - } - - private String getDeviceName() { - return Build.MODEL; - } - - private String getDeviceManufacturer() { - return Build.MANUFACTURER; - } - - private String getOsName() { - return "android"; - } - - private String getOsVersion() { - return osVersion = "" + Build.VERSION.SDK_INT; - } - - private String getLanguage(Locale locale) { - return locale.getLanguage(); - } - - private String getCountry(Locale locale) { - return locale.getCountry(); - } - - private String getScreenSize(int screenLayout) { - int screenSize = screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK; - - switch (screenSize) { - case Configuration.SCREENLAYOUT_SIZE_SMALL: - return SMALL; - case Configuration.SCREENLAYOUT_SIZE_NORMAL: - return NORMAL; - case Configuration.SCREENLAYOUT_SIZE_LARGE: - return LARGE; - case 4: - return XLARGE; - default: - return null; - } - } - - private String getScreenFormat(int screenLayout) { - int screenFormat = screenLayout & Configuration.SCREENLAYOUT_LONG_MASK; - - switch (screenFormat) { - case Configuration.SCREENLAYOUT_LONG_YES: - return LONG; - case Configuration.SCREENLAYOUT_LONG_NO: - return NORMAL; - default: - return null; - } - } - - private String getScreenDensity(DisplayMetrics displayMetrics) { - int density = displayMetrics.densityDpi; - int low = (DisplayMetrics.DENSITY_MEDIUM + DisplayMetrics.DENSITY_LOW) / 2; - int high = (DisplayMetrics.DENSITY_MEDIUM + DisplayMetrics.DENSITY_HIGH) / 2; - - if (0 == density) { - return null; - } else if (density < low) { - return LOW; - } else if (density > high) { - return HIGH; - } - return MEDIUM; - } - - private String getDisplayWidth(DisplayMetrics displayMetrics) { - return String.valueOf(displayMetrics.widthPixels); - } - - private String getDisplayHeight(DisplayMetrics displayMetrics) { - return String.valueOf(displayMetrics.heightPixels); - } - - private String getClientSdk(String sdkPrefix) { - if (sdkPrefix == null) { - return Constants.CLIENT_SDK; - } else { - return String.format("%s@%s", sdkPrefix, Constants.CLIENT_SDK); - } - } - - private String getMacSha1(String macAddress) { - if (macAddress == null) { - return null; - } - String macSha1 = sha1(macAddress); - - return macSha1; - } - - private String getMacShortMd5(String macAddress) { - if (macAddress == null) { - return null; - } - String macShort = macAddress.replaceAll(":", ""); - String macShortMd5 = md5(macShort); - - return macShortMd5; - } - - private String getAndroidId(Context context, boolean isGooglePlayServicesAvailable) { - if (!isGooglePlayServicesAvailable) { - return Reflection.getAndroidId(context); - } else { - return null; - } - } - - private String sha1(final String text) { - return hash(text, SHA1); - } - - private String md5(final String text) { - return hash(text, MD5); - } - - private String hash(final String text, final String method) { - String hashString = null; - try { - final byte[] bytes = text.getBytes(ENCODING); - final MessageDigest mesd = MessageDigest.getInstance(method); - mesd.update(bytes, 0, bytes.length); - final byte[] hash = mesd.digest(); - hashString = convertToHex(hash); - } catch (Exception e) { - } - return hashString; - } - - private static String convertToHex(final byte[] bytes) { - final BigInteger bigInt = new BigInteger(1, bytes); - final String formatString = "%0" + (bytes.length << 1) + "x"; - return String.format(formatString, bigInt); - } - - private String getFacebookAttributionId(final Context context) { - try { - final ContentResolver contentResolver = context.getContentResolver(); - final Uri uri = Uri.parse("content://com.facebook.katana.provider.AttributionIdProvider"); - final String columnName = "aid"; - final String[] projection = {columnName}; - final Cursor cursor = contentResolver.query(uri, projection, null, null, null); - - if (null == cursor) { - return null; - } - if (!cursor.moveToFirst()) { - cursor.close(); - return null; - } - - final String attributionId = cursor.getString(cursor.getColumnIndex(columnName)); - cursor.close(); - return attributionId; - } catch (Exception e) { - return null; - } - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/IActivityHandler.java b/mobile/android/thirdparty/com/adjust/sdk/IActivityHandler.java deleted file mode 100644 index 10b92205d..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/IActivityHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.adjust.sdk; - -import android.net.Uri; - -import org.json.JSONObject; - -/** - * Created by pfms on 15/12/14. - */ -public interface IActivityHandler { - public void init(AdjustConfig config); - - public void trackSubsessionStart(); - - public void trackSubsessionEnd(); - - public void trackEvent(AdjustEvent event); - - public void finishedTrackingActivity(JSONObject jsonResponse); - - public void setEnabled(boolean enabled); - - public boolean isEnabled(); - - public void readOpenUrl(Uri url, long clickTime); - - public boolean tryUpdateAttribution(AdjustAttribution attribution); - - public void sendReferrer(String referrer, long clickTime); - - public void setOfflineMode(boolean enabled); - - public void setAskingAttribution(boolean askingAttribution); - - public ActivityPackage getAttributionPackage(); -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/IAttributionHandler.java b/mobile/android/thirdparty/com/adjust/sdk/IAttributionHandler.java deleted file mode 100644 index d4e701f75..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/IAttributionHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.adjust.sdk; - -import org.json.JSONObject; - -/** - * Created by pfms on 15/12/14. - */ -public interface IAttributionHandler { - public void init(IActivityHandler activityHandler, - ActivityPackage attributionPackage, - boolean startPaused); - - public void getAttribution(); - - public void checkAttribution(JSONObject jsonResponse); - - public void pauseSending(); - - public void resumeSending(); -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/ILogger.java b/mobile/android/thirdparty/com/adjust/sdk/ILogger.java deleted file mode 100644 index 28f92af4b..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/ILogger.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.adjust.sdk; - -public interface ILogger { - public void setLogLevel(LogLevel logLevel); - - public void setLogLevelString(String logLevelString); - - public void verbose(String message, Object... parameters); - - public void debug(String message, Object... parameters); - - public void info(String message, Object... parameters); - - public void warn(String message, Object... parameters); - - public void error(String message, Object... parameters); - - public void Assert(String message, Object... parameters); - -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/IPackageHandler.java b/mobile/android/thirdparty/com/adjust/sdk/IPackageHandler.java deleted file mode 100644 index 99c300364..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/IPackageHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.adjust.sdk; - -import android.content.Context; - -import org.json.JSONObject; - -public interface IPackageHandler { - public void init(IActivityHandler activityHandler, Context context, boolean startPaused); - - public void addPackage(ActivityPackage pack); - - public void sendFirstPackage(); - - public void sendNextPackage(); - - public void closeFirstPackage(); - - public void pauseSending(); - - public void resumeSending(); - - public String getFailureMessage(); - - public void finishedTrackingActivity(JSONObject jsonResponse); - - public void sendClickPackage(ActivityPackage clickPackage); -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/IRequestHandler.java b/mobile/android/thirdparty/com/adjust/sdk/IRequestHandler.java deleted file mode 100644 index 5b18e2ee9..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/IRequestHandler.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.adjust.sdk; - -public interface IRequestHandler { - public void init(IPackageHandler packageHandler); - - public void sendPackage(ActivityPackage pack); - - public void sendClickPackage(ActivityPackage clickPackage); -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/LICENSE b/mobile/android/thirdparty/com/adjust/sdk/LICENSE deleted file mode 100644 index 25e1d5eb5..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2012-2014 adjust GmbH, -http://www.adjust.com - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mobile/android/thirdparty/com/adjust/sdk/LogLevel.java b/mobile/android/thirdparty/com/adjust/sdk/LogLevel.java deleted file mode 100644 index 5c0b410c2..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/LogLevel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.adjust.sdk; - -import android.util.Log; - -/** - * Created by pfms on 11/03/15. - */ -public enum LogLevel { - VERBOSE(Log.VERBOSE), DEBUG(Log.DEBUG), INFO(Log.INFO), WARN(Log.WARN), ERROR(Log.ERROR), ASSERT(Log.ASSERT); - final int androidLogLevel; - - LogLevel(final int androidLogLevel) { - this.androidLogLevel = androidLogLevel; - } - - public int getAndroidLogLevel() { - return androidLogLevel; - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/Logger.java b/mobile/android/thirdparty/com/adjust/sdk/Logger.java deleted file mode 100644 index 86a644d4a..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/Logger.java +++ /dev/null @@ -1,107 +0,0 @@ -// -// Logger.java -// Adjust -// -// Created by Christian Wellenbrock on 2013-04-18. -// Copyright (c) 2013 adjust GmbH. All rights reserved. -// See the file MIT-LICENSE for copying permission. -// - -package com.adjust.sdk; - -import android.util.Log; - -import java.util.Arrays; -import java.util.Locale; - -import static com.adjust.sdk.Constants.LOGTAG; - -public class Logger implements ILogger { - - private LogLevel logLevel; - private static String formatErrorMessage = "Error formating log message: %s, with params: %s"; - - public Logger() { - setLogLevel(LogLevel.INFO); - } - - @Override - public void setLogLevel(LogLevel logLevel) { - this.logLevel = logLevel; - } - - @Override - public void setLogLevelString(String logLevelString) { - if (null != logLevelString) { - try { - setLogLevel(LogLevel.valueOf(logLevelString.toUpperCase(Locale.US))); - } catch (IllegalArgumentException iae) { - error("Malformed logLevel '%s', falling back to 'info'", logLevelString); - } - } - } - - @Override - public void verbose(String message, Object... parameters) { - if (logLevel.androidLogLevel <= Log.VERBOSE) { - try { - Log.v(LOGTAG, String.format(message, parameters)); - } catch (Exception e) { - Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters))); - } - } - } - - @Override - public void debug(String message, Object... parameters) { - if (logLevel.androidLogLevel <= Log.DEBUG) { - try { - Log.d(LOGTAG, String.format(message, parameters)); - } catch (Exception e) { - Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters))); - } - } - } - - @Override - public void info(String message, Object... parameters) { - if (logLevel.androidLogLevel <= Log.INFO) { - try { - Log.i(LOGTAG, String.format(message, parameters)); - } catch (Exception e) { - Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters))); - } - } - } - - @Override - public void warn(String message, Object... parameters) { - if (logLevel.androidLogLevel <= Log.WARN) { - try { - Log.w(LOGTAG, String.format(message, parameters)); - } catch (Exception e) { - Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters))); - } - } - } - - @Override - public void error(String message, Object... parameters) { - if (logLevel.androidLogLevel <= Log.ERROR) { - try { - Log.e(LOGTAG, String.format(message, parameters)); - } catch (Exception e) { - Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters))); - } - } - } - - @Override - public void Assert(String message, Object... parameters) { - try { - Log.println(Log.ASSERT, LOGTAG, String.format(message, parameters)); - } catch (Exception e) { - Log.e(LOGTAG, String.format(formatErrorMessage, message, Arrays.toString(parameters))); - } - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/OnAttributionChangedListener.java b/mobile/android/thirdparty/com/adjust/sdk/OnAttributionChangedListener.java deleted file mode 100644 index 137d50d4d..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/OnAttributionChangedListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.adjust.sdk; - -public interface OnAttributionChangedListener { - public void onAttributionChanged(AdjustAttribution attribution); -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/PackageBuilder.java b/mobile/android/thirdparty/com/adjust/sdk/PackageBuilder.java deleted file mode 100644 index 3a43045fd..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/PackageBuilder.java +++ /dev/null @@ -1,291 +0,0 @@ -// -// PackageBuilder.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.text.TextUtils; - -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -class PackageBuilder { - private AdjustConfig adjustConfig; - private DeviceInfo deviceInfo; - private ActivityState activityState; - private long createdAt; - - // reattributions - Map<String, String> extraParameters; - AdjustAttribution attribution; - String reftag; - - private static ILogger logger = AdjustFactory.getLogger(); - - public PackageBuilder(AdjustConfig adjustConfig, - DeviceInfo deviceInfo, - ActivityState activityState, - long createdAt) { - this.adjustConfig = adjustConfig; - this.deviceInfo = deviceInfo; - this.activityState = activityState.clone(); - this.createdAt = createdAt; - } - - public ActivityPackage buildSessionPackage() { - Map<String, String> parameters = getDefaultParameters(); - addDuration(parameters, "last_interval", activityState.lastInterval); - addString(parameters, "default_tracker", adjustConfig.defaultTracker); - - ActivityPackage sessionPackage = getDefaultActivityPackage(); - sessionPackage.setPath("/session"); - sessionPackage.setActivityKind(ActivityKind.SESSION); - sessionPackage.setSuffix(""); - sessionPackage.setParameters(parameters); - - return sessionPackage; - } - - public ActivityPackage buildEventPackage(AdjustEvent event) { - Map<String, String> parameters = getDefaultParameters(); - addInt(parameters, "event_count", activityState.eventCount); - addString(parameters, "event_token", event.eventToken); - addDouble(parameters, "revenue", event.revenue); - addString(parameters, "currency", event.currency); - addMapJson(parameters, "callback_params", event.callbackParameters); - addMapJson(parameters, "partner_params", event.partnerParameters); - - ActivityPackage eventPackage = getDefaultActivityPackage(); - eventPackage.setPath("/event"); - eventPackage.setActivityKind(ActivityKind.EVENT); - eventPackage.setSuffix(getEventSuffix(event)); - eventPackage.setParameters(parameters); - - return eventPackage; - } - - public ActivityPackage buildClickPackage(String source, long clickTime) { - Map<String, String> parameters = getDefaultParameters(); - - addString(parameters, "source", source); - addDate(parameters, "click_time", clickTime); - addString(parameters, "reftag", reftag); - addMapJson(parameters, "params", extraParameters); - injectAttribution(parameters); - - ActivityPackage clickPackage = getDefaultActivityPackage(); - clickPackage.setPath("/sdk_click"); - clickPackage.setActivityKind(ActivityKind.CLICK); - clickPackage.setSuffix(""); - clickPackage.setParameters(parameters); - - return clickPackage; - } - - public ActivityPackage buildAttributionPackage() { - Map<String, String> parameters = getIdsParameters(); - - ActivityPackage attributionPackage = getDefaultActivityPackage(); - attributionPackage.setPath("attribution"); // does not contain '/' because of Uri.Builder.appendPath - attributionPackage.setActivityKind(ActivityKind.ATTRIBUTION); - attributionPackage.setSuffix(""); - attributionPackage.setParameters(parameters); - - return attributionPackage; - } - - private ActivityPackage getDefaultActivityPackage() { - ActivityPackage activityPackage = new ActivityPackage(); - activityPackage.setClientSdk(deviceInfo.clientSdk); - return activityPackage; - } - - private Map<String, String> getDefaultParameters() { - Map<String, String> parameters = new HashMap<String, String>(); - - injectDeviceInfo(parameters); - injectConfig(parameters); - injectActivityState(parameters); - addDate(parameters, "created_at", createdAt); - - // general - checkDeviceIds(parameters); - - return parameters; - } - - private Map<String, String> getIdsParameters() { - Map<String, String> parameters = new HashMap<String, String>(); - - injectDeviceInfoIds(parameters); - injectConfig(parameters); - injectActivityStateIds(parameters); - - checkDeviceIds(parameters); - - return parameters; - } - - private void injectDeviceInfo(Map<String, String> parameters) { - injectDeviceInfoIds(parameters); - addString(parameters, "fb_id", deviceInfo.fbAttributionId); - addString(parameters, "package_name", deviceInfo.packageName); - addString(parameters, "app_version", deviceInfo.appVersion); - addString(parameters, "device_type", deviceInfo.deviceType); - addString(parameters, "device_name", deviceInfo.deviceName); - addString(parameters, "device_manufacturer", deviceInfo.deviceManufacturer); - addString(parameters, "os_name", deviceInfo.osName); - addString(parameters, "os_version", deviceInfo.osVersion); - addString(parameters, "language", deviceInfo.language); - addString(parameters, "country", deviceInfo.country); - addString(parameters, "screen_size", deviceInfo.screenSize); - addString(parameters, "screen_format", deviceInfo.screenFormat); - addString(parameters, "screen_density", deviceInfo.screenDensity); - addString(parameters, "display_width", deviceInfo.displayWidth); - addString(parameters, "display_height", deviceInfo.displayHeight); - fillPluginKeys(parameters); - } - - private void injectDeviceInfoIds(Map<String, String> parameters) { - addString(parameters, "mac_sha1", deviceInfo.macSha1); - addString(parameters, "mac_md5", deviceInfo.macShortMd5); - addString(parameters, "android_id", deviceInfo.androidId); - } - - private void injectConfig(Map<String, String> parameters) { - addString(parameters, "app_token", adjustConfig.appToken); - addString(parameters, "environment", adjustConfig.environment); - addBoolean(parameters, "device_known", adjustConfig.knownDevice); - addBoolean(parameters, "needs_attribution_data", adjustConfig.hasListener()); - - String playAdId = Util.getPlayAdId(adjustConfig.context); - addString(parameters, "gps_adid", playAdId); - Boolean isTrackingEnabled = Util.isPlayTrackingEnabled(adjustConfig.context); - addBoolean(parameters, "tracking_enabled", isTrackingEnabled); - } - - private void injectActivityState(Map<String, String> parameters) { - injectActivityStateIds(parameters); - addInt(parameters, "session_count", activityState.sessionCount); - addInt(parameters, "subsession_count", activityState.subsessionCount); - addDuration(parameters, "session_length", activityState.sessionLength); - addDuration(parameters, "time_spent", activityState.timeSpent); - } - - private void injectActivityStateIds(Map<String, String> parameters) { - addString(parameters, "android_uuid", activityState.uuid); - } - - private void injectAttribution(Map<String, String> parameters) { - if (attribution == null) { - return; - } - addString(parameters, "tracker", attribution.trackerName); - addString(parameters, "campaign", attribution.campaign); - addString(parameters, "adgroup", attribution.adgroup); - addString(parameters, "creative", attribution.creative); - } - - private void checkDeviceIds(Map<String, String> parameters) { - if (!parameters.containsKey("mac_sha1") - && !parameters.containsKey("mac_md5") - && !parameters.containsKey("android_id") - && !parameters.containsKey("gps_adid")) { - logger.error("Missing device id's. Please check if Proguard is correctly set with Adjust SDK"); - } - } - - private void fillPluginKeys(Map<String, String> parameters) { - if (deviceInfo.pluginKeys == null) { - return; - } - - for (Map.Entry<String, String> entry : deviceInfo.pluginKeys.entrySet()) { - addString(parameters, entry.getKey(), entry.getValue()); - } - } - - private String getEventSuffix(AdjustEvent event) { - if (event.revenue == null) { - return String.format(" '%s'", event.eventToken); - } else { - return String.format(Locale.US, " (%.4f %s, '%s')", event.revenue, event.currency, event.eventToken); - } - } - - private void addString(Map<String, String> parameters, String key, String value) { - if (TextUtils.isEmpty(value)) { - return; - } - - parameters.put(key, value); - } - - private void addInt(Map<String, String> parameters, String key, long value) { - if (value < 0) { - return; - } - - String valueString = Long.toString(value); - addString(parameters, key, valueString); - } - - private void addDate(Map<String, String> parameters, String key, long value) { - if (value < 0) { - return; - } - - String dateString = Util.dateFormat(value); - addString(parameters, key, dateString); - } - - private void addDuration(Map<String, String> parameters, String key, long durationInMilliSeconds) { - if (durationInMilliSeconds < 0) { - return; - } - - long durationInSeconds = (durationInMilliSeconds + 500) / 1000; - addInt(parameters, key, durationInSeconds); - } - - private void addMapJson(Map<String, String> parameters, String key, Map<String, String> map) { - if (map == null) { - return; - } - - if (map.size() == 0) { - return; - } - - JSONObject jsonObject = new JSONObject(map); - String jsonString = jsonObject.toString(); - - addString(parameters, key, jsonString); - } - - private void addBoolean(Map<String, String> parameters, String key, Boolean value) { - if (value == null) { - return; - } - - int intValue = value ? 1 : 0; - - addInt(parameters, key, intValue); - } - - private void addDouble(Map<String, String> parameters, String key, Double value) { - if (value == null) return; - - String doubleString = String.format("%.5f", value); - - addString(parameters, key, doubleString); - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/PackageHandler.java b/mobile/android/thirdparty/com/adjust/sdk/PackageHandler.java deleted file mode 100644 index d0a84ccd1..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/PackageHandler.java +++ /dev/null @@ -1,274 +0,0 @@ -// -// PackageHandler.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.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; - -import org.json.JSONObject; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.NotSerializableException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OptionalDataException; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -// persistent -public class PackageHandler extends HandlerThread implements IPackageHandler { - private static final String PACKAGE_QUEUE_FILENAME = "AdjustIoPackageQueue"; - - private final InternalHandler internalHandler; - private IRequestHandler requestHandler; - private IActivityHandler activityHandler; - private List<ActivityPackage> packageQueue; - private AtomicBoolean isSending; - private boolean paused; - private Context context; - private ILogger logger; - - public PackageHandler(IActivityHandler activityHandler, - Context context, - boolean startPaused) { - super(Constants.LOGTAG, MIN_PRIORITY); - setDaemon(true); - start(); - this.internalHandler = new InternalHandler(getLooper(), this); - this.logger = AdjustFactory.getLogger(); - - init(activityHandler, context, startPaused); - - Message message = Message.obtain(); - message.arg1 = InternalHandler.INIT; - internalHandler.sendMessage(message); - } - - @Override - public void init(IActivityHandler activityHandler, Context context, boolean startPaused) { - this.activityHandler = activityHandler; - this.context = context; - this.paused = startPaused; - } - - // add a package to the queue - @Override - public void addPackage(ActivityPackage pack) { - Message message = Message.obtain(); - message.arg1 = InternalHandler.ADD; - message.obj = pack; - internalHandler.sendMessage(message); - } - - // try to send the oldest package - @Override - public void sendFirstPackage() { - Message message = Message.obtain(); - message.arg1 = InternalHandler.SEND_FIRST; - internalHandler.sendMessage(message); - } - - // remove oldest package and try to send the next one - // (after success or possibly permanent failure) - @Override - public void sendNextPackage() { - Message message = Message.obtain(); - message.arg1 = InternalHandler.SEND_NEXT; - internalHandler.sendMessage(message); - } - - // close the package to retry in the future (after temporary failure) - @Override - public void closeFirstPackage() { - isSending.set(false); - } - - // interrupt the sending loop after the current request has finished - @Override - public void pauseSending() { - paused = true; - } - - // allow sending requests again - @Override - public void resumeSending() { - paused = false; - } - - // short info about how failing packages are handled - @Override - public String getFailureMessage() { - return "Will retry later."; - } - - @Override - public void finishedTrackingActivity(JSONObject jsonResponse) { - activityHandler.finishedTrackingActivity(jsonResponse); - } - - @Override - public void sendClickPackage(ActivityPackage clickPackage) { - logger.debug("Sending click package (%s)", clickPackage); - logger.verbose("%s", clickPackage.getExtendedString()); - requestHandler.sendClickPackage(clickPackage); - } - - private static final class InternalHandler extends Handler { - private static final int INIT = 1; - private static final int ADD = 2; - private static final int SEND_NEXT = 3; - private static final int SEND_FIRST = 4; - - private final WeakReference<PackageHandler> packageHandlerReference; - - protected InternalHandler(Looper looper, PackageHandler packageHandler) { - super(looper); - this.packageHandlerReference = new WeakReference<PackageHandler>(packageHandler); - } - - @Override - public void handleMessage(Message message) { - super.handleMessage(message); - - PackageHandler packageHandler = packageHandlerReference.get(); - if (null == packageHandler) { - return; - } - - switch (message.arg1) { - case INIT: - packageHandler.initInternal(); - break; - case ADD: - ActivityPackage activityPackage = (ActivityPackage) message.obj; - packageHandler.addInternal(activityPackage); - break; - case SEND_FIRST: - packageHandler.sendFirstInternal(); - break; - case SEND_NEXT: - packageHandler.sendNextInternal(); - break; - } - } - } - - // internal methods run in dedicated queue thread - - private void initInternal() { - requestHandler = AdjustFactory.getRequestHandler(this); - - isSending = new AtomicBoolean(); - - readPackageQueue(); - } - - private void addInternal(ActivityPackage newPackage) { - packageQueue.add(newPackage); - logger.debug("Added package %d (%s)", packageQueue.size(), newPackage); - logger.verbose("%s", newPackage.getExtendedString()); - - writePackageQueue(); - } - - private void sendFirstInternal() { - if (packageQueue.isEmpty()) { - return; - } - - if (paused) { - logger.debug("Package handler is paused"); - return; - } - if (isSending.getAndSet(true)) { - logger.verbose("Package handler is already sending"); - return; - } - - ActivityPackage firstPackage = packageQueue.get(0); - requestHandler.sendPackage(firstPackage); - } - - private void sendNextInternal() { - packageQueue.remove(0); - writePackageQueue(); - isSending.set(false); - sendFirstInternal(); - } - - private void readPackageQueue() { - try { - FileInputStream inputStream = context.openFileInput(PACKAGE_QUEUE_FILENAME); - BufferedInputStream bufferedStream = new BufferedInputStream(inputStream); - ObjectInputStream objectStream = new ObjectInputStream(bufferedStream); - - try { - Object object = objectStream.readObject(); - @SuppressWarnings("unchecked") - List<ActivityPackage> packageQueue = (List<ActivityPackage>) object; - logger.debug("Package handler read %d packages", packageQueue.size()); - this.packageQueue = packageQueue; - return; - } catch (ClassNotFoundException e) { - logger.error("Failed to find package queue class"); - } catch (OptionalDataException e) { - /* no-op */ - } catch (IOException e) { - logger.error("Failed to read package queue object"); - } catch (ClassCastException e) { - logger.error("Failed to cast package queue object"); - } finally { - objectStream.close(); - } - } catch (FileNotFoundException e) { - logger.verbose("Package queue file not found"); - } catch (Exception e) { - logger.error("Failed to read package queue file"); - } - - // start with a fresh package queue in case of any exception - packageQueue = new ArrayList<ActivityPackage>(); - } - - public static Boolean deletePackageQueue(Context context) { - return context.deleteFile(PACKAGE_QUEUE_FILENAME); - } - - - private void writePackageQueue() { - try { - FileOutputStream outputStream = context.openFileOutput(PACKAGE_QUEUE_FILENAME, Context.MODE_PRIVATE); - BufferedOutputStream bufferedStream = new BufferedOutputStream(outputStream); - ObjectOutputStream objectStream = new ObjectOutputStream(bufferedStream); - - try { - objectStream.writeObject(packageQueue); - logger.debug("Package handler wrote %d packages", packageQueue.size()); - } catch (NotSerializableException e) { - logger.error("Failed to serialize packages"); - } finally { - objectStream.close(); - } - } catch (Exception e) { - logger.error("Failed to write packages (%s)", e.getLocalizedMessage()); - e.printStackTrace(); - } - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/Reflection.java b/mobile/android/thirdparty/com/adjust/sdk/Reflection.java deleted file mode 100644 index d9d9a9dbc..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/Reflection.java +++ /dev/null @@ -1,210 +0,0 @@ -package com.adjust.sdk; - -import android.content.Context; - -import com.adjust.sdk.plugin.Plugin; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.adjust.sdk.Constants.PLUGINS; - -public class Reflection { - - public static String getPlayAdId(Context context) { - try { - Object AdvertisingInfoObject = getAdvertisingInfoObject(context); - - String playAdid = (String) invokeInstanceMethod(AdvertisingInfoObject, "getId", null); - - return playAdid; - } catch (Throwable t) { - return null; - } - } - - public static Boolean isPlayTrackingEnabled(Context context) { - try { - Object AdvertisingInfoObject = getAdvertisingInfoObject(context); - - Boolean isLimitedTrackingEnabled = (Boolean) invokeInstanceMethod(AdvertisingInfoObject, "isLimitAdTrackingEnabled", null); - - return !isLimitedTrackingEnabled; - } catch (Throwable t) { - return null; - } - } - - public static boolean isGooglePlayServicesAvailable(Context context) { - try { - Integer isGooglePlayServicesAvailableStatusCode = (Integer) invokeStaticMethod( - "com.google.android.gms.common.GooglePlayServicesUtil", - "isGooglePlayServicesAvailable", - new Class[]{Context.class}, context - ); - - boolean isGooglePlayServicesAvailable = (Boolean) isConnectionResultSuccess(isGooglePlayServicesAvailableStatusCode); - - return isGooglePlayServicesAvailable; - } catch (Throwable t) { - return false; - } - } - - public static String getMacAddress(Context context) { - try { - String macSha1 = (String) invokeStaticMethod( - "com.adjust.sdk.plugin.MacAddressUtil", - "getMacAddress", - new Class[]{Context.class}, context - ); - - return macSha1; - } catch (Throwable t) { - return null; - } - } - - public static String getAndroidId(Context context) { - try { - String androidId = (String) invokeStaticMethod("com.adjust.sdk.plugin.AndroidIdUtil", "getAndroidId" - , new Class[]{Context.class}, context); - - return androidId; - } catch (Throwable t) { - return null; - } - } - - public static String getSha1EmailAddress(Context context, String key) { - try { - String sha1EmailAddress = (String) invokeStaticMethod("com.adjust.sdk.plugin.EmailUtil", "getSha1EmailAddress" - , new Class[]{Context.class, String.class}, context, key); - - return sha1EmailAddress; - } catch (Throwable t) { - return null; - } - } - - private static Object getAdvertisingInfoObject(Context context) - throws Exception { - return invokeStaticMethod("com.google.android.gms.ads.identifier.AdvertisingIdClient", - "getAdvertisingIdInfo", - new Class[]{Context.class}, context - ); - } - - private static boolean isConnectionResultSuccess(Integer statusCode) { - if (statusCode == null) { - return false; - } - - try { - Class ConnectionResultClass = Class.forName("com.google.android.gms.common.ConnectionResult"); - - Field SuccessField = ConnectionResultClass.getField("SUCCESS"); - - int successStatusCode = SuccessField.getInt(null); - - return successStatusCode == statusCode; - } catch (Throwable t) { - return false; - } - } - - public static Class forName(String className) { - try { - Class classObject = Class.forName(className); - return classObject; - } catch (Throwable t) { - return null; - } - } - - public static Object createDefaultInstance(String className) { - Class classObject = forName(className); - Object instance = createDefaultInstance(classObject); - return instance; - } - - public static Object createDefaultInstance(Class classObject) { - try { - Object instance = classObject.newInstance(); - return instance; - } catch (Throwable t) { - return null; - } - } - - public static Object createInstance(String className, Class[] cArgs, Object... args) { - try { - Class classObject = Class.forName(className); - @SuppressWarnings("unchecked") - Constructor constructor = classObject.getConstructor(cArgs); - Object instance = constructor.newInstance(args); - return instance; - } catch (Throwable t) { - return null; - } - } - - public static Object invokeStaticMethod(String className, String methodName, Class[] cArgs, Object... args) - throws Exception { - Class classObject = Class.forName(className); - - return invokeMethod(classObject, methodName, null, cArgs, args); - } - - public static Object invokeInstanceMethod(Object instance, String methodName, Class[] cArgs, Object... args) - throws Exception { - Class classObject = instance.getClass(); - - return invokeMethod(classObject, methodName, instance, cArgs, args); - } - - public static Object invokeMethod(Class classObject, String methodName, Object instance, Class[] cArgs, Object... args) - throws Exception { - @SuppressWarnings("unchecked") - Method methodObject = classObject.getMethod(methodName, cArgs); - - Object resultObject = methodObject.invoke(instance, args); - - return resultObject; - } - - public static Map<String, String> getPluginKeys(Context context) { - Map<String, String> pluginKeys = new HashMap<String, String>(); - - for (Plugin plugin : getPlugins()) { - Map.Entry<String, String> pluginEntry = plugin.getParameter(context); - if (pluginEntry != null) { - pluginKeys.put(pluginEntry.getKey(), pluginEntry.getValue()); - } - } - - if (pluginKeys.size() == 0) { - return null; - } else { - return pluginKeys; - } - } - - private static List<Plugin> getPlugins() { - List<Plugin> plugins = new ArrayList<Plugin>(PLUGINS.size()); - - for (String pluginName : PLUGINS) { - Object pluginObject = Reflection.createDefaultInstance(pluginName); - if (pluginObject != null && pluginObject instanceof Plugin) { - plugins.add((Plugin) pluginObject); - } - } - - return plugins; - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/RequestHandler.java b/mobile/android/thirdparty/com/adjust/sdk/RequestHandler.java deleted file mode 100644 index 84d45d0ce..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/RequestHandler.java +++ /dev/null @@ -1,210 +0,0 @@ -// -// RequestHandler.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.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; - -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.NameValuePair; -import ch.boye.httpclientandroidlib.client.ClientProtocolException; -import ch.boye.httpclientandroidlib.client.HttpClient; -import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity; -import ch.boye.httpclientandroidlib.client.methods.HttpPost; -import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest; -import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils; -import ch.boye.httpclientandroidlib.message.BasicNameValuePair; -import org.json.JSONObject; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.lang.ref.WeakReference; -import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -public class RequestHandler extends HandlerThread implements IRequestHandler { - private InternalHandler internalHandler; - private IPackageHandler packageHandler; - private HttpClient httpClient; - private ILogger logger; - - public RequestHandler(IPackageHandler packageHandler) { - super(Constants.LOGTAG, MIN_PRIORITY); - setDaemon(true); - start(); - - this.logger = AdjustFactory.getLogger(); - this.internalHandler = new InternalHandler(getLooper(), this); - init(packageHandler); - - Message message = Message.obtain(); - message.arg1 = InternalHandler.INIT; - internalHandler.sendMessage(message); - } - - @Override - public void init(IPackageHandler packageHandler) { - this.packageHandler = packageHandler; - } - - @Override - public void sendPackage(ActivityPackage pack) { - Message message = Message.obtain(); - message.arg1 = InternalHandler.SEND; - message.obj = pack; - internalHandler.sendMessage(message); - } - - @Override - public void sendClickPackage(ActivityPackage clickPackage) { - Message message = Message.obtain(); - message.arg1 = InternalHandler.SEND_CLICK; - message.obj = clickPackage; - internalHandler.sendMessage(message); - - } - - private static final class InternalHandler extends Handler { - private static final int INIT = 72401; - private static final int SEND = 72400; - private static final int SEND_CLICK = 72402; - - private final WeakReference<RequestHandler> requestHandlerReference; - - protected InternalHandler(Looper looper, RequestHandler requestHandler) { - super(looper); - this.requestHandlerReference = new WeakReference<RequestHandler>(requestHandler); - } - - @Override - public void handleMessage(Message message) { - super.handleMessage(message); - - RequestHandler requestHandler = requestHandlerReference.get(); - if (null == requestHandler) { - return; - } - - switch (message.arg1) { - case INIT: - requestHandler.initInternal(); - break; - case SEND: - ActivityPackage activityPackage = (ActivityPackage) message.obj; - requestHandler.sendInternal(activityPackage, true); - break; - case SEND_CLICK: - ActivityPackage clickPackage = (ActivityPackage) message.obj; - requestHandler.sendInternal(clickPackage, false); - break; - } - } - } - - private void initInternal() { - httpClient = Util.getHttpClient(); - } - - private void sendInternal(ActivityPackage activityPackage, boolean sendToPackageHandler) { - try { - HttpUriRequest request = getRequest(activityPackage); - HttpResponse response = httpClient.execute(request); - requestFinished(response, sendToPackageHandler); - } catch (UnsupportedEncodingException e) { - sendNextPackage(activityPackage, "Failed to encode parameters", e, sendToPackageHandler); - } catch (ClientProtocolException e) { - closePackage(activityPackage, "Client protocol error", e, sendToPackageHandler); - } catch (SocketTimeoutException e) { - closePackage(activityPackage, "Request timed out", e, sendToPackageHandler); - } catch (IOException e) { - closePackage(activityPackage, "Request failed", e, sendToPackageHandler); - } catch (Throwable e) { - sendNextPackage(activityPackage, "Runtime exception", e, sendToPackageHandler); - } - } - - private void requestFinished(HttpResponse response, boolean sendToPackageHandler) { - JSONObject jsonResponse = Util.parseJsonResponse(response, logger); - - if (jsonResponse == null) { - if (sendToPackageHandler) { - packageHandler.closeFirstPackage(); - } - return; - } - - packageHandler.finishedTrackingActivity(jsonResponse); - if (sendToPackageHandler) { - packageHandler.sendNextPackage(); - } - } - - // close current package because it failed - private void closePackage(ActivityPackage activityPackage, String message, Throwable throwable, boolean sendToPackageHandler) { - final String packageMessage = activityPackage.getFailureMessage(); - final String handlerMessage = packageHandler.getFailureMessage(); - final String reasonString = getReasonString(message, throwable); - logger.error("%s. (%s) %s", packageMessage, reasonString, handlerMessage); - - if (sendToPackageHandler) { - packageHandler.closeFirstPackage(); - } - } - - // send next package because the current package failed - private void sendNextPackage(ActivityPackage activityPackage, String message, Throwable throwable, boolean sendToPackageHandler) { - final String failureMessage = activityPackage.getFailureMessage(); - final String reasonString = getReasonString(message, throwable); - logger.error("%s. (%s)", failureMessage, reasonString); - - if (sendToPackageHandler) { - packageHandler.sendNextPackage(); - } - } - - private String getReasonString(String message, Throwable throwable) { - if (throwable != null) { - return String.format("%s: %s", message, throwable); - } else { - return String.format("%s", message); - } - } - - private HttpUriRequest getRequest(ActivityPackage activityPackage) throws UnsupportedEncodingException { - String url = Constants.BASE_URL + activityPackage.getPath(); - HttpPost request = new HttpPost(url); - - String language = Locale.getDefault().getLanguage(); - request.addHeader("Client-SDK", activityPackage.getClientSdk()); - request.addHeader("Accept-Language", language); - - List<NameValuePair> pairs = new ArrayList<NameValuePair>(); - for (Map.Entry<String, String> entry : activityPackage.getParameters().entrySet()) { - NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue()); - pairs.add(pair); - } - - long now = System.currentTimeMillis(); - String dateString = Util.dateFormat(now); - NameValuePair sentAtPair = new BasicNameValuePair("sent_at", dateString); - pairs.add(sentAtPair); - - UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs); - entity.setContentType(URLEncodedUtils.CONTENT_TYPE); - request.setEntity(entity); - - return request; - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/UnitTestActivity.java b/mobile/android/thirdparty/com/adjust/sdk/UnitTestActivity.java deleted file mode 100644 index 799fb8982..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/UnitTestActivity.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.adjust.sdk; - -import android.app.Activity; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; - -public class UnitTestActivity extends Activity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - //setContentView(com.adjust.sdk.test.R.layout.activity_unit_test); - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. - //getMenuInflater().inflate(com.adjust.sdk.test.R.menu.menu_unit_test, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. -/* int id = item.getItemId(); - - //noinspection SimplifiableIfStatement - if (id == com.adjust.sdk.test.R.id.action_settings) { - return true; - } -*/ - return super.onOptionsItemSelected(item); - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/Util.java b/mobile/android/thirdparty/com/adjust/sdk/Util.java deleted file mode 100644 index 84c47f87e..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/Util.java +++ /dev/null @@ -1,202 +0,0 @@ -// -// Util.java -// Adjust -// -// Created by Christian Wellenbrock on 2012-10-11. -// Copyright (c) 2012-2014 adjust GmbH. All rights reserved. -// See the file MIT-LICENSE for copying permission. -// - -package com.adjust.sdk; - -import android.content.Context; -import android.content.pm.PackageManager; - -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.HttpStatus; -import ch.boye.httpclientandroidlib.client.HttpClient; -import ch.boye.httpclientandroidlib.params.BasicHttpParams; -import ch.boye.httpclientandroidlib.params.HttpConnectionParams; -import ch.boye.httpclientandroidlib.params.HttpParams; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.NotSerializableException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OptionalDataException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Collects utility functions used by Adjust. - */ -public class Util { - - private static SimpleDateFormat dateFormat; - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'Z"; - - protected static String createUuid() { - return UUID.randomUUID().toString(); - } - - public static String quote(String string) { - if (string == null) { - return null; - } - - Pattern pattern = Pattern.compile("\\s"); - Matcher matcher = pattern.matcher(string); - if (!matcher.find()) { - return string; - } - - return String.format("'%s'", string); - } - - public static String dateFormat(long date) { - if (null == dateFormat) { - dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US); - } - return dateFormat.format(date); - } - - public static String getPlayAdId(Context context) { - return Reflection.getPlayAdId(context); - } - - public static Boolean isPlayTrackingEnabled(Context context) { - return Reflection.isPlayTrackingEnabled(context); - } - - public static <T> T readObject(Context context, String filename, String objectName) { - ILogger logger = AdjustFactory.getLogger(); - try { - FileInputStream inputStream = context.openFileInput(filename); - BufferedInputStream bufferedStream = new BufferedInputStream(inputStream); - ObjectInputStream objectStream = new ObjectInputStream(bufferedStream); - - try { - @SuppressWarnings("unchecked") - T t = (T) objectStream.readObject(); - logger.debug("Read %s: %s", objectName, t); - return t; - } catch (ClassNotFoundException e) { - logger.error("Failed to find %s class", objectName); - } catch (OptionalDataException e) { - /* no-op */ - } catch (IOException e) { - logger.error("Failed to read %s object", objectName); - } catch (ClassCastException e) { - logger.error("Failed to cast %s object", objectName); - } finally { - objectStream.close(); - } - - } catch (FileNotFoundException e) { - logger.verbose("%s file not found", objectName); - } catch (Exception e) { - logger.error("Failed to open %s file for reading (%s)", objectName, e); - } - - return null; - } - - public static <T> void writeObject(T object, Context context, String filename, String objectName) { - ILogger logger = AdjustFactory.getLogger(); - try { - FileOutputStream outputStream = context.openFileOutput(filename, Context.MODE_PRIVATE); - BufferedOutputStream bufferedStream = new BufferedOutputStream(outputStream); - ObjectOutputStream objectStream = new ObjectOutputStream(bufferedStream); - - try { - objectStream.writeObject(object); - logger.debug("Wrote %s: %s", objectName, object); - } catch (NotSerializableException e) { - logger.error("Failed to serialize %s", objectName); - } finally { - objectStream.close(); - } - - } catch (Exception e) { - logger.error("Failed to open %s for writing (%s)", objectName, e); - } - } - - public static String parseResponse(HttpResponse httpResponse, ILogger logger) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - httpResponse.getEntity().writeTo(out); - out.close(); - String response = out.toString().trim(); - logger.verbose("Response: %s", response); - return response; - } catch (Exception e) { - logger.error("Failed to parse response (%s)", e); - return null; - } - } - - public static JSONObject parseJsonResponse(HttpResponse httpResponse, ILogger logger) { - if (httpResponse == null) { - return null; - } - String stringResponse = null; - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - httpResponse.getEntity().writeTo(out); - out.close(); - stringResponse = out.toString().trim(); - } catch (Exception e) { - logger.error("Failed to parse response (%s)", e.getMessage()); - } - - logger.verbose("Response: %s", stringResponse); - if (stringResponse == null) return null; - - JSONObject jsonResponse = null; - try { - jsonResponse = new JSONObject(stringResponse); - } catch (JSONException e) { - logger.error("Failed to parse json response: %s (%s)", stringResponse, e.getMessage()); - } - - if (jsonResponse == null) return null; - - String message = jsonResponse.optString("message", null); - - if (message == null) { - message = "No message found"; - } - - if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { - logger.info("%s", message); - } else { - logger.error("%s", message); - } - - return jsonResponse; - } - - public static HttpClient getHttpClient() { - HttpParams httpParams = new BasicHttpParams(); - HttpConnectionParams.setConnectionTimeout(httpParams, Constants.CONNECTION_TIMEOUT); - HttpConnectionParams.setSoTimeout(httpParams, Constants.SOCKET_TIMEOUT); - return AdjustFactory.getHttpClient(httpParams); - } - - public static boolean checkPermission(Context context, String permission) { - int result = context.checkCallingOrSelfPermission(permission); - return result == PackageManager.PERMISSION_GRANTED; - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/plugin/AndroidIdUtil.java b/mobile/android/thirdparty/com/adjust/sdk/plugin/AndroidIdUtil.java deleted file mode 100644 index 96a072287..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/plugin/AndroidIdUtil.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.adjust.sdk.plugin; - -import android.content.Context; -import android.provider.Settings.Secure; - -public class AndroidIdUtil { - public static String getAndroidId(final Context context) { - return Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/plugin/MacAddressUtil.java b/mobile/android/thirdparty/com/adjust/sdk/plugin/MacAddressUtil.java deleted file mode 100644 index c8bdbadd7..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/plugin/MacAddressUtil.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.adjust.sdk.plugin; - -import android.content.Context; -import android.net.wifi.WifiManager; -import android.text.TextUtils; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.util.Locale; - -public class MacAddressUtil { - public static String getMacAddress(Context context) { - final String rawAddress = getRawMacAddress(context); - if (rawAddress == null) { - return null; - } - final String upperAddress = rawAddress.toUpperCase(Locale.US); - return removeSpaceString(upperAddress); - } - - private static String getRawMacAddress(Context context) { - // android devices should have a wlan address - final String wlanAddress = loadAddress("wlan0"); - if (wlanAddress != null) { - return wlanAddress; - } - - // emulators should have an ethernet address - final String ethAddress = loadAddress("eth0"); - if (ethAddress != null) { - return ethAddress; - } - - // query the wifi manager (requires the ACCESS_WIFI_STATE permission) - try { - final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - final String wifiAddress = wifiManager.getConnectionInfo().getMacAddress(); - if (wifiAddress != null) { - return wifiAddress; - } - } catch (Exception e) { - /* no-op */ - } - - return null; - } - - private static String loadAddress(final String interfaceName) { - try { - final String filePath = "/sys/class/net/" + interfaceName + "/address"; - final StringBuilder fileData = new StringBuilder(1000); - final BufferedReader reader = new BufferedReader(new FileReader(filePath), 1024); - final char[] buf = new char[1024]; - int numRead; - - String readData; - while ((numRead = reader.read(buf)) != -1) { - readData = String.valueOf(buf, 0, numRead); - fileData.append(readData); - } - - reader.close(); - return fileData.toString(); - } catch (IOException e) { - return null; - } - } - - private static String removeSpaceString(final String inputString) { - if (inputString == null) { - return null; - } - - String outputString = inputString.replaceAll("\\s", ""); - if (TextUtils.isEmpty(outputString)) { - return null; - } - - return outputString; - } -} diff --git a/mobile/android/thirdparty/com/adjust/sdk/plugin/Plugin.java b/mobile/android/thirdparty/com/adjust/sdk/plugin/Plugin.java deleted file mode 100644 index ab704e6d3..000000000 --- a/mobile/android/thirdparty/com/adjust/sdk/plugin/Plugin.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.adjust.sdk.plugin; - -import android.content.Context; - -import java.util.Map; - -/** - * Created by pfms on 18/09/14. - */ -public interface Plugin { - Map.Entry<String, String> getParameter(Context context); -} diff --git a/mobile/android/thirdparty/com/jakewharton/disklrucache/DiskLruCache.java b/mobile/android/thirdparty/com/jakewharton/disklrucache/DiskLruCache.java deleted file mode 100644 index e81e7fbcc..000000000 --- a/mobile/android/thirdparty/com/jakewharton/disklrucache/DiskLruCache.java +++ /dev/null @@ -1,943 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.jakewharton.disklrucache; - -import java.io.BufferedWriter; -import java.io.Closeable; -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A cache that uses a bounded amount of space on a filesystem. Each cache - * entry has a string key and a fixed number of values. Each key must match - * the regex <strong>[a-z0-9_-]{1,120}</strong>. Values are byte sequences, - * accessible as streams or files. Each value must be between {@code 0} and - * {@code Integer.MAX_VALUE} bytes in length. - * - * <p>The cache stores its data in a directory on the filesystem. This - * directory must be exclusive to the cache; the cache may delete or overwrite - * files from its directory. It is an error for multiple processes to use the - * same cache directory at the same time. - * - * <p>This cache limits the number of bytes that it will store on the - * filesystem. When the number of stored bytes exceeds the limit, the cache will - * remove entries in the background until the limit is satisfied. The limit is - * not strict: the cache may temporarily exceed it while waiting for files to be - * deleted. The limit does not include filesystem overhead or the cache - * journal so space-sensitive applications should set a conservative limit. - * - * <p>Clients call {@link #edit} to create or update the values of an entry. An - * entry may have only one editor at one time; if a value is not available to be - * edited then {@link #edit} will return null. - * <ul> - * <li>When an entry is being <strong>created</strong> it is necessary to - * supply a full set of values; the empty value should be used as a - * placeholder if necessary. - * <li>When an entry is being <strong>edited</strong>, it is not necessary - * to supply data for every value; values default to their previous - * value. - * </ul> - * Every {@link #edit} call must be matched by a call to {@link Editor#commit} - * or {@link Editor#abort}. Committing is atomic: a read observes the full set - * of values as they were before or after the commit, but never a mix of values. - * - * <p>Clients call {@link #get} to read a snapshot of an entry. The read will - * observe the value at the time that {@link #get} was called. Updates and - * removals after the call do not impact ongoing reads. - * - * <p>This class is tolerant of some I/O errors. If files are missing from the - * filesystem, the corresponding entries will be dropped from the cache. If - * an error occurs while writing a cache value, the edit will fail silently. - * Callers should handle other problems by catching {@code IOException} and - * responding appropriately. - */ -public final class DiskLruCache implements Closeable { - static final String JOURNAL_FILE = "journal"; - static final String JOURNAL_FILE_TEMP = "journal.tmp"; - static final String JOURNAL_FILE_BACKUP = "journal.bkp"; - static final String MAGIC = "libcore.io.DiskLruCache"; - static final String VERSION_1 = "1"; - static final long ANY_SEQUENCE_NUMBER = -1; - static final String STRING_KEY_PATTERN = "[a-z0-9_-]{1,120}"; - static final Pattern LEGAL_KEY_PATTERN = Pattern.compile(STRING_KEY_PATTERN); - private static final String CLEAN = "CLEAN"; - private static final String DIRTY = "DIRTY"; - private static final String REMOVE = "REMOVE"; - private static final String READ = "READ"; - - /* - * This cache uses a journal file named "journal". A typical journal file - * looks like this: - * libcore.io.DiskLruCache - * 1 - * 100 - * 2 - * - * CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054 - * DIRTY 335c4c6028171cfddfbaae1a9c313c52 - * CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342 - * REMOVE 335c4c6028171cfddfbaae1a9c313c52 - * DIRTY 1ab96a171faeeee38496d8b330771a7a - * CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234 - * READ 335c4c6028171cfddfbaae1a9c313c52 - * READ 3400330d1dfc7f3f7f4b8d4d803dfcf6 - * - * The first five lines of the journal form its header. They are the - * constant string "libcore.io.DiskLruCache", the disk cache's version, - * the application's version, the value count, and a blank line. - * - * Each of the subsequent lines in the file is a record of the state of a - * cache entry. Each line contains space-separated values: a state, a key, - * and optional state-specific values. - * o DIRTY lines track that an entry is actively being created or updated. - * Every successful DIRTY action should be followed by a CLEAN or REMOVE - * action. DIRTY lines without a matching CLEAN or REMOVE indicate that - * temporary files may need to be deleted. - * o CLEAN lines track a cache entry that has been successfully published - * and may be read. A publish line is followed by the lengths of each of - * its values. - * o READ lines track accesses for LRU. - * o REMOVE lines track entries that have been deleted. - * - * The journal file is appended to as cache operations occur. The journal may - * occasionally be compacted by dropping redundant lines. A temporary file named - * "journal.tmp" will be used during compaction; that file should be deleted if - * it exists when the cache is opened. - */ - - private final File directory; - private final File journalFile; - private final File journalFileTmp; - private final File journalFileBackup; - private final int appVersion; - private long maxSize; - private final int valueCount; - private long size = 0; - private Writer journalWriter; - private final LinkedHashMap<String, Entry> lruEntries = - new LinkedHashMap<String, Entry>(0, 0.75f, true); - private int redundantOpCount; - - /** - * To differentiate between old and current snapshots, each entry is given - * a sequence number each time an edit is committed. A snapshot is stale if - * its sequence number is not equal to its entry's sequence number. - */ - private long nextSequenceNumber = 0; - - /** This cache uses a single background thread to evict entries. */ - final ThreadPoolExecutor executorService = - new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); - private final Callable<Void> cleanupCallable = new Callable<Void>() { - public Void call() throws Exception { - synchronized (DiskLruCache.this) { - if (journalWriter == null) { - return null; // Closed. - } - trimToSize(); - if (journalRebuildRequired()) { - rebuildJournal(); - redundantOpCount = 0; - } - } - return null; - } - }; - - private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) { - this.directory = directory; - this.appVersion = appVersion; - this.journalFile = new File(directory, JOURNAL_FILE); - this.journalFileTmp = new File(directory, JOURNAL_FILE_TEMP); - this.journalFileBackup = new File(directory, JOURNAL_FILE_BACKUP); - this.valueCount = valueCount; - this.maxSize = maxSize; - } - - /** - * Opens the cache in {@code directory}, creating a cache if none exists - * there. - * - * @param directory a writable directory - * @param valueCount the number of values per cache entry. Must be positive. - * @param maxSize the maximum number of bytes this cache should use to store - * @throws IOException if reading or writing the cache directory fails - */ - public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize) - throws IOException { - if (maxSize <= 0) { - throw new IllegalArgumentException("maxSize <= 0"); - } - if (valueCount <= 0) { - throw new IllegalArgumentException("valueCount <= 0"); - } - - // If a bkp file exists, use it instead. - File backupFile = new File(directory, JOURNAL_FILE_BACKUP); - if (backupFile.exists()) { - File journalFile = new File(directory, JOURNAL_FILE); - // If journal file also exists just delete backup file. - if (journalFile.exists()) { - backupFile.delete(); - } else { - renameTo(backupFile, journalFile, false); - } - } - - // Prefer to pick up where we left off. - DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize); - if (cache.journalFile.exists()) { - try { - cache.readJournal(); - cache.processJournal(); - return cache; - } catch (IOException journalIsCorrupt) { - System.out - .println("DiskLruCache " - + directory - + " is corrupt: " - + journalIsCorrupt.getMessage() - + ", removing"); - cache.delete(); - } - } - - // Create a new empty cache. - directory.mkdirs(); - cache = new DiskLruCache(directory, appVersion, valueCount, maxSize); - cache.rebuildJournal(); - return cache; - } - - private void readJournal() throws IOException { - StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile), Util.US_ASCII); - try { - String magic = reader.readLine(); - String version = reader.readLine(); - String appVersionString = reader.readLine(); - String valueCountString = reader.readLine(); - String blank = reader.readLine(); - if (!MAGIC.equals(magic) - || !VERSION_1.equals(version) - || !Integer.toString(appVersion).equals(appVersionString) - || !Integer.toString(valueCount).equals(valueCountString) - || !"".equals(blank)) { - throw new IOException("unexpected journal header: [" + magic + ", " + version + ", " - + valueCountString + ", " + blank + "]"); - } - - int lineCount = 0; - while (true) { - try { - readJournalLine(reader.readLine()); - lineCount++; - } catch (EOFException endOfJournal) { - break; - } - } - redundantOpCount = lineCount - lruEntries.size(); - - // If we ended on a truncated line, rebuild the journal before appending to it. - if (reader.hasUnterminatedLine()) { - rebuildJournal(); - } else { - journalWriter = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(journalFile, true), Util.US_ASCII)); - } - } finally { - Util.closeQuietly(reader); - } - } - - private void readJournalLine(String line) throws IOException { - int firstSpace = line.indexOf(' '); - if (firstSpace == -1) { - throw new IOException("unexpected journal line: " + line); - } - - int keyBegin = firstSpace + 1; - int secondSpace = line.indexOf(' ', keyBegin); - final String key; - if (secondSpace == -1) { - key = line.substring(keyBegin); - if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) { - lruEntries.remove(key); - return; - } - } else { - key = line.substring(keyBegin, secondSpace); - } - - Entry entry = lruEntries.get(key); - if (entry == null) { - entry = new Entry(key); - lruEntries.put(key, entry); - } - - if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) { - String[] parts = line.substring(secondSpace + 1).split(" "); - entry.readable = true; - entry.currentEditor = null; - entry.setLengths(parts); - } else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) { - entry.currentEditor = new Editor(entry); - } else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) { - // This work was already done by calling lruEntries.get(). - } else { - throw new IOException("unexpected journal line: " + line); - } - } - - /** - * Computes the initial size and collects garbage as a part of opening the - * cache. Dirty entries are assumed to be inconsistent and will be deleted. - */ - private void processJournal() throws IOException { - deleteIfExists(journalFileTmp); - for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) { - Entry entry = i.next(); - if (entry.currentEditor == null) { - for (int t = 0; t < valueCount; t++) { - size += entry.lengths[t]; - } - } else { - entry.currentEditor = null; - for (int t = 0; t < valueCount; t++) { - deleteIfExists(entry.getCleanFile(t)); - deleteIfExists(entry.getDirtyFile(t)); - } - i.remove(); - } - } - } - - /** - * Creates a new journal that omits redundant information. This replaces the - * current journal if it exists. - */ - private synchronized void rebuildJournal() throws IOException { - if (journalWriter != null) { - journalWriter.close(); - } - - Writer writer = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(journalFileTmp), Util.US_ASCII)); - try { - writer.write(MAGIC); - writer.write("\n"); - writer.write(VERSION_1); - writer.write("\n"); - writer.write(Integer.toString(appVersion)); - writer.write("\n"); - writer.write(Integer.toString(valueCount)); - writer.write("\n"); - writer.write("\n"); - - for (Entry entry : lruEntries.values()) { - if (entry.currentEditor != null) { - writer.write(DIRTY + ' ' + entry.key + '\n'); - } else { - writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n'); - } - } - } finally { - writer.close(); - } - - if (journalFile.exists()) { - renameTo(journalFile, journalFileBackup, true); - } - renameTo(journalFileTmp, journalFile, false); - journalFileBackup.delete(); - - journalWriter = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(journalFile, true), Util.US_ASCII)); - } - - private static void deleteIfExists(File file) throws IOException { - if (file.exists() && !file.delete()) { - throw new IOException(); - } - } - - private static void renameTo(File from, File to, boolean deleteDestination) throws IOException { - if (deleteDestination) { - deleteIfExists(to); - } - if (!from.renameTo(to)) { - throw new IOException(); - } - } - - /** - * Returns a snapshot of the entry named {@code key}, or null if it doesn't - * exist is not currently readable. If a value is returned, it is moved to - * the head of the LRU queue. - */ - public synchronized Snapshot get(String key) throws IOException { - checkNotClosed(); - validateKey(key); - Entry entry = lruEntries.get(key); - if (entry == null) { - return null; - } - - if (!entry.readable) { - return null; - } - - // Open all streams eagerly to guarantee that we see a single published - // snapshot. If we opened streams lazily then the streams could come - // from different edits. - InputStream[] ins = new InputStream[valueCount]; - try { - for (int i = 0; i < valueCount; i++) { - ins[i] = new FileInputStream(entry.getCleanFile(i)); - } - } catch (FileNotFoundException e) { - // A file must have been deleted manually! - for (int i = 0; i < valueCount; i++) { - if (ins[i] != null) { - Util.closeQuietly(ins[i]); - } else { - break; - } - } - return null; - } - - redundantOpCount++; - journalWriter.append(READ + ' ' + key + '\n'); - if (journalRebuildRequired()) { - executorService.submit(cleanupCallable); - } - - return new Snapshot(key, entry.sequenceNumber, ins, entry.lengths); - } - - /** - * Returns an editor for the entry named {@code key}, or null if another - * edit is in progress. - */ - public Editor edit(String key) throws IOException { - return edit(key, ANY_SEQUENCE_NUMBER); - } - - private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException { - checkNotClosed(); - validateKey(key); - Entry entry = lruEntries.get(key); - if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER && (entry == null - || entry.sequenceNumber != expectedSequenceNumber)) { - return null; // Snapshot is stale. - } - if (entry == null) { - entry = new Entry(key); - lruEntries.put(key, entry); - } else if (entry.currentEditor != null) { - return null; // Another edit is in progress. - } - - Editor editor = new Editor(entry); - entry.currentEditor = editor; - - // Flush the journal before creating files to prevent file leaks. - journalWriter.write(DIRTY + ' ' + key + '\n'); - journalWriter.flush(); - return editor; - } - - /** Returns the directory where this cache stores its data. */ - public File getDirectory() { - return directory; - } - - /** - * Returns the maximum number of bytes that this cache should use to store - * its data. - */ - public synchronized long getMaxSize() { - return maxSize; - } - - /** - * Changes the maximum number of bytes the cache can store and queues a job - * to trim the existing store, if necessary. - */ - public synchronized void setMaxSize(long maxSize) { - this.maxSize = maxSize; - executorService.submit(cleanupCallable); - } - - /** - * Returns the number of bytes currently being used to store the values in - * this cache. This may be greater than the max size if a background - * deletion is pending. - */ - public synchronized long size() { - return size; - } - - private synchronized void completeEdit(Editor editor, boolean success) throws IOException { - Entry entry = editor.entry; - if (entry.currentEditor != editor) { - throw new IllegalStateException(); - } - - // If this edit is creating the entry for the first time, every index must have a value. - if (success && !entry.readable) { - for (int i = 0; i < valueCount; i++) { - if (!editor.written[i]) { - editor.abort(); - throw new IllegalStateException("Newly created entry didn't create value for index " + i); - } - if (!entry.getDirtyFile(i).exists()) { - editor.abort(); - return; - } - } - } - - for (int i = 0; i < valueCount; i++) { - File dirty = entry.getDirtyFile(i); - if (success) { - if (dirty.exists()) { - File clean = entry.getCleanFile(i); - dirty.renameTo(clean); - long oldLength = entry.lengths[i]; - long newLength = clean.length(); - entry.lengths[i] = newLength; - size = size - oldLength + newLength; - } - } else { - deleteIfExists(dirty); - } - } - - redundantOpCount++; - entry.currentEditor = null; - if (entry.readable | success) { - entry.readable = true; - journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n'); - if (success) { - entry.sequenceNumber = nextSequenceNumber++; - } - } else { - lruEntries.remove(entry.key); - journalWriter.write(REMOVE + ' ' + entry.key + '\n'); - } - journalWriter.flush(); - - if (size > maxSize || journalRebuildRequired()) { - executorService.submit(cleanupCallable); - } - } - - /** - * We only rebuild the journal when it will halve the size of the journal - * and eliminate at least 2000 ops. - */ - private boolean journalRebuildRequired() { - final int redundantOpCompactThreshold = 2000; - return redundantOpCount >= redundantOpCompactThreshold // - && redundantOpCount >= lruEntries.size(); - } - - /** - * Drops the entry for {@code key} if it exists and can be removed. Entries - * actively being edited cannot be removed. - * - * @return true if an entry was removed. - */ - public synchronized boolean remove(String key) throws IOException { - checkNotClosed(); - validateKey(key); - Entry entry = lruEntries.get(key); - if (entry == null || entry.currentEditor != null) { - return false; - } - - for (int i = 0; i < valueCount; i++) { - File file = entry.getCleanFile(i); - if (file.exists() && !file.delete()) { - throw new IOException("failed to delete " + file); - } - size -= entry.lengths[i]; - entry.lengths[i] = 0; - } - - redundantOpCount++; - journalWriter.append(REMOVE + ' ' + key + '\n'); - lruEntries.remove(key); - - if (journalRebuildRequired()) { - executorService.submit(cleanupCallable); - } - - return true; - } - - /** Returns true if this cache has been closed. */ - public synchronized boolean isClosed() { - return journalWriter == null; - } - - private void checkNotClosed() { - if (journalWriter == null) { - throw new IllegalStateException("cache is closed"); - } - } - - /** Force buffered operations to the filesystem. */ - public synchronized void flush() throws IOException { - checkNotClosed(); - trimToSize(); - journalWriter.flush(); - } - - /** Closes this cache. Stored values will remain on the filesystem. */ - public synchronized void close() throws IOException { - if (journalWriter == null) { - return; // Already closed. - } - for (Entry entry : new ArrayList<Entry>(lruEntries.values())) { - if (entry.currentEditor != null) { - entry.currentEditor.abort(); - } - } - trimToSize(); - journalWriter.close(); - journalWriter = null; - } - - private void trimToSize() throws IOException { - while (size > maxSize) { - Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next(); - remove(toEvict.getKey()); - } - } - - /** - * Closes the cache and deletes all of its stored values. This will delete - * all files in the cache directory including files that weren't created by - * the cache. - */ - public void delete() throws IOException { - close(); - Util.deleteContents(directory); - } - - private void validateKey(String key) { - Matcher matcher = LEGAL_KEY_PATTERN.matcher(key); - if (!matcher.matches()) { - throw new IllegalArgumentException("keys must match regex " - + STRING_KEY_PATTERN + ": \"" + key + "\""); - } - } - - private static String inputStreamToString(InputStream in) throws IOException { - return Util.readFully(new InputStreamReader(in, Util.UTF_8)); - } - - /** A snapshot of the values for an entry. */ - public final class Snapshot implements Closeable { - private final String key; - private final long sequenceNumber; - private final InputStream[] ins; - private final long[] lengths; - - private Snapshot(String key, long sequenceNumber, InputStream[] ins, long[] lengths) { - this.key = key; - this.sequenceNumber = sequenceNumber; - this.ins = ins; - this.lengths = lengths; - } - - /** - * Returns an editor for this snapshot's entry, or null if either the - * entry has changed since this snapshot was created or if another edit - * is in progress. - */ - public Editor edit() throws IOException { - return DiskLruCache.this.edit(key, sequenceNumber); - } - - /** Returns the unbuffered stream with the value for {@code index}. */ - public InputStream getInputStream(int index) { - return ins[index]; - } - - /** Returns the string value for {@code index}. */ - public String getString(int index) throws IOException { - return inputStreamToString(getInputStream(index)); - } - - /** Returns the byte length of the value for {@code index}. */ - public long getLength(int index) { - return lengths[index]; - } - - public void close() { - for (InputStream in : ins) { - Util.closeQuietly(in); - } - } - } - - private static final OutputStream NULL_OUTPUT_STREAM = new OutputStream() { - @Override - public void write(int b) throws IOException { - // Eat all writes silently. Nom nom. - } - }; - - /** Edits the values for an entry. */ - public final class Editor { - private final Entry entry; - private final boolean[] written; - private boolean hasErrors; - private boolean committed; - - private Editor(Entry entry) { - this.entry = entry; - this.written = (entry.readable) ? null : new boolean[valueCount]; - } - - /** - * Returns an unbuffered input stream to read the last committed value, - * or null if no value has been committed. - */ - public InputStream newInputStream(int index) throws IOException { - synchronized (DiskLruCache.this) { - if (entry.currentEditor != this) { - throw new IllegalStateException(); - } - if (!entry.readable) { - return null; - } - try { - return new FileInputStream(entry.getCleanFile(index)); - } catch (FileNotFoundException e) { - return null; - } - } - } - - /** - * Returns the last committed value as a string, or null if no value - * has been committed. - */ - public String getString(int index) throws IOException { - InputStream in = newInputStream(index); - return in != null ? inputStreamToString(in) : null; - } - - /** - * Returns a new unbuffered output stream to write the value at - * {@code index}. If the underlying output stream encounters errors - * when writing to the filesystem, this edit will be aborted when - * {@link #commit} is called. The returned output stream does not throw - * IOExceptions. - */ - public OutputStream newOutputStream(int index) throws IOException { - if (index < 0 || index >= valueCount) { - throw new IllegalArgumentException("Expected index " + index + " to " - + "be greater than 0 and less than the maximum value count " - + "of " + valueCount); - } - synchronized (DiskLruCache.this) { - if (entry.currentEditor != this) { - throw new IllegalStateException(); - } - if (!entry.readable) { - written[index] = true; - } - File dirtyFile = entry.getDirtyFile(index); - FileOutputStream outputStream; - try { - outputStream = new FileOutputStream(dirtyFile); - } catch (FileNotFoundException e) { - // Attempt to recreate the cache directory. - directory.mkdirs(); - try { - outputStream = new FileOutputStream(dirtyFile); - } catch (FileNotFoundException e2) { - // We are unable to recover. Silently eat the writes. - return NULL_OUTPUT_STREAM; - } - } - return new FaultHidingOutputStream(outputStream); - } - } - - /** Sets the value at {@code index} to {@code value}. */ - public void set(int index, String value) throws IOException { - Writer writer = null; - try { - writer = new OutputStreamWriter(newOutputStream(index), Util.UTF_8); - writer.write(value); - } finally { - Util.closeQuietly(writer); - } - } - - /** - * Commits this edit so it is visible to readers. This releases the - * edit lock so another edit may be started on the same key. - */ - public void commit() throws IOException { - if (hasErrors) { - completeEdit(this, false); - remove(entry.key); // The previous entry is stale. - } else { - completeEdit(this, true); - } - committed = true; - } - - /** - * Aborts this edit. This releases the edit lock so another edit may be - * started on the same key. - */ - public void abort() throws IOException { - completeEdit(this, false); - } - - public void abortUnlessCommitted() { - if (!committed) { - try { - abort(); - } catch (IOException ignored) { - } - } - } - - private class FaultHidingOutputStream extends FilterOutputStream { - private FaultHidingOutputStream(OutputStream out) { - super(out); - } - - @Override public void write(int oneByte) { - try { - out.write(oneByte); - } catch (IOException e) { - hasErrors = true; - } - } - - @Override public void write(byte[] buffer, int offset, int length) { - try { - out.write(buffer, offset, length); - } catch (IOException e) { - hasErrors = true; - } - } - - @Override public void close() { - try { - out.close(); - } catch (IOException e) { - hasErrors = true; - } - } - - @Override public void flush() { - try { - out.flush(); - } catch (IOException e) { - hasErrors = true; - } - } - } - } - - private final class Entry { - private final String key; - - /** Lengths of this entry's files. */ - private final long[] lengths; - - /** True if this entry has ever been published. */ - private boolean readable; - - /** The ongoing edit or null if this entry is not being edited. */ - private Editor currentEditor; - - /** The sequence number of the most recently committed edit to this entry. */ - private long sequenceNumber; - - private Entry(String key) { - this.key = key; - this.lengths = new long[valueCount]; - } - - public String getLengths() throws IOException { - StringBuilder result = new StringBuilder(); - for (long size : lengths) { - result.append(' ').append(size); - } - return result.toString(); - } - - /** Set lengths using decimal numbers like "10123". */ - private void setLengths(String[] strings) throws IOException { - if (strings.length != valueCount) { - throw invalidLengths(strings); - } - - try { - for (int i = 0; i < strings.length; i++) { - lengths[i] = Long.parseLong(strings[i]); - } - } catch (NumberFormatException e) { - throw invalidLengths(strings); - } - } - - private IOException invalidLengths(String[] strings) throws IOException { - throw new IOException("unexpected journal line: " + java.util.Arrays.toString(strings)); - } - - public File getCleanFile(int i) { - return new File(directory, key + "." + i); - } - - public File getDirtyFile(int i) { - return new File(directory, key + "." + i + ".tmp"); - } - } -} diff --git a/mobile/android/thirdparty/com/jakewharton/disklrucache/StrictLineReader.java b/mobile/android/thirdparty/com/jakewharton/disklrucache/StrictLineReader.java deleted file mode 100644 index c90691ce4..000000000 --- a/mobile/android/thirdparty/com/jakewharton/disklrucache/StrictLineReader.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.jakewharton.disklrucache; - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; - -/** - * Buffers input from an {@link InputStream} for reading lines. - * - * <p>This class is used for buffered reading of lines. For purposes of this class, a line ends - * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated - * line at end of input is invalid and will be ignored, the caller may use {@code - * hasUnterminatedLine()} to detect it after catching the {@code EOFException}. - * - * <p>This class is intended for reading input that strictly consists of lines, such as line-based - * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction - * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different - * end-of-input reporting and a more restrictive definition of a line. - * - * <p>This class supports only charsets that encode '\r' and '\n' as a single byte with value 13 - * and 10, respectively, and the representation of no other character contains these values. - * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1. - * The default charset is US_ASCII. - */ -class StrictLineReader implements Closeable { - private static final byte CR = (byte) '\r'; - private static final byte LF = (byte) '\n'; - - private final InputStream in; - private final Charset charset; - - /* - * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end - * and the data in the range [pos, end) is buffered for reading. At end of input, if there is - * an unterminated line, we set end == -1, otherwise end == pos. If the underlying - * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1. - */ - private byte[] buf; - private int pos; - private int end; - - /** - * Constructs a new {@code LineReader} with the specified charset and the default capacity. - * - * @param in the {@code InputStream} to read data from. - * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are - * supported. - * @throws NullPointerException if {@code in} or {@code charset} is null. - * @throws IllegalArgumentException if the specified charset is not supported. - */ - public StrictLineReader(InputStream in, Charset charset) { - this(in, 8192, charset); - } - - /** - * Constructs a new {@code LineReader} with the specified capacity and charset. - * - * @param in the {@code InputStream} to read data from. - * @param capacity the capacity of the buffer. - * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are - * supported. - * @throws NullPointerException if {@code in} or {@code charset} is null. - * @throws IllegalArgumentException if {@code capacity} is negative or zero - * or the specified charset is not supported. - */ - public StrictLineReader(InputStream in, int capacity, Charset charset) { - if (in == null || charset == null) { - throw new NullPointerException(); - } - if (capacity < 0) { - throw new IllegalArgumentException("capacity <= 0"); - } - if (!(charset.equals(Util.US_ASCII))) { - throw new IllegalArgumentException("Unsupported encoding"); - } - - this.in = in; - this.charset = charset; - buf = new byte[capacity]; - } - - /** - * Closes the reader by closing the underlying {@code InputStream} and - * marking this reader as closed. - * - * @throws IOException for errors when closing the underlying {@code InputStream}. - */ - public void close() throws IOException { - synchronized (in) { - if (buf != null) { - buf = null; - in.close(); - } - } - } - - /** - * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"}, - * this end of line marker is not included in the result. - * - * @return the next line from the input. - * @throws IOException for underlying {@code InputStream} errors. - * @throws EOFException for the end of source stream. - */ - public String readLine() throws IOException { - synchronized (in) { - if (buf == null) { - throw new IOException("LineReader is closed"); - } - - // Read more data if we are at the end of the buffered data. - // Though it's an error to read after an exception, we will let {@code fillBuf()} - // throw again if that happens; thus we need to handle end == -1 as well as end == pos. - if (pos >= end) { - fillBuf(); - } - // Try to find LF in the buffered data and return the line if successful. - for (int i = pos; i != end; ++i) { - if (buf[i] == LF) { - int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i; - String res = new String(buf, pos, lineEnd - pos, charset.name()); - pos = i + 1; - return res; - } - } - - // Let's anticipate up to 80 characters on top of those already read. - ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) { - @Override - public String toString() { - int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count; - try { - return new String(buf, 0, length, charset.name()); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); // Since we control the charset this will never happen. - } - } - }; - - while (true) { - out.write(buf, pos, end - pos); - // Mark unterminated line in case fillBuf throws EOFException or IOException. - end = -1; - fillBuf(); - // Try to find LF in the buffered data and return the line if successful. - for (int i = pos; i != end; ++i) { - if (buf[i] == LF) { - if (i != pos) { - out.write(buf, pos, i - pos); - } - pos = i + 1; - return out.toString(); - } - } - } - } - } - - public boolean hasUnterminatedLine() { - return end == -1; - } - - /** - * Reads new input data into the buffer. Call only with pos == end or end == -1, - * depending on the desired outcome if the function throws. - */ - private void fillBuf() throws IOException { - int result = in.read(buf, 0, buf.length); - if (result == -1) { - throw new EOFException(); - } - pos = 0; - end = result; - } -} - diff --git a/mobile/android/thirdparty/com/jakewharton/disklrucache/Util.java b/mobile/android/thirdparty/com/jakewharton/disklrucache/Util.java deleted file mode 100644 index 0a7dba9bc..000000000 --- a/mobile/android/thirdparty/com/jakewharton/disklrucache/Util.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.jakewharton.disklrucache; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.Reader; -import java.io.StringWriter; -import java.nio.charset.Charset; - -/** Junk drawer of utility methods. */ -final class Util { - static final Charset US_ASCII = Charset.forName("US-ASCII"); - static final Charset UTF_8 = Charset.forName("UTF-8"); - - private Util() { - } - - static String readFully(Reader reader) throws IOException { - try { - StringWriter writer = new StringWriter(); - char[] buffer = new char[1024]; - int count; - while ((count = reader.read(buffer)) != -1) { - writer.write(buffer, 0, count); - } - return writer.toString(); - } finally { - reader.close(); - } - } - - /** - * Deletes the contents of {@code dir}. Throws an IOException if any file - * could not be deleted, or if {@code dir} is not a readable directory. - */ - static void deleteContents(File dir) throws IOException { - File[] files = dir.listFiles(); - if (files == null) { - throw new IOException("not a readable directory: " + dir); - } - for (File file : files) { - if (file.isDirectory()) { - deleteContents(file); - } - if (!file.delete()) { - throw new IOException("failed to delete file: " + file); - } - } - } - - static void closeQuietly(/*Auto*/Closeable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (RuntimeException rethrown) { - throw rethrown; - } catch (Exception ignored) { - } - } - } -} diff --git a/mobile/android/thirdparty/com/keepsafe/switchboard/AsyncConfigLoader.java b/mobile/android/thirdparty/com/keepsafe/switchboard/AsyncConfigLoader.java deleted file mode 100644 index 2cff4b4c3..000000000 --- a/mobile/android/thirdparty/com/keepsafe/switchboard/AsyncConfigLoader.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright 2012 KeepSafe Software Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -package com.keepsafe.switchboard; - - -import android.content.Context; -import android.os.AsyncTask; - -/** - * An async loader to load user config in background thread based on internal generated UUID. - * - * Call <code>AsyncConfigLoader.execute()</code> to load SwitchBoard.loadConfig() with own ID. - * To use your custom UUID call <code>AsyncConfigLoader.execute(uuid)</code> with uuid being your unique user id - * as a String - * - * @author Philipp Berner - * - */ -public class AsyncConfigLoader extends AsyncTask<Void, Void, Void> { - - private Context context; - private String defaultServerUrl; - - /** - * Sets the params for async loading either SwitchBoard.updateConfigServerUrl() - * or SwitchBoard.loadConfig. - * Loads config with a custom UUID - * @param c Application context - * @param defaultServerUrl Default URL endpoint for Switchboard config. - */ - public AsyncConfigLoader(Context c, String defaultServerUrl) { - this.context = c; - this.defaultServerUrl = defaultServerUrl; - } - - @Override - protected Void doInBackground(Void... params) { - SwitchBoard.loadConfig(context, defaultServerUrl); - return null; - } -} diff --git a/mobile/android/thirdparty/com/keepsafe/switchboard/DeviceUuidFactory.java b/mobile/android/thirdparty/com/keepsafe/switchboard/DeviceUuidFactory.java deleted file mode 100644 index c4476d2cd..000000000 --- a/mobile/android/thirdparty/com/keepsafe/switchboard/DeviceUuidFactory.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright 2012 KeepSafe Software Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -package com.keepsafe.switchboard; - -import java.util.UUID; - -import android.content.Context; -import android.content.SharedPreferences; - -/** - * Generates a UUID and stores is persistent as in the apps shared preferences. - * - * @author Philipp Berner - */ -public class DeviceUuidFactory { - protected static final String PREFS_FILE = "com.keepsafe.switchboard.uuid"; - protected static final String PREFS_DEVICE_ID = "device_id"; - - private static UUID uuid = null; - - public DeviceUuidFactory(Context context) { - if (uuid == null) { - synchronized (DeviceUuidFactory.class) { - if (uuid == null) { - final SharedPreferences prefs = context - .getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE); - final String id = prefs.getString(PREFS_DEVICE_ID, null); - - if (id != null) { - // Use the ids previously computed and stored in the prefs file - uuid = UUID.fromString(id); - } else { - uuid = UUID.randomUUID(); - - // Write the value out to the prefs file - prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString()).apply(); - } - } - } - } - } - - /** - * Returns a unique UUID for the current android device. As with all UUIDs, - * this unique ID is "very highly likely" to be unique across all Android - * devices. Much more so than ANDROID_ID is. - * - * The UUID is generated with <code>UUID.randomUUID()</code>. - * - * @return a UUID that may be used to uniquely identify your device for most - * purposes. - */ - public UUID getDeviceUuid() { - return uuid; - } - -}
\ No newline at end of file diff --git a/mobile/android/thirdparty/com/keepsafe/switchboard/Preferences.java b/mobile/android/thirdparty/com/keepsafe/switchboard/Preferences.java deleted file mode 100644 index f7f6f7cb7..000000000 --- a/mobile/android/thirdparty/com/keepsafe/switchboard/Preferences.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2012 KeepSafe Software Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -package com.keepsafe.switchboard; - - -import android.content.Context; -import android.content.SharedPreferences; -import android.support.annotation.Nullable; - -/** - * Application preferences for SwitchBoard. - * @author Philipp Berner - * - */ -public class Preferences { - - private static final String switchBoardSettings = "com.keepsafe.switchboard.settings"; - - private static final String CONFIG_JSON = "config-json"; - private static final String OVERRIDE_PREFIX = "experiment.override."; - - - /** - * Gets the user config as a JSON string. - * @param c Context - * @return Config JSON - */ - @Nullable public static String getDynamicConfigJson(Context c) { - final SharedPreferences prefs = c.getApplicationContext().getSharedPreferences(switchBoardSettings, Context.MODE_PRIVATE); - return prefs.getString(CONFIG_JSON, null); - } - - /** - * Saves the user config as a JSON sting. - * @param c Context - * @param configJson Config JSON - */ - public static void setDynamicConfigJson(Context c, String configJson) { - final SharedPreferences.Editor editor = c.getApplicationContext(). - getSharedPreferences(switchBoardSettings, Context.MODE_PRIVATE).edit(); - editor.putString(CONFIG_JSON, configJson); - editor.apply(); - } - - /** - * Gets the override value for an experiment. - * - * @param c Context - * @param experimentName Experiment name - * @return Whether or not the experiment should be enabled, or null if there is no override. - */ - @Nullable public static Boolean getOverrideValue(Context c, String experimentName) { - final SharedPreferences prefs = c.getApplicationContext(). - getSharedPreferences(switchBoardSettings, Context.MODE_PRIVATE); - - final String key = OVERRIDE_PREFIX + experimentName; - if (prefs.contains(key)) { - // This will never fall back to the default value. - return prefs.getBoolean(key, false); - } - - // Default to returning null if no override was found. - return null; - } - - /** - * Saves an override value for an experiment. - * - * @param c Context - * @param experimentName Experiment name - * @param isEnabled Whether or not to enable the experiment - */ - public static void setOverrideValue(Context c, String experimentName, boolean isEnabled) { - final SharedPreferences.Editor editor = c.getApplicationContext(). - getSharedPreferences(switchBoardSettings, Context.MODE_PRIVATE).edit(); - editor.putBoolean(OVERRIDE_PREFIX + experimentName, isEnabled); - editor.apply(); - } - - /** - * Clears the override value for an experiment. - * - * @param c Context - * @param experimentName Experiment name - */ - public static void clearOverrideValue(Context c, String experimentName) { - final SharedPreferences.Editor editor = c.getApplicationContext(). - getSharedPreferences(switchBoardSettings, Context.MODE_PRIVATE).edit(); - editor.remove(OVERRIDE_PREFIX + experimentName); - editor.apply(); - } -} diff --git a/mobile/android/thirdparty/com/keepsafe/switchboard/Switch.java b/mobile/android/thirdparty/com/keepsafe/switchboard/Switch.java deleted file mode 100644 index 5307750bb..000000000 --- a/mobile/android/thirdparty/com/keepsafe/switchboard/Switch.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - Copyright 2012 KeepSafe Software Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -package com.keepsafe.switchboard; - -import org.json.JSONObject; - -import android.content.Context; - -/** - * Single instance of an existing experiment for easier and cleaner code. - * - * @author Philipp Berner - * - */ -public class Switch { - - private Context context; - private String experimentName; - - /** - * Creates an instance of a single experiment to give more convenient access to its values. - * When the given experiment does not exist, it will give back default valued that can be found - * in <code>Switchboard</code>. Developer has to know that experiment exists when using it. - * @param c Application context - * @param experimentName Name of the experiment as defined on the server - */ - public Switch(Context c, String experimentName) { - this.context = c; - this.experimentName = experimentName; - } - - /** - * Returns true if the experiment is active for this particular user. - * @return Status of the experiment and false when experiment does not exist. - */ - public boolean isActive() { - return SwitchBoard.isInExperiment(context, experimentName); - } - - /** - * Returns true if the experiment has additional values. - * @return true when values exist - */ - public boolean hasValues() { - return SwitchBoard.hasExperimentValues(context, experimentName); - } - - /** - * Gives back all the experiment values in a JSONObject. This function checks if - * values exists. If no values exist, it returns null. - * @return Values in JSONObject or null if non - */ - public JSONObject getValues() { - if(hasValues()) - return SwitchBoard.getExperimentValuesFromJson(context, experimentName); - else - return null; - } -} diff --git a/mobile/android/thirdparty/com/keepsafe/switchboard/SwitchBoard.java b/mobile/android/thirdparty/com/keepsafe/switchboard/SwitchBoard.java deleted file mode 100644 index e99144045..000000000 --- a/mobile/android/thirdparty/com/keepsafe/switchboard/SwitchBoard.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - Copyright 2012 KeepSafe Software Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -package com.keepsafe.switchboard; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.MissingResourceException; -import java.util.zip.CRC32; - -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONArray; - -import android.content.Context; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Log; - - -/** - * SwitchBoard is the core class of the KeepSafe Switchboard mobile A/B testing framework. - * This class provides a bunch of static methods that can be used in your app to run A/B tests. - * - * The SwitchBoard supports production and staging environment. - * - * For usage <code>initDefaultServerUrls</code> for first time usage. Server URLs can be updates from - * a remote location with <code>initConfigServerUrl</code>. - * - * To run a experiment use <code>isInExperiment()</code>. The experiment name has to match the one you - * setup on the server. - * All functions are design to be safe for programming mistakes and network connection issues. If the - * experiment does not exists it will return false and pretend the user is not part of it. - * - * @author Philipp Berner - * - */ -public class SwitchBoard { - - private static final String TAG = "SwitchBoard"; - - /** Set if the application is run in debug mode. */ - public static boolean DEBUG = true; - - // Top-level experiment keys. - private static final String KEY_DATA = "data"; - private static final String KEY_NAME = "name"; - private static final String KEY_MATCH = "match"; - private static final String KEY_BUCKETS = "buckets"; - private static final String KEY_VALUES = "values"; - - // Match keys. - private static final String KEY_APP_ID = "appId"; - private static final String KEY_COUNTRY = "country"; - private static final String KEY_DEVICE = "device"; - private static final String KEY_LANG = "lang"; - private static final String KEY_MANUFACTURER = "manufacturer"; - private static final String KEY_VERSION = "version"; - - // Bucket keys. - private static final String KEY_MIN = "min"; - private static final String KEY_MAX = "max"; - - /** - * Loads a new config for a user. This method does network I/O, so it - * should not be called on the main thread. - * - * @param c ApplicationContext - * @param serverUrl Server URL endpoint. - */ - static void loadConfig(Context c, @NonNull String serverUrl) { - final URL url; - try { - url = new URL(serverUrl); - } catch (MalformedURLException e) { - Log.e(TAG, "Exception creating server URL", e); - return; - } - - final String result = readFromUrlGET(url); - if (DEBUG) Log.d(TAG, "Result: " + result); - if (result == null) { - return; - } - - // Cache result locally in shared preferences. - Preferences.setDynamicConfigJson(c, result); - } - - public static boolean isInBucket(Context c, int low, int high) { - final int userBucket = getUserBucket(c); - return (userBucket >= low) && (userBucket < high); - } - - /** - * Looks up in config if user is in certain experiment. Returns false as a default value when experiment - * does not exist. - * Experiment names are defined server side as Key in array for return values. - * @param experimentName Name of the experiment to lookup - * @return returns value for experiment or false if experiment does not exist. - */ - public static boolean isInExperiment(Context c, String experimentName) { - final Boolean override = Preferences.getOverrideValue(c, experimentName); - if (override != null) { - return override; - } - - final String config = Preferences.getDynamicConfigJson(c); - if (config == null) { - return false; - } - - try { - // TODO: cache the array into a mapping so we don't do a loop everytime we are looking for a experiment key - final JSONArray experiments = new JSONObject(config).getJSONArray(KEY_DATA); - JSONObject experiment = null; - - for (int i = 0; i < experiments.length(); i++) { - JSONObject entry = experiments.getJSONObject(i); - final String name = entry.getString(KEY_NAME); - if (name.equals(experimentName)) { - experiment = entry; - break; - } - } - - if (experiment == null) { - return false; - } - - if (!isMatch(c, experiment.optJSONObject(KEY_MATCH))) { - return false; - } - - final JSONObject buckets = experiment.getJSONObject(KEY_BUCKETS); - final boolean inExperiment = isInBucket(c, buckets.getInt(KEY_MIN), buckets.getInt(KEY_MAX)); - - if (DEBUG) { - Log.d(TAG, experimentName + " = " + inExperiment); - } - return inExperiment; - } catch (JSONException e) { - // If the experiment name is not found in the JSON, just return false. - // There is no need to log an error, since we don't really care if an - // inactive experiment is missing from the config. - return false; - } - } - - private static List<String> getExperimentNames(Context c) throws JSONException { - // TODO: cache the array into a mapping so we don't do a loop everytime we are looking for a experiment key - final List<String> returnList = new ArrayList<>(); - final String config = Preferences.getDynamicConfigJson(c); - final JSONArray experiments = new JSONObject(config).getJSONArray(KEY_DATA); - - for (int i = 0; i < experiments.length(); i++) { - JSONObject entry = experiments.getJSONObject(i); - returnList.add(entry.getString(KEY_NAME)); - } - return returnList; - } - - @Nullable - private static JSONObject getExperiment(Context c, String experimentName) throws JSONException { - // TODO: cache the array into a mapping so we don't do a loop everytime we are looking for a experiment key - final String config = Preferences.getDynamicConfigJson(c); - final JSONArray experiments = new JSONObject(config).getJSONArray(KEY_DATA); - JSONObject experiment = null; - - for (int i = 0; i < experiments.length(); i++) { - JSONObject entry = experiments.getJSONObject(i); - if (entry.getString(KEY_NAME).equals(experimentName)) { - experiment = entry; - break; - } - } - return experiment; - } - - private static boolean isMatch(Context c, @Nullable JSONObject matchKeys) { - // If no match keys are specified, default to enabling the experiment. - if (matchKeys == null) { - return true; - } - - if (matchKeys.has(KEY_APP_ID)) { - final String packageName = c.getPackageName(); - try { - if (!packageName.matches(matchKeys.getString(KEY_APP_ID))) { - return false; - } - } catch (JSONException e) { - Log.e(TAG, "Exception matching appId", e); - } - } - - if (matchKeys.has(KEY_COUNTRY)) { - try { - final String country = Locale.getDefault().getISO3Country(); - if (!country.matches(matchKeys.getString(KEY_COUNTRY))) { - return false; - } - } catch (MissingResourceException|JSONException e) { - Log.e(TAG, "Exception matching country", e); - } - } - - if (matchKeys.has(KEY_DEVICE)) { - final String device = Build.DEVICE; - try { - if (!device.matches(matchKeys.getString(KEY_DEVICE))) { - return false; - } - } catch (JSONException e) { - Log.e(TAG, "Exception matching device", e); - } - - } - if (matchKeys.has(KEY_LANG)) { - try { - final String lang = Locale.getDefault().getISO3Language(); - if (!lang.matches(matchKeys.getString(KEY_LANG))) { - return false; - } - } catch (MissingResourceException|JSONException e) { - Log.e(TAG, "Exception matching lang", e); - } - } - if (matchKeys.has(KEY_MANUFACTURER)) { - final String manufacturer = Build.MANUFACTURER; - try { - if (!manufacturer.matches(matchKeys.getString(KEY_MANUFACTURER))) { - return false; - } - } catch (JSONException e) { - Log.e(TAG, "Exception matching manufacturer", e); - } - } - - if (matchKeys.has(KEY_VERSION)) { - try { - final String version = c.getPackageManager().getPackageInfo(c.getPackageName(), 0).versionName; - if (!version.matches(matchKeys.getString(KEY_VERSION))) { - return false; - } - } catch (NameNotFoundException|JSONException e) { - Log.e(TAG, "Exception matching version", e); - } - } - - // Default to return true if no matches failed. - return true; - } - - /** - * @return a list of all active experiments. - */ - public static List<String> getActiveExperiments(Context c) { - final List<String> returnList = new ArrayList<>(); - - final String config = Preferences.getDynamicConfigJson(c); - if (config == null) { - return returnList; - } - - try { - final JSONObject data = new JSONObject(config); - final List<String> experiments = getExperimentNames(c); - - for (int i = 0; i < experiments.size(); i++) { - final String name = experiments.get(i); - - // Check override value before reading saved JSON. - Boolean isActive = Preferences.getOverrideValue(c, name); - if (isActive == null) { - // TODO: This is inefficient because it will check all the match cases on all experiments. - isActive = isInExperiment(c, name); - } - if (isActive) { - returnList.add(name); - } - } - } catch (JSONException e) { - // Something went wrong! - } - - return returnList; - } - - /** - * Checks if a certain experiment has additional values. - * @param c ApplicationContext - * @param experimentName Name of the experiment - * @return true when experiment exists - */ - public static boolean hasExperimentValues(Context c, String experimentName) { - return getExperimentValuesFromJson(c, experimentName) != null; - } - - /** - * Returns the experiment value as a JSONObject. - * @param experimentName Name of the experiment - * @return Experiment value as String, null if experiment does not exist. - */ - @Nullable - public static JSONObject getExperimentValuesFromJson(Context c, String experimentName) { - final String config = Preferences.getDynamicConfigJson(c); - - if (config == null) { - return null; - } - - try { - final JSONObject experiment = getExperiment(c, experimentName); - if (experiment == null) { - return null; - } - return experiment.getJSONObject(KEY_VALUES); - } catch (JSONException e) { - Log.e(TAG, "Could not create JSON object from config string", e); - } - - return null; - } - - /** - * Returns a String containing the server response from a GET request - * @param url URL for GET request. - * @return Returns String from server or null when failed. - */ - @Nullable private static String readFromUrlGET(URL url) { - try { - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - connection.setUseCaches(false); - - InputStream is = connection.getInputStream(); - InputStreamReader inputStreamReader = new InputStreamReader(is); - BufferedReader bufferReader = new BufferedReader(inputStreamReader, 8192); - String line; - StringBuilder resultContent = new StringBuilder(); - while ((line = bufferReader.readLine()) != null) { - resultContent.append(line); - } - bufferReader.close(); - - return resultContent.toString(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - /** - * Return the bucket number of the user. There are 100 possible buckets. - */ - private static int getUserBucket(Context c) { - final DeviceUuidFactory df = new DeviceUuidFactory(c); - final String uuid = df.getDeviceUuid().toString(); - - CRC32 crc = new CRC32(); - crc.update(uuid.getBytes()); - long checksum = crc.getValue(); - return (int)(checksum % 100L); - } -} diff --git a/mobile/android/thirdparty/com/squareup/leakcanary/LeakCanary.java b/mobile/android/thirdparty/com/squareup/leakcanary/LeakCanary.java deleted file mode 100644 index a9e44437d..000000000 --- a/mobile/android/thirdparty/com/squareup/leakcanary/LeakCanary.java +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package com.squareup.leakcanary; - -import android.app.Application; - -/** - * A no-op version of {@link LeakCanary} that can be used in release builds. - */ -public final class LeakCanary { - public static RefWatcher install(Application application) { - return RefWatcher.DISABLED; - } - - private LeakCanary() { - throw new AssertionError(); - } -} diff --git a/mobile/android/thirdparty/com/squareup/leakcanary/RefWatcher.java b/mobile/android/thirdparty/com/squareup/leakcanary/RefWatcher.java deleted file mode 100644 index 3c75dcdee..000000000 --- a/mobile/android/thirdparty/com/squareup/leakcanary/RefWatcher.java +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package com.squareup.leakcanary; - -/** - * No-op implementation of {@link RefWatcher} for release builds. Please use {@link - * RefWatcher#DISABLED}. - */ -public final class RefWatcher { - public static final RefWatcher DISABLED = new RefWatcher(); - - private RefWatcher() {} - - public void watch(Object watchedReference) {} - - public void watch(Object watchedReference, String referenceName) {} -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Action.java b/mobile/android/thirdparty/com/squareup/picasso/Action.java deleted file mode 100644 index 5f176d770..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Action.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; - -abstract class Action<T> { - static class RequestWeakReference<T> extends WeakReference<T> { - final Action action; - - public RequestWeakReference(Action action, T referent, ReferenceQueue<? super T> q) { - super(referent, q); - this.action = action; - } - } - - final Picasso picasso; - final Request data; - final WeakReference<T> target; - final boolean skipCache; - final boolean noFade; - final int errorResId; - final Drawable errorDrawable; - final String key; - - boolean cancelled; - - Action(Picasso picasso, T target, Request data, boolean skipCache, boolean noFade, - int errorResId, Drawable errorDrawable, String key) { - this.picasso = picasso; - this.data = data; - this.target = new RequestWeakReference<T>(this, target, picasso.referenceQueue); - this.skipCache = skipCache; - this.noFade = noFade; - this.errorResId = errorResId; - this.errorDrawable = errorDrawable; - this.key = key; - } - - abstract void complete(Bitmap result, Picasso.LoadedFrom from); - - abstract void error(); - - void cancel() { - cancelled = true; - } - - Request getData() { - return data; - } - - T getTarget() { - return target.get(); - } - - String getKey() { - return key; - } - - boolean isCancelled() { - return cancelled; - } - - Picasso getPicasso() { - return picasso; - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/AssetBitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/AssetBitmapHunter.java deleted file mode 100644 index c0245ed3f..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/AssetBitmapHunter.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.squareup.picasso; - -import android.content.Context; -import android.content.res.AssetManager; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import java.io.IOException; -import java.io.InputStream; - -import static com.squareup.picasso.Picasso.LoadedFrom.DISK; - -class AssetBitmapHunter extends BitmapHunter { - private AssetManager assetManager; - - public AssetBitmapHunter(Context context, Picasso picasso, Dispatcher dispatcher, Cache cache, - Stats stats, Action action) { - super(picasso, dispatcher, cache, stats, action); - assetManager = context.getAssets(); - } - - @Override Bitmap decode(Request data) throws IOException { - String filePath = data.uri.toString().substring(ASSET_PREFIX_LENGTH); - return decodeAsset(filePath); - } - - @Override Picasso.LoadedFrom getLoadedFrom() { - return DISK; - } - - Bitmap decodeAsset(String filePath) throws IOException { - BitmapFactory.Options options = null; - if (data.hasSize()) { - options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - InputStream is = null; - try { - is = assetManager.open(filePath); - BitmapFactory.decodeStream(is, null, options); - } finally { - Utils.closeQuietly(is); - } - calculateInSampleSize(data.targetWidth, data.targetHeight, options); - } - InputStream is = assetManager.open(filePath); - try { - return BitmapFactory.decodeStream(is, null, options); - } finally { - Utils.closeQuietly(is); - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/BitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/BitmapHunter.java deleted file mode 100644 index b8aa87c48..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/BitmapHunter.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.net.NetworkInfo; -import android.net.Uri; -import android.provider.MediaStore; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Future; - -import static android.content.ContentResolver.SCHEME_ANDROID_RESOURCE; -import static android.content.ContentResolver.SCHEME_CONTENT; -import static android.content.ContentResolver.SCHEME_FILE; -import static android.provider.ContactsContract.Contacts; -import static com.squareup.picasso.Picasso.LoadedFrom.MEMORY; - -abstract class BitmapHunter implements Runnable { - - /** - * Global lock for bitmap decoding to ensure that we are only are decoding one at a time. Since - * this will only ever happen in background threads we help avoid excessive memory thrashing as - * well as potential OOMs. Shamelessly stolen from Volley. - */ - private static final Object DECODE_LOCK = new Object(); - private static final String ANDROID_ASSET = "android_asset"; - protected static final int ASSET_PREFIX_LENGTH = - (SCHEME_FILE + ":///" + ANDROID_ASSET + "/").length(); - - final Picasso picasso; - final Dispatcher dispatcher; - final Cache cache; - final Stats stats; - final String key; - final Request data; - final List<Action> actions; - final boolean skipMemoryCache; - - Bitmap result; - Future<?> future; - Picasso.LoadedFrom loadedFrom; - Exception exception; - int exifRotation; // Determined during decoding of original resource. - - BitmapHunter(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats, Action action) { - this.picasso = picasso; - this.dispatcher = dispatcher; - this.cache = cache; - this.stats = stats; - this.key = action.getKey(); - this.data = action.getData(); - this.skipMemoryCache = action.skipCache; - this.actions = new ArrayList<Action>(4); - attach(action); - } - - protected void setExifRotation(int exifRotation) { - this.exifRotation = exifRotation; - } - - @Override public void run() { - try { - Thread.currentThread().setName(Utils.THREAD_PREFIX + data.getName()); - - result = hunt(); - - if (result == null) { - dispatcher.dispatchFailed(this); - } else { - dispatcher.dispatchComplete(this); - } - } catch (Downloader.ResponseException e) { - exception = e; - dispatcher.dispatchFailed(this); - } catch (IOException e) { - exception = e; - dispatcher.dispatchRetry(this); - } catch (OutOfMemoryError e) { - StringWriter writer = new StringWriter(); - stats.createSnapshot().dump(new PrintWriter(writer)); - exception = new RuntimeException(writer.toString(), e); - dispatcher.dispatchFailed(this); - } catch (Exception e) { - exception = e; - dispatcher.dispatchFailed(this); - } finally { - Thread.currentThread().setName(Utils.THREAD_IDLE_NAME); - } - } - - abstract Bitmap decode(Request data) throws IOException; - - Bitmap hunt() throws IOException { - Bitmap bitmap; - - if (!skipMemoryCache) { - bitmap = cache.get(key); - if (bitmap != null) { - stats.dispatchCacheHit(); - loadedFrom = MEMORY; - return bitmap; - } - } - - bitmap = decode(data); - - if (bitmap != null) { - stats.dispatchBitmapDecoded(bitmap); - if (data.needsTransformation() || exifRotation != 0) { - synchronized (DECODE_LOCK) { - if (data.needsMatrixTransform() || exifRotation != 0) { - bitmap = transformResult(data, bitmap, exifRotation); - } - if (data.hasCustomTransformations()) { - bitmap = applyCustomTransformations(data.transformations, bitmap); - } - } - stats.dispatchBitmapTransformed(bitmap); - } - } - - return bitmap; - } - - void attach(Action action) { - actions.add(action); - } - - void detach(Action action) { - actions.remove(action); - } - - boolean cancel() { - return actions.isEmpty() && future != null && future.cancel(false); - } - - boolean isCancelled() { - return future != null && future.isCancelled(); - } - - boolean shouldSkipMemoryCache() { - return skipMemoryCache; - } - - boolean shouldRetry(boolean airplaneMode, NetworkInfo info) { - return false; - } - - Bitmap getResult() { - return result; - } - - String getKey() { - return key; - } - - Request getData() { - return data; - } - - List<Action> getActions() { - return actions; - } - - Exception getException() { - return exception; - } - - Picasso.LoadedFrom getLoadedFrom() { - return loadedFrom; - } - - static BitmapHunter forRequest(Context context, Picasso picasso, Dispatcher dispatcher, - Cache cache, Stats stats, Action action, Downloader downloader) { - if (action.getData().resourceId != 0) { - return new ResourceBitmapHunter(context, picasso, dispatcher, cache, stats, action); - } - Uri uri = action.getData().uri; - String scheme = uri.getScheme(); - if (SCHEME_CONTENT.equals(scheme)) { - if (Contacts.CONTENT_URI.getHost().equals(uri.getHost()) // - && !uri.getPathSegments().contains(Contacts.Photo.CONTENT_DIRECTORY)) { - return new ContactsPhotoBitmapHunter(context, picasso, dispatcher, cache, stats, action); - } else if (MediaStore.AUTHORITY.equals(uri.getAuthority())) { - return new MediaStoreBitmapHunter(context, picasso, dispatcher, cache, stats, action); - } else { - return new ContentStreamBitmapHunter(context, picasso, dispatcher, cache, stats, action); - } - } else if (SCHEME_FILE.equals(scheme)) { - if (!uri.getPathSegments().isEmpty() && ANDROID_ASSET.equals(uri.getPathSegments().get(0))) { - return new AssetBitmapHunter(context, picasso, dispatcher, cache, stats, action); - } - return new FileBitmapHunter(context, picasso, dispatcher, cache, stats, action); - } else if (SCHEME_ANDROID_RESOURCE.equals(scheme)) { - return new ResourceBitmapHunter(context, picasso, dispatcher, cache, stats, action); - } else { - return new NetworkBitmapHunter(picasso, dispatcher, cache, stats, action, downloader); - } - } - - static void calculateInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options) { - calculateInSampleSize(reqWidth, reqHeight, options.outWidth, options.outHeight, options); - } - - static void calculateInSampleSize(int reqWidth, int reqHeight, int width, int height, - BitmapFactory.Options options) { - int sampleSize = 1; - if (height > reqHeight || width > reqWidth) { - final int heightRatio = Math.round((float) height / (float) reqHeight); - final int widthRatio = Math.round((float) width / (float) reqWidth); - sampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; - } - - options.inSampleSize = sampleSize; - options.inJustDecodeBounds = false; - } - - static Bitmap applyCustomTransformations(List<Transformation> transformations, Bitmap result) { - for (int i = 0, count = transformations.size(); i < count; i++) { - final Transformation transformation = transformations.get(i); - Bitmap newResult = transformation.transform(result); - - if (newResult == null) { - final StringBuilder builder = new StringBuilder() // - .append("Transformation ") - .append(transformation.key()) - .append(" returned null after ") - .append(i) - .append(" previous transformation(s).\n\nTransformation list:\n"); - for (Transformation t : transformations) { - builder.append(t.key()).append('\n'); - } - Picasso.HANDLER.post(new Runnable() { - @Override public void run() { - throw new NullPointerException(builder.toString()); - } - }); - return null; - } - - if (newResult == result && result.isRecycled()) { - Picasso.HANDLER.post(new Runnable() { - @Override public void run() { - throw new IllegalStateException("Transformation " - + transformation.key() - + " returned input Bitmap but recycled it."); - } - }); - return null; - } - - // If the transformation returned a new bitmap ensure they recycled the original. - if (newResult != result && !result.isRecycled()) { - Picasso.HANDLER.post(new Runnable() { - @Override public void run() { - throw new IllegalStateException("Transformation " - + transformation.key() - + " mutated input Bitmap but failed to recycle the original."); - } - }); - return null; - } - - result = newResult; - } - return result; - } - - static Bitmap transformResult(Request data, Bitmap result, int exifRotation) { - int inWidth = result.getWidth(); - int inHeight = result.getHeight(); - - int drawX = 0; - int drawY = 0; - int drawWidth = inWidth; - int drawHeight = inHeight; - - Matrix matrix = new Matrix(); - - if (data.needsMatrixTransform()) { - int targetWidth = data.targetWidth; - int targetHeight = data.targetHeight; - - float targetRotation = data.rotationDegrees; - if (targetRotation != 0) { - if (data.hasRotationPivot) { - matrix.setRotate(targetRotation, data.rotationPivotX, data.rotationPivotY); - } else { - matrix.setRotate(targetRotation); - } - } - - if (data.centerCrop) { - float widthRatio = targetWidth / (float) inWidth; - float heightRatio = targetHeight / (float) inHeight; - float scale; - if (widthRatio > heightRatio) { - scale = widthRatio; - int newSize = (int) Math.ceil(inHeight * (heightRatio / widthRatio)); - drawY = (inHeight - newSize) / 2; - drawHeight = newSize; - } else { - scale = heightRatio; - int newSize = (int) Math.ceil(inWidth * (widthRatio / heightRatio)); - drawX = (inWidth - newSize) / 2; - drawWidth = newSize; - } - matrix.preScale(scale, scale); - } else if (data.centerInside) { - float widthRatio = targetWidth / (float) inWidth; - float heightRatio = targetHeight / (float) inHeight; - float scale = widthRatio < heightRatio ? widthRatio : heightRatio; - matrix.preScale(scale, scale); - } else if (targetWidth != 0 && targetHeight != 0 // - && (targetWidth != inWidth || targetHeight != inHeight)) { - // If an explicit target size has been specified and they do not match the results bounds, - // pre-scale the existing matrix appropriately. - float sx = targetWidth / (float) inWidth; - float sy = targetHeight / (float) inHeight; - matrix.preScale(sx, sy); - } - } - - if (exifRotation != 0) { - matrix.preRotate(exifRotation); - } - - Bitmap newResult = - Bitmap.createBitmap(result, drawX, drawY, drawWidth, drawHeight, matrix, true); - if (newResult != result) { - result.recycle(); - result = newResult; - } - - return result; - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Cache.java b/mobile/android/thirdparty/com/squareup/picasso/Cache.java deleted file mode 100644 index bce297f9e..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Cache.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; - -/** - * A memory cache for storing the most recently used images. - * <p/> - * <em>Note:</em> The {@link Cache} is accessed by multiple threads. You must ensure - * your {@link Cache} implementation is thread safe when {@link Cache#get(String)} or {@link - * Cache#set(String, android.graphics.Bitmap)} is called. - */ -public interface Cache { - /** Retrieve an image for the specified {@code key} or {@code null}. */ - Bitmap get(String key); - - /** Store an image in the cache for the specified {@code key}. */ - void set(String key, Bitmap bitmap); - - /** Returns the current size of the cache in bytes. */ - int size(); - - /** Returns the maximum size in bytes that the cache can hold. */ - int maxSize(); - - /** Clears the cache. */ - void clear(); - - /** A cache which does not store any values. */ - Cache NONE = new Cache() { - @Override public Bitmap get(String key) { - return null; - } - - @Override public void set(String key, Bitmap bitmap) { - // Ignore. - } - - @Override public int size() { - return 0; - } - - @Override public int maxSize() { - return 0; - } - - @Override public void clear() { - } - }; -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Callback.java b/mobile/android/thirdparty/com/squareup/picasso/Callback.java deleted file mode 100644 index d93620889..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Callback.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -public interface Callback { - void onSuccess(); - - void onError(); - - public static class EmptyCallback implements Callback { - - @Override public void onSuccess() { - } - - @Override public void onError() { - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/ContactsPhotoBitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/ContactsPhotoBitmapHunter.java deleted file mode 100644 index 9444167b4..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/ContactsPhotoBitmapHunter.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.content.Context; -import android.content.UriMatcher; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.provider.ContactsContract; - -import java.io.IOException; -import java.io.InputStream; - -import static android.os.Build.VERSION.SDK_INT; -import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH; -import static android.provider.ContactsContract.Contacts.openContactPhotoInputStream; -import static com.squareup.picasso.Picasso.LoadedFrom.DISK; - -class ContactsPhotoBitmapHunter extends BitmapHunter { - /** A lookup uri (e.g. content://com.android.contacts/contacts/lookup/3570i61d948d30808e537) */ - private static final int ID_LOOKUP = 1; - /** A contact thumbnail uri (e.g. content://com.android.contacts/contacts/38/photo) */ - private static final int ID_THUMBNAIL = 2; - /** A contact uri (e.g. content://com.android.contacts/contacts/38) */ - private static final int ID_CONTACT = 3; - /** - * A contact display photo (high resolution) uri - * (e.g. content://com.android.contacts/display_photo/5) - */ - private static final int ID_DISPLAY_PHOTO = 4; - - private static final UriMatcher matcher; - - static { - matcher = new UriMatcher(UriMatcher.NO_MATCH); - matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", ID_LOOKUP); - matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", ID_LOOKUP); - matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", ID_THUMBNAIL); - matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", ID_CONTACT); - matcher.addURI(ContactsContract.AUTHORITY, "display_photo/#", ID_DISPLAY_PHOTO); - } - - final Context context; - - ContactsPhotoBitmapHunter(Context context, Picasso picasso, Dispatcher dispatcher, Cache cache, - Stats stats, Action action) { - super(picasso, dispatcher, cache, stats, action); - this.context = context; - } - - @Override Bitmap decode(Request data) throws IOException { - InputStream is = null; - try { - is = getInputStream(); - return decodeStream(is, data); - } finally { - Utils.closeQuietly(is); - } - } - - @Override Picasso.LoadedFrom getLoadedFrom() { - return DISK; - } - - private InputStream getInputStream() throws IOException { - ContentResolver contentResolver = context.getContentResolver(); - Uri uri = getData().uri; - switch (matcher.match(uri)) { - case ID_LOOKUP: - uri = ContactsContract.Contacts.lookupContact(contentResolver, uri); - if (uri == null) { - return null; - } - // Resolved the uri to a contact uri, intentionally fall through to process the resolved uri - case ID_CONTACT: - if (SDK_INT < ICE_CREAM_SANDWICH) { - return openContactPhotoInputStream(contentResolver, uri); - } else { - return ContactPhotoStreamIcs.get(contentResolver, uri); - } - case ID_THUMBNAIL: - case ID_DISPLAY_PHOTO: - return contentResolver.openInputStream(uri); - default: - throw new IllegalStateException("Invalid uri: " + uri); - } - } - - private Bitmap decodeStream(InputStream stream, Request data) throws IOException { - if (stream == null) { - return null; - } - BitmapFactory.Options options = null; - if (data.hasSize()) { - options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - InputStream is = getInputStream(); - try { - BitmapFactory.decodeStream(is, null, options); - } finally { - Utils.closeQuietly(is); - } - calculateInSampleSize(data.targetWidth, data.targetHeight, options); - } - return BitmapFactory.decodeStream(stream, null, options); - } - - @TargetApi(ICE_CREAM_SANDWICH) - private static class ContactPhotoStreamIcs { - static InputStream get(ContentResolver contentResolver, Uri uri) { - return openContactPhotoInputStream(contentResolver, uri, true); - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/ContentStreamBitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/ContentStreamBitmapHunter.java deleted file mode 100644 index 624ffe078..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/ContentStreamBitmapHunter.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.ContentResolver; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import java.io.IOException; -import java.io.InputStream; - -import static com.squareup.picasso.Picasso.LoadedFrom.DISK; - -class ContentStreamBitmapHunter extends BitmapHunter { - final Context context; - - ContentStreamBitmapHunter(Context context, Picasso picasso, Dispatcher dispatcher, Cache cache, - Stats stats, Action action) { - super(picasso, dispatcher, cache, stats, action); - this.context = context; - } - - @Override Bitmap decode(Request data) - throws IOException { - return decodeContentStream(data); - } - - @Override Picasso.LoadedFrom getLoadedFrom() { - return DISK; - } - - protected Bitmap decodeContentStream(Request data) throws IOException { - ContentResolver contentResolver = context.getContentResolver(); - BitmapFactory.Options options = null; - if (data.hasSize()) { - options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - InputStream is = null; - try { - is = contentResolver.openInputStream(data.uri); - BitmapFactory.decodeStream(is, null, options); - } finally { - Utils.closeQuietly(is); - } - calculateInSampleSize(data.targetWidth, data.targetHeight, options); - } - InputStream is = contentResolver.openInputStream(data.uri); - try { - return BitmapFactory.decodeStream(is, null, options); - } finally { - Utils.closeQuietly(is); - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/DeferredRequestCreator.java b/mobile/android/thirdparty/com/squareup/picasso/DeferredRequestCreator.java deleted file mode 100644 index fbdaab1c3..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/DeferredRequestCreator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.view.ViewTreeObserver; -import android.widget.ImageView; -import java.lang.ref.WeakReference; - -class DeferredRequestCreator implements ViewTreeObserver.OnPreDrawListener { - - final RequestCreator creator; - final WeakReference<ImageView> target; - Callback callback; - - DeferredRequestCreator(RequestCreator creator, ImageView target, Callback callback) { - this.creator = creator; - this.target = new WeakReference<ImageView>(target); - this.callback = callback; - target.getViewTreeObserver().addOnPreDrawListener(this); - } - - @Override public boolean onPreDraw() { - ImageView target = this.target.get(); - if (target == null) { - return true; - } - ViewTreeObserver vto = target.getViewTreeObserver(); - if (!vto.isAlive()) { - return true; - } - - int width = target.getMeasuredWidth(); - int height = target.getMeasuredHeight(); - - if (width <= 0 || height <= 0) { - return true; - } - - vto.removeOnPreDrawListener(this); - - this.creator.unfit().resize(width, height).into(target, callback); - return true; - } - - void cancel() { - callback = null; - ImageView target = this.target.get(); - if (target == null) { - return; - } - ViewTreeObserver vto = target.getViewTreeObserver(); - if (!vto.isAlive()) { - return; - } - vto.removeOnPreDrawListener(this); - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Dispatcher.java b/mobile/android/thirdparty/com/squareup/picasso/Dispatcher.java deleted file mode 100644 index 6401431fb..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Dispatcher.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.Manifest; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; - -import static android.content.Context.CONNECTIVITY_SERVICE; -import static android.content.Intent.ACTION_AIRPLANE_MODE_CHANGED; -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; -import static com.squareup.picasso.BitmapHunter.forRequest; - -class Dispatcher { - private static final int RETRY_DELAY = 500; - private static final int AIRPLANE_MODE_ON = 1; - private static final int AIRPLANE_MODE_OFF = 0; - - static final int REQUEST_SUBMIT = 1; - static final int REQUEST_CANCEL = 2; - static final int REQUEST_GCED = 3; - static final int HUNTER_COMPLETE = 4; - static final int HUNTER_RETRY = 5; - static final int HUNTER_DECODE_FAILED = 6; - static final int HUNTER_DELAY_NEXT_BATCH = 7; - static final int HUNTER_BATCH_COMPLETE = 8; - static final int NETWORK_STATE_CHANGE = 9; - static final int AIRPLANE_MODE_CHANGE = 10; - - private static final String DISPATCHER_THREAD_NAME = "Dispatcher"; - private static final int BATCH_DELAY = 200; // ms - - final DispatcherThread dispatcherThread; - final Context context; - final ExecutorService service; - final Downloader downloader; - final Map<String, BitmapHunter> hunterMap; - final Handler handler; - final Handler mainThreadHandler; - final Cache cache; - final Stats stats; - final List<BitmapHunter> batch; - final NetworkBroadcastReceiver receiver; - - NetworkInfo networkInfo; - boolean airplaneMode; - - Dispatcher(Context context, ExecutorService service, Handler mainThreadHandler, - Downloader downloader, Cache cache, Stats stats) { - this.dispatcherThread = new DispatcherThread(); - this.dispatcherThread.start(); - this.context = context; - this.service = service; - this.hunterMap = new LinkedHashMap<String, BitmapHunter>(); - this.handler = new DispatcherHandler(dispatcherThread.getLooper(), this); - this.downloader = downloader; - this.mainThreadHandler = mainThreadHandler; - this.cache = cache; - this.stats = stats; - this.batch = new ArrayList<BitmapHunter>(4); - this.airplaneMode = Utils.isAirplaneModeOn(this.context); - this.receiver = new NetworkBroadcastReceiver(this.context); - receiver.register(); - } - - void shutdown() { - service.shutdown(); - dispatcherThread.quit(); - receiver.unregister(); - } - - void dispatchSubmit(Action action) { - handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action)); - } - - void dispatchCancel(Action action) { - handler.sendMessage(handler.obtainMessage(REQUEST_CANCEL, action)); - } - - void dispatchComplete(BitmapHunter hunter) { - handler.sendMessage(handler.obtainMessage(HUNTER_COMPLETE, hunter)); - } - - void dispatchRetry(BitmapHunter hunter) { - handler.sendMessageDelayed(handler.obtainMessage(HUNTER_RETRY, hunter), RETRY_DELAY); - } - - void dispatchFailed(BitmapHunter hunter) { - handler.sendMessage(handler.obtainMessage(HUNTER_DECODE_FAILED, hunter)); - } - - void dispatchNetworkStateChange(NetworkInfo info) { - handler.sendMessage(handler.obtainMessage(NETWORK_STATE_CHANGE, info)); - } - - void dispatchAirplaneModeChange(boolean airplaneMode) { - handler.sendMessage(handler.obtainMessage(AIRPLANE_MODE_CHANGE, - airplaneMode ? AIRPLANE_MODE_ON : AIRPLANE_MODE_OFF, 0)); - } - - void performSubmit(Action action) { - BitmapHunter hunter = hunterMap.get(action.getKey()); - if (hunter != null) { - hunter.attach(action); - return; - } - - if (service.isShutdown()) { - return; - } - - hunter = forRequest(context, action.getPicasso(), this, cache, stats, action, downloader); - hunter.future = service.submit(hunter); - hunterMap.put(action.getKey(), hunter); - } - - void performCancel(Action action) { - String key = action.getKey(); - BitmapHunter hunter = hunterMap.get(key); - if (hunter != null) { - hunter.detach(action); - if (hunter.cancel()) { - hunterMap.remove(key); - } - } - } - - void performRetry(BitmapHunter hunter) { - if (hunter.isCancelled()) return; - - if (service.isShutdown()) { - performError(hunter); - return; - } - - if (hunter.shouldRetry(airplaneMode, networkInfo)) { - hunter.future = service.submit(hunter); - } else { - performError(hunter); - } - } - - void performComplete(BitmapHunter hunter) { - if (!hunter.shouldSkipMemoryCache()) { - cache.set(hunter.getKey(), hunter.getResult()); - } - hunterMap.remove(hunter.getKey()); - batch(hunter); - } - - void performBatchComplete() { - List<BitmapHunter> copy = new ArrayList<BitmapHunter>(batch); - batch.clear(); - mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage(HUNTER_BATCH_COMPLETE, copy)); - } - - void performError(BitmapHunter hunter) { - hunterMap.remove(hunter.getKey()); - batch(hunter); - } - - void performAirplaneModeChange(boolean airplaneMode) { - this.airplaneMode = airplaneMode; - } - - void performNetworkStateChange(NetworkInfo info) { - networkInfo = info; - if (service instanceof PicassoExecutorService) { - ((PicassoExecutorService) service).adjustThreadCount(info); - } - } - - private void batch(BitmapHunter hunter) { - if (hunter.isCancelled()) { - return; - } - batch.add(hunter); - if (!handler.hasMessages(HUNTER_DELAY_NEXT_BATCH)) { - handler.sendEmptyMessageDelayed(HUNTER_DELAY_NEXT_BATCH, BATCH_DELAY); - } - } - - private static class DispatcherHandler extends Handler { - private final Dispatcher dispatcher; - - public DispatcherHandler(Looper looper, Dispatcher dispatcher) { - super(looper); - this.dispatcher = dispatcher; - } - - @Override public void handleMessage(final Message msg) { - switch (msg.what) { - case REQUEST_SUBMIT: { - Action action = (Action) msg.obj; - dispatcher.performSubmit(action); - break; - } - case REQUEST_CANCEL: { - Action action = (Action) msg.obj; - dispatcher.performCancel(action); - break; - } - case HUNTER_COMPLETE: { - BitmapHunter hunter = (BitmapHunter) msg.obj; - dispatcher.performComplete(hunter); - break; - } - case HUNTER_RETRY: { - BitmapHunter hunter = (BitmapHunter) msg.obj; - dispatcher.performRetry(hunter); - break; - } - case HUNTER_DECODE_FAILED: { - BitmapHunter hunter = (BitmapHunter) msg.obj; - dispatcher.performError(hunter); - break; - } - case HUNTER_DELAY_NEXT_BATCH: { - dispatcher.performBatchComplete(); - break; - } - case NETWORK_STATE_CHANGE: { - NetworkInfo info = (NetworkInfo) msg.obj; - dispatcher.performNetworkStateChange(info); - break; - } - case AIRPLANE_MODE_CHANGE: { - dispatcher.performAirplaneModeChange(msg.arg1 == AIRPLANE_MODE_ON); - break; - } - default: - Picasso.HANDLER.post(new Runnable() { - @Override public void run() { - throw new AssertionError("Unknown handler message received: " + msg.what); - } - }); - } - } - } - - static class DispatcherThread extends HandlerThread { - DispatcherThread() { - super(Utils.THREAD_PREFIX + DISPATCHER_THREAD_NAME, THREAD_PRIORITY_BACKGROUND); - } - } - - private class NetworkBroadcastReceiver extends BroadcastReceiver { - private static final String EXTRA_AIRPLANE_STATE = "state"; - - private final ConnectivityManager connectivityManager; - - NetworkBroadcastReceiver(Context context) { - connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE); - } - - void register() { - boolean shouldScanState = service instanceof PicassoExecutorService && // - Utils.hasPermission(context, Manifest.permission.ACCESS_NETWORK_STATE); - IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_AIRPLANE_MODE_CHANGED); - if (shouldScanState) { - filter.addAction(CONNECTIVITY_ACTION); - } - context.registerReceiver(this, filter); - } - - void unregister() { - context.unregisterReceiver(this); - } - - @Override public void onReceive(Context context, Intent intent) { - // On some versions of Android this may be called with a null Intent - if (null == intent) { - return; - } - - String action = intent.getAction(); - Bundle extras = intent.getExtras(); - - if (ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { - dispatchAirplaneModeChange(extras.getBoolean(EXTRA_AIRPLANE_STATE, false)); - } else if (CONNECTIVITY_ACTION.equals(action)) { - dispatchNetworkStateChange(connectivityManager.getActiveNetworkInfo()); - } - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Downloader.java b/mobile/android/thirdparty/com/squareup/picasso/Downloader.java deleted file mode 100644 index 33a909371..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Downloader.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; -import android.net.Uri; -import java.io.IOException; -import java.io.InputStream; - -/** A mechanism to load images from external resources such as a disk cache and/or the internet. */ -public interface Downloader { - /** - * Download the specified image {@code url} from the internet. - * - * @param uri Remote image URL. - * @param localCacheOnly If {@code true} the URL should only be loaded if available in a local - * disk cache. - * @return {@link Response} containing either a {@link Bitmap} representation of the request or an - * {@link InputStream} for the image data. {@code null} can be returned to indicate a problem - * loading the bitmap. - * @throws IOException if the requested URL cannot successfully be loaded. - */ - Response load(Uri uri, boolean localCacheOnly) throws IOException; - - /** Thrown for non-2XX responses. */ - class ResponseException extends IOException { - public ResponseException(String message) { - super(message); - } - } - - /** Response stream or bitmap and info. */ - class Response { - final InputStream stream; - final Bitmap bitmap; - final boolean cached; - - /** - * Response image and info. - * - * @param bitmap Image. - * @param loadedFromCache {@code true} if the source of the image is from a local disk cache. - */ - public Response(Bitmap bitmap, boolean loadedFromCache) { - if (bitmap == null) { - throw new IllegalArgumentException("Bitmap may not be null."); - } - this.stream = null; - this.bitmap = bitmap; - this.cached = loadedFromCache; - } - - /** - * Response stream and info. - * - * @param stream Image data stream. - * @param loadedFromCache {@code true} if the source of the stream is from a local disk cache. - */ - public Response(InputStream stream, boolean loadedFromCache) { - if (stream == null) { - throw new IllegalArgumentException("Stream may not be null."); - } - this.stream = stream; - this.bitmap = null; - this.cached = loadedFromCache; - } - - /** - * Input stream containing image data. - * <p> - * If this returns {@code null}, image data will be available via {@link #getBitmap()}. - */ - public InputStream getInputStream() { - return stream; - } - - /** - * Bitmap representing the image. - * <p> - * If this returns {@code null}, image data will be available via {@link #getInputStream()}. - */ - public Bitmap getBitmap() { - return bitmap; - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/FetchAction.java b/mobile/android/thirdparty/com/squareup/picasso/FetchAction.java deleted file mode 100644 index d8f1c3fb4..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/FetchAction.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; - -class FetchAction extends Action<Void> { - FetchAction(Picasso picasso, Request data, boolean skipCache, String key) { - super(picasso, null, data, skipCache, false, 0, null, key); - } - - @Override void complete(Bitmap result, Picasso.LoadedFrom from) { - } - - @Override public void error() { - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/FileBitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/FileBitmapHunter.java deleted file mode 100644 index dac38fb80..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/FileBitmapHunter.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.graphics.Bitmap; -import android.media.ExifInterface; -import android.net.Uri; -import java.io.IOException; - -import static android.media.ExifInterface.ORIENTATION_NORMAL; -import static android.media.ExifInterface.ORIENTATION_ROTATE_180; -import static android.media.ExifInterface.ORIENTATION_ROTATE_270; -import static android.media.ExifInterface.ORIENTATION_ROTATE_90; -import static android.media.ExifInterface.TAG_ORIENTATION; - -class FileBitmapHunter extends ContentStreamBitmapHunter { - - FileBitmapHunter(Context context, Picasso picasso, Dispatcher dispatcher, Cache cache, - Stats stats, Action action) { - super(context, picasso, dispatcher, cache, stats, action); - } - - @Override Bitmap decode(Request data) - throws IOException { - setExifRotation(getFileExifRotation(data.uri)); - return super.decode(data); - } - - static int getFileExifRotation(Uri uri) throws IOException { - ExifInterface exifInterface = new ExifInterface(uri.getPath()); - int orientation = exifInterface.getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL); - switch (orientation) { - case ORIENTATION_ROTATE_90: - return 90; - case ORIENTATION_ROTATE_180: - return 180; - case ORIENTATION_ROTATE_270: - return 270; - default: - return 0; - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/GetAction.java b/mobile/android/thirdparty/com/squareup/picasso/GetAction.java deleted file mode 100644 index e30024e89..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/GetAction.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; - -class GetAction extends Action<Void> { - GetAction(Picasso picasso, Request data, boolean skipCache, String key) { - super(picasso, null, data, skipCache, false, 0, null, key); - } - - @Override void complete(Bitmap result, Picasso.LoadedFrom from) { - } - - @Override public void error() { - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/ImageViewAction.java b/mobile/android/thirdparty/com/squareup/picasso/ImageViewAction.java deleted file mode 100644 index 16f550907..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/ImageViewAction.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.widget.ImageView; - -class ImageViewAction extends Action<ImageView> { - - Callback callback; - - ImageViewAction(Picasso picasso, ImageView imageView, Request data, boolean skipCache, - boolean noFade, int errorResId, Drawable errorDrawable, String key, Callback callback) { - super(picasso, imageView, data, skipCache, noFade, errorResId, errorDrawable, key); - this.callback = callback; - } - - @Override public void complete(Bitmap result, Picasso.LoadedFrom from) { - if (result == null) { - throw new AssertionError( - String.format("Attempted to complete action with no result!\n%s", this)); - } - - ImageView target = this.target.get(); - if (target == null) { - return; - } - - Context context = picasso.context; - boolean debugging = picasso.debugging; - PicassoDrawable.setBitmap(target, context, result, from, noFade, debugging); - - if (callback != null) { - callback.onSuccess(); - } - } - - @Override public void error() { - ImageView target = this.target.get(); - if (target == null) { - return; - } - if (errorResId != 0) { - target.setImageResource(errorResId); - } else if (errorDrawable != null) { - target.setImageDrawable(errorDrawable); - } - - if (callback != null) { - callback.onError(); - } - } - - @Override void cancel() { - super.cancel(); - if (callback != null) { - callback = null; - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/LruCache.java b/mobile/android/thirdparty/com/squareup/picasso/LruCache.java deleted file mode 100644 index 5d5f07fcb..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/LruCache.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.graphics.Bitmap; -import java.util.LinkedHashMap; -import java.util.Map; - -/** A memory cache which uses a least-recently used eviction policy. */ -public class LruCache implements Cache { - final LinkedHashMap<String, Bitmap> map; - private final int maxSize; - - private int size; - private int putCount; - private int evictionCount; - private int hitCount; - private int missCount; - - /** Create a cache using an appropriate portion of the available RAM as the maximum size. */ - public LruCache(Context context) { - this(Utils.calculateMemoryCacheSize(context)); - } - - /** Create a cache with a given maximum size in bytes. */ - public LruCache(int maxSize) { - if (maxSize <= 0) { - throw new IllegalArgumentException("Max size must be positive."); - } - this.maxSize = maxSize; - this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true); - } - - @Override public Bitmap get(String key) { - if (key == null) { - throw new NullPointerException("key == null"); - } - - Bitmap mapValue; - synchronized (this) { - mapValue = map.get(key); - if (mapValue != null) { - hitCount++; - return mapValue; - } - missCount++; - } - - return null; - } - - @Override public void set(String key, Bitmap bitmap) { - if (key == null || bitmap == null) { - throw new NullPointerException("key == null || bitmap == null"); - } - - Bitmap previous; - synchronized (this) { - putCount++; - size += Utils.getBitmapBytes(bitmap); - previous = map.put(key, bitmap); - if (previous != null) { - size -= Utils.getBitmapBytes(previous); - } - } - - trimToSize(maxSize); - } - - private void trimToSize(int maxSize) { - while (true) { - String key; - Bitmap value; - synchronized (this) { - if (size < 0 || (map.isEmpty() && size != 0)) { - throw new IllegalStateException( - getClass().getName() + ".sizeOf() is reporting inconsistent results!"); - } - - if (size <= maxSize || map.isEmpty()) { - break; - } - - Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next(); - key = toEvict.getKey(); - value = toEvict.getValue(); - map.remove(key); - size -= Utils.getBitmapBytes(value); - evictionCount++; - } - } - } - - /** Clear the cache. */ - public final void evictAll() { - trimToSize(-1); // -1 will evict 0-sized elements - } - - /** Returns the sum of the sizes of the entries in this cache. */ - public final synchronized int size() { - return size; - } - - /** Returns the maximum sum of the sizes of the entries in this cache. */ - public final synchronized int maxSize() { - return maxSize; - } - - public final synchronized void clear() { - evictAll(); - } - - /** Returns the number of times {@link #get} returned a value. */ - public final synchronized int hitCount() { - return hitCount; - } - - /** Returns the number of times {@link #get} returned {@code null}. */ - public final synchronized int missCount() { - return missCount; - } - - /** Returns the number of times {@link #set(String, Bitmap)} was called. */ - public final synchronized int putCount() { - return putCount; - } - - /** Returns the number of values that have been evicted. */ - public final synchronized int evictionCount() { - return evictionCount; - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/MarkableInputStream.java b/mobile/android/thirdparty/com/squareup/picasso/MarkableInputStream.java deleted file mode 100644 index 17043a1b0..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/MarkableInputStream.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * An input stream wrapper that supports unlimited independent cursors for - * marking and resetting. Each cursor is a token, and it's the caller's - * responsibility to keep track of these. - */ -final class MarkableInputStream extends InputStream { - private final InputStream in; - - private long offset; - private long reset; - private long limit; - - private long defaultMark = -1; - - public MarkableInputStream(InputStream in) { - if (!in.markSupported()) { - in = new BufferedInputStream(in); - } - this.in = in; - } - - /** Marks this place in the stream so we can reset back to it later. */ - @Override public void mark(int readLimit) { - defaultMark = savePosition(readLimit); - } - - /** - * Returns an opaque token representing the current position in the stream. - * Call {@link #reset(long)} to return to this position in the stream later. - * It is an error to call {@link #reset(long)} after consuming more than - * {@code readLimit} bytes from this stream. - */ - public long savePosition(int readLimit) { - long offsetLimit = offset + readLimit; - if (limit < offsetLimit) { - setLimit(offsetLimit); - } - return offset; - } - - /** - * Makes sure that the underlying stream can backtrack the full range from - * {@code reset} thru {@code limit}. Since we can't call {@code mark()} - * without also adjusting the reset-to-position on the underlying stream this - * method resets first and then marks the union of the two byte ranges. On - * buffered streams this additional cursor motion shouldn't result in any - * additional I/O. - */ - private void setLimit(long limit) { - try { - if (reset < offset && offset <= this.limit) { - in.reset(); - in.mark((int) (limit - reset)); - skip(reset, offset); - } else { - reset = offset; - in.mark((int) (limit - offset)); - } - this.limit = limit; - } catch (IOException e) { - throw new IllegalStateException("Unable to mark: " + e); - } - } - - /** Resets the stream to the most recent {@link #mark mark}. */ - @Override public void reset() throws IOException { - reset(defaultMark); - } - - /** Resets the stream to the position recorded by {@code token}. */ - public void reset(long token) throws IOException { - if (offset > limit || token < reset) { - throw new IOException("Cannot reset"); - } - in.reset(); - skip(reset, token); - offset = token; - } - - /** Skips {@code target - current} bytes and returns. */ - private void skip(long current, long target) throws IOException { - while (current < target) { - long skipped = in.skip(target - current); - if (skipped == 0) { - if (read() == -1) { - break; // EOF - } else { - skipped = 1; - } - } - current += skipped; - } - } - - @Override public int read() throws IOException { - int result = in.read(); - if (result != -1) { - offset++; - } - return result; - } - - @Override public int read(byte[] buffer) throws IOException { - int count = in.read(buffer); - if (count != -1) { - offset += count; - } - return count; - } - - @Override public int read(byte[] buffer, int offset, int length) throws IOException { - int count = in.read(buffer, offset, length); - if (count != -1) { - this.offset += count; - } - return count; - } - - @Override public long skip(long byteCount) throws IOException { - long skipped = in.skip(byteCount); - offset += skipped; - return skipped; - } - - @Override public int available() throws IOException { - return in.available(); - } - - @Override public void close() throws IOException { - in.close(); - } - - @Override public boolean markSupported() { - return in.markSupported(); - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/MediaStoreBitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/MediaStoreBitmapHunter.java deleted file mode 100644 index 4f8ae1c24..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/MediaStoreBitmapHunter.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2014 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.provider.MediaStore; -import java.io.IOException; - -import static android.content.ContentUris.parseId; -import static android.provider.MediaStore.Images.Thumbnails.FULL_SCREEN_KIND; -import static android.provider.MediaStore.Images.Thumbnails.MICRO_KIND; -import static android.provider.MediaStore.Images.Thumbnails.MINI_KIND; -import static android.provider.MediaStore.Images.Thumbnails.getThumbnail; -import static com.squareup.picasso.MediaStoreBitmapHunter.PicassoKind.FULL; -import static com.squareup.picasso.MediaStoreBitmapHunter.PicassoKind.MICRO; -import static com.squareup.picasso.MediaStoreBitmapHunter.PicassoKind.MINI; - -class MediaStoreBitmapHunter extends ContentStreamBitmapHunter { - private static final String[] CONTENT_ORIENTATION = new String[] { - MediaStore.Images.ImageColumns.ORIENTATION - }; - - MediaStoreBitmapHunter(Context context, Picasso picasso, Dispatcher dispatcher, Cache cache, - Stats stats, Action action) { - super(context, picasso, dispatcher, cache, stats, action); - } - - @Override Bitmap decode(Request data) throws IOException { - ContentResolver contentResolver = context.getContentResolver(); - setExifRotation(getExitOrientation(contentResolver, data.uri)); - - if (data.hasSize()) { - PicassoKind picassoKind = getPicassoKind(data.targetWidth, data.targetHeight); - if (picassoKind == FULL) { - return super.decode(data); - } - - long id = parseId(data.uri); - - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - - calculateInSampleSize(data.targetWidth, data.targetHeight, picassoKind.width, - picassoKind.height, options); - - Bitmap result = getThumbnail(contentResolver, id, picassoKind.androidKind, options); - - if (result != null) { - return result; - } - } - - return super.decode(data); - } - - static PicassoKind getPicassoKind(int targetWidth, int targetHeight) { - if (targetWidth <= MICRO.width && targetHeight <= MICRO.height) { - return MICRO; - } else if (targetWidth <= MINI.width && targetHeight <= MINI.height) { - return MINI; - } - return FULL; - } - - static int getExitOrientation(ContentResolver contentResolver, Uri uri) { - Cursor cursor = null; - try { - cursor = contentResolver.query(uri, CONTENT_ORIENTATION, null, null, null); - if (cursor == null || !cursor.moveToFirst()) { - return 0; - } - return cursor.getInt(0); - } catch (RuntimeException ignored) { - // If the orientation column doesn't exist, assume no rotation. - return 0; - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - enum PicassoKind { - MICRO(MICRO_KIND, 96, 96), - MINI(MINI_KIND, 512, 384), - FULL(FULL_SCREEN_KIND, -1, -1); - - final int androidKind; - final int width; - final int height; - - PicassoKind(int androidKind, int width, int height) { - this.androidKind = androidKind; - this.width = width; - this.height = height; - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/NetworkBitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/NetworkBitmapHunter.java deleted file mode 100644 index 6d148211d..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/NetworkBitmapHunter.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.NetworkInfo; -import java.io.IOException; -import java.io.InputStream; - -import static com.squareup.picasso.Downloader.Response; -import static com.squareup.picasso.Picasso.LoadedFrom.DISK; -import static com.squareup.picasso.Picasso.LoadedFrom.NETWORK; - -class NetworkBitmapHunter extends BitmapHunter { - static final int DEFAULT_RETRY_COUNT = 2; - private static final int MARKER = 65536; - - private final Downloader downloader; - - int retryCount; - - public NetworkBitmapHunter(Picasso picasso, Dispatcher dispatcher, Cache cache, Stats stats, - Action action, Downloader downloader) { - super(picasso, dispatcher, cache, stats, action); - this.downloader = downloader; - this.retryCount = DEFAULT_RETRY_COUNT; - } - - @Override Bitmap decode(Request data) throws IOException { - boolean loadFromLocalCacheOnly = retryCount == 0; - - Response response = downloader.load(data.uri, loadFromLocalCacheOnly); - if (response == null) { - return null; - } - - loadedFrom = response.cached ? DISK : NETWORK; - - Bitmap result = response.getBitmap(); - if (result != null) { - return result; - } - - InputStream is = response.getInputStream(); - try { - return decodeStream(is, data); - } finally { - Utils.closeQuietly(is); - } - } - - @Override boolean shouldRetry(boolean airplaneMode, NetworkInfo info) { - boolean hasRetries = retryCount > 0; - if (!hasRetries) { - return false; - } - retryCount--; - return info == null || info.isConnectedOrConnecting(); - } - - private Bitmap decodeStream(InputStream stream, Request data) throws IOException { - if (stream == null) { - return null; - } - MarkableInputStream markStream = new MarkableInputStream(stream); - stream = markStream; - - long mark = markStream.savePosition(MARKER); - - boolean isWebPFile = Utils.isWebPFile(stream); - markStream.reset(mark); - // When decode WebP network stream, BitmapFactory throw JNI Exception and make app crash. - // Decode byte array instead - if (isWebPFile) { - byte[] bytes = Utils.toByteArray(stream); - BitmapFactory.Options options = null; - if (data.hasSize()) { - options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - - BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); - calculateInSampleSize(data.targetWidth, data.targetHeight, options); - } - return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); - } else { - BitmapFactory.Options options = null; - if (data.hasSize()) { - options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - - BitmapFactory.decodeStream(stream, null, options); - calculateInSampleSize(data.targetWidth, data.targetHeight, options); - - markStream.reset(mark); - } - return BitmapFactory.decodeStream(stream, null, options); - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Picasso.java b/mobile/android/thirdparty/com/squareup/picasso/Picasso.java deleted file mode 100644 index 9b510f977..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Picasso.java +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Process; -import android.widget.ImageView; -import java.io.File; -import java.lang.ref.ReferenceQueue; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.ExecutorService; - -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; -import static com.squareup.picasso.Action.RequestWeakReference; -import static com.squareup.picasso.Dispatcher.HUNTER_BATCH_COMPLETE; -import static com.squareup.picasso.Dispatcher.REQUEST_GCED; -import static com.squareup.picasso.Utils.THREAD_PREFIX; - -/** - * Image downloading, transformation, and caching manager. - * <p/> - * Use {@link #with(android.content.Context)} for the global singleton instance or construct your - * own instance with {@link Builder}. - */ -public class Picasso { - - /** Callbacks for Picasso events. */ - public interface Listener { - /** - * Invoked when an image has failed to load. This is useful for reporting image failures to a - * remote analytics service, for example. - */ - void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception); - } - - /** - * A transformer that is called immediately before every request is submitted. This can be used to - * modify any information about a request. - * <p> - * For example, if you use a CDN you can change the hostname for the image based on the current - * location of the user in order to get faster download speeds. - * <p> - * <b>NOTE:</b> This is a beta feature. The API is subject to change in a backwards incompatible - * way at any time. - */ - public interface RequestTransformer { - /** - * Transform a request before it is submitted to be processed. - * - * @return The original request or a new request to replace it. Must not be null. - */ - Request transformRequest(Request request); - - /** A {@link RequestTransformer} which returns the original request. */ - RequestTransformer IDENTITY = new RequestTransformer() { - @Override public Request transformRequest(Request request) { - return request; - } - }; - } - - static final Handler HANDLER = new Handler(Looper.getMainLooper()) { - @Override public void handleMessage(Message msg) { - switch (msg.what) { - case HUNTER_BATCH_COMPLETE: { - @SuppressWarnings("unchecked") List<BitmapHunter> batch = (List<BitmapHunter>) msg.obj; - for (BitmapHunter hunter : batch) { - hunter.picasso.complete(hunter); - } - break; - } - case REQUEST_GCED: { - Action action = (Action) msg.obj; - action.picasso.cancelExistingRequest(action.getTarget()); - break; - } - default: - throw new AssertionError("Unknown handler message received: " + msg.what); - } - } - }; - - static Picasso singleton = null; - - private final Listener listener; - private final RequestTransformer requestTransformer; - private final CleanupThread cleanupThread; - - final Context context; - final Dispatcher dispatcher; - final Cache cache; - final Stats stats; - final Map<Object, Action> targetToAction; - final Map<ImageView, DeferredRequestCreator> targetToDeferredRequestCreator; - final ReferenceQueue<Object> referenceQueue; - - boolean debugging; - boolean shutdown; - - Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener, - RequestTransformer requestTransformer, Stats stats, boolean debugging) { - this.context = context; - this.dispatcher = dispatcher; - this.cache = cache; - this.listener = listener; - this.requestTransformer = requestTransformer; - this.stats = stats; - this.targetToAction = new WeakHashMap<Object, Action>(); - this.targetToDeferredRequestCreator = new WeakHashMap<ImageView, DeferredRequestCreator>(); - this.debugging = debugging; - this.referenceQueue = new ReferenceQueue<Object>(); - this.cleanupThread = new CleanupThread(referenceQueue, HANDLER); - this.cleanupThread.start(); - } - - /** Cancel any existing requests for the specified target {@link ImageView}. */ - public void cancelRequest(ImageView view) { - cancelExistingRequest(view); - } - - /** Cancel any existing requests for the specified {@link Target} instance. */ - public void cancelRequest(Target target) { - cancelExistingRequest(target); - } - - /** - * Start an image request using the specified URI. - * <p> - * Passing {@code null} as a {@code uri} will not trigger any request but will set a placeholder, - * if one is specified. - * - * @see #load(File) - * @see #load(String) - * @see #load(int) - */ - public RequestCreator load(Uri uri) { - return new RequestCreator(this, uri, 0); - } - - /** - * Start an image request using the specified path. This is a convenience method for calling - * {@link #load(Uri)}. - * <p> - * This path may be a remote URL, file resource (prefixed with {@code file:}), content resource - * (prefixed with {@code content:}), or android resource (prefixed with {@code - * android.resource:}. - * <p> - * Passing {@code null} as a {@code path} will not trigger any request but will set a - * placeholder, if one is specified. - * - * @see #load(Uri) - * @see #load(File) - * @see #load(int) - */ - public RequestCreator load(String path) { - if (path == null) { - return new RequestCreator(this, null, 0); - } - if (path.trim().length() == 0) { - throw new IllegalArgumentException("Path must not be empty."); - } - return load(Uri.parse(path)); - } - - /** - * Start an image request using the specified image file. This is a convenience method for - * calling {@link #load(Uri)}. - * <p> - * Passing {@code null} as a {@code file} will not trigger any request but will set a - * placeholder, if one is specified. - * - * @see #load(Uri) - * @see #load(String) - * @see #load(int) - */ - public RequestCreator load(File file) { - if (file == null) { - return new RequestCreator(this, null, 0); - } - return load(Uri.fromFile(file)); - } - - /** - * Start an image request using the specified drawable resource ID. - * - * @see #load(Uri) - * @see #load(String) - * @see #load(File) - */ - public RequestCreator load(int resourceId) { - if (resourceId == 0) { - throw new IllegalArgumentException("Resource ID must not be zero."); - } - return new RequestCreator(this, null, resourceId); - } - - /** {@code true} if debug display, logging, and statistics are enabled. */ - @SuppressWarnings("UnusedDeclaration") public boolean isDebugging() { - return debugging; - } - - /** Toggle whether debug display, logging, and statistics are enabled. */ - @SuppressWarnings("UnusedDeclaration") public void setDebugging(boolean debugging) { - this.debugging = debugging; - } - - /** Creates a {@link StatsSnapshot} of the current stats for this instance. */ - @SuppressWarnings("UnusedDeclaration") public StatsSnapshot getSnapshot() { - return stats.createSnapshot(); - } - - /** Stops this instance from accepting further requests. */ - public void shutdown() { - if (this == singleton) { - throw new UnsupportedOperationException("Default singleton instance cannot be shutdown."); - } - if (shutdown) { - return; - } - cache.clear(); - cleanupThread.shutdown(); - stats.shutdown(); - dispatcher.shutdown(); - for (DeferredRequestCreator deferredRequestCreator : targetToDeferredRequestCreator.values()) { - deferredRequestCreator.cancel(); - } - targetToDeferredRequestCreator.clear(); - shutdown = true; - } - - Request transformRequest(Request request) { - Request transformed = requestTransformer.transformRequest(request); - if (transformed == null) { - throw new IllegalStateException("Request transformer " - + requestTransformer.getClass().getCanonicalName() - + " returned null for " - + request); - } - return transformed; - } - - void defer(ImageView view, DeferredRequestCreator request) { - targetToDeferredRequestCreator.put(view, request); - } - - void enqueueAndSubmit(Action action) { - Object target = action.getTarget(); - if (target != null) { - cancelExistingRequest(target); - targetToAction.put(target, action); - } - submit(action); - } - - void submit(Action action) { - dispatcher.dispatchSubmit(action); - } - - Bitmap quickMemoryCacheCheck(String key) { - Bitmap cached = cache.get(key); - if (cached != null) { - stats.dispatchCacheHit(); - } else { - stats.dispatchCacheMiss(); - } - return cached; - } - - void complete(BitmapHunter hunter) { - List<Action> joined = hunter.getActions(); - if (joined.isEmpty()) { - return; - } - - Uri uri = hunter.getData().uri; - Exception exception = hunter.getException(); - Bitmap result = hunter.getResult(); - LoadedFrom from = hunter.getLoadedFrom(); - - for (Action join : joined) { - if (join.isCancelled()) { - continue; - } - targetToAction.remove(join.getTarget()); - if (result != null) { - if (from == null) { - throw new AssertionError("LoadedFrom cannot be null."); - } - join.complete(result, from); - } else { - join.error(); - } - } - - if (listener != null && exception != null) { - listener.onImageLoadFailed(this, uri, exception); - } - } - - private void cancelExistingRequest(Object target) { - Action action = targetToAction.remove(target); - if (action != null) { - action.cancel(); - dispatcher.dispatchCancel(action); - } - if (target instanceof ImageView) { - ImageView targetImageView = (ImageView) target; - DeferredRequestCreator deferredRequestCreator = - targetToDeferredRequestCreator.remove(targetImageView); - if (deferredRequestCreator != null) { - deferredRequestCreator.cancel(); - } - } - } - - private static class CleanupThread extends Thread { - private final ReferenceQueue<?> referenceQueue; - private final Handler handler; - - CleanupThread(ReferenceQueue<?> referenceQueue, Handler handler) { - this.referenceQueue = referenceQueue; - this.handler = handler; - setDaemon(true); - setName(THREAD_PREFIX + "refQueue"); - } - - @Override public void run() { - Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); - while (true) { - try { - RequestWeakReference<?> remove = (RequestWeakReference<?>) referenceQueue.remove(); - handler.sendMessage(handler.obtainMessage(REQUEST_GCED, remove.action)); - } catch (InterruptedException e) { - break; - } catch (final Exception e) { - handler.post(new Runnable() { - @Override public void run() { - throw new RuntimeException(e); - } - }); - break; - } - } - } - - void shutdown() { - interrupt(); - } - } - - /** - * The global default {@link Picasso} instance. - * <p> - * This instance is automatically initialized with defaults that are suitable to most - * implementations. - * <ul> - * <li>LRU memory cache of 15% the available application RAM</li> - * <li>Disk cache of 2% storage space up to 50MB but no less than 5MB. (Note: this is only - * available on API 14+ <em>or</em> if you are using a standalone library that provides a disk - * cache on all API levels like OkHttp)</li> - * <li>Three download threads for disk and network access.</li> - * </ul> - * <p> - * If these settings do not meet the requirements of your application you can construct your own - * instance with full control over the configuration by using {@link Picasso.Builder}. - */ - public static Picasso with(Context context) { - if (singleton == null) { - singleton = new Builder(context).build(); - } - return singleton; - } - - /** Fluent API for creating {@link Picasso} instances. */ - @SuppressWarnings("UnusedDeclaration") // Public API. - public static class Builder { - private final Context context; - private Downloader downloader; - private ExecutorService service; - private Cache cache; - private Listener listener; - private RequestTransformer transformer; - private boolean debugging; - - /** Start building a new {@link Picasso} instance. */ - public Builder(Context context) { - if (context == null) { - throw new IllegalArgumentException("Context must not be null."); - } - this.context = context.getApplicationContext(); - } - - /** Specify the {@link Downloader} that will be used for downloading images. */ - public Builder downloader(Downloader downloader) { - if (downloader == null) { - throw new IllegalArgumentException("Downloader must not be null."); - } - if (this.downloader != null) { - throw new IllegalStateException("Downloader already set."); - } - this.downloader = downloader; - return this; - } - - /** Specify the executor service for loading images in the background. */ - public Builder executor(ExecutorService executorService) { - if (executorService == null) { - throw new IllegalArgumentException("Executor service must not be null."); - } - if (this.service != null) { - throw new IllegalStateException("Executor service already set."); - } - this.service = executorService; - return this; - } - - /** Specify the memory cache used for the most recent images. */ - public Builder memoryCache(Cache memoryCache) { - if (memoryCache == null) { - throw new IllegalArgumentException("Memory cache must not be null."); - } - if (this.cache != null) { - throw new IllegalStateException("Memory cache already set."); - } - this.cache = memoryCache; - return this; - } - - /** Specify a listener for interesting events. */ - public Builder listener(Listener listener) { - if (listener == null) { - throw new IllegalArgumentException("Listener must not be null."); - } - if (this.listener != null) { - throw new IllegalStateException("Listener already set."); - } - this.listener = listener; - return this; - } - - /** - * Specify a transformer for all incoming requests. - * <p> - * <b>NOTE:</b> This is a beta feature. The API is subject to change in a backwards incompatible - * way at any time. - */ - public Builder requestTransformer(RequestTransformer transformer) { - if (transformer == null) { - throw new IllegalArgumentException("Transformer must not be null."); - } - if (this.transformer != null) { - throw new IllegalStateException("Transformer already set."); - } - this.transformer = transformer; - return this; - } - - /** Whether debugging is enabled or not. */ - public Builder debugging(boolean debugging) { - this.debugging = debugging; - return this; - } - - /** Create the {@link Picasso} instance. */ - public Picasso build() { - Context context = this.context; - - if (downloader == null) { - downloader = Utils.createDefaultDownloader(context); - } - if (cache == null) { - cache = new LruCache(context); - } - if (service == null) { - service = new PicassoExecutorService(); - } - if (transformer == null) { - transformer = RequestTransformer.IDENTITY; - } - - Stats stats = new Stats(cache); - - Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats); - - return new Picasso(context, dispatcher, cache, listener, transformer, stats, debugging); - } - } - - /** Describes where the image was loaded from. */ - public enum LoadedFrom { - MEMORY(Color.GREEN), - DISK(Color.YELLOW), - NETWORK(Color.RED); - - final int debugColor; - - private LoadedFrom(int debugColor) { - this.debugColor = debugColor; - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/PicassoDrawable.java b/mobile/android/thirdparty/com/squareup/picasso/PicassoDrawable.java deleted file mode 100644 index 07f762c31..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/PicassoDrawable.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.drawable.AnimationDrawable; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.SystemClock; -import android.widget.ImageView; - -import static android.graphics.Color.WHITE; -import static com.squareup.picasso.Picasso.LoadedFrom.MEMORY; - -final class PicassoDrawable extends Drawable { - // Only accessed from main thread. - private static final Paint DEBUG_PAINT = new Paint(); - - private static final float FADE_DURATION = 200f; //ms - - /** - * Create or update the drawable on the target {@link ImageView} to display the supplied bitmap - * image. - */ - static void setBitmap(ImageView target, Context context, Bitmap bitmap, - Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) { - Drawable placeholder = target.getDrawable(); - if (placeholder instanceof AnimationDrawable) { - ((AnimationDrawable) placeholder).stop(); - } - PicassoDrawable drawable = - new PicassoDrawable(context, placeholder, bitmap, loadedFrom, noFade, debugging); - target.setImageDrawable(drawable); - } - - /** - * Create or update the drawable on the target {@link ImageView} to display the supplied - * placeholder image. - */ - static void setPlaceholder(ImageView target, int placeholderResId, Drawable placeholderDrawable) { - if (placeholderResId != 0) { - target.setImageResource(placeholderResId); - } else { - target.setImageDrawable(placeholderDrawable); - } - if (target.getDrawable() instanceof AnimationDrawable) { - ((AnimationDrawable) target.getDrawable()).start(); - } - } - - private final boolean debugging; - private final float density; - private final Picasso.LoadedFrom loadedFrom; - final BitmapDrawable image; - - Drawable placeholder; - - long startTimeMillis; - boolean animating; - int alpha = 0xFF; - - PicassoDrawable(Context context, Drawable placeholder, Bitmap bitmap, - Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) { - Resources res = context.getResources(); - - this.debugging = debugging; - this.density = res.getDisplayMetrics().density; - - this.loadedFrom = loadedFrom; - - this.image = new BitmapDrawable(res, bitmap); - - boolean fade = loadedFrom != MEMORY && !noFade; - if (fade) { - this.placeholder = placeholder; - animating = true; - startTimeMillis = SystemClock.uptimeMillis(); - } - } - - @Override public void draw(Canvas canvas) { - if (!animating) { - image.draw(canvas); - } else { - float normalized = (SystemClock.uptimeMillis() - startTimeMillis) / FADE_DURATION; - if (normalized >= 1f) { - animating = false; - placeholder = null; - image.draw(canvas); - } else { - if (placeholder != null) { - placeholder.draw(canvas); - } - - int partialAlpha = (int) (alpha * normalized); - image.setAlpha(partialAlpha); - image.draw(canvas); - image.setAlpha(alpha); - invalidateSelf(); - } - } - - if (debugging) { - drawDebugIndicator(canvas); - } - } - - @Override public int getIntrinsicWidth() { - return image.getIntrinsicWidth(); - } - - @Override public int getIntrinsicHeight() { - return image.getIntrinsicHeight(); - } - - @Override public void setAlpha(int alpha) { - this.alpha = alpha; - if (placeholder != null) { - placeholder.setAlpha(alpha); - } - image.setAlpha(alpha); - } - - @Override public void setColorFilter(ColorFilter cf) { - if (placeholder != null) { - placeholder.setColorFilter(cf); - } - image.setColorFilter(cf); - } - - @Override public int getOpacity() { - return image.getOpacity(); - } - - @Override protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - - image.setBounds(bounds); - if (placeholder != null) { - placeholder.setBounds(bounds); - } - } - - private void drawDebugIndicator(Canvas canvas) { - DEBUG_PAINT.setColor(WHITE); - Path path = getTrianglePath(new Point(0, 0), (int) (16 * density)); - canvas.drawPath(path, DEBUG_PAINT); - - DEBUG_PAINT.setColor(loadedFrom.debugColor); - path = getTrianglePath(new Point(0, 0), (int) (15 * density)); - canvas.drawPath(path, DEBUG_PAINT); - } - - private static Path getTrianglePath(Point p1, int width) { - Point p2 = new Point(p1.x + width, p1.y); - Point p3 = new Point(p1.x, p1.y + width); - - Path path = new Path(); - path.moveTo(p1.x, p1.y); - path.lineTo(p2.x, p2.y); - path.lineTo(p3.x, p3.y); - - return path; - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/PicassoExecutorService.java b/mobile/android/thirdparty/com/squareup/picasso/PicassoExecutorService.java deleted file mode 100644 index 875dd2dda..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/PicassoExecutorService.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.telephony.TelephonyManager; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * The default {@link java.util.concurrent.ExecutorService} used for new {@link Picasso} instances. - * <p/> - * Exists as a custom type so that we can differentiate the use of defaults versus a user-supplied - * instance. - */ -class PicassoExecutorService extends ThreadPoolExecutor { - private static final int DEFAULT_THREAD_COUNT = 3; - - PicassoExecutorService() { - super(DEFAULT_THREAD_COUNT, DEFAULT_THREAD_COUNT, 0, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue<Runnable>(), new Utils.PicassoThreadFactory()); - } - - void adjustThreadCount(NetworkInfo info) { - if (info == null || !info.isConnectedOrConnecting()) { - setThreadCount(DEFAULT_THREAD_COUNT); - return; - } - switch (info.getType()) { - case ConnectivityManager.TYPE_WIFI: - case ConnectivityManager.TYPE_WIMAX: - case ConnectivityManager.TYPE_ETHERNET: - setThreadCount(4); - break; - case ConnectivityManager.TYPE_MOBILE: - switch (info.getSubtype()) { - case TelephonyManager.NETWORK_TYPE_LTE: // 4G - case TelephonyManager.NETWORK_TYPE_HSPAP: - case TelephonyManager.NETWORK_TYPE_EHRPD: - setThreadCount(3); - break; - case TelephonyManager.NETWORK_TYPE_UMTS: // 3G - case TelephonyManager.NETWORK_TYPE_CDMA: - case TelephonyManager.NETWORK_TYPE_EVDO_0: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - setThreadCount(2); - break; - case TelephonyManager.NETWORK_TYPE_GPRS: // 2G - case TelephonyManager.NETWORK_TYPE_EDGE: - setThreadCount(1); - break; - default: - setThreadCount(DEFAULT_THREAD_COUNT); - } - break; - default: - setThreadCount(DEFAULT_THREAD_COUNT); - } - } - - private void setThreadCount(int threadCount) { - setCorePoolSize(threadCount); - setMaximumPoolSize(threadCount); - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Request.java b/mobile/android/thirdparty/com/squareup/picasso/Request.java deleted file mode 100644 index 8e9c32460..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Request.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.net.Uri; -import java.util.ArrayList; -import java.util.List; - -import static java.util.Collections.unmodifiableList; - -/** Immutable data about an image and the transformations that will be applied to it. */ -public final class Request { - /** - * The image URI. - * <p> - * This is mutually exclusive with {@link #resourceId}. - */ - public final Uri uri; - /** - * The image resource ID. - * <p> - * This is mutually exclusive with {@link #uri}. - */ - public final int resourceId; - /** List of custom transformations to be applied after the built-in transformations. */ - public final List<Transformation> transformations; - /** Target image width for resizing. */ - public final int targetWidth; - /** Target image height for resizing. */ - public final int targetHeight; - /** - * True if the final image should use the 'centerCrop' scale technique. - * <p> - * This is mutually exclusive with {@link #centerInside}. - */ - public final boolean centerCrop; - /** - * True if the final image should use the 'centerInside' scale technique. - * <p> - * This is mutually exclusive with {@link #centerCrop}. - */ - public final boolean centerInside; - /** Amount to rotate the image in degrees. */ - public final float rotationDegrees; - /** Rotation pivot on the X axis. */ - public final float rotationPivotX; - /** Rotation pivot on the Y axis. */ - public final float rotationPivotY; - /** Whether or not {@link #rotationPivotX} and {@link #rotationPivotY} are set. */ - public final boolean hasRotationPivot; - - private Request(Uri uri, int resourceId, List<Transformation> transformations, int targetWidth, - int targetHeight, boolean centerCrop, boolean centerInside, float rotationDegrees, - float rotationPivotX, float rotationPivotY, boolean hasRotationPivot) { - this.uri = uri; - this.resourceId = resourceId; - if (transformations == null) { - this.transformations = null; - } else { - this.transformations = unmodifiableList(transformations); - } - this.targetWidth = targetWidth; - this.targetHeight = targetHeight; - this.centerCrop = centerCrop; - this.centerInside = centerInside; - this.rotationDegrees = rotationDegrees; - this.rotationPivotX = rotationPivotX; - this.rotationPivotY = rotationPivotY; - this.hasRotationPivot = hasRotationPivot; - } - - String getName() { - if (uri != null) { - return uri.getPath(); - } - return Integer.toHexString(resourceId); - } - - public boolean hasSize() { - return targetWidth != 0; - } - - boolean needsTransformation() { - return needsMatrixTransform() || hasCustomTransformations(); - } - - boolean needsMatrixTransform() { - return targetWidth != 0 || rotationDegrees != 0; - } - - boolean hasCustomTransformations() { - return transformations != null; - } - - public Builder buildUpon() { - return new Builder(this); - } - - /** Builder for creating {@link Request} instances. */ - public static final class Builder { - private Uri uri; - private int resourceId; - private int targetWidth; - private int targetHeight; - private boolean centerCrop; - private boolean centerInside; - private float rotationDegrees; - private float rotationPivotX; - private float rotationPivotY; - private boolean hasRotationPivot; - private List<Transformation> transformations; - - /** Start building a request using the specified {@link Uri}. */ - public Builder(Uri uri) { - setUri(uri); - } - - /** Start building a request using the specified resource ID. */ - public Builder(int resourceId) { - setResourceId(resourceId); - } - - Builder(Uri uri, int resourceId) { - this.uri = uri; - this.resourceId = resourceId; - } - - private Builder(Request request) { - uri = request.uri; - resourceId = request.resourceId; - targetWidth = request.targetWidth; - targetHeight = request.targetHeight; - centerCrop = request.centerCrop; - centerInside = request.centerInside; - rotationDegrees = request.rotationDegrees; - rotationPivotX = request.rotationPivotX; - rotationPivotY = request.rotationPivotY; - hasRotationPivot = request.hasRotationPivot; - if (request.transformations != null) { - transformations = new ArrayList<Transformation>(request.transformations); - } - } - - boolean hasImage() { - return uri != null || resourceId != 0; - } - - boolean hasSize() { - return targetWidth != 0; - } - - /** - * Set the target image Uri. - * <p> - * This will clear an image resource ID if one is set. - */ - public Builder setUri(Uri uri) { - if (uri == null) { - throw new IllegalArgumentException("Image URI may not be null."); - } - this.uri = uri; - this.resourceId = 0; - return this; - } - - /** - * Set the target image resource ID. - * <p> - * This will clear an image Uri if one is set. - */ - public Builder setResourceId(int resourceId) { - if (resourceId == 0) { - throw new IllegalArgumentException("Image resource ID may not be 0."); - } - this.resourceId = resourceId; - this.uri = null; - return this; - } - - /** Resize the image to the specified size in pixels. */ - public Builder resize(int targetWidth, int targetHeight) { - if (targetWidth <= 0) { - throw new IllegalArgumentException("Width must be positive number."); - } - if (targetHeight <= 0) { - throw new IllegalArgumentException("Height must be positive number."); - } - this.targetWidth = targetWidth; - this.targetHeight = targetHeight; - return this; - } - - /** Clear the resize transformation, if any. This will also clear center crop/inside if set. */ - public Builder clearResize() { - targetWidth = 0; - targetHeight = 0; - centerCrop = false; - centerInside = false; - return this; - } - - /** - * Crops an image inside of the bounds specified by {@link #resize(int, int)} rather than - * distorting the aspect ratio. This cropping technique scales the image so that it fills the - * requested bounds and then crops the extra. - */ - public Builder centerCrop() { - if (centerInside) { - throw new IllegalStateException("Center crop can not be used after calling centerInside"); - } - centerCrop = true; - return this; - } - - /** Clear the center crop transformation flag, if set. */ - public Builder clearCenterCrop() { - centerCrop = false; - return this; - } - - /** - * Centers an image inside of the bounds specified by {@link #resize(int, int)}. This scales - * the image so that both dimensions are equal to or less than the requested bounds. - */ - public Builder centerInside() { - if (centerCrop) { - throw new IllegalStateException("Center inside can not be used after calling centerCrop"); - } - centerInside = true; - return this; - } - - /** Clear the center inside transformation flag, if set. */ - public Builder clearCenterInside() { - centerInside = false; - return this; - } - - /** Rotate the image by the specified degrees. */ - public Builder rotate(float degrees) { - rotationDegrees = degrees; - return this; - } - - /** Rotate the image by the specified degrees around a pivot point. */ - public Builder rotate(float degrees, float pivotX, float pivotY) { - rotationDegrees = degrees; - rotationPivotX = pivotX; - rotationPivotY = pivotY; - hasRotationPivot = true; - return this; - } - - /** Clear the rotation transformation, if any. */ - public Builder clearRotation() { - rotationDegrees = 0; - rotationPivotX = 0; - rotationPivotY = 0; - hasRotationPivot = false; - return this; - } - - /** - * Add a custom transformation to be applied to the image. - * <p/> - * Custom transformations will always be run after the built-in transformations. - */ - public Builder transform(Transformation transformation) { - if (transformation == null) { - throw new IllegalArgumentException("Transformation must not be null."); - } - if (transformations == null) { - transformations = new ArrayList<Transformation>(2); - } - transformations.add(transformation); - return this; - } - - /** Create the immutable {@link Request} object. */ - public Request build() { - if (centerInside && centerCrop) { - throw new IllegalStateException("Center crop and center inside can not be used together."); - } - if (centerCrop && targetWidth == 0) { - throw new IllegalStateException("Center crop requires calling resize."); - } - if (centerInside && targetWidth == 0) { - throw new IllegalStateException("Center inside requires calling resize."); - } - return new Request(uri, resourceId, transformations, targetWidth, targetHeight, centerCrop, - centerInside, rotationDegrees, rotationPivotX, rotationPivotY, hasRotationPivot); - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/RequestCreator.java b/mobile/android/thirdparty/com/squareup/picasso/RequestCreator.java deleted file mode 100644 index 3a5ca3a9f..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/RequestCreator.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.widget.ImageView; -import java.io.IOException; - -import static com.squareup.picasso.BitmapHunter.forRequest; -import static com.squareup.picasso.Picasso.LoadedFrom.MEMORY; -import static com.squareup.picasso.Utils.checkNotMain; -import static com.squareup.picasso.Utils.createKey; - -/** Fluent API for building an image download request. */ -@SuppressWarnings("UnusedDeclaration") // Public API. -public class RequestCreator { - private final Picasso picasso; - private final Request.Builder data; - - private boolean skipMemoryCache; - private boolean noFade; - private boolean deferred; - private int placeholderResId; - private Drawable placeholderDrawable; - private int errorResId; - private Drawable errorDrawable; - - RequestCreator(Picasso picasso, Uri uri, int resourceId) { - if (picasso.shutdown) { - throw new IllegalStateException( - "Picasso instance already shut down. Cannot submit new requests."); - } - this.picasso = picasso; - this.data = new Request.Builder(uri, resourceId); - } - - /** - * A placeholder drawable to be used while the image is being loaded. If the requested image is - * not immediately available in the memory cache then this resource will be set on the target - * {@link ImageView}. - */ - public RequestCreator placeholder(int placeholderResId) { - if (placeholderResId == 0) { - throw new IllegalArgumentException("Placeholder image resource invalid."); - } - if (placeholderDrawable != null) { - throw new IllegalStateException("Placeholder image already set."); - } - this.placeholderResId = placeholderResId; - return this; - } - - /** - * A placeholder drawable to be used while the image is being loaded. If the requested image is - * not immediately available in the memory cache then this resource will be set on the target - * {@link ImageView}. - * <p> - * If you are not using a placeholder image but want to clear an existing image (such as when - * used in an {@link android.widget.Adapter adapter}), pass in {@code null}. - */ - public RequestCreator placeholder(Drawable placeholderDrawable) { - if (placeholderResId != 0) { - throw new IllegalStateException("Placeholder image already set."); - } - this.placeholderDrawable = placeholderDrawable; - return this; - } - - /** An error drawable to be used if the request image could not be loaded. */ - public RequestCreator error(int errorResId) { - if (errorResId == 0) { - throw new IllegalArgumentException("Error image resource invalid."); - } - if (errorDrawable != null) { - throw new IllegalStateException("Error image already set."); - } - this.errorResId = errorResId; - return this; - } - - /** An error drawable to be used if the request image could not be loaded. */ - public RequestCreator error(Drawable errorDrawable) { - if (errorDrawable == null) { - throw new IllegalArgumentException("Error image may not be null."); - } - if (errorResId != 0) { - throw new IllegalStateException("Error image already set."); - } - this.errorDrawable = errorDrawable; - return this; - } - - /** - * Attempt to resize the image to fit exactly into the target {@link ImageView}'s bounds. This - * will result in delayed execution of the request until the {@link ImageView} has been measured. - * <p/> - * <em>Note:</em> This method works only when your target is an {@link ImageView}. - */ - public RequestCreator fit() { - deferred = true; - return this; - } - - /** Internal use only. Used by {@link DeferredRequestCreator}. */ - RequestCreator unfit() { - deferred = false; - return this; - } - - /** Resize the image to the specified dimension size. */ - public RequestCreator resizeDimen(int targetWidthResId, int targetHeightResId) { - Resources resources = picasso.context.getResources(); - int targetWidth = resources.getDimensionPixelSize(targetWidthResId); - int targetHeight = resources.getDimensionPixelSize(targetHeightResId); - return resize(targetWidth, targetHeight); - } - - /** Resize the image to the specified size in pixels. */ - public RequestCreator resize(int targetWidth, int targetHeight) { - data.resize(targetWidth, targetHeight); - return this; - } - - /** - * Crops an image inside of the bounds specified by {@link #resize(int, int)} rather than - * distorting the aspect ratio. This cropping technique scales the image so that it fills the - * requested bounds and then crops the extra. - */ - public RequestCreator centerCrop() { - data.centerCrop(); - return this; - } - - /** - * Centers an image inside of the bounds specified by {@link #resize(int, int)}. This scales - * the image so that both dimensions are equal to or less than the requested bounds. - */ - public RequestCreator centerInside() { - data.centerInside(); - return this; - } - - /** Rotate the image by the specified degrees. */ - public RequestCreator rotate(float degrees) { - data.rotate(degrees); - return this; - } - - /** Rotate the image by the specified degrees around a pivot point. */ - public RequestCreator rotate(float degrees, float pivotX, float pivotY) { - data.rotate(degrees, pivotX, pivotY); - return this; - } - - /** - * Add a custom transformation to be applied to the image. - * <p/> - * Custom transformations will always be run after the built-in transformations. - */ - // TODO show example of calling resize after a transform in the javadoc - public RequestCreator transform(Transformation transformation) { - data.transform(transformation); - return this; - } - - /** - * Indicate that this action should not use the memory cache for attempting to load or save the - * image. This can be useful when you know an image will only ever be used once (e.g., loading - * an image from the filesystem and uploading to a remote server). - */ - public RequestCreator skipMemoryCache() { - skipMemoryCache = true; - return this; - } - - /** Disable brief fade in of images loaded from the disk cache or network. */ - public RequestCreator noFade() { - noFade = true; - return this; - } - - /** Synchronously fulfill this request. Must not be called from the main thread. */ - public Bitmap get() throws IOException { - checkNotMain(); - if (deferred) { - throw new IllegalStateException("Fit cannot be used with get."); - } - if (!data.hasImage()) { - return null; - } - - Request finalData = picasso.transformRequest(data.build()); - String key = createKey(finalData); - - Action action = new GetAction(picasso, finalData, skipMemoryCache, key); - return forRequest(picasso.context, picasso, picasso.dispatcher, picasso.cache, picasso.stats, - action, picasso.dispatcher.downloader).hunt(); - } - - /** - * Asynchronously fulfills the request without a {@link ImageView} or {@link Target}. This is - * useful when you want to warm up the cache with an image. - */ - public void fetch() { - if (deferred) { - throw new IllegalStateException("Fit cannot be used with fetch."); - } - if (data.hasImage()) { - Request finalData = picasso.transformRequest(data.build()); - String key = createKey(finalData); - - Action action = new FetchAction(picasso, finalData, skipMemoryCache, key); - picasso.enqueueAndSubmit(action); - } - } - - /** - * Asynchronously fulfills the request into the specified {@link Target}. In most cases, you - * should use this when you are dealing with a custom {@link android.view.View View} or view - * holder which should implement the {@link Target} interface. - * <p> - * Implementing on a {@link android.view.View View}: - * <blockquote><pre> - * public class ProfileView extends FrameLayout implements Target { - * {@literal @}Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) { - * setBackgroundDrawable(new BitmapDrawable(bitmap)); - * } - * - * {@literal @}Override public void onBitmapFailed() { - * setBackgroundResource(R.drawable.profile_error); - * } - * } - * </pre></blockquote> - * Implementing on a view holder object for use inside of an adapter: - * <blockquote><pre> - * public class ViewHolder implements Target { - * public FrameLayout frame; - * public TextView name; - * - * {@literal @}Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) { - * frame.setBackgroundDrawable(new BitmapDrawable(bitmap)); - * } - * - * {@literal @}Override public void onBitmapFailed() { - * frame.setBackgroundResource(R.drawable.profile_error); - * } - * } - * </pre></blockquote> - * <p> - * <em>Note:</em> This method keeps a weak reference to the {@link Target} instance and will be - * garbage collected if you do not keep a strong reference to it. To receive callbacks when an - * image is loaded use {@link #into(android.widget.ImageView, Callback)}. - */ - public void into(Target target) { - if (target == null) { - throw new IllegalArgumentException("Target must not be null."); - } - if (deferred) { - throw new IllegalStateException("Fit cannot be used with a Target."); - } - - Drawable drawable = - placeholderResId != 0 ? picasso.context.getResources().getDrawable(placeholderResId) - : placeholderDrawable; - - if (!data.hasImage()) { - picasso.cancelRequest(target); - target.onPrepareLoad(drawable); - return; - } - - Request finalData = picasso.transformRequest(data.build()); - String requestKey = createKey(finalData); - - if (!skipMemoryCache) { - Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey); - if (bitmap != null) { - picasso.cancelRequest(target); - target.onBitmapLoaded(bitmap, MEMORY); - return; - } - } - - target.onPrepareLoad(drawable); - - Action action = new TargetAction(picasso, target, finalData, skipMemoryCache, requestKey); - picasso.enqueueAndSubmit(action); - } - - /** - * Asynchronously fulfills the request into the specified {@link ImageView}. - * <p/> - * <em>Note:</em> This method keeps a weak reference to the {@link ImageView} instance and will - * automatically support object recycling. - */ - public void into(ImageView target) { - into(target, null); - } - - /** - * Asynchronously fulfills the request into the specified {@link ImageView} and invokes the - * target {@link Callback} if it's not {@code null}. - * <p/> - * <em>Note:</em> The {@link Callback} param is a strong reference and will prevent your - * {@link android.app.Activity} or {@link android.app.Fragment} from being garbage collected. If - * you use this method, it is <b>strongly</b> recommended you invoke an adjacent - * {@link Picasso#cancelRequest(android.widget.ImageView)} call to prevent temporary leaking. - */ - public void into(ImageView target, Callback callback) { - if (target == null) { - throw new IllegalArgumentException("Target must not be null."); - } - - if (!data.hasImage()) { - picasso.cancelRequest(target); - PicassoDrawable.setPlaceholder(target, placeholderResId, placeholderDrawable); - return; - } - - if (deferred) { - if (data.hasSize()) { - throw new IllegalStateException("Fit cannot be used with resize."); - } - int measuredWidth = target.getMeasuredWidth(); - int measuredHeight = target.getMeasuredHeight(); - if (measuredWidth == 0 || measuredHeight == 0) { - PicassoDrawable.setPlaceholder(target, placeholderResId, placeholderDrawable); - picasso.defer(target, new DeferredRequestCreator(this, target, callback)); - return; - } - data.resize(measuredWidth, measuredHeight); - } - - Request finalData = picasso.transformRequest(data.build()); - String requestKey = createKey(finalData); - - if (!skipMemoryCache) { - Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey); - if (bitmap != null) { - picasso.cancelRequest(target); - PicassoDrawable.setBitmap(target, picasso.context, bitmap, MEMORY, noFade, - picasso.debugging); - if (callback != null) { - callback.onSuccess(); - } - return; - } - } - - PicassoDrawable.setPlaceholder(target, placeholderResId, placeholderDrawable); - - Action action = - new ImageViewAction(picasso, target, finalData, skipMemoryCache, noFade, errorResId, - errorDrawable, requestKey, callback); - - picasso.enqueueAndSubmit(action); - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/ResourceBitmapHunter.java b/mobile/android/thirdparty/com/squareup/picasso/ResourceBitmapHunter.java deleted file mode 100644 index fee76b200..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/ResourceBitmapHunter.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import java.io.IOException; - -import static com.squareup.picasso.Picasso.LoadedFrom.DISK; - -class ResourceBitmapHunter extends BitmapHunter { - private final Context context; - - ResourceBitmapHunter(Context context, Picasso picasso, Dispatcher dispatcher, Cache cache, - Stats stats, Action action) { - super(picasso, dispatcher, cache, stats, action); - this.context = context; - } - - @Override Bitmap decode(Request data) throws IOException { - Resources res = Utils.getResources(context, data); - int id = Utils.getResourceId(res, data); - return decodeResource(res, id, data); - } - - @Override Picasso.LoadedFrom getLoadedFrom() { - return DISK; - } - - private Bitmap decodeResource(Resources resources, int id, Request data) { - BitmapFactory.Options bitmapOptions = null; - if (data.hasSize()) { - bitmapOptions = new BitmapFactory.Options(); - bitmapOptions.inJustDecodeBounds = true; - BitmapFactory.decodeResource(resources, id, bitmapOptions); - calculateInSampleSize(data.targetWidth, data.targetHeight, bitmapOptions); - } - return BitmapFactory.decodeResource(resources, id, bitmapOptions); - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Stats.java b/mobile/android/thirdparty/com/squareup/picasso/Stats.java deleted file mode 100644 index 3eaac0249..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Stats.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; - -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; - -class Stats { - private static final int CACHE_HIT = 0; - private static final int CACHE_MISS = 1; - private static final int BITMAP_DECODE_FINISHED = 2; - private static final int BITMAP_TRANSFORMED_FINISHED = 3; - - private static final String STATS_THREAD_NAME = Utils.THREAD_PREFIX + "Stats"; - - final HandlerThread statsThread; - final Cache cache; - final Handler handler; - - long cacheHits; - long cacheMisses; - long totalOriginalBitmapSize; - long totalTransformedBitmapSize; - long averageOriginalBitmapSize; - long averageTransformedBitmapSize; - int originalBitmapCount; - int transformedBitmapCount; - - Stats(Cache cache) { - this.cache = cache; - this.statsThread = new HandlerThread(STATS_THREAD_NAME, THREAD_PRIORITY_BACKGROUND); - this.statsThread.start(); - this.handler = new StatsHandler(statsThread.getLooper(), this); - } - - void dispatchBitmapDecoded(Bitmap bitmap) { - processBitmap(bitmap, BITMAP_DECODE_FINISHED); - } - - void dispatchBitmapTransformed(Bitmap bitmap) { - processBitmap(bitmap, BITMAP_TRANSFORMED_FINISHED); - } - - void dispatchCacheHit() { - handler.sendEmptyMessage(CACHE_HIT); - } - - void dispatchCacheMiss() { - handler.sendEmptyMessage(CACHE_MISS); - } - - void shutdown() { - statsThread.quit(); - } - - void performCacheHit() { - cacheHits++; - } - - void performCacheMiss() { - cacheMisses++; - } - - void performBitmapDecoded(long size) { - originalBitmapCount++; - totalOriginalBitmapSize += size; - averageOriginalBitmapSize = getAverage(originalBitmapCount, totalOriginalBitmapSize); - } - - void performBitmapTransformed(long size) { - transformedBitmapCount++; - totalTransformedBitmapSize += size; - averageTransformedBitmapSize = getAverage(originalBitmapCount, totalTransformedBitmapSize); - } - - synchronized StatsSnapshot createSnapshot() { - return new StatsSnapshot(cache.maxSize(), cache.size(), cacheHits, cacheMisses, - totalOriginalBitmapSize, totalTransformedBitmapSize, averageOriginalBitmapSize, - averageTransformedBitmapSize, originalBitmapCount, transformedBitmapCount, - System.currentTimeMillis()); - } - - private void processBitmap(Bitmap bitmap, int what) { - // Never send bitmaps to the handler as they could be recycled before we process them. - int bitmapSize = Utils.getBitmapBytes(bitmap); - handler.sendMessage(handler.obtainMessage(what, bitmapSize, 0)); - } - - private static long getAverage(int count, long totalSize) { - return totalSize / count; - } - - private static class StatsHandler extends Handler { - - private final Stats stats; - - public StatsHandler(Looper looper, Stats stats) { - super(looper); - this.stats = stats; - } - - @Override public void handleMessage(final Message msg) { - switch (msg.what) { - case CACHE_HIT: - stats.performCacheHit(); - break; - case CACHE_MISS: - stats.performCacheMiss(); - break; - case BITMAP_DECODE_FINISHED: - stats.performBitmapDecoded(msg.arg1); - break; - case BITMAP_TRANSFORMED_FINISHED: - stats.performBitmapTransformed(msg.arg1); - break; - default: - Picasso.HANDLER.post(new Runnable() { - @Override public void run() { - throw new AssertionError("Unhandled stats message." + msg.what); - } - }); - } - } - } -}
\ No newline at end of file diff --git a/mobile/android/thirdparty/com/squareup/picasso/StatsSnapshot.java b/mobile/android/thirdparty/com/squareup/picasso/StatsSnapshot.java deleted file mode 100644 index 5f276ebf2..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/StatsSnapshot.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.util.Log; -import java.io.PrintWriter; -import java.io.StringWriter; - -/** Represents all stats for a {@link Picasso} instance at a single point in time. */ -public class StatsSnapshot { - private static final String TAG = "Picasso"; - - public final int maxSize; - public final int size; - public final long cacheHits; - public final long cacheMisses; - public final long totalOriginalBitmapSize; - public final long totalTransformedBitmapSize; - public final long averageOriginalBitmapSize; - public final long averageTransformedBitmapSize; - public final int originalBitmapCount; - public final int transformedBitmapCount; - - public final long timeStamp; - - public StatsSnapshot(int maxSize, int size, long cacheHits, long cacheMisses, - long totalOriginalBitmapSize, long totalTransformedBitmapSize, long averageOriginalBitmapSize, - long averageTransformedBitmapSize, int originalBitmapCount, int transformedBitmapCount, - long timeStamp) { - this.maxSize = maxSize; - this.size = size; - this.cacheHits = cacheHits; - this.cacheMisses = cacheMisses; - this.totalOriginalBitmapSize = totalOriginalBitmapSize; - this.totalTransformedBitmapSize = totalTransformedBitmapSize; - this.averageOriginalBitmapSize = averageOriginalBitmapSize; - this.averageTransformedBitmapSize = averageTransformedBitmapSize; - this.originalBitmapCount = originalBitmapCount; - this.transformedBitmapCount = transformedBitmapCount; - this.timeStamp = timeStamp; - } - - /** Prints out this {@link StatsSnapshot} into log. */ - public void dump() { - StringWriter logWriter = new StringWriter(); - dump(new PrintWriter(logWriter)); - Log.i(TAG, logWriter.toString()); - } - - /** Prints out this {@link StatsSnapshot} with the the provided {@link PrintWriter}. */ - public void dump(PrintWriter writer) { - writer.println("===============BEGIN PICASSO STATS ==============="); - writer.println("Memory Cache Stats"); - writer.print(" Max Cache Size: "); - writer.println(maxSize); - writer.print(" Cache Size: "); - writer.println(size); - writer.print(" Cache % Full: "); - writer.println((int) Math.ceil((float) size / maxSize * 100)); - writer.print(" Cache Hits: "); - writer.println(cacheHits); - writer.print(" Cache Misses: "); - writer.println(cacheMisses); - writer.println("Bitmap Stats"); - writer.print(" Total Bitmaps Decoded: "); - writer.println(originalBitmapCount); - writer.print(" Total Bitmap Size: "); - writer.println(totalOriginalBitmapSize); - writer.print(" Total Transformed Bitmaps: "); - writer.println(transformedBitmapCount); - writer.print(" Total Transformed Bitmap Size: "); - writer.println(totalTransformedBitmapSize); - writer.print(" Average Bitmap Size: "); - writer.println(averageOriginalBitmapSize); - writer.print(" Average Transformed Bitmap Size: "); - writer.println(averageTransformedBitmapSize); - writer.println("===============END PICASSO STATS ==============="); - writer.flush(); - } - - @Override public String toString() { - return "StatsSnapshot{" - + "maxSize=" - + maxSize - + ", size=" - + size - + ", cacheHits=" - + cacheHits - + ", cacheMisses=" - + cacheMisses - + ", totalOriginalBitmapSize=" - + totalOriginalBitmapSize - + ", totalTransformedBitmapSize=" - + totalTransformedBitmapSize - + ", averageOriginalBitmapSize=" - + averageOriginalBitmapSize - + ", averageTransformedBitmapSize=" - + averageTransformedBitmapSize - + ", originalBitmapCount=" - + originalBitmapCount - + ", transformedBitmapCount=" - + transformedBitmapCount - + ", timeStamp=" - + timeStamp - + '}'; - } -}
\ No newline at end of file diff --git a/mobile/android/thirdparty/com/squareup/picasso/Target.java b/mobile/android/thirdparty/com/squareup/picasso/Target.java deleted file mode 100644 index ad3ce6fcf..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Target.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; - -import static com.squareup.picasso.Picasso.LoadedFrom; - -/** - * Represents an arbitrary listener for image loading. - * <p/> - * Objects implementing this class <strong>must</strong> have a working implementation of - * {@link #equals(Object)} and {@link #hashCode()} for proper storage internally. Instances of this - * interface will also be compared to determine if view recycling is occurring. It is recommended - * that you add this interface directly on to a custom view type when using in an adapter to ensure - * correct recycling behavior. - */ -public interface Target { - /** - * Callback when an image has been successfully loaded. - * <p/> - * <strong>Note:</strong> You must not recycle the bitmap. - */ - void onBitmapLoaded(Bitmap bitmap, LoadedFrom from); - - /** Callback indicating the image could not be successfully loaded. */ - void onBitmapFailed(Drawable errorDrawable); - - /** Callback invoked right before your request is submitted. */ - void onPrepareLoad(Drawable placeHolderDrawable); -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/TargetAction.java b/mobile/android/thirdparty/com/squareup/picasso/TargetAction.java deleted file mode 100644 index 77a40f51d..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/TargetAction.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; - -final class TargetAction extends Action<Target> { - - TargetAction(Picasso picasso, Target target, Request data, boolean skipCache, String key) { - super(picasso, target, data, skipCache, false, 0, null, key); - } - - @Override void complete(Bitmap result, Picasso.LoadedFrom from) { - if (result == null) { - throw new AssertionError( - String.format("Attempted to complete action with no result!\n%s", this)); - } - Target target = getTarget(); - if (target != null) { - target.onBitmapLoaded(result, from); - if (result.isRecycled()) { - throw new IllegalStateException("Target callback must not recycle bitmap!"); - } - } - } - - @Override void error() { - Target target = getTarget(); - if (target != null) { - target.onBitmapFailed(errorDrawable); - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Transformation.java b/mobile/android/thirdparty/com/squareup/picasso/Transformation.java deleted file mode 100644 index 2c59f160c..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Transformation.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.graphics.Bitmap; - -/** Image transformation. */ -public interface Transformation { - /** - * Transform the source bitmap into a new bitmap. If you create a new bitmap instance, you must - * call {@link android.graphics.Bitmap#recycle()} on {@code source}. You may return the original - * if no transformation is required. - */ - Bitmap transform(Bitmap source); - - /** - * Returns a unique key for the transformation, used for caching purposes. If the transformation - * has parameters (e.g. size, scale factor, etc) then these should be part of the key. - */ - String key(); -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/UrlConnectionDownloader.java b/mobile/android/thirdparty/com/squareup/picasso/UrlConnectionDownloader.java deleted file mode 100644 index 50f9b2b98..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/UrlConnectionDownloader.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.content.Context; -import android.net.Uri; -import android.net.http.HttpResponseCache; -import android.os.Build; -import java.io.File; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; - -import static com.squareup.picasso.Utils.parseResponseSourceHeader; - -/** - * A {@link Downloader} which uses {@link HttpURLConnection} to download images. A disk cache of 2% - * of the total available space will be used (capped at 50MB) will automatically be installed in the - * application's cache directory, when available. - */ -public class UrlConnectionDownloader implements Downloader { - static final String RESPONSE_SOURCE = "X-Android-Response-Source"; - - private static final Object lock = new Object(); - static volatile Object cache; - - private final Context context; - - public UrlConnectionDownloader(Context context) { - this.context = context.getApplicationContext(); - } - - protected HttpURLConnection openConnection(Uri path) throws IOException { - HttpURLConnection connection = (HttpURLConnection) new URL(path.toString()).openConnection(); - connection.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT); - connection.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT); - return connection; - } - - @Override public Response load(Uri uri, boolean localCacheOnly) throws IOException { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - installCacheIfNeeded(context); - } - - HttpURLConnection connection = openConnection(uri); - connection.setUseCaches(true); - if (localCacheOnly) { - connection.setRequestProperty("Cache-Control", "only-if-cached,max-age=" + Integer.MAX_VALUE); - } - - int responseCode = connection.getResponseCode(); - if (responseCode >= 300) { - connection.disconnect(); - throw new ResponseException(responseCode + " " + connection.getResponseMessage()); - } - - boolean fromCache = parseResponseSourceHeader(connection.getHeaderField(RESPONSE_SOURCE)); - - return new Response(connection.getInputStream(), fromCache); - } - - private static void installCacheIfNeeded(Context context) { - // DCL + volatile should be safe after Java 5. - if (cache == null) { - try { - synchronized (lock) { - if (cache == null) { - cache = ResponseCacheIcs.install(context); - } - } - } catch (IOException ignored) { - } - } - } - - private static class ResponseCacheIcs { - static Object install(Context context) throws IOException { - File cacheDir = Utils.createDefaultCacheDir(context); - HttpResponseCache cache = HttpResponseCache.getInstalled(); - if (cache == null) { - long maxSize = Utils.calculateDiskCacheSize(cacheDir); - cache = HttpResponseCache.install(cacheDir, maxSize); - } - return cache; - } - } -} diff --git a/mobile/android/thirdparty/com/squareup/picasso/Utils.java b/mobile/android/thirdparty/com/squareup/picasso/Utils.java deleted file mode 100644 index bafe93f98..000000000 --- a/mobile/android/thirdparty/com/squareup/picasso/Utils.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.squareup.picasso; - -import android.annotation.TargetApi; -import android.app.ActivityManager; -import android.content.ContentResolver; -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.os.Looper; -import android.os.Process; -import android.os.StatFs; -import android.provider.Settings; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.concurrent.ThreadFactory; - -import static android.content.Context.ACTIVITY_SERVICE; -import static android.content.pm.ApplicationInfo.FLAG_LARGE_HEAP; -import static android.os.Build.VERSION.SDK_INT; -import static android.os.Build.VERSION_CODES.HONEYCOMB; -import static android.os.Build.VERSION_CODES.HONEYCOMB_MR1; -import static android.os.Process.THREAD_PRIORITY_BACKGROUND; -import static android.provider.Settings.System.AIRPLANE_MODE_ON; - -final class Utils { - static final String THREAD_PREFIX = "Picasso-"; - static final String THREAD_IDLE_NAME = THREAD_PREFIX + "Idle"; - static final int DEFAULT_READ_TIMEOUT = 20 * 1000; // 20s - static final int DEFAULT_CONNECT_TIMEOUT = 15 * 1000; // 15s - private static final String PICASSO_CACHE = "picasso-cache"; - private static final int KEY_PADDING = 50; // Determined by exact science. - private static final int MIN_DISK_CACHE_SIZE = 5 * 1024 * 1024; // 5MB - private static final int MAX_DISK_CACHE_SIZE = 50 * 1024 * 1024; // 50MB - - /* WebP file header - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 'R' | 'I' | 'F' | 'F' | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | File Size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 'W' | 'E' | 'B' | 'P' | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - private static final int WEBP_FILE_HEADER_SIZE = 12; - private static final String WEBP_FILE_HEADER_RIFF = "RIFF"; - private static final String WEBP_FILE_HEADER_WEBP = "WEBP"; - - private Utils() { - // No instances. - } - - static int getBitmapBytes(Bitmap bitmap) { - int result; - if (SDK_INT >= HONEYCOMB_MR1) { - result = BitmapHoneycombMR1.getByteCount(bitmap); - } else { - result = bitmap.getRowBytes() * bitmap.getHeight(); - } - if (result < 0) { - throw new IllegalStateException("Negative size: " + bitmap); - } - return result; - } - - static void checkNotMain() { - if (Looper.getMainLooper().getThread() == Thread.currentThread()) { - throw new IllegalStateException("Method call should not happen from the main thread."); - } - } - - static String createKey(Request data) { - StringBuilder builder; - - if (data.uri != null) { - String path = data.uri.toString(); - builder = new StringBuilder(path.length() + KEY_PADDING); - builder.append(path); - } else { - builder = new StringBuilder(KEY_PADDING); - builder.append(data.resourceId); - } - builder.append('\n'); - - if (data.rotationDegrees != 0) { - builder.append("rotation:").append(data.rotationDegrees); - if (data.hasRotationPivot) { - builder.append('@').append(data.rotationPivotX).append('x').append(data.rotationPivotY); - } - builder.append('\n'); - } - if (data.targetWidth != 0) { - builder.append("resize:").append(data.targetWidth).append('x').append(data.targetHeight); - builder.append('\n'); - } - if (data.centerCrop) { - builder.append("centerCrop\n"); - } else if (data.centerInside) { - builder.append("centerInside\n"); - } - - if (data.transformations != null) { - //noinspection ForLoopReplaceableByForEach - for (int i = 0, count = data.transformations.size(); i < count; i++) { - builder.append(data.transformations.get(i).key()); - builder.append('\n'); - } - } - - return builder.toString(); - } - - static void closeQuietly(InputStream is) { - if (is == null) return; - try { - is.close(); - } catch (IOException ignored) { - } - } - - /** Returns {@code true} if header indicates the response body was loaded from the disk cache. */ - static boolean parseResponseSourceHeader(String header) { - if (header == null) { - return false; - } - String[] parts = header.split(" ", 2); - if ("CACHE".equals(parts[0])) { - return true; - } - if (parts.length == 1) { - return false; - } - try { - return "CONDITIONAL_CACHE".equals(parts[0]) && Integer.parseInt(parts[1]) == 304; - } catch (NumberFormatException e) { - return false; - } - } - - static Downloader createDefaultDownloader(Context context) { - return new UrlConnectionDownloader(context); - } - - static File createDefaultCacheDir(Context context) { - File cache = new File(context.getApplicationContext().getCacheDir(), PICASSO_CACHE); - if (!cache.exists()) { - cache.mkdirs(); - } - return cache; - } - - static long calculateDiskCacheSize(File dir) { - long size = MIN_DISK_CACHE_SIZE; - - try { - StatFs statFs = new StatFs(dir.getAbsolutePath()); - long available = ((long) statFs.getBlockCount()) * statFs.getBlockSize(); - // Target 2% of the total space. - size = available / 50; - } catch (IllegalArgumentException ignored) { - } - - // Bound inside min/max size for disk cache. - return Math.max(Math.min(size, MAX_DISK_CACHE_SIZE), MIN_DISK_CACHE_SIZE); - } - - static int calculateMemoryCacheSize(Context context) { - ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE); - boolean largeHeap = (context.getApplicationInfo().flags & FLAG_LARGE_HEAP) != 0; - int memoryClass = am.getMemoryClass(); - if (largeHeap && SDK_INT >= HONEYCOMB) { - memoryClass = ActivityManagerHoneycomb.getLargeMemoryClass(am); - } - // Target ~15% of the available heap. - return 1024 * 1024 * memoryClass / 7; - } - - static boolean isAirplaneModeOn(Context context) { - ContentResolver contentResolver = context.getContentResolver(); - return Settings.System.getInt(contentResolver, AIRPLANE_MODE_ON, 0) != 0; - } - - static boolean hasPermission(Context context, String permission) { - return context.checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED; - } - - static byte[] toByteArray(InputStream input) throws IOException { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024 * 4]; - int n = 0; - while (-1 != (n = input.read(buffer))) { - byteArrayOutputStream.write(buffer, 0, n); - } - return byteArrayOutputStream.toByteArray(); - } - - static boolean isWebPFile(InputStream stream) throws IOException { - byte[] fileHeaderBytes = new byte[WEBP_FILE_HEADER_SIZE]; - boolean isWebPFile = false; - if (stream.read(fileHeaderBytes, 0, WEBP_FILE_HEADER_SIZE) == WEBP_FILE_HEADER_SIZE) { - // If a file's header starts with RIFF and end with WEBP, the file is a WebP file - isWebPFile = WEBP_FILE_HEADER_RIFF.equals(new String(fileHeaderBytes, 0, 4, "US-ASCII")) - && WEBP_FILE_HEADER_WEBP.equals(new String(fileHeaderBytes, 8, 4, "US-ASCII")); - } - return isWebPFile; - } - - static int getResourceId(Resources resources, Request data) throws FileNotFoundException { - if (data.resourceId != 0 || data.uri == null) { - return data.resourceId; - } - - String pkg = data.uri.getAuthority(); - if (pkg == null) throw new FileNotFoundException("No package provided: " + data.uri); - - int id; - List<String> segments = data.uri.getPathSegments(); - if (segments == null || segments.isEmpty()) { - throw new FileNotFoundException("No path segments: " + data.uri); - } else if (segments.size() == 1) { - try { - id = Integer.parseInt(segments.get(0)); - } catch (NumberFormatException e) { - throw new FileNotFoundException("Last path segment is not a resource ID: " + data.uri); - } - } else if (segments.size() == 2) { - String type = segments.get(0); - String name = segments.get(1); - - id = resources.getIdentifier(name, type, pkg); - } else { - throw new FileNotFoundException("More than two path segments: " + data.uri); - } - return id; - } - - static Resources getResources(Context context, Request data) throws FileNotFoundException { - if (data.resourceId != 0 || data.uri == null) { - return context.getResources(); - } - - String pkg = data.uri.getAuthority(); - if (pkg == null) throw new FileNotFoundException("No package provided: " + data.uri); - try { - PackageManager pm = context.getPackageManager(); - return pm.getResourcesForApplication(pkg); - } catch (PackageManager.NameNotFoundException e) { - throw new FileNotFoundException("Unable to obtain resources for package: " + data.uri); - } - } - - @TargetApi(HONEYCOMB) - private static class ActivityManagerHoneycomb { - static int getLargeMemoryClass(ActivityManager activityManager) { - return activityManager.getLargeMemoryClass(); - } - } - - static class PicassoThreadFactory implements ThreadFactory { - @SuppressWarnings("NullableProblems") - public Thread newThread(Runnable r) { - return new PicassoThread(r); - } - } - - private static class PicassoThread extends Thread { - public PicassoThread(Runnable r) { - super(r); - } - - @Override public void run() { - Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); - super.run(); - } - } - - @TargetApi(HONEYCOMB_MR1) - private static class BitmapHoneycombMR1 { - static int getByteCount(Bitmap bitmap) { - return bitmap.getByteCount(); - } - } -} |