1 /* 2 * Copyright 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 androidx.tracing.perfetto 18 19 import android.content.Context 20 import android.os.Build 21 import android.os.StrictMode 22 import android.util.Log 23 import androidx.startup.Initializer 24 import androidx.tracing.perfetto.internal.handshake.protocol.Response 25 import java.io.File 26 27 /** Enables tracing at app startup if configured prior to app starting */ 28 class StartupTracingInitializer : Initializer<Unit> { 29 private companion object { 30 private val TAG = StartupTracingInitializer::class.java.name 31 } 32 createnull33 override fun create(context: Context) { 34 // TODO(234351579): Support API < 30 35 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) return 36 37 suppressStrictModeDiskWrites { 38 // read startup tracing config if present 39 val config = 40 StartupTracingConfigStore.load(context) 41 ?: return // early exit if no config is found 42 43 // delete config if not meant to be preserved between runs 44 if (!config.isPersistent) StartupTracingConfigStore.clear(context) 45 46 // enable tracing 47 val libFilePath = config.libFilePath 48 val enableTracingResponse = 49 if (libFilePath == null) PerfettoSdkTrace.enable() 50 else PerfettoSdkTrace.enable(File(libFilePath), context) 51 52 // log the result for debuggability 53 Log.d( 54 TAG, 55 "${Response::class.java.name}: { " + 56 "resultCode: ${enableTracingResponse.resultCode}, " + 57 "message: ${enableTracingResponse.message}, " + 58 "requiredVersion: ${enableTracingResponse.requiredVersion} " + 59 "}" 60 ) 61 } 62 } 63 dependenciesnull64 override fun dependencies(): List<Class<out Initializer<*>>> = emptyList() 65 66 // TODO(245426369): test in TrivialStartupTracingBenchmark 67 private inline fun <R> suppressStrictModeDiskWrites(block: () -> R): R { 68 val oldPolicy = StrictMode.allowThreadDiskWrites() 69 try { 70 return block() 71 } finally { 72 StrictMode.setThreadPolicy(oldPolicy) 73 } 74 } 75 } 76