2020import androidx .annotation .Nullable ;
2121import androidx .annotation .VisibleForTesting ;
2222import com .google .firebase .components .Lazy ;
23+ import com .google .firebase .perf .application .AppStateUpdateHandler ;
2324import com .google .firebase .perf .config .ConfigResolver ;
2425import com .google .firebase .perf .logging .AndroidLogger ;
2526import com .google .firebase .perf .session .PerfSession ;
3132import com .google .firebase .perf .v1 .GaugeMetadata ;
3233import com .google .firebase .perf .v1 .GaugeMetric ;
3334import java .util .concurrent .Executors ;
34- import java .util .concurrent .RejectedExecutionException ;
3535import java .util .concurrent .ScheduledExecutorService ;
3636import java .util .concurrent .ScheduledFuture ;
3737import java .util .concurrent .TimeUnit ;
4141 * information and logging it to the Transport.
4242 */
4343@ Keep // Needed because of b/117526359.
44- public class GaugeManager {
44+ public class GaugeManager extends AppStateUpdateHandler {
4545
4646 private static final AndroidLogger logger = AndroidLogger .getInstance ();
4747 private static final GaugeManager instance = new GaugeManager ();
@@ -59,8 +59,8 @@ public class GaugeManager {
5959 private final TransportManager transportManager ;
6060
6161 @ Nullable private GaugeMetadataManager gaugeMetadataManager ;
62- @ Nullable private ScheduledFuture gaugeManagerDataCollectionJob = null ;
63- @ Nullable private String sessionId = null ;
62+ @ Nullable private ScheduledFuture <?> gaugeManagerDataCollectionJob = null ;
63+ @ Nullable private PerfSession session = null ;
6464 private ApplicationProcessState applicationProcessState =
6565 ApplicationProcessState .APPLICATION_PROCESS_STATE_UNKNOWN ;
6666
@@ -91,13 +91,27 @@ private GaugeManager() {
9191 this .gaugeMetadataManager = gaugeMetadataManager ;
9292 this .cpuGaugeCollector = cpuGaugeCollector ;
9393 this .memoryGaugeCollector = memoryGaugeCollector ;
94+ registerForAppState ();
9495 }
9596
9697 /** Initializes GaugeMetadataManager which requires application context. */
9798 public void initializeGaugeMetadataManager (Context appContext ) {
9899 this .gaugeMetadataManager = new GaugeMetadataManager (appContext );
99100 }
100101
102+ @ Override
103+ public void onUpdateAppState (ApplicationProcessState applicationProcessState ) {
104+ this .applicationProcessState = applicationProcessState ;
105+
106+ if (session == null ) {
107+ // If the session is null, it means there's no gauges being collected.
108+ return ;
109+ }
110+
111+ stopCollectingGauges ();
112+ startCollectingGauges (this .applicationProcessState , session .getTimer ());
113+ }
114+
101115 /** Returns the singleton instance of this class. */
102116 public static synchronized GaugeManager getInstance () {
103117 return instance ;
@@ -112,47 +126,22 @@ public static synchronized GaugeManager getInstance() {
112126 * will then be associated with the same or new sessionId and applicationProcessState.
113127 *
114128 * @param session The {@link PerfSession} to which the collected gauges will be associated with.
115- * @param applicationProcessState The {@link ApplicationProcessState} the collected GaugeMetrics
116- * will be associated with.
117129 * @note: This method is NOT thread safe - {@link this.startCollectingGauges()} and {@link
118- * this.stopCollectingGauges()} should always be called from the same thread.
130+ * this.stopCollectingGauges()} should always be called from the same thread.
119131 */
120- public void startCollectingGauges (
121- PerfSession session , ApplicationProcessState applicationProcessState ) {
122- if (this .sessionId != null ) {
132+ public void startCollectingGauges (PerfSession session ) {
133+ if (this .session != null ) {
123134 stopCollectingGauges ();
124135 }
125136
126- long collectionFrequency = startCollectingGauges (applicationProcessState , session .getTimer ());
137+ long collectionFrequency =
138+ startCollectingGauges (this .applicationProcessState , session .getTimer ());
127139 if (collectionFrequency == INVALID_GAUGE_COLLECTION_FREQUENCY ) {
128140 logger .warn ("Invalid gauge collection frequency. Unable to start collecting Gauges." );
129141 return ;
130142 }
131143
132- this .sessionId = session .sessionId ();
133- this .applicationProcessState = applicationProcessState ;
134-
135- // This is needed, otherwise the Runnable might use a stale value.
136- final String sessionIdForScheduledTask = sessionId ;
137- final ApplicationProcessState applicationProcessStateForScheduledTask = applicationProcessState ;
138-
139- // TODO(b/394127311): Switch to using AQS.
140- try {
141- gaugeManagerDataCollectionJob =
142- gaugeManagerExecutor
143- .get ()
144- .scheduleWithFixedDelay (
145- () -> {
146- syncFlush (sessionIdForScheduledTask , applicationProcessStateForScheduledTask );
147- },
148- /* initialDelay= */ collectionFrequency
149- * APPROX_NUMBER_OF_DATA_POINTS_PER_GAUGE_METRIC ,
150- /* period= */ collectionFrequency * APPROX_NUMBER_OF_DATA_POINTS_PER_GAUGE_METRIC ,
151- TimeUnit .MILLISECONDS );
152-
153- } catch (RejectedExecutionException e ) {
154- logger .warn ("Unable to start collecting Gauges: " + e .getMessage ());
155- }
144+ this .session = session ;
156145 }
157146
158147 /**
@@ -190,12 +179,12 @@ private long startCollectingGauges(ApplicationProcessState appState, Timer refer
190179 * this.stopCollectingGauges()} should always be called from the same thread.
191180 */
192181 public void stopCollectingGauges () {
193- if (this . sessionId == null ) {
182+ if (session == null ) {
194183 return ;
195184 }
196185
197186 // This is needed, otherwise the Runnable might use a stale value.
198- final String sessionIdForScheduledTask = sessionId ;
187+ final String sessionIdForScheduledTask = session . sessionId () ;
199188 final ApplicationProcessState applicationProcessStateForScheduledTask = applicationProcessState ;
200189
201190 cpuGaugeCollector .get ().stopCollecting ();
@@ -205,10 +194,9 @@ public void stopCollectingGauges() {
205194 gaugeManagerDataCollectionJob .cancel (false );
206195 }
207196
208- // TODO(b/394127311): Switch to using AQS.
209197 // Flush any data that was collected for this session one last time.
210198 @ SuppressWarnings ("FutureReturnValueIgnored" )
211- ScheduledFuture unusedFuture =
199+ ScheduledFuture <?> unusedFuture =
212200 gaugeManagerExecutor
213201 .get ()
214202 .schedule (
@@ -218,7 +206,7 @@ public void stopCollectingGauges() {
218206 TIME_TO_WAIT_BEFORE_FLUSHING_GAUGES_QUEUE_MS ,
219207 TimeUnit .MILLISECONDS );
220208
221- this .sessionId = null ;
209+ this .session = null ;
222210 this .applicationProcessState = ApplicationProcessState .APPLICATION_PROCESS_STATE_UNKNOWN ;
223211 }
224212
@@ -227,7 +215,7 @@ public void stopCollectingGauges() {
227215 * proto and logs it to transport.
228216 *
229217 * @param sessionId The sessionId to which the collected GaugeMetrics should be associated with.
230- * @param appState The app state for which these gauges are collected .
218+ * @param appState The app state for which these gauges are attributed to .
231219 */
232220 private void syncFlush (String sessionId , ApplicationProcessState appState ) {
233221 GaugeMetric .Builder gaugeMetricBuilder = GaugeMetric .newBuilder ();
@@ -244,7 +232,6 @@ private void syncFlush(String sessionId, ApplicationProcessState appState) {
244232 }
245233
246234 // Adding Session ID info.
247- // TODO(b/394127311): Switch to using AQS.
248235 gaugeMetricBuilder .setSessionId (sessionId );
249236
250237 transportManager .log (gaugeMetricBuilder .build (), appState );
@@ -253,16 +240,16 @@ private void syncFlush(String sessionId, ApplicationProcessState appState) {
253240 /**
254241 * Log the Gauge Metadata information to the transport.
255242 *
256- * @param aqsSessionId The {@link PerfSession#aqsSessionId ()} ()} to which the collected Gauge Metrics
243+ * @param sessionId The {@link PerfSession#sessionId ()} ()} to which the collected Gauge Metrics
257244 * should be associated with.
258245 * @param appState The {@link ApplicationProcessState} for which these gauges are collected.
259246 * @return true if GaugeMetadata was logged, false otherwise.
260247 */
261- public boolean logGaugeMetadata (String aqsSessionId , ApplicationProcessState appState ) {
248+ public boolean logGaugeMetadata (String sessionId , ApplicationProcessState appState ) {
262249 if (gaugeMetadataManager != null ) {
263250 GaugeMetric gaugeMetric =
264251 GaugeMetric .newBuilder ()
265- .setSessionId (aqsSessionId )
252+ .setSessionId (sessionId )
266253 .setGaugeMetadata (getGaugeMetadata ())
267254 .build ();
268255 transportManager .log (gaugeMetric , appState );
0 commit comments