1313import org .json .JSONException ;
1414import org .json .JSONObject ;
1515
16+ import java .text .SimpleDateFormat ;
1617import java .util .Arrays ;
1718import java .util .ConcurrentModificationException ;
1819import java .util .HashSet ;
1920import java .util .Iterator ;
21+ import java .util .Locale ;
2022import java .util .Set ;
23+ import java .util .TimeZone ;
2124import java .util .concurrent .ConcurrentHashMap ;
2225
26+ import java .util .UUID ;
27+
2328/**
2429 * Abstract class defining the structure of a Branch Server request.
2530 */
@@ -34,6 +39,8 @@ public abstract class ServerRequest {
3439
3540 private static final String POST_KEY = "REQ_POST" ;
3641 private static final String POST_PATH_KEY = "REQ_POST_PATH" ;
42+ protected long creation_ts = 0 ;
43+ protected String uuid ;
3744
3845 private JSONObject params_ ;
3946 final Defines .RequestPath requestPath_ ;
@@ -67,11 +74,7 @@ public enum BRANCH_API_VERSION {
6774 * @param requestPath Path to server for this request.
6875 */
6976 public ServerRequest (Context context , Defines .RequestPath requestPath ) {
70- context_ = context ;
71- requestPath_ = requestPath ;
72- prefHelper_ = PrefHelper .getInstance (context );
73- params_ = new JSONObject ();
74- locks_ = new HashSet <>();
77+ this (requestPath , new JSONObject (), context );
7578 }
7679
7780 /**
@@ -83,13 +86,40 @@ public ServerRequest(Context context, Defines.RequestPath requestPath) {
8386 * @param context Application context.
8487 */
8588 protected ServerRequest (Defines .RequestPath requestPath , JSONObject post , Context context ) {
89+ BranchLogger .v ("ServerRequest constructor" );
8690 context_ = context ;
8791 requestPath_ = requestPath ;
8892 params_ = post ;
8993 prefHelper_ = PrefHelper .getInstance (context );
9094 locks_ = new HashSet <>();
95+
96+ creation_ts = System .currentTimeMillis ();
97+ String creation_ts_date_formatted = formatUnixEpochToDateFormat (creation_ts );
98+ uuid = getRequestUuid (creation_ts_date_formatted );
9199 }
92-
100+
101+ /**
102+ * Returns Unix epoch time converted to readable date format: year-month-dayOfMonth-hour with - prefix
103+ * Force Locale US character representation
104+ * @param creationTs
105+ * @return
106+ */
107+ private String formatUnixEpochToDateFormat (long creationTs ) {
108+ SimpleDateFormat sdf = new SimpleDateFormat ("-yyyyMMddHH" , Locale .US );
109+ sdf .setTimeZone (TimeZone .getTimeZone ("UTC" ));
110+
111+ return sdf .format (creationTs );
112+ }
113+
114+ /**
115+ * Appends formatted time stamp to randomly generated UUID
116+ * @param creationTsDateFormatted
117+ * @return
118+ */
119+ private String getRequestUuid (String creationTsDateFormatted ) {
120+ return UUID .randomUUID ().toString () + creationTsDateFormatted ;
121+ }
122+
93123 /**
94124 * <p>Should be implemented by the child class.Specifies any error associated with request.
95125 * If there are errors request will not be executed.</p>
@@ -139,16 +169,7 @@ protected ServerRequest(Defines.RequestPath requestPath, JSONObject post, Contex
139169 public boolean shouldRetryOnFail () {
140170 return false ;
141171 }
142-
143- /**
144- * Specifies whether this request should be persisted to memory in order to re send in the next session
145- *
146- * @return {@code true} by default. Should be override for request that need not to be persisted
147- */
148- boolean isPersistable () {
149- return true ;
150- }
151-
172+
152173 /**
153174 * Specifies whether this request should add the limit app tracking value
154175 *
@@ -241,6 +262,7 @@ public String getRequestUrl() {
241262 * as key-value pairs.
242263 */
243264 protected void setPost (JSONObject post ) throws JSONException {
265+ BranchLogger .v ("setPost " + post );
244266 params_ = post ;
245267
246268 if (getBranchRemoteAPIVersion () == BRANCH_API_VERSION .V1 ) {
@@ -364,7 +386,8 @@ public JSONObject toJSON() {
364386 }
365387 return json ;
366388 }
367-
389+
390+ // TODO: Replace with in-memory only ServerRequest objects.
368391 /**
369392 * <p>Converts a {@link JSONObject} object containing keys stored as key-value pairs into
370393 * a {@link ServerRequest}.</p>
@@ -404,13 +427,14 @@ public static ServerRequest fromJSON(JSONObject json, Context context) {
404427 } catch (JSONException e ) {
405428 BranchLogger .w ("Caught JSONException " + e .getMessage ());
406429 }
407-
430+
408431 if (!TextUtils .isEmpty (requestPath )) {
409432 return getExtendedServerRequest (requestPath , post , context , initiatedByClient );
410433 }
411434 return null ;
412435 }
413-
436+
437+ // TODO: Replace with in-memory only ServerRequest objects.
414438 /**
415439 * <p>Factory method for creating the specific server requests objects. Creates requests according
416440 * to the request path.</p>
@@ -422,18 +446,17 @@ public static ServerRequest fromJSON(JSONObject json, Context context) {
422446 */
423447 private static ServerRequest getExtendedServerRequest (String requestPath , JSONObject post , Context context , boolean initiatedByClient ) {
424448 ServerRequest extendedReq = null ;
425-
449+
426450 if (requestPath .equalsIgnoreCase (Defines .RequestPath .GetURL .getPath ())) {
427451 extendedReq = new ServerRequestCreateUrl (Defines .RequestPath .GetURL , post , context );
428452 } else if (requestPath .equalsIgnoreCase (Defines .RequestPath .RegisterInstall .getPath ())) {
429453 extendedReq = new ServerRequestRegisterInstall (Defines .RequestPath .RegisterInstall , post , context , initiatedByClient );
430454 } else if (requestPath .equalsIgnoreCase (Defines .RequestPath .RegisterOpen .getPath ())) {
431455 extendedReq = new ServerRequestRegisterOpen (Defines .RequestPath .RegisterOpen , post , context , initiatedByClient );
432456 }
433-
434457 return extendedReq ;
435458 }
436-
459+
437460 /**
438461 * Updates the google ads parameters. This should be called only from a background thread since it involves GADS method invocation using reflection
439462 * Ensure that when there is a valid GAID/AID, remove the SSAID if it's being used
@@ -639,17 +662,37 @@ private void removePreinstallData(JSONObject params) {
639662 }
640663
641664 void doFinalUpdateOnMainThread () {
665+ BranchLogger .v ("doFinalUpdateOnMainThread" );
642666 updateRequestMetadata ();
643667 if (shouldUpdateLimitFacebookTracking ()) {
644668 updateLimitFacebookTracking ();
645669 }
646670 if (shouldAddDMAParams ()) {
647671 addDMAParams ();
648672 }
649- addConsumerProtectionAttributionLevel ();
673+
674+ addConsumerProtectionAttributionLevel ();
675+
676+ // Always add these fields
677+ addClientRequestParameters ();
650678 }
651-
679+
680+ /**
681+ * Put request time stamp and uuid at top level of POST body
682+ */
683+ private void addClientRequestParameters () {
684+ if (prefHelper_ != null ){
685+ try {
686+ params_ .put (Defines .Jsonkey .Branch_Sdk_Request_Creation_Time_Stamp .getKey (), this .creation_ts );
687+ params_ .put (Defines .Jsonkey .Branch_Sdk_Request_Uuid .getKey (), this .uuid );
688+ } catch (JSONException e ) {
689+ throw new RuntimeException (e );
690+ }
691+ }
692+ }
693+
652694 void doFinalUpdateOnBackgroundThread () {
695+ BranchLogger .v ("doFinalUpdateOnBackgroundThread" );
653696 if (this instanceof ServerRequestInitSession ) {
654697 ((ServerRequestInitSession ) this ).updateLinkReferrerParams ();
655698 if (prioritizeLinkAttribution (this .params_ )) {
0 commit comments