Skip to content

Commit c343c4a

Browse files
committed
NR-517762: rebased with stable-beta
1 parent 56f48df commit c343c4a

File tree

6 files changed

+146
-46
lines changed

6 files changed

+146
-46
lines changed

NRExoPlayerTracker/src/main/java/com/newrelic/videoagent/exoplayer/tracker/NRTrackerExoPlayer.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import androidx.media3.exoplayer.source.LoadEventInfo;
2020
import androidx.media3.exoplayer.source.MediaLoadData;
2121

22+
import com.newrelic.videoagent.core.NRVideoConfiguration;
2223
import com.newrelic.videoagent.core.tracker.NRVideoTracker;
2324
import com.newrelic.videoagent.core.utils.NRLog;
2425
import com.newrelic.videoagent.exoplayer.BuildConfig;
@@ -73,15 +74,39 @@ public class NRTrackerExoPlayer extends NRVideoTracker implements Player.Listene
7374
/**
7475
* Init a new ExoPlayer tracker.
7576
*/
77+
public NRTrackerExoPlayer(NRVideoConfiguration configuration) {
78+
super(configuration);
79+
}
80+
81+
/**
82+
* Create a new NRTrackerExoPlayer (deprecated - use constructor with configuration).
83+
* @deprecated Use NRTrackerExoPlayer(NRVideoConfiguration) constructor instead
84+
*/
85+
@Deprecated
7686
public NRTrackerExoPlayer() {
87+
super();
7788
}
7889

7990
/**
8091
* Init a new ExoPlayer tracker.
8192
*
93+
* @param configuration Video configuration
94+
* @param player ExoPlayer instance.
95+
*/
96+
public NRTrackerExoPlayer(NRVideoConfiguration configuration, ExoPlayer player) {
97+
super(configuration);
98+
setPlayer(player);
99+
}
100+
101+
/**
102+
* Init a new ExoPlayer tracker (deprecated).
103+
*
82104
* @param player ExoPlayer instance.
105+
* @deprecated Use NRTrackerExoPlayer(NRVideoConfiguration, ExoPlayer) constructor instead
83106
*/
107+
@Deprecated
84108
public NRTrackerExoPlayer(ExoPlayer player) {
109+
super();
85110
setPlayer(player);
86111
}
87112

NRIMATracker/src/main/java/com/newrelic/videoagent/ima/tracker/NRTrackerIMA.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.google.ads.interactivemedia.v3.api.Ad;
44
import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
55
import com.google.ads.interactivemedia.v3.api.AdEvent;
6+
import com.newrelic.videoagent.core.NRVideoConfiguration;
67
import com.newrelic.videoagent.core.tracker.NRVideoTracker;
78
import com.newrelic.videoagent.core.utils.NRLog;
89
import com.newrelic.videoagent.ima.BuildConfig;
@@ -13,6 +14,22 @@
1314

1415
public class NRTrackerIMA extends NRVideoTracker implements AdErrorEvent.AdErrorListener, AdEvent.AdEventListener {
1516

17+
/**
18+
* Create a new IMA tracker with configuration.
19+
*/
20+
public NRTrackerIMA(NRVideoConfiguration configuration) {
21+
super(configuration);
22+
}
23+
24+
/**
25+
* Create a new IMA tracker (deprecated - use constructor with configuration).
26+
* @deprecated Use NRTrackerIMA(NRVideoConfiguration) constructor instead
27+
*/
28+
@Deprecated
29+
public NRTrackerIMA() {
30+
super();
31+
}
32+
1633
private String adPosition = null;
1734
private String creativeId = null;
1835
private Long quartile = null;

NewRelicVideoCore/src/main/java/com/newrelic/videoagent/core/NRVideo.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public final class NRVideo {
2222
private static final Object lock = new Object();
2323

2424
private volatile HarvestManager harvestManager;
25+
private volatile NRVideoConfiguration configuration;
2526
private final Map<String, Integer> trackerIds = new HashMap<>();
2627

2728
// Private constructor for singleton
@@ -60,10 +61,10 @@ public static Integer addPlayer(NRVideoPlayerConfiguration config) {
6061
}
6162

6263
// Create content tracker with ExoPlayer instance
63-
NRTracker contentTracker = createContentTracker();
64+
NRTracker contentTracker = createContentTracker(instance.configuration);
6465
NRTracker adsTracker = null;
6566
if (config.isAdEnabled()) {
66-
adsTracker = createAdTracker();
67+
adsTracker = createAdTracker(instance.configuration);
6768
NRLog.d("add tracker is added");
6869
}
6970

@@ -228,6 +229,9 @@ private NRVideo initialize(Context context, NRVideoConfiguration config) {
228229
try {
229230
Context applicationContext = context.getApplicationContext();
230231

232+
// Store configuration for tracker creation
233+
this.configuration = config;
234+
231235
// Always use crash-safe storage - it's now the default behavior
232236
harvestManager = new HarvestManager(config, applicationContext);
233237

@@ -256,25 +260,35 @@ private NRVideo initialize(Context context, NRVideoConfiguration config) {
256260
}
257261
}
258262

259-
private static NRTracker createContentTracker() {
263+
private static NRTracker createContentTracker(NRVideoConfiguration config) {
260264
try {
261-
// Create ExoPlayer tracker with player instance
265+
// Create ExoPlayer tracker with configuration
262266
Class<?> exoTrackerClass = Class.forName("com.newrelic.videoagent.exoplayer.tracker.NRTrackerExoPlayer");
263-
return (NRTracker) exoTrackerClass.newInstance();
267+
return (NRTracker) exoTrackerClass.getConstructor(NRVideoConfiguration.class).newInstance(config);
264268
} catch (Exception e) {
265-
// Fallback to basic video tracker
266-
throw new RuntimeException("Failed to create NRTrackerExoPlayer", e);
269+
// Fallback to deprecated constructor for backward compatibility
270+
try {
271+
Class<?> exoTrackerClass = Class.forName("com.newrelic.videoagent.exoplayer.tracker.NRTrackerExoPlayer");
272+
return (NRTracker) exoTrackerClass.newInstance();
273+
} catch (Exception fallbackException) {
274+
throw new RuntimeException("Failed to create NRTrackerExoPlayer", fallbackException);
275+
}
267276
}
268277
}
269278

270-
private static NRTracker createAdTracker() {
271-
279+
private static NRTracker createAdTracker(NRVideoConfiguration config) {
272280
try {
273-
// Always use IMA tracker for ads
281+
// Always use IMA tracker for ads with configuration
274282
Class<?> imaTrackerClass = Class.forName("com.newrelic.videoagent.ima.tracker.NRTrackerIMA");
275-
return (NRTracker) imaTrackerClass.newInstance();
283+
return (NRTracker) imaTrackerClass.getConstructor(NRVideoConfiguration.class).newInstance(config);
276284
} catch (Exception e) {
277-
return null;
285+
// Fallback to deprecated constructor for backward compatibility
286+
try {
287+
Class<?> imaTrackerClass = Class.forName("com.newrelic.videoagent.ima.tracker.NRTrackerIMA");
288+
return (NRTracker) imaTrackerClass.newInstance();
289+
} catch (Exception fallbackException) {
290+
return null;
291+
}
278292
}
279293
}
280294

NewRelicVideoCore/src/main/java/com/newrelic/videoagent/core/NRVideoConfiguration.java

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,12 @@ public final class NRVideoConfiguration {
4343
private final boolean memoryOptimized;
4444
private final boolean debugLoggingEnabled;
4545
private final boolean isTV;
46+
private final String collectorAddress;
4647

4748
// Runtime configuration fields (mutable, thread-safe) - Using AtomicBoolean for better performance
4849
private final AtomicBoolean qoeAggregateEnabled = new AtomicBoolean(true);
4950
private final AtomicBoolean runtimeConfigInitialized = new AtomicBoolean(false);
5051

51-
// Static holder for current configuration instance (for tracker access)
52-
// WeakReference to prevent memory leaks if static cleanup is missed
53-
private static volatile java.lang.ref.WeakReference<NRVideoConfiguration> currentInstanceRef;
5452

5553
// Performance optimization constants
5654
private static final int DEFAULT_HARVEST_CYCLE_SECONDS = 5 * 60; // 5 minutes
@@ -139,23 +137,6 @@ public void initializeFromClient(Boolean clientQoeAggregateEnabled) {
139137
}
140138
}
141139

142-
/**
143-
* Get the current configuration instance (for tracker access)
144-
* @return Current NRVideoConfiguration instance
145-
* @throws IllegalStateException if no configuration has been built yet
146-
*/
147-
public static NRVideoConfiguration getCurrentInstance() {
148-
if (currentInstanceRef == null) {
149-
throw new IllegalStateException("No NRVideoConfiguration has been built yet!");
150-
}
151-
152-
NRVideoConfiguration instance = currentInstanceRef.get();
153-
if (instance == null) {
154-
throw new IllegalStateException("NRVideoConfiguration has been garbage collected! Create a new instance.");
155-
}
156-
157-
return instance;
158-
}
159140
/**
160141
* Get dead letter retry interval in milliseconds
161142
* Optimized for different device types and network conditions
@@ -347,8 +328,6 @@ private void applyMemoryOptimizations() {
347328

348329
public NRVideoConfiguration build() {
349330
NRVideoConfiguration config = new NRVideoConfiguration(this);
350-
// Set current instance for tracker access using WeakReference
351-
NRVideoConfiguration.currentInstanceRef = new java.lang.ref.WeakReference<>(config);
352331
// Mark runtime configuration as initialized
353332
config.runtimeConfigInitialized.set(true);
354333
return config;

NewRelicVideoCore/src/main/java/com/newrelic/videoagent/core/tracker/NRTracker.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.newrelic.videoagent.core.tracker;
22

33
import com.newrelic.videoagent.core.NRVideo;
4+
import com.newrelic.videoagent.core.NRVideoConfiguration;
45
import com.newrelic.videoagent.core.NewRelicVideoAgent;
56
import com.newrelic.videoagent.core.model.NREventAttributes;
67
import com.newrelic.videoagent.core.model.NRTimeSince;
@@ -21,17 +22,37 @@ public class NRTracker {
2122
*/
2223
public NRTracker linkedTracker;
2324

25+
protected final NRVideoConfiguration configuration;
2426
private final NREventAttributes eventAttributes;
2527
private NRTimeSinceTable timeSinceTable;
2628

2729
/**
28-
* Create a new NRTracker.
30+
* Create a new NRTracker with configuration.
2931
*/
32+
public NRTracker(NRVideoConfiguration configuration) {
33+
this.configuration = configuration;
34+
eventAttributes = new NREventAttributes();
35+
generateTimeSinceTable();
36+
}
37+
38+
/**
39+
* Create a new NRTracker (deprecated - use constructor with configuration).
40+
* @deprecated Use NRTracker(NRVideoConfiguration) constructor instead
41+
*/
42+
@Deprecated
3043
public NRTracker() {
44+
this.configuration = null;
3145
eventAttributes = new NREventAttributes();
3246
generateTimeSinceTable();
3347
}
3448

49+
/**
50+
* Get the tracker configuration.
51+
*/
52+
public NRVideoConfiguration getConfiguration() {
53+
return configuration;
54+
}
55+
3556
/**
3657
* Tracker is ready.
3758
*/

NewRelicVideoCore/src/main/java/com/newrelic/videoagent/core/tracker/NRVideoTracker.java

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,44 @@ public class NRVideoTracker extends NRTracker {
7070
/**
7171
* Create a new NRVideoTracker.
7272
*/
73+
public NRVideoTracker(NRVideoConfiguration configuration) {
74+
super(configuration);
75+
state = new NRTrackerState();
76+
numberOfAds = 0;
77+
numberOfErrors = 0;
78+
numberOfVideos = 0;
79+
viewIdIndex = 0;
80+
adBreakIdIndex = 0;
81+
viewSessionId = getAgentSession() + "-" + (System.currentTimeMillis() / 1000) + new Random().nextInt(10);
82+
playtimeSinceLastEventTimestamp = 0L;
83+
totalPlaytime = 0L;
84+
totalAdPlaytime = 0L;
85+
playtimeSinceLastEvent = 0L;
86+
bufferType = null;
87+
isHeartbeatRunning = false;
88+
89+
// Initialize heartbeat components
90+
heartbeatHandler = new Handler();
91+
heartbeatRunnable = new Runnable() {
92+
@Override
93+
public void run() {
94+
if (isHeartbeatRunning) {
95+
sendHeartbeat();
96+
heartbeatHandler.postDelayed(heartbeatRunnable, getHeartbeatIntervalMillis());
97+
}
98+
}
99+
};
100+
101+
initializeTracker();
102+
}
103+
104+
/**
105+
* Create a new NRVideoTracker (deprecated - use constructor with configuration).
106+
* @deprecated Use NRVideoTracker(NRVideoConfiguration) constructor instead
107+
*/
108+
@Deprecated
73109
public NRVideoTracker() {
110+
super();
74111
state = new NRTrackerState();
75112
numberOfAds = 0;
76113
numberOfErrors = 0;
@@ -85,6 +122,23 @@ public NRVideoTracker() {
85122
bufferType = null;
86123
isHeartbeatRunning = false;
87124

125+
// Initialize heartbeat components
126+
heartbeatHandler = new Handler();
127+
heartbeatRunnable = new Runnable() {
128+
@Override
129+
public void run() {
130+
if (isHeartbeatRunning) {
131+
sendHeartbeat();
132+
heartbeatHandler.postDelayed(heartbeatRunnable, getHeartbeatIntervalMillis());
133+
}
134+
}
135+
};
136+
137+
initializeTracker();
138+
}
139+
140+
private void initializeTracker() {
141+
88142
// Initialize QoE tracking fields
89143
qoePeakBitrate = 0L;
90144
qoeHadPlaybackFailure = false;
@@ -106,16 +160,6 @@ public NRVideoTracker() {
106160
qoeLastRenditionChangeTime = null;
107161
qoeTotalBitrateWeightedTime = 0L;
108162
qoeTotalActiveTime = 0L;
109-
heartbeatHandler = new Handler();
110-
heartbeatRunnable = new Runnable() {
111-
@Override
112-
public void run() {
113-
if (isHeartbeatRunning) {
114-
sendHeartbeat();
115-
heartbeatHandler.postDelayed(heartbeatRunnable, getHeartbeatIntervalMillis());
116-
}
117-
}
118-
};
119163
}
120164

121165
/**
@@ -593,7 +637,7 @@ private void resetHarvestCycleFlags() {
593637
* Send QOE_AGGREGATE event (internal method - called once per cycle)
594638
*/
595639
private void sendQoeAggregate() {
596-
if (!state.isAd && NRVideoConfiguration.getCurrentInstance().isQoeAggregateEnabled()) {
640+
if (!state.isAd && configuration != null && configuration.isQoeAggregateEnabled()) {
597641
// Only send for content, not ads, and only if QOE aggregate is enabled
598642
Map<String, Object> kpiAttributes = calculateQOEKpiAttributes();
599643
sendVideoEvent(QOE_AGGREGATE, kpiAttributes);

0 commit comments

Comments
 (0)