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 com.android.server.power.feature; 18 19 import android.os.Build; 20 import android.os.SystemProperties; 21 import android.text.TextUtils; 22 import android.util.Slog; 23 24 import com.android.server.power.feature.flags.Flags; 25 26 import java.io.PrintWriter; 27 import java.util.function.Supplier; 28 29 /** 30 * Utility class to read the flags used in the power manager server. 31 */ 32 public class PowerManagerFlags { 33 private static final boolean DEBUG = false; 34 private static final String TAG = "PowerManagerFlags"; 35 36 private final FlagState mEarlyScreenTimeoutDetectorFlagState = new FlagState( 37 Flags.FLAG_ENABLE_EARLY_SCREEN_TIMEOUT_DETECTOR, 38 Flags::enableEarlyScreenTimeoutDetector); 39 40 private final FlagState mEnableScreenTimeoutPolicyListenerApi = new FlagState( 41 Flags.FLAG_ENABLE_SCREEN_TIMEOUT_POLICY_LISTENER_API, 42 Flags::enableScreenTimeoutPolicyListenerApi 43 ); 44 45 private final FlagState mImproveWakelockLatency = new FlagState( 46 Flags.FLAG_IMPROVE_WAKELOCK_LATENCY, 47 Flags::improveWakelockLatency 48 ); 49 50 private final FlagState mPerDisplayWakeByTouch = new FlagState( 51 Flags.FLAG_PER_DISPLAY_WAKE_BY_TOUCH, 52 Flags::perDisplayWakeByTouch 53 ); 54 55 private final FlagState mFrameworkWakelockInfo = 56 new FlagState(Flags.FLAG_FRAMEWORK_WAKELOCK_INFO, Flags::frameworkWakelockInfo); 57 58 private final FlagState mPolicyReasonInDisplayPowerRequest = new FlagState( 59 Flags.FLAG_POLICY_REASON_IN_DISPLAY_POWER_REQUEST, 60 Flags::policyReasonInDisplayPowerRequest 61 ); 62 63 private final FlagState mMoveWscLoggingToNotifier = 64 new FlagState(Flags.FLAG_MOVE_WSC_LOGGING_TO_NOTIFIER, Flags::moveWscLoggingToNotifier); 65 66 private final FlagState mWakelockAttributionViaWorkchain = 67 new FlagState(Flags.FLAG_WAKELOCK_ATTRIBUTION_VIA_WORKCHAIN, 68 Flags::wakelockAttributionViaWorkchain); 69 70 private final FlagState mDisableFrozenProcessWakelocks = 71 new FlagState(Flags.FLAG_DISABLE_FROZEN_PROCESS_WAKELOCKS, 72 Flags::disableFrozenProcessWakelocks); 73 74 /** Returns whether early-screen-timeout-detector is enabled on not. */ isEarlyScreenTimeoutDetectorEnabled()75 public boolean isEarlyScreenTimeoutDetectorEnabled() { 76 return mEarlyScreenTimeoutDetectorFlagState.isEnabled(); 77 } 78 79 /** Returns whether screen timeout policy listener APIs are enabled on not. */ isScreenTimeoutPolicyListenerApiEnabled()80 public boolean isScreenTimeoutPolicyListenerApiEnabled() { 81 return mEnableScreenTimeoutPolicyListenerApi.isEnabled(); 82 } 83 84 /** 85 * @return Whether to improve the wakelock acquire/release latency or not 86 */ improveWakelockLatency()87 public boolean improveWakelockLatency() { 88 return mImproveWakelockLatency.isEnabled(); 89 } 90 91 /** 92 * @return Whether per-display wake by touch is enabled or not. 93 */ isPerDisplayWakeByTouchEnabled()94 public boolean isPerDisplayWakeByTouchEnabled() { 95 return mPerDisplayWakeByTouch.isEnabled(); 96 } 97 98 /** 99 * @return Whether FrameworkWakelockInfo atom logging is enabled or not. 100 */ isFrameworkWakelockInfoEnabled()101 public boolean isFrameworkWakelockInfoEnabled() { 102 return mFrameworkWakelockInfo.isEnabled(); 103 } 104 105 /** 106 * @return Whether the wakefulness reason is populated in DisplayPowerRequest. 107 */ isPolicyReasonInDisplayPowerRequestEnabled()108 public boolean isPolicyReasonInDisplayPowerRequestEnabled() { 109 return mPolicyReasonInDisplayPowerRequest.isEnabled(); 110 } 111 112 /** 113 * @return Whether we move WakelockStateChanged atom logging to Notifier (enabled) or leave it 114 * in BatteryStatsImpl (disabled). 115 */ isMoveWscLoggingToNotifierEnabled()116 public boolean isMoveWscLoggingToNotifierEnabled() { 117 return mMoveWscLoggingToNotifier.isEnabled(); 118 } 119 120 /** 121 * @return Whether the wakelock attribution via workchain is enabled 122 */ isWakelockAttributionViaWorkchainEnabled()123 public boolean isWakelockAttributionViaWorkchainEnabled() { 124 return mWakelockAttributionViaWorkchain.isEnabled(); 125 } 126 127 /** 128 * @return Whether the feature to disable the frozen process wakelocks is enabled 129 */ isDisableFrozenProcessWakelocksEnabled()130 public boolean isDisableFrozenProcessWakelocksEnabled() { 131 return mDisableFrozenProcessWakelocks.isEnabled(); 132 } 133 134 /** 135 * dumps all flagstates 136 * @param pw printWriter 137 */ dump(PrintWriter pw)138 public void dump(PrintWriter pw) { 139 pw.println("PowerManagerFlags:"); 140 pw.println(" " + mEarlyScreenTimeoutDetectorFlagState); 141 pw.println(" " + mImproveWakelockLatency); 142 pw.println(" " + mPerDisplayWakeByTouch); 143 pw.println(" " + mFrameworkWakelockInfo); 144 pw.println(" " + mMoveWscLoggingToNotifier); 145 pw.println(" " + mWakelockAttributionViaWorkchain); 146 pw.println(" " + mDisableFrozenProcessWakelocks); 147 } 148 149 private static class FlagState { 150 151 private final String mName; 152 153 private final Supplier<Boolean> mFlagFunction; 154 private boolean mEnabledSet; 155 private boolean mEnabled; 156 FlagState(String name, Supplier<Boolean> flagFunction)157 private FlagState(String name, Supplier<Boolean> flagFunction) { 158 mName = name; 159 mFlagFunction = flagFunction; 160 } 161 isEnabled()162 private boolean isEnabled() { 163 if (mEnabledSet) { 164 if (DEBUG) { 165 Slog.d(TAG, mName + ": mEnabled. Recall = " + mEnabled); 166 } 167 return mEnabled; 168 } 169 mEnabled = flagOrSystemProperty(mFlagFunction, mName); 170 if (DEBUG) { 171 Slog.d(TAG, mName + ": mEnabled. Flag value = " + mEnabled); 172 } 173 mEnabledSet = true; 174 return mEnabled; 175 } 176 flagOrSystemProperty(Supplier<Boolean> flagFunction, String flagName)177 private boolean flagOrSystemProperty(Supplier<Boolean> flagFunction, String flagName) { 178 boolean flagValue = flagFunction.get(); 179 if (Build.IS_ENG || Build.IS_USERDEBUG) { 180 return SystemProperties.getBoolean("persist.sys." + flagName + "-override", 181 flagValue); 182 } 183 return flagValue; 184 } 185 186 @Override toString()187 public String toString() { 188 // remove com.android.server.power.feature.flags. from the beginning of the name. 189 // align all isEnabled() values. 190 // Adjust lengths if we end up with longer names 191 final int nameLength = mName.length(); 192 return TextUtils.substring(mName, 39, nameLength) + ": " 193 + TextUtils.formatSimple("%" + (91 - nameLength) + "s%s", " " , isEnabled()) 194 + " (def:" + mFlagFunction.get() + ")"; 195 } 196 } 197 } 198