• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.os.profiling;
18 
19 import android.annotation.Nullable;
20 import android.os.Bundle;
21 import android.os.ProfilingManager;
22 import android.provider.DeviceConfig;
23 
24 import perfetto.protos.DataSourceConfigOuterClass.DataSourceConfig;
25 import perfetto.protos.FtraceConfigOuterClass.FtraceConfig;
26 import perfetto.protos.HeapprofdConfigOuterClass.HeapprofdConfig;
27 import perfetto.protos.JavaHprofConfigOuterClass.JavaHprofConfig;
28 import perfetto.protos.PackagesListConfigOuterClass.PackagesListConfig;
29 import perfetto.protos.PerfEventConfigOuterClass.PerfEventConfig;
30 import perfetto.protos.PerfEventsOuterClass.PerfEvents;
31 import perfetto.protos.ProcessStatsConfigOuterClass.ProcessStatsConfig;
32 import perfetto.protos.TraceConfigOuterClass.TraceConfig;
33 
34 public final class Configs {
35 
36     // Time to wait beyond trace timeout to ensure perfetto has time to finish writing output.
37     private static final int FILE_PROCESSING_DELAY_MS = 2000;
38     // Time used to account for any delay in starting up the underlying profiling process. This
39     // value is used to calculate max profiling time.
40     private static final int MAX_PROFILING_TIME_BUFFER_MS = 10 * 1000;
41 
42     private static final int FOUR_MB = 4096;
43 
44     private static final int ONE_DAY_MS = 24 * 60 * 60 * 1000;
45 
46     private static boolean sSystemTriggeredSystemTraceConfigsInitialized = false;
47     private static boolean sSystemTraceConfigsInitialized = false;
48     private static boolean sHeapProfileConfigsInitialized = false;
49     private static boolean sJavaHeapDumpConfigsInitialized = false;
50     private static boolean sStackSamplingConfigsInitialized = false;
51 
52     private static int sSystemTriggeredSystemTraceDurationMs;
53     private static int sSystemTriggeredSystemTraceDiscardBufferSizeKb;
54     private static int sSystemTriggeredSystemTraceRingBufferSizeKb;
55 
56     private static boolean sKillswitchSystemTrace;
57     private static int sSystemTraceDurationMsDefault;
58     private static int sSystemTraceDurationMsMin;
59     private static int sSystemTraceDurationMsMax;
60     private static int sSystemTraceSizeKbDefault;
61     private static int sSystemTraceSizeKbMin;
62     private static int sSystemTraceSizeKbMax;
63 
64     private static boolean sKillswitchHeapProfile;
65     private static boolean sHeapProfileTrackJavaAllocationsDefault;
66     private static int sHeapProfileFlushTimeoutMsDefault;
67     private static int sHeapProfileDurationMsDefault;
68     private static int sHeapProfileDurationMsMin;
69     private static int sHeapProfileDurationMsMax;
70     private static int sHeapProfileSizeKbDefault;
71     private static int sHeapProfileSizeKbMin;
72     private static int sHeapProfileSizeKbMax;
73     private static long sHeapProfileSamplingIntervalBytesDefault;
74     private static long sHeapProfileSamplingIntervalBytesMin;
75     private static long sHeapProfileSamplingIntervalBytesMax;
76 
77     private static boolean sKillswitchJavaHeapDump;
78     private static int sJavaHeapDumpDurationMsDefault;
79     private static int sJavaHeapDumpDataSourceStopTimeoutMsDefault;
80     private static int sJavaHeapDumpSizeKbDefault;
81     private static int sJavaHeapDumpSizeKbMin;
82     private static int sJavaHeapDumpSizeKbMax;
83 
84     private static boolean sKillswitchStackSampling;
85     private static int sStackSamplingFlushTimeoutMsDefault;
86     private static int sStackSamplingDurationMsDefault;
87     private static int sStackSamplingDurationMsMin;
88     private static int sStackSamplingDurationMsMax;
89     private static int sStackSamplingSizeKbDefault;
90     private static int sStackSamplingSizeKbMin;
91     private static int sStackSamplingSizeKbMax;
92     private static int sStackSamplingSamplingFrequencyDefault;
93     private static int sStackSamplingSamplingFrequencyMin;
94     private static int sStackSamplingSamplingFrequencyMax;
95 
96     /**
97      * Initialize System Triggered System Trace related DeviceConfig values if they have not been
98      * yet.
99      */
initializeSystemTriggeredSystemTraceConfigsIfNecessary()100     private static void initializeSystemTriggeredSystemTraceConfigsIfNecessary() {
101         if (sSystemTriggeredSystemTraceConfigsInitialized) {
102             return;
103         }
104 
105         DeviceConfig.Properties properties =
106                 DeviceConfigHelper.getAllSystemTriggeredSystemTraceProperties();
107 
108         sSystemTriggeredSystemTraceDurationMs = properties.getInt(
109                 DeviceConfigHelper.SYSTEM_TRIGGERED_SYSTEM_TRACE_DURATION_MS,
110                 30 * 60 * 1000 /* 30 minutes */);
111         sSystemTriggeredSystemTraceDiscardBufferSizeKb = properties.getInt(
112                 DeviceConfigHelper.SYSTEM_TRIGGERED_SYSTEM_TRACE_DISCARD_BUFFER_SIZE_KB, FOUR_MB);
113         sSystemTriggeredSystemTraceRingBufferSizeKb = properties.getInt(
114                 DeviceConfigHelper.SYSTEM_TRIGGERED_SYSTEM_TRACE_RING_BUFFER_SIZE_KB, 32768);
115 
116         sSystemTriggeredSystemTraceConfigsInitialized = true;
117     }
118 
119     /** Initialize System Trace related DeviceConfig set values if they have not been yet. */
initializeSystemTraceConfigsIfNecessary()120     private static void initializeSystemTraceConfigsIfNecessary() {
121         if (sSystemTraceConfigsInitialized) {
122             return;
123         }
124 
125         DeviceConfig.Properties properties = DeviceConfigHelper.getAllSystemTraceProperties();
126 
127         sKillswitchSystemTrace = properties.getBoolean(
128                 DeviceConfigHelper.KILLSWITCH_SYSTEM_TRACE, false);
129         sSystemTraceDurationMsDefault = properties.getInt(
130                 DeviceConfigHelper.SYSTEM_TRACE_DURATION_MS_DEFAULT, 300000);
131         sSystemTraceDurationMsMin = properties.getInt(
132                 DeviceConfigHelper.SYSTEM_TRACE_DURATION_MS_MIN, 1000);
133         sSystemTraceDurationMsMax = properties.getInt(
134                 DeviceConfigHelper.SYSTEM_TRACE_DURATION_MS_MAX, 600000);
135         sSystemTraceSizeKbDefault = properties.getInt(
136                 DeviceConfigHelper.SYSTEM_TRACE_SIZE_KB_DEFAULT, 32768);
137         sSystemTraceSizeKbMin = properties.getInt(
138                 DeviceConfigHelper.SYSTEM_TRACE_SIZE_KB_MIN, 64);
139         sSystemTraceSizeKbMax = properties.getInt(
140                 DeviceConfigHelper.SYSTEM_TRACE_SIZE_KB_MAX, 32768);
141 
142         sSystemTraceConfigsInitialized = true;
143     }
144 
145     /** Initialize Java Heap Dump related DeviceConfig set values if they have not been yet. */
initializeJavaHeapDumpConfigsIfNecessary()146     private static void initializeJavaHeapDumpConfigsIfNecessary() {
147         if (sJavaHeapDumpConfigsInitialized) {
148             return;
149         }
150 
151         DeviceConfig.Properties properties = DeviceConfigHelper.getAllJavaHeapDumpProperties();
152 
153         sKillswitchJavaHeapDump = properties.getBoolean(
154                 DeviceConfigHelper.KILLSWITCH_JAVA_HEAP_DUMP, false);
155         sJavaHeapDumpDurationMsDefault = properties.getInt(
156                 DeviceConfigHelper.JAVA_HEAP_DUMP_DURATION_MS_DEFAULT, 1000);
157         sJavaHeapDumpDataSourceStopTimeoutMsDefault = properties.getInt(
158                 DeviceConfigHelper.JAVA_HEAP_DUMP_DATA_SOURCE_STOP_TIMEOUT_MS_DEFAULT, 100000);
159         sJavaHeapDumpSizeKbDefault = properties.getInt(
160                 DeviceConfigHelper.JAVA_HEAP_DUMP_SIZE_KB_DEFAULT, 256000);
161         sJavaHeapDumpSizeKbMin = properties.getInt(
162                 DeviceConfigHelper.JAVA_HEAP_DUMP_SIZE_KB_MIN, 8192 /* 8 MB */);
163         sJavaHeapDumpSizeKbMax = properties.getInt(
164                 DeviceConfigHelper.JAVA_HEAP_DUMP_SIZE_KB_MAX, 256000);
165 
166         sJavaHeapDumpConfigsInitialized = true;
167     }
168 
169     /** Initialize Heap Profile related DeviceConfig set values if they have not been yet. */
initializeHeapProfileConfigsIfNecessary()170     private static void initializeHeapProfileConfigsIfNecessary() {
171         if (sHeapProfileConfigsInitialized) {
172             return;
173         }
174 
175         DeviceConfig.Properties properties = DeviceConfigHelper.getAllHeapProfileProperties();
176 
177         sKillswitchHeapProfile = properties.getBoolean(
178                 DeviceConfigHelper.KILLSWITCH_HEAP_PROFILE, false);
179         sHeapProfileTrackJavaAllocationsDefault = properties.getBoolean(
180                 DeviceConfigHelper.HEAP_PROFILE_TRACK_JAVA_ALLOCATIONS_DEFAULT, false);
181         sHeapProfileFlushTimeoutMsDefault = properties.getInt(
182                 DeviceConfigHelper.HEAP_PROFILE_FLUSH_TIMEOUT_MS_DEFAULT, 30000);
183         sHeapProfileDurationMsDefault = properties.getInt(
184                 DeviceConfigHelper.HEAP_PROFILE_DURATION_MS_DEFAULT, 120000);
185         sHeapProfileDurationMsMin = properties.getInt(
186                 DeviceConfigHelper.HEAP_PROFILE_DURATION_MS_MIN, 1000);
187         sHeapProfileDurationMsMax = properties.getInt(
188                 DeviceConfigHelper.HEAP_PROFILE_DURATION_MS_MAX, 300000);
189         sHeapProfileSizeKbDefault = properties.getInt(
190                 DeviceConfigHelper.HEAP_PROFILE_SIZE_KB_DEFAULT, 65536);
191         sHeapProfileSizeKbMin = properties.getInt(
192                 DeviceConfigHelper.HEAP_PROFILE_SIZE_KB_MIN, 256);
193         sHeapProfileSizeKbMax = properties.getInt(
194                 DeviceConfigHelper.HEAP_PROFILE_SIZE_KB_MAX, 65536);
195         sHeapProfileSamplingIntervalBytesDefault = properties.getLong(
196                 DeviceConfigHelper.HEAP_PROFILE_SAMPLING_INTERVAL_BYTES_DEFAULT, 4096L);
197         sHeapProfileSamplingIntervalBytesMin = properties.getLong(
198                 DeviceConfigHelper.HEAP_PROFILE_SAMPLING_INTERVAL_BYTES_MIN, 1L);
199         sHeapProfileSamplingIntervalBytesMax = properties.getLong(
200                 DeviceConfigHelper.HEAP_PROFILE_SAMPLING_INTERVAL_BYTES_MAX, 65536L);
201 
202         sHeapProfileConfigsInitialized = true;
203     }
204 
205     /** Initialize Stack Sampling related DeviceConfig set values if they have not been yet. */
initializeStackSamplingConfigsIfNecessary()206     private static void initializeStackSamplingConfigsIfNecessary() {
207         if (sStackSamplingConfigsInitialized) {
208             return;
209         }
210 
211         DeviceConfig.Properties properties = DeviceConfigHelper.getAllStackSamplingProperties();
212 
213         sKillswitchStackSampling = properties.getBoolean(
214                 DeviceConfigHelper.KILLSWITCH_STACK_SAMPLING, false);
215         sStackSamplingFlushTimeoutMsDefault = properties.getInt(
216                 DeviceConfigHelper.STACK_SAMPLING_FLUSH_TIMEOUT_MS_DEFAULT, 30000);
217         sStackSamplingDurationMsDefault = properties.getInt(
218                 DeviceConfigHelper.STACK_SAMPLING_DURATION_MS_DEFAULT, 60000);
219         sStackSamplingDurationMsMin = properties.getInt(
220                 DeviceConfigHelper.STACK_SAMPLING_DURATION_MS_MIN, 1000);
221         sStackSamplingDurationMsMax = properties.getInt(
222                 DeviceConfigHelper.STACK_SAMPLING_DURATION_MS_MAX, 300000);
223         sStackSamplingSizeKbDefault = properties.getInt(
224                 DeviceConfigHelper.STACK_SAMPLING_SAMPLING_SIZE_KB_DEFAULT, 65536);
225         sStackSamplingSizeKbMin = properties.getInt(
226                 DeviceConfigHelper.STACK_SAMPLING_SAMPLING_SIZE_KB_MIN, 64);
227         sStackSamplingSizeKbMax = properties.getInt(
228                 DeviceConfigHelper.STACK_SAMPLING_SAMPLING_SIZE_KB_MAX, 65536);
229         sStackSamplingSamplingFrequencyDefault = properties.getInt(
230                 DeviceConfigHelper.STACK_SAMPLING_FREQUENCY_DEFAULT, 100);
231         sStackSamplingSamplingFrequencyMin = properties.getInt(
232                 DeviceConfigHelper.STACK_SAMPLING_FREQUENCY_MIN, 1);
233         sStackSamplingSamplingFrequencyMax = properties.getInt(
234                 DeviceConfigHelper.STACK_SAMPLING_FREQUENCY_MAX, 200);
235 
236         sStackSamplingConfigsInitialized = true;
237     }
238 
239     /**
240      * Update DeviceConfig set configuration values if present in the provided properties, leaving
241      * not present values unchanged.
242      *
243      * Will only update values that have already been initialized as initialization is required
244      * before use and the changed values will be available under the normal access path.
245      */
maybeUpdateConfigs(DeviceConfig.Properties properties)246     public static void maybeUpdateConfigs(DeviceConfig.Properties properties) {
247         // TODO(b/330940387): Revisit defaults before release
248 
249         if (sSystemTraceConfigsInitialized) {
250             sKillswitchSystemTrace = properties.getBoolean(
251                     DeviceConfigHelper.KILLSWITCH_SYSTEM_TRACE, sKillswitchSystemTrace);
252             sSystemTraceDurationMsDefault = properties.getInt(
253                     DeviceConfigHelper.SYSTEM_TRACE_DURATION_MS_DEFAULT,
254                     sSystemTraceDurationMsDefault);
255             sSystemTraceDurationMsMin = properties.getInt(
256                     DeviceConfigHelper.SYSTEM_TRACE_DURATION_MS_MIN, sSystemTraceDurationMsMin);
257             sSystemTraceDurationMsMax = properties.getInt(
258                     DeviceConfigHelper.SYSTEM_TRACE_DURATION_MS_MAX, sSystemTraceDurationMsMax);
259             sSystemTraceSizeKbDefault = properties.getInt(
260                     DeviceConfigHelper.SYSTEM_TRACE_SIZE_KB_DEFAULT, sSystemTraceSizeKbDefault);
261             sSystemTraceSizeKbMin = properties.getInt(
262                     DeviceConfigHelper.SYSTEM_TRACE_SIZE_KB_MIN, sSystemTraceSizeKbMin);
263             sSystemTraceSizeKbMax = properties.getInt(
264                     DeviceConfigHelper.SYSTEM_TRACE_SIZE_KB_MAX, sSystemTraceSizeKbMax);
265         }
266 
267         if (sHeapProfileConfigsInitialized) {
268             sKillswitchHeapProfile = properties.getBoolean(
269                     DeviceConfigHelper.KILLSWITCH_HEAP_PROFILE, sKillswitchHeapProfile);
270             sHeapProfileTrackJavaAllocationsDefault = properties.getBoolean(
271                     DeviceConfigHelper.HEAP_PROFILE_TRACK_JAVA_ALLOCATIONS_DEFAULT,
272                     sHeapProfileTrackJavaAllocationsDefault);
273             sHeapProfileFlushTimeoutMsDefault = properties.getInt(
274                     DeviceConfigHelper.HEAP_PROFILE_FLUSH_TIMEOUT_MS_DEFAULT,
275                     sHeapProfileFlushTimeoutMsDefault);
276             sHeapProfileDurationMsDefault = properties.getInt(
277                     DeviceConfigHelper.HEAP_PROFILE_DURATION_MS_DEFAULT,
278                     sHeapProfileDurationMsDefault);
279             sHeapProfileDurationMsMin = properties.getInt(
280                     DeviceConfigHelper.HEAP_PROFILE_DURATION_MS_MIN, sHeapProfileDurationMsMin);
281             sHeapProfileDurationMsMax = properties.getInt(
282                     DeviceConfigHelper.HEAP_PROFILE_DURATION_MS_MAX, sHeapProfileDurationMsMax);
283             sHeapProfileSizeKbDefault = properties.getInt(
284                     DeviceConfigHelper.HEAP_PROFILE_SIZE_KB_DEFAULT, sHeapProfileSizeKbDefault);
285             sHeapProfileSizeKbMin = properties.getInt(
286                     DeviceConfigHelper.HEAP_PROFILE_SIZE_KB_MIN, sHeapProfileSizeKbMin);
287             sHeapProfileSizeKbMax = properties.getInt(
288                     DeviceConfigHelper.HEAP_PROFILE_SIZE_KB_MAX, sHeapProfileSizeKbMax);
289             sHeapProfileSamplingIntervalBytesDefault = properties.getLong(
290                     DeviceConfigHelper.HEAP_PROFILE_SAMPLING_INTERVAL_BYTES_DEFAULT,
291                     sHeapProfileSamplingIntervalBytesDefault);
292             sHeapProfileSamplingIntervalBytesMin = properties.getLong(
293                     DeviceConfigHelper.HEAP_PROFILE_SAMPLING_INTERVAL_BYTES_MIN,
294                     sHeapProfileSamplingIntervalBytesMin);
295             sHeapProfileSamplingIntervalBytesMax = properties.getLong(
296                     DeviceConfigHelper.HEAP_PROFILE_SAMPLING_INTERVAL_BYTES_MAX,
297                     sHeapProfileSamplingIntervalBytesMax);
298         }
299 
300         if (sJavaHeapDumpConfigsInitialized) {
301             sKillswitchJavaHeapDump = properties.getBoolean(
302                     DeviceConfigHelper.KILLSWITCH_JAVA_HEAP_DUMP, sKillswitchJavaHeapDump);
303             sJavaHeapDumpDurationMsDefault = properties.getInt(
304                     DeviceConfigHelper.JAVA_HEAP_DUMP_DURATION_MS_DEFAULT,
305                     sJavaHeapDumpDurationMsDefault);
306             sJavaHeapDumpDataSourceStopTimeoutMsDefault = properties.getInt(
307                     DeviceConfigHelper.JAVA_HEAP_DUMP_DATA_SOURCE_STOP_TIMEOUT_MS_DEFAULT,
308                     sJavaHeapDumpDataSourceStopTimeoutMsDefault);
309             sJavaHeapDumpSizeKbDefault = properties.getInt(
310                     DeviceConfigHelper.JAVA_HEAP_DUMP_SIZE_KB_DEFAULT, sJavaHeapDumpSizeKbDefault);
311             sJavaHeapDumpSizeKbMin = properties.getInt(
312                     DeviceConfigHelper.JAVA_HEAP_DUMP_SIZE_KB_MIN, sJavaHeapDumpSizeKbMin);
313             sJavaHeapDumpSizeKbMax = properties.getInt(
314                     DeviceConfigHelper.JAVA_HEAP_DUMP_SIZE_KB_MAX, sJavaHeapDumpSizeKbMax);
315         }
316 
317         if (sStackSamplingConfigsInitialized) {
318             sKillswitchStackSampling = properties.getBoolean(
319                     DeviceConfigHelper.KILLSWITCH_STACK_SAMPLING, sKillswitchStackSampling);
320             sStackSamplingFlushTimeoutMsDefault = properties.getInt(
321                     DeviceConfigHelper.STACK_SAMPLING_FLUSH_TIMEOUT_MS_DEFAULT,
322                     sStackSamplingFlushTimeoutMsDefault);
323             sStackSamplingDurationMsDefault = properties.getInt(
324                     DeviceConfigHelper.STACK_SAMPLING_DURATION_MS_DEFAULT,
325                     sStackSamplingDurationMsDefault);
326             sStackSamplingDurationMsMin = properties.getInt(
327                     DeviceConfigHelper.STACK_SAMPLING_DURATION_MS_MIN, sStackSamplingDurationMsMin);
328             sStackSamplingDurationMsMax = properties.getInt(
329                     DeviceConfigHelper.STACK_SAMPLING_DURATION_MS_MAX, sStackSamplingDurationMsMax);
330             sStackSamplingSizeKbDefault = properties.getInt(
331                     DeviceConfigHelper.STACK_SAMPLING_SAMPLING_SIZE_KB_DEFAULT,
332                     sStackSamplingSizeKbDefault);
333             sStackSamplingSizeKbMin = properties.getInt(
334                     DeviceConfigHelper.STACK_SAMPLING_SAMPLING_SIZE_KB_MIN,
335                     sStackSamplingSizeKbMin);
336             sStackSamplingSizeKbMax = properties.getInt(
337                     DeviceConfigHelper.STACK_SAMPLING_SAMPLING_SIZE_KB_MAX,
338                     sStackSamplingSizeKbMax);
339             sStackSamplingSamplingFrequencyDefault = properties.getInt(
340                     DeviceConfigHelper.STACK_SAMPLING_FREQUENCY_DEFAULT,
341                     sStackSamplingSamplingFrequencyDefault);
342             sStackSamplingSamplingFrequencyMin = properties.getInt(
343                     DeviceConfigHelper.STACK_SAMPLING_FREQUENCY_MIN,
344                     sStackSamplingSamplingFrequencyMin);
345             sStackSamplingSamplingFrequencyMax = properties.getInt(
346                     DeviceConfigHelper.STACK_SAMPLING_FREQUENCY_MAX,
347                     sStackSamplingSamplingFrequencyMax);
348         }
349     }
350 
351     /** This method transforms a request into a useable config for perfetto. */
generateConfigForRequest(int profilingType, final @Nullable Bundle params, String packageName)352     public static byte[] generateConfigForRequest(int profilingType, final @Nullable Bundle params,
353             String packageName) throws IllegalArgumentException {
354         // Create a copy to modify. Entries will be removed from the copy as they're accessed to
355         // ensure that no invalid parameters are present.
356         Bundle paramsCopy = params == null ? null : new Bundle(params);
357 
358         switch (profilingType) {
359             // Java heap dump
360             case ProfilingManager.PROFILING_TYPE_JAVA_HEAP_DUMP:
361                 // This should be unnecessary, but make sure configs are initialized just in case.
362                 initializeJavaHeapDumpConfigsIfNecessary();
363 
364                 if (sKillswitchJavaHeapDump) {
365                     throw new IllegalArgumentException("Java heap dump is disabled");
366                 }
367 
368                 int javaHeapDumpSizeKb = roundUpForBufferSize(getAndRemoveWithinBounds(
369                         ProfilingManager.KEY_SIZE_KB,
370                         sJavaHeapDumpSizeKbDefault,
371                         sJavaHeapDumpSizeKbMin,
372                         sJavaHeapDumpSizeKbMax,
373                         paramsCopy));
374 
375                 confirmEmptyOrThrow(paramsCopy);
376 
377                 return generateJavaHeapDumpConfig(packageName, javaHeapDumpSizeKb);
378 
379             // Heap profile
380             case ProfilingManager.PROFILING_TYPE_HEAP_PROFILE:
381                 // This should be unnecessary, but make sure configs are initialized just in case.
382                 initializeHeapProfileConfigsIfNecessary();
383 
384                 if (sKillswitchHeapProfile) {
385                     throw new IllegalArgumentException("Heap profile is disabled");
386                 }
387 
388                 boolean trackJavaAllocations = getAndRemove(
389                         ProfilingManager.KEY_TRACK_JAVA_ALLOCATIONS,
390                         sHeapProfileTrackJavaAllocationsDefault, paramsCopy);
391                 long samplingIntervalBytes = getAndRemoveWithinBounds(
392                         ProfilingManager.KEY_SAMPLING_INTERVAL_BYTES,
393                         sHeapProfileSamplingIntervalBytesDefault,
394                         sHeapProfileSamplingIntervalBytesMin,
395                         sHeapProfileSamplingIntervalBytesMax,
396                         paramsCopy);
397                 int heapProfileDurationMs = getAndRemoveWithinBounds(
398                         ProfilingManager.KEY_DURATION_MS,
399                         sHeapProfileDurationMsDefault,
400                         sHeapProfileDurationMsMin,
401                         sHeapProfileDurationMsMax,
402                         paramsCopy);
403                 int heapProfileSizeKb = roundUpForBufferSize(getAndRemoveWithinBounds(
404                         ProfilingManager.KEY_SIZE_KB,
405                         sHeapProfileSizeKbDefault,
406                         sHeapProfileSizeKbMin,
407                         sHeapProfileSizeKbMax,
408                         paramsCopy));
409 
410                 confirmEmptyOrThrow(paramsCopy);
411 
412                 return generateHeapProfileConfig(packageName, heapProfileSizeKb,
413                         heapProfileDurationMs, samplingIntervalBytes, trackJavaAllocations);
414 
415             // Stack sampling
416             case ProfilingManager.PROFILING_TYPE_STACK_SAMPLING:
417                 // This should be unnecessary, but make sure configs are initialized just in case.
418                 initializeStackSamplingConfigsIfNecessary();
419 
420                 if (sKillswitchStackSampling) {
421                     throw new IllegalArgumentException("Stack sampling is disabled");
422                 }
423 
424                 long frequency = getAndRemoveWithinBounds(ProfilingManager.KEY_FREQUENCY_HZ,
425                         sStackSamplingSamplingFrequencyDefault,
426                         sStackSamplingSamplingFrequencyMin,
427                         sStackSamplingSamplingFrequencyMax,
428                         paramsCopy);
429                 int stackSamplingDurationMs = getAndRemoveWithinBounds(
430                         ProfilingManager.KEY_DURATION_MS,
431                         sStackSamplingDurationMsDefault,
432                         sStackSamplingDurationMsMin,
433                         sStackSamplingDurationMsMax,
434                         paramsCopy);
435                 int stackSamplingSizeKb = roundUpForBufferSize(getAndRemoveWithinBounds(
436                         ProfilingManager.KEY_SIZE_KB,
437                         sStackSamplingSizeKbDefault,
438                         sStackSamplingSizeKbMin,
439                         sStackSamplingSizeKbMax,
440                         paramsCopy));
441 
442                 confirmEmptyOrThrow(paramsCopy);
443 
444                 return generateStackSamplingConfig(packageName, stackSamplingSizeKb,
445                         stackSamplingDurationMs, frequency);
446 
447             // System trace
448             case ProfilingManager.PROFILING_TYPE_SYSTEM_TRACE:
449                 // This should be unnecessary, but make sure configs are initialized just in case.
450                 initializeSystemTraceConfigsIfNecessary();
451 
452                 if (sKillswitchSystemTrace) {
453                     throw new IllegalArgumentException("System trace is disabled");
454                 }
455 
456                 int systemTraceDurationMs = getAndRemoveWithinBounds(
457                         ProfilingManager.KEY_DURATION_MS,
458                         sSystemTraceDurationMsDefault,
459                         sSystemTraceDurationMsMin,
460                         sSystemTraceDurationMsMax,
461                         paramsCopy);
462                 int systemTraceSizeKb = roundUpForBufferSize(getAndRemoveWithinBounds(
463                         ProfilingManager.KEY_SIZE_KB,
464                         sSystemTraceSizeKbDefault,
465                         sSystemTraceSizeKbMin,
466                         sSystemTraceSizeKbMax,
467                         paramsCopy));
468                 TraceConfig.BufferConfig.FillPolicy systemTraceBufferFillPolicy =
469                         getBufferFillPolicy(getAndRemove(ProfilingManager.KEY_BUFFER_FILL_POLICY,
470                                 ProfilingManager.VALUE_BUFFER_FILL_POLICY_RING_BUFFER, paramsCopy));
471 
472                 confirmEmptyOrThrow(paramsCopy);
473 
474                 return generateSystemTraceConfig(packageName, systemTraceSizeKb,
475                         systemTraceDurationMs, systemTraceBufferFillPolicy);
476 
477             // Invalid type
478             default:
479                 throw new IllegalArgumentException("Invalid profiling type");
480         }
481     }
482 
483     /**
484      * This method returns how long in ms to wait initially before checking if profiling is complete
485      * and rescheduling another check or post processing and cleaning up the result in the event
486      * that it's not stopped manually.
487      */
getInitialProfilingTimeMs(int profilingType, @Nullable Bundle params)488     public static int getInitialProfilingTimeMs(int profilingType,
489             @Nullable Bundle params) {
490         int duration;
491         switch (profilingType) {
492             case ProfilingManager.PROFILING_TYPE_JAVA_HEAP_DUMP:
493                 initializeJavaHeapDumpConfigsIfNecessary();
494                 duration = sJavaHeapDumpDurationMsDefault;
495                 break;
496 
497             case ProfilingManager.PROFILING_TYPE_HEAP_PROFILE:
498                 initializeHeapProfileConfigsIfNecessary();
499                 duration = getWithinBounds(ProfilingManager.KEY_DURATION_MS,
500                         sHeapProfileDurationMsDefault, sHeapProfileDurationMsMin,
501                         sHeapProfileDurationMsMax, params);
502                 break;
503 
504             case ProfilingManager.PROFILING_TYPE_STACK_SAMPLING:
505                 initializeStackSamplingConfigsIfNecessary();
506                 duration = getWithinBounds(ProfilingManager.KEY_DURATION_MS,
507                         sStackSamplingDurationMsDefault, sStackSamplingDurationMsMin,
508                         sStackSamplingDurationMsMax, params);
509                 break;
510 
511             case ProfilingManager.PROFILING_TYPE_SYSTEM_TRACE:
512                 initializeSystemTraceConfigsIfNecessary();
513                 duration = getWithinBounds(ProfilingManager.KEY_DURATION_MS,
514                         sSystemTraceDurationMsDefault, sSystemTraceDurationMsMin,
515                         sSystemTraceDurationMsMax, params);
516                 break;
517 
518             default:
519                 throw new IllegalArgumentException("Invalid profiling type");
520         }
521         return duration + FILE_PROCESSING_DELAY_MS;
522     }
523 
524     /**
525      * This method returns the maximum profiling time allowed for the different profiling types.
526      */
getMaxProfilingTimeAllowedMs(int profilingType, @Nullable Bundle params)527     public static int getMaxProfilingTimeAllowedMs(int profilingType, @Nullable Bundle params) {
528         // Get the initial delay
529         int maxAllowedProcessingTime =
530                 getInitialProfilingTimeMs(profilingType, params);
531 
532         // Add the respective flush and data source timeouts for the types that have them.
533         switch (profilingType) {
534             case ProfilingManager.PROFILING_TYPE_HEAP_PROFILE:
535                 maxAllowedProcessingTime += sHeapProfileFlushTimeoutMsDefault;
536                 break;
537 
538             case ProfilingManager.PROFILING_TYPE_JAVA_HEAP_DUMP:
539                 maxAllowedProcessingTime += sJavaHeapDumpDataSourceStopTimeoutMsDefault;
540                 break;
541 
542             case ProfilingManager.PROFILING_TYPE_STACK_SAMPLING:
543                 maxAllowedProcessingTime += sStackSamplingFlushTimeoutMsDefault;
544                 break;
545         }
546         // Add extra buffer time to account for the time it may take to start the underlying
547         // process.
548         return maxAllowedProcessingTime + MAX_PROFILING_TIME_BUFFER_MS;
549     }
550 
getBufferFillPolicy(int bufferFillPolicy)551     private static TraceConfig.BufferConfig.FillPolicy getBufferFillPolicy(int bufferFillPolicy)
552             throws IllegalArgumentException {
553         switch (bufferFillPolicy) {
554             case ProfilingManager.VALUE_BUFFER_FILL_POLICY_DISCARD:
555                 return TraceConfig.BufferConfig.FillPolicy.DISCARD;
556             case ProfilingManager.VALUE_BUFFER_FILL_POLICY_RING_BUFFER:
557                 return TraceConfig.BufferConfig.FillPolicy.RING_BUFFER;
558             default:
559                 throw new IllegalArgumentException("Invalid buffer fill policy.");
560         }
561     }
562 
getWithinBounds(String key, int defaultValue, int minValue, int maxValue, @Nullable Bundle params)563     private static int getWithinBounds(String key, int defaultValue, int minValue,
564             int maxValue, @Nullable Bundle params) {
565         if (params == null) {
566             return defaultValue;
567         }
568         int value = params.getInt(key, defaultValue);
569         if (value < minValue) {
570             return minValue;
571         } else if (value > maxValue) {
572             return maxValue;
573         } else {
574             return value;
575         }
576     }
577 
getAndRemove(String key, boolean defaultValue, @Nullable Bundle bundle)578     private static boolean getAndRemove(String key, boolean defaultValue, @Nullable Bundle bundle) {
579         if (bundle == null) {
580             return defaultValue;
581         }
582         if (bundle.containsKey(key)) {
583             boolean value = bundle.getBoolean(key);
584             bundle.remove(key);
585             return value;
586         }
587         return defaultValue;
588     }
589 
getAndRemove(String key, int defaultValue, @Nullable Bundle bundle)590     private static int getAndRemove(String key, int defaultValue, @Nullable Bundle bundle) {
591         if (bundle == null) {
592             return defaultValue;
593         }
594         if (bundle.containsKey(key)) {
595             int value = bundle.getInt(key);
596             bundle.remove(key);
597             return value;
598         }
599         return defaultValue;
600     }
601 
getAndRemoveWithinBounds(String key, int defaultValue, int minValue, int maxValue, @Nullable Bundle bundle)602     private static int getAndRemoveWithinBounds(String key, int defaultValue, int minValue,
603             int maxValue, @Nullable Bundle bundle) {
604         if (bundle == null) {
605             return defaultValue;
606         }
607         if (bundle.containsKey(key)) {
608             int value = bundle.getInt(key);
609             bundle.remove(key);
610             if (value < minValue) {
611                 value = minValue;
612             } else if (value > maxValue) {
613                 value = maxValue;
614             }
615             return value;
616         }
617         return defaultValue;
618     }
619 
getAndRemoveWithinBounds(String key, long defaultValue, long minValue, long maxValue, @Nullable Bundle bundle)620     private static long getAndRemoveWithinBounds(String key, long defaultValue, long minValue,
621             long maxValue, @Nullable Bundle bundle) {
622         if (bundle == null) {
623             return defaultValue;
624         }
625         if (bundle.containsKey(key)) {
626             long value = bundle.getLong(key);
627             bundle.remove(key);
628             if (value < minValue) {
629                 value = minValue;
630             } else if (value > maxValue) {
631                 value = maxValue;
632             }
633             return value;
634         }
635         return defaultValue;
636     }
637 
638     /** Buffer sizes are preferred to be multiples of 4kb, round up to next lowest 4 multiple. */
roundUpForBufferSize(int bufferSize)639     private static int roundUpForBufferSize(int bufferSize) {
640         return (bufferSize % 4 == 0) ? bufferSize : bufferSize + (4 - (bufferSize % 4));
641     }
642 
confirmEmptyOrThrow(@ullable Bundle bundle)643     private static void confirmEmptyOrThrow(@Nullable Bundle bundle)
644             throws IllegalArgumentException {
645         if (bundle != null && !bundle.isEmpty()) {
646             throw new IllegalArgumentException(
647                     "Bundle contains invalid or unsupported parameters");
648         }
649     }
650 
generateJavaHeapDumpConfig(String packageName, int bufferSizeKb)651     private static byte[] generateJavaHeapDumpConfig(String packageName, int bufferSizeKb) {
652         TraceConfig.Builder builder = TraceConfig.newBuilder();
653 
654         // Add a buffer
655         TraceConfig.BufferConfig buffer = TraceConfig.BufferConfig.newBuilder()
656                 .setSizeKb(bufferSizeKb)
657                 .setFillPolicy(TraceConfig.BufferConfig.FillPolicy.DISCARD)
658                 .build();
659         builder.addBuffers(buffer);
660 
661         // Add data source
662         JavaHprofConfig javaHprofConfig = JavaHprofConfig.newBuilder()
663                 .addProcessCmdline(packageName)
664                 .setDumpSmaps(true)
665                 .build();
666         DataSourceConfig dataSourceConfig = DataSourceConfig.newBuilder()
667                 .setName("android.java_hprof")
668                 .setJavaHprofConfig(javaHprofConfig)
669                 .build();
670         TraceConfig.DataSource dataSource = TraceConfig.DataSource.newBuilder()
671                 .setConfig(dataSourceConfig)
672                 .build();
673         builder.addDataSources(dataSource);
674 
675         // Add duration and timeout
676         builder.setDurationMs(sJavaHeapDumpDurationMsDefault);
677         builder.setDataSourceStopTimeoutMs(sJavaHeapDumpDataSourceStopTimeoutMsDefault);
678 
679         return builder.build().toByteArray();
680     }
681 
generateHeapProfileConfig(String packageName, int bufferSizeKb, int durationMs, long samplingIntervalBytes, boolean trackJavaAllocations)682     private static byte[] generateHeapProfileConfig(String packageName, int bufferSizeKb,
683             int durationMs, long samplingIntervalBytes, boolean trackJavaAllocations) {
684         TraceConfig.Builder builder = TraceConfig.newBuilder();
685 
686         // Add a buffer
687         TraceConfig.BufferConfig buffer = TraceConfig.BufferConfig.newBuilder()
688                 .setSizeKb(bufferSizeKb)
689                 .setFillPolicy(TraceConfig.BufferConfig.FillPolicy.DISCARD)
690                 .build();
691         builder.addBuffers(buffer);
692 
693         // Add data source
694         HeapprofdConfig.Builder heapprofdConfigBuilder = HeapprofdConfig.newBuilder()
695                 .setShmemSizeBytes(8388608) //8MB
696                 .setSamplingIntervalBytes(samplingIntervalBytes)
697                 .addProcessCmdline(packageName);
698         if (trackJavaAllocations) {
699             heapprofdConfigBuilder.addHeaps("com.android.art");
700         }
701         DataSourceConfig dataSourceConfig = DataSourceConfig.newBuilder()
702                 .setName("android.heapprofd")
703                 .setHeapprofdConfig(heapprofdConfigBuilder.build())
704                 .build();
705         TraceConfig.DataSource dataSource = TraceConfig.DataSource.newBuilder()
706                 .setConfig(dataSourceConfig)
707                 .build();
708         builder.addDataSources(dataSource);
709 
710         // Add duration and timeout
711         builder.setDurationMs(durationMs);
712         builder.setFlushTimeoutMs(sHeapProfileFlushTimeoutMsDefault);
713 
714         return builder.build().toByteArray();
715     }
716 
generateStackSamplingConfig(String packageName, int bufferSizeKb, int durationMs, long frequency)717     private static byte[] generateStackSamplingConfig(String packageName, int bufferSizeKb,
718             int durationMs, long frequency) {
719         TraceConfig.Builder builder = TraceConfig.newBuilder();
720 
721         // Add a buffer
722         TraceConfig.BufferConfig buffer = TraceConfig.BufferConfig.newBuilder()
723                 .setSizeKb(bufferSizeKb)
724                 .setFillPolicy(TraceConfig.BufferConfig.FillPolicy.DISCARD)
725                 .build();
726         builder.addBuffers(buffer);
727 
728         // Add data source
729         PerfEvents.Timebase timebase = PerfEvents.Timebase.newBuilder()
730                 .setCounter(PerfEvents.Counter.SW_CPU_CLOCK)
731                 .setFrequency(frequency)
732                 .setTimestampClock(PerfEvents.PerfClock.PERF_CLOCK_MONOTONIC)
733                 .build();
734         PerfEventConfig.Scope scope = PerfEventConfig.Scope.newBuilder()
735                 .addTargetCmdline(packageName)
736                 .build();
737         PerfEventConfig.CallstackSampling callstackSampling = PerfEventConfig.CallstackSampling
738                 .newBuilder()
739                 .setScope(scope)
740                 .build();
741         PerfEventConfig perfEventConfig = PerfEventConfig.newBuilder()
742                 .setTimebase(timebase)
743                 .setCallstackSampling(callstackSampling)
744                 .build();
745         DataSourceConfig dataSourceConfig = DataSourceConfig.newBuilder()
746                 .setName("linux.perf")
747                 .setPerfEventConfig(perfEventConfig)
748                 .build();
749         TraceConfig.DataSource dataSource = TraceConfig.DataSource.newBuilder()
750                 .setConfig(dataSourceConfig)
751                 .build();
752         builder.addDataSources(dataSource);
753 
754         // Add duration and timeout
755         builder.setDurationMs(durationMs);
756         builder.setFlushTimeoutMs(sStackSamplingFlushTimeoutMsDefault);
757 
758         return builder.build().toByteArray();
759     }
760 
generateSystemTraceConfig(String packageName, int bufferSizeKb, int durationMs, TraceConfig.BufferConfig.FillPolicy bufferFillPolicy)761     private static byte[] generateSystemTraceConfig(String packageName, int bufferSizeKb,
762             int durationMs, TraceConfig.BufferConfig.FillPolicy bufferFillPolicy) {
763         TraceConfig.Builder builder = TraceConfig.newBuilder();
764 
765         addSystemTraceGeneralConfigs(
766                 builder,
767                 new String[] {packageName},
768                 FOUR_MB,
769                 bufferSizeKb,
770                 durationMs,
771                 bufferFillPolicy);
772 
773         return builder.build().toByteArray();
774     }
775 
776     /**
777      * Generate config for system triggered background system trace.
778      *
779      * @param extraLong should only be set to true for testing.
780      */
generateSystemTriggeredTraceConfig(String uniqueSessionName, String[] packageNames, boolean extraLong)781     public static byte[] generateSystemTriggeredTraceConfig(String uniqueSessionName,
782             String[] packageNames, boolean extraLong) {
783         // Make sure we have our config values set. This is the only config specific method which is
784         // called directly and therefore needs to verify the config value initialization directly.
785         initializeSystemTriggeredSystemTraceConfigsIfNecessary();
786 
787         TraceConfig.Builder builder = TraceConfig.newBuilder();
788 
789         addSystemTraceGeneralConfigs(
790                 builder,
791                 packageNames,
792                 sSystemTriggeredSystemTraceDiscardBufferSizeKb,
793                 sSystemTriggeredSystemTraceRingBufferSizeKb,
794                 extraLong
795                         ? ONE_DAY_MS
796                         : sSystemTriggeredSystemTraceDurationMs,
797                 TraceConfig.BufferConfig.FillPolicy.RING_BUFFER);
798 
799         builder.setUniqueSessionName(uniqueSessionName);
800 
801         return builder.build().toByteArray();
802     }
803 
addSystemTraceGeneralConfigs(TraceConfig.Builder builder, String[] packageNames, int bufferOneSizeKb, int bufferTwoSizeKb, int durationMs, TraceConfig.BufferConfig.FillPolicy bufferTwoFillPolicy)804     private static void addSystemTraceGeneralConfigs(TraceConfig.Builder builder,
805             String[] packageNames, int bufferOneSizeKb, int bufferTwoSizeKb, int durationMs,
806             TraceConfig.BufferConfig.FillPolicy bufferTwoFillPolicy) {
807         // Add 2 buffers, discard for data sources dumped at beginning and caller set for all other
808         // data sources.
809         TraceConfig.BufferConfig buffer0 = TraceConfig.BufferConfig.newBuilder()
810                 .setSizeKb(bufferOneSizeKb)
811                 .setFillPolicy(TraceConfig.BufferConfig.FillPolicy.DISCARD)
812                 .build();
813         builder.addBuffers(buffer0);
814         TraceConfig.BufferConfig buffer1 = TraceConfig.BufferConfig.newBuilder()
815                 .setSizeKb(bufferTwoSizeKb)
816                 .setFillPolicy(bufferTwoFillPolicy)
817                 .build();
818         builder.addBuffers(buffer1);
819 
820         // Add a whole bunch of data sources
821 
822         // Scan and dump all processes to buffer 0 when trace starts
823         ProcessStatsConfig processStatsConfig = ProcessStatsConfig.newBuilder()
824                 .setScanAllProcessesOnStart(true)
825                 .build();
826         DataSourceConfig dataSourceConfigProcessStats = DataSourceConfig.newBuilder()
827                 .setName("linux.process_stats")
828                 .setTargetBuffer(0)
829                 .setProcessStatsConfig(processStatsConfig)
830                 .build();
831         TraceConfig.DataSource dataSourceProcessStats = TraceConfig.DataSource.newBuilder()
832                 .setConfig(dataSourceConfigProcessStats)
833                 .build();
834         builder.addDataSources(dataSourceProcessStats);
835 
836         // Initialize the builders that require package names so we only need to iterate through the
837         // list once. These will be used in the following two sections.
838         PackagesListConfig.Builder packagesListConfigBuilder = PackagesListConfig.newBuilder();
839         FtraceConfig.Builder ftraceConfigBuilder = FtraceConfig.newBuilder();
840 
841         for (int i = 0; i < packageNames.length; i++) {
842             String packageName = packageNames[i];
843 
844             // Enable atrace events for each app.
845             ftraceConfigBuilder.addAtraceApps(packageName);
846 
847             // Add to package list config so data is kept by filter.
848             packagesListConfigBuilder.addPackageNameFilter(packageName);
849         }
850 
851         // Dump details about all listed packages to buffer 0. Redactor will filter out the ones
852         // that should not end up in the finished output.
853         DataSourceConfig dataSourceConfigPackagesList = DataSourceConfig.newBuilder()
854                 .setName("android.packages_list")
855                 .setTargetBuffer(0)
856                 .setPackagesListConfig(packagesListConfigBuilder.build())
857                 .build();
858         TraceConfig.DataSource dataSourcePackagesList = TraceConfig.DataSource.newBuilder()
859                 .setConfig(dataSourceConfigPackagesList)
860                 .build();
861         builder.addDataSources(dataSourcePackagesList);
862 
863         // Dump select ftrace events to buffer 1
864         FtraceConfig.CompactSchedConfig compactSchedConfig = FtraceConfig.CompactSchedConfig
865                 .newBuilder()
866                 .setEnabled(true)
867                 .build();
868         ftraceConfigBuilder
869                 .setThrottleRssStat(true)
870                 .setDisableGenericEvents(true)
871                 .setCompactSched(compactSchedConfig)
872                 // RSS and ION buffer events:
873                 .addFtraceEvents("gpu_mem/gpu_mem_total")
874                 // Scheduling information & process tracking. Useful for:
875                 // - what is happening on each CPU at each moment
876                 // - why a thread was descheduled
877                 // - parent/child relationships between processes and threads
878                 .addFtraceEvents("power/suspend_resume")
879                 .addFtraceEvents("sched/sched_process_free")
880                 .addFtraceEvents("sched/sched_switch")
881                 .addFtraceEvents("task/task_newtask")
882                 .addFtraceEvents("task/task_rename")
883                 // Wakeup info. Allows you to compute how long a task was:
884                 .addFtraceEvents("sched/sched_waking")
885                 .addFtraceEvents("sched/sched_wakeup_new")
886                 // vmscan and mm_compaction events:
887                 .addFtraceEvents("vmscan/mm_vmscan_direct_reclaim_begin")
888                 .addFtraceEvents("vmscan/mm_vmscan_direct_reclaim_end")
889                 // Atrace activity manager:
890                 .addAtraceCategories("am")
891                 // Java and C:
892                 .addAtraceCategories("dalvik")
893                 // Bionic C library:
894                 .addAtraceCategories("bionic")
895                 // Binder kernel driver
896                 .addAtraceCategories("binder_driver")
897                 // View system:
898                 .addAtraceCategories("view")
899                 // Input:
900                 .addAtraceCategories("input")
901                 // Graphics:
902                 .addAtraceCategories("gfx");
903 
904         DataSourceConfig dataSourceConfigFtrace = DataSourceConfig.newBuilder()
905                 .setName("linux.ftrace")
906                 .setTargetBuffer(1)
907                 .setFtraceConfig(ftraceConfigBuilder.build())
908                 .build();
909         TraceConfig.DataSource dataSourceFtrace = TraceConfig.DataSource.newBuilder()
910                 .setConfig(dataSourceConfigFtrace)
911                 .build();
912         builder.addDataSources(dataSourceFtrace);
913 
914         // Dump surfaceflinger frame timeline to buffer 1
915         DataSourceConfig dataSourceConfigSurfaceFlinger = DataSourceConfig.newBuilder()
916                 .setName("android.surfaceflinger.frametimeline")
917                 .setTargetBuffer(1)
918                 .build();
919         TraceConfig.DataSource dataSourceSurfaceFlinger = TraceConfig.DataSource.newBuilder()
920                 .setConfig(dataSourceConfigSurfaceFlinger)
921                 .build();
922         builder.addDataSources(dataSourceSurfaceFlinger);
923 
924         // Clear incremental state
925         TraceConfig.IncrementalStateConfig incrementalStateConfig = TraceConfig
926                 .IncrementalStateConfig.newBuilder()
927                         .setClearPeriodMs(10000)
928                         .build();
929         builder.setIncrementalStateConfig(incrementalStateConfig);
930 
931         // Add duration
932         builder.setDurationMs(durationMs);
933     }
934 
935 }
936