1 /* 2 * Copyright 2022 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.benchmark.macro 18 19 import androidx.annotation.RestrictTo 20 import androidx.benchmark.Shell 21 22 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) 23 object PowerRail { 24 25 private const val DUMPSYS_POWERSTATS = "dumpsys powerstats" 26 27 /** 28 * Looking for something like this: 29 * 30 * ChannelId: 10, ChannelName: S9S_VDD_AOC, ChannelSubsystem: AOC PowerStatsService dumpsys: 31 * available Channels ChannelId: 0, ChannelName: S10M_VDD_TPU, ChannelSubsystem: TPU ChannelId: 32 * 1, ChannelName: VSYS_PWR_MODEM, ChannelSubsystem: Modem ChannelId: 2, ChannelName: 33 * VSYS_PWR_RFFE, ChannelSubsystem: Cellular ChannelId: 3, ChannelName: S2M_VDD_CPUCL2, 34 * ChannelSubsystem: CPU(BIG) ChannelId: 4, ChannelName: S3M_VDD_CPUCL1, ChannelSubsystem: 35 * CPU(MID) 36 */ 37 private val CHANNEL_ID_REGEX = "ChannelId:(.*)".toRegex() 38 39 /** 40 * Checks if rail metrics are generated on specified device. 41 * 42 * @Throws UnsupportedOperationException if `hasException == true` and no rail metrics are 43 * found. 44 */ hasMetricsnull45 fun hasMetrics(throwOnMissingMetrics: Boolean = false): Boolean { 46 // Note - we don't capture stderr, since if dumpsys fails due to missing 47 // service, we'll correctly fail to find channels in stdout 48 val output = Shell.executeCommandCaptureStdoutOnly(DUMPSYS_POWERSTATS) 49 return hasMetrics(output, throwOnMissingMetrics) 50 } 51 hasMetricsnull52 internal fun hasMetrics(output: String, throwOnMissingMetrics: Boolean = false): Boolean { 53 val line = output.splitToSequence("\r?\n".toRegex()).find { it.contains(CHANNEL_ID_REGEX) } 54 if (!line.isNullOrBlank()) { 55 return true 56 } 57 if (throwOnMissingMetrics) { 58 throw UnsupportedOperationException( 59 """ 60 Rail metrics are not available on this device. 61 To check a device for power/energy measurement support, the following command's 62 output must contain rows underneath the "available Channels" section: 63 64 adb shell $DUMPSYS_POWERSTATS 65 66 To check at runtime for this, use PowerMetric.deviceSupportsPowerEnergy() 67 68 """ 69 .trimIndent() 70 ) 71 } 72 return false 73 } 74 } 75