1515import android .content .pm .PackageManager ;
1616import android .content .pm .ResolveInfo ;
1717import android .net .Uri ;
18+ import android .net .UrlQuerySanitizer ;
1819import android .os .Handler ;
1920import android .util .*;
2021
@@ -119,6 +120,8 @@ public class InternalState {
119120 boolean background ;
120121 boolean delayStart ;
121122 boolean updatePackages ;
123+ boolean firstLaunch ;
124+ boolean sessionResponseProcessed ;
122125
123126 public boolean isEnabled () {
124127 return enabled ;
@@ -155,6 +158,14 @@ public boolean isToStartNow() {
155158 public boolean isToUpdatePackages () {
156159 return updatePackages ;
157160 }
161+
162+ public boolean isFirstLaunch () {
163+ return firstLaunch ;
164+ }
165+
166+ public boolean isSessionResponseProcessed () {
167+ return sessionResponseProcessed ;
168+ }
158169 }
159170
160171 private ActivityHandler (AdjustConfig adjustConfig ) {
@@ -178,6 +189,8 @@ private ActivityHandler(AdjustConfig adjustConfig) {
178189 internalState .delayStart = false ;
179190 // does not need to update packages by default
180191 internalState .updatePackages = false ;
192+ // does not have the session response by default
193+ internalState .sessionResponseProcessed = false ;
181194
182195 scheduledExecutor .submit (new Runnable () {
183196 @ Override
@@ -579,6 +592,24 @@ public void run() {
579592 });
580593 }
581594
595+ public void foregroundTimerFired () {
596+ scheduledExecutor .submit (new Runnable () {
597+ @ Override
598+ public void run () {
599+ foregroundTimerFiredI ();
600+ }
601+ });
602+ }
603+
604+ public void backgroundTimerFired () {
605+ scheduledExecutor .submit (new Runnable () {
606+ @ Override
607+ public void run () {
608+ backgroundTimerFiredI ();
609+ }
610+ });
611+ }
612+
582613 public String getAdid () {
583614 if (activityState == null ) {
584615 return null ;
@@ -631,6 +662,9 @@ private void initI() {
631662 if (activityState != null ) {
632663 internalState .enabled = activityState .enabled ;
633664 internalState .updatePackages = activityState .updatePackages ;
665+ internalState .firstLaunch = false ;
666+ } else {
667+ internalState .firstLaunch = true ; // first launch if activity state is null
634668 }
635669
636670 readConfigFile (adjustConfig .context );
@@ -669,18 +703,18 @@ private void initI() {
669703 new Runnable () {
670704 @ Override
671705 public void run () {
672- foregroundTimerFiredI ();
706+ foregroundTimerFired ();
673707 }
674708 }, FOREGROUND_TIMER_START , FOREGROUND_TIMER_INTERVAL , FOREGROUND_TIMER_NAME );
675709
676710 // create background timer
677711 if (adjustConfig .sendInBackground ) {
678712 logger .info ("Send in background configured" );
679713
680- backgroundTimer = new TimerOnce (scheduledExecutor , new Runnable () {
714+ backgroundTimer = new TimerOnce (new Runnable () {
681715 @ Override
682716 public void run () {
683- backgroundTimerFiredI ();
717+ backgroundTimerFired ();
684718 }
685719 }, BACKGROUND_TIMER_NAME );
686720 }
@@ -692,10 +726,10 @@ public void run() {
692726 {
693727 logger .info ("Delay start configured" );
694728 internalState .delayStart = true ;
695- delayStartTimer = new TimerOnce (scheduledExecutor , new Runnable () {
729+ delayStartTimer = new TimerOnce (new Runnable () {
696730 @ Override
697731 public void run () {
698- sendFirstPackagesI ();
732+ sendFirstPackages ();
699733 }
700734 }, DELAY_START_TIMER_NAME );
701735 }
@@ -823,9 +857,12 @@ private void processSessionI() {
823857 private void checkAttributionStateI () {
824858 if (!checkActivityStateI (activityState )) { return ; }
825859
826- // if it's a new session
827- if (activityState .subsessionCount <= 1 ) {
828- return ;
860+ // if it's the first launch
861+ if (internalState .isFirstLaunch ()) {
862+ // and it hasn't received the session response
863+ if (!internalState .isSessionResponseProcessed ()) {
864+ return ;
865+ }
829866 }
830867
831868 // if there is already an attribution saved and there was no attribution being asked
@@ -929,6 +966,9 @@ private void launchSessionResponseTasksI(SessionResponseData sessionResponseData
929966
930967 // launch Session tracking listener if available
931968 launchSessionResponseListenerI (sessionResponseData , handler );
969+
970+ // mark session response has proccessed
971+ internalState .sessionResponseProcessed = true ;
932972 }
933973
934974 private void launchSessionResponseListenerI (final SessionResponseData sessionResponseData , Handler handler ) {
@@ -1053,7 +1093,15 @@ private void sendReferrerI(String referrer, long clickTime) {
10531093 if (referrer == null || referrer .length () == 0 ) {
10541094 return ;
10551095 }
1056- PackageBuilder clickPackageBuilder = queryStringClickPackageBuilderI (referrer );
1096+
1097+ logger .verbose ("Referrer to parse (%s)" , referrer );
1098+
1099+ UrlQuerySanitizer querySanitizer = new UrlQuerySanitizer ();
1100+ querySanitizer .setUnregisteredParameterValueSanitizer (UrlQuerySanitizer .getAllButNulLegal ());
1101+ querySanitizer .setAllowUnregisteredParamaters (true );
1102+ querySanitizer .parseQuery (referrer );
1103+
1104+ PackageBuilder clickPackageBuilder = queryStringClickPackageBuilderI (querySanitizer .getParameterList ());
10571105
10581106 if (clickPackageBuilder == null ) {
10591107 return ;
@@ -1071,13 +1119,15 @@ private void readOpenUrlI(Uri url, long clickTime) {
10711119 return ;
10721120 }
10731121
1074- String queryString = url .getQuery ();
1122+ String urlString = url .toString ();
1123+ logger .verbose ("Url to parse (%s)" , url );
10751124
1076- if (queryString == null && url .toString ().length () > 0 ) {
1077- queryString = "" ;
1078- }
1125+ UrlQuerySanitizer querySanitizer = new UrlQuerySanitizer ();
1126+ querySanitizer .setUnregisteredParameterValueSanitizer (UrlQuerySanitizer .getAllButNulLegal ());
1127+ querySanitizer .setAllowUnregisteredParamaters (true );
1128+ querySanitizer .parseUrl (urlString );
10791129
1080- PackageBuilder clickPackageBuilder = queryStringClickPackageBuilderI (queryString );
1130+ PackageBuilder clickPackageBuilder = queryStringClickPackageBuilderI (querySanitizer . getParameterList () );
10811131 if (clickPackageBuilder == null ) {
10821132 return ;
10831133 }
@@ -1089,20 +1139,19 @@ private void readOpenUrlI(Uri url, long clickTime) {
10891139 sdkClickHandler .sendSdkClick (clickPackage );
10901140 }
10911141
1092- private PackageBuilder queryStringClickPackageBuilderI (String queryString ) {
1093- if (queryString == null ) {
1142+ private PackageBuilder queryStringClickPackageBuilderI (
1143+ List <UrlQuerySanitizer .ParameterValuePair > queryList ) {
1144+ if (queryList == null ) {
10941145 return null ;
10951146 }
10961147
10971148 Map <String , String > queryStringParameters = new LinkedHashMap <String , String >();
10981149 AdjustAttribution queryStringAttribution = new AdjustAttribution ();
10991150
1100- logger .verbose ("Reading query string (%s)" , queryString );
1101-
1102- String [] queryPairs = queryString .split ("&" );
1103-
1104- for (String pair : queryPairs ) {
1105- readQueryStringI (pair , queryStringParameters , queryStringAttribution );
1151+ for (UrlQuerySanitizer .ParameterValuePair parameterValuePair : queryList ) {
1152+ readQueryStringI (parameterValuePair .mParameter ,
1153+ parameterValuePair .mValue ,
1154+ queryStringParameters , queryStringAttribution );
11061155 }
11071156
11081157 String reftag = queryStringParameters .remove (Constants .REFTAG );
@@ -1116,17 +1165,13 @@ private PackageBuilder queryStringClickPackageBuilderI(String queryString) {
11161165 return builder ;
11171166 }
11181167
1119- private boolean readQueryStringI (String queryString ,
1168+ private boolean readQueryStringI (String key , String value ,
11201169 Map <String , String > extraParameters ,
11211170 AdjustAttribution queryStringAttribution ) {
1122- String [] pairComponents = queryString .split ("=" );
1123- if (pairComponents .length != 2 ) return false ;
1124-
1125- String key = pairComponents [0 ];
1126- if (!key .startsWith (ADJUST_PREFIX )) return false ;
1171+ if (key == null || value == null ) { return false ; }
11271172
1128- String value = pairComponents [ 1 ];
1129- if (value . length () == 0 ) return false ;
1173+ // parameter key does not start with "adjust_"
1174+ if (! key . startsWith ( ADJUST_PREFIX )) { return false ; }
11301175
11311176 String keyWOutPrefix = key .substring (ADJUST_PREFIX .length ());
11321177 if (keyWOutPrefix .length () == 0 ) return false ;
0 commit comments